Copyright (c) 1996 Object Mentor, Inc. All Rights Reserved. 1The Inter translation - Copyright (c) 1996 Object Mentor, Inc. All Rights Reserved. 1The Inter Indonesian how to say

Copyright (c) 1996 Object Mentor, I

Copyright (c) 1996 Object Mentor, Inc. All Rights Reserved. 1
The Interface Segregation
Principle
This is the fourth of my Engineering Notebookcolumns for The C++ Report. The articles
that appear in this column focus on the use of C++ and OOD, and address issues of software engineering. I strive
for articles that are pragmatic and directly useful to
the software engineer in the
trenches. In these articles I
make use of Booch’s and
Rumbaugh’s new unified
Modeling Langage (UML
Version 0.8) for documenting object oriented designs.
The sidebar provides a
brief lexicon of this notation.
Introduction
In my last column (May 96) I discussed the principle of Dependency Inversion (DIP). This
principle states that modules that encapsulate high level policy should not depend upon
modules that implement details. Rather, both kinds of modules should depend upon
abstractions. To be more succinct and simplistic, abstract classes should not depend upon
concrete classes; concrete classes should depend upon abstract classes. A good example of
this principle is the TEMPLATEMETHODpattern from the GOF
1
book. In this pattern, a
high level algorithm is encoded in an abstract base class and makes use of pure virtual
functions to implement its details. Derived classes implement those detailed virtual functions. Thus, the class containing the details depend upon the class containing the abstraction.
In this article we will examine yet another structural principle: the Interface Segregation Principle (ISP). This principle deals with the disadvantages of “fat” interfaces.
Classes that have “fat” interfaces are classes whose interfaces are not cohesive. In other
1. Design Patterns, Gamma, et. al. Addison Wesley, 1995
Sidebar:Unified Notation 0.8
Base Class Base Class Base Class
Derived 1 Derived 2
Had by
Reference
Had By Value
Used
2 Interface Pollution
words, the interfaces of the class can be broken up into groups of member functions. Each
group serves a different set of clients. Thus some clients use one group of member functions, and other clients use the other groups.
The ISP acknowledges that there are objects that require non-cohesive interfaces;
however it suggests that clients should not know about them as a single class. Instead, clients should know about abstract base classes that have cohesive interfaces. Some languages refer to these abstract base classes as “interfaces”, “protocols” or “signatures”.
In this article we will discuss the disadvantages of “fat” or “polluted” interfacse. We
will show how these interfaces get created, and how to design classes which hide them.
Finally we will present a case study in which the a “fat” interface naturally occurs, and we
will employ the ISP to correct it.
Interface Pollution
Consider a security system. In this system there are Door objects that can be locked and
unlocked, and which know whether they are open or closed. (See Listing 1).
Listing 1
Security Door
class Door
{
public:
virtual void Lock() = 0;
virtual void Unlock() = 0;
virtual bool IsDoorOpen() = 0;
};
This class is abstract so that clients can use objects that conform to the Door interface,
without having to depend upon particular implementations of Door.
Now consider that one such implementation. TimedDoor needs to sound an alarm
when the door has been left open for too long. In order to do this the TimedDoor object
communicates with another object called a Timer. (See Listing 2.)
Listing 2
Timer
class Timer
{
public:
void Regsiter(int timeout, TimerClient* client);
};
class TimerClient
{
public:
virtual void TimeOut() = 0;
};
3 : The Interface Segregation Principle
When an object wishes to be informed about a timeout, it calls the Register function
of the Timer. The arguments of this function are the time of the timeout, and a pointer to a
TimerClient object whose TimeOut function will be called when the timeout expires.
How can we get the TimerClient class to communicate with the TimedDoor class so
that the code in the TimedDoor can be notified of the timeout? There are several alternatives. Figure 1 shows a common solution. We force Door, and therefore TimedDoor, to
inherit from TimerClient. This ensures that TimerClient can register itself with the Timer
and receive the TimeOut message.
Although this solution is common, it is not without problems. Chief among these is
that the Door class now depends upon TimerClient. Not all varieties of Door need timing.
Indeed, the original Door abstraction had nothing whatever to do with timing. If timingfree derivatives of Door are created, those derivatives will have to provide nil implementations for the TimeOut method. Moreover, the applications that use those derivatives will
have to #include the definition of the TimerClient class, even though it is not used.
Figure 1 shows a common syndrome of object oriented design in statically typed languates like C++. This is the syndrome of interface pollution. The interface of Door has
been polluted with an interface that it does not require. It has been forced to incorporate
this interface solely for the benefit of one of its subclasses. If this practice is pursued, then
every time a derivative needs a new interface, that interface will be added to the base class.
This will further pollute the interface of the base class, making it “fat”.
Moreover, each time a new interface is added to the base class, that interface must be
implemented (or allowed to default) in derived classes. Indeed, an associated practice is to
add these interfaces to the base class as nilvirtual functions rather than pure virtual functions; specifically so that derived classes are not burdened with the need to implement
them. As we learned in the second article of this column, such a practice violates the
Liskov Substitution Principle (LSP), leading to maintenance and reusability problems.
TimerClient
Door
TimedDoor
Figure 1
TimerClient at top of hierarchy
4 Interface Pollution
Separate Clients mean Separate Interfaces.
Door and TimerClient represent interfaces that are used by complely different clients.
Timer uses TimerClient, and classes that manipulate doors use Door. Since the clients are
separate, the interfaces should remain separate too. Why? Because, as we will see in the
next section, clients exert forces upon their server interfaces.
The backwards force applied by clients upon interfaces.
When we think of forces that cause changes in software, we normally think about how
changes to interfaces will affect their users. For example, we would be concerned about
the changes to all the users of TimerClient, if the TimerClient interface changed. However,
there is a force that operates in the other direction. That is, sometimes it is the user that
forces a change to the interface.
For example, some users of Timer will register more than one timeout request. Consider the TimedDoor. When it detects that the Door has been opened, it sends the Register
message to the Timer, requesting a timeout. However, before that timeout expires the door
closes; remains closed for awhile, and then opens again. This causes us to register a new
timeout request before the old one has expired. Finally, the first timeout request expires
and the TimeOut function of the TimedDoor is invoked. And the Door alarms falsely.
We can correct this situation by using the convention shown in Listing 3. We include a
unique timeOutId code in each timeout registration, and repeat that code in the TimeOut
call to the TimerClient. This allows each derivative of TimerClient to know which timeout
request is being responded to.
Listing 3
Timer with ID
class Timer
{
public:
void Regsiter(int timeout,
int timeOutId,
TimerClient* client);
};
class TimerClient
{
public:
virtual void TimeOut(int timeOutId) = 0;
};
Clearly this change will affect all the users of TimerClient. We accept this since the
lack of the timeOutId is an oversight that needs correction. However, the design in Figure
1 will also cause Door, and all clients of Door to be affected (i.e. at least recompiled) by
this fix! Why should a bug in TimerClient have anyaffect on clients of Door derivatives
that do not require timing? It is this kind of strange interdependency that chills customers
5 : The Interface Segregation Principle
and managers to the bone. When a change in one part of the program affects other completely unerlated parts of the program, the cost and repercussions of changes become
unpredictable; and the risk of fallout from the change increases dramatically.
But it’s just a recompile.
True. But recompiles can be very expensive for a number of reasons. First of all, they take
time. When recompiles take too much time, developers begin to take shortcuts. They may
hack a change in the “wrong” place, rather than engineer a change in the “right” place;
because the “right” place will force a huge recompilation. Secondly, a recompilation
means a new object module. In this day and age of dynamically linked libraries and incremental loaders, generating more object modules than necessary can be a significant disadvantage. The more DLLs that are affected by a change, the greater the problem of
distributing and managing the change.
The Interface Segregation Principle (ISP)
CLIENTSSHOULDNOTBEFORCEDTODEPENDUPONINTERFACES
THATTHEYDONOTUSE.
When clients are forced to depend upon interfaces that they don’t use, then those clients
are subject to changes to those interfaces. This results in an inadvertent coupling between
all the clients. Said another way, when a client depends upon a class that contains interfaces that the client does not use, but that other clients douse, then that client will be
affected by the changes that those other clients force upon the class. We would like to
avoid such couplings where possible, and so we want to separate the interfaces where possible.
Class Interfaces vs Object Interfaces
Consider the TimedDoor again. Here is an object which has two separate interfaces used
by tw
0/5000
From: -
To: -
Results (Indonesian) 1: [Copy]
Copied!
Hak cipta (c) 1996 Mentor objek, Inc All Rights Reserved. 1Pemisahan antarmukaPrinsipIni adalah keempat dari Notebookcolumns saya teknik untuk The C++ laporan. Artikelyang muncul dalam fokus kolom ini menggunakan C++ dan OOD, dan isu-isu rekayasa perangkat lunak. Saya berusahauntuk artikel yang pragmatis dan langsung bermanfaat untuksoftware engineer diparit. Dalam artikel ini sayamenggunakan Beli batu mangan 's danRumbaugh baru yang bersatuPemodelan bahasa Indonesia (UMLVersi 0.8) untuk mendokumentasikan desain berorientasi objek.Sidebar menyediakanleksikon singkat notasi ini.PengenalanDalam kolom (Mei 96) saya terakhir saya membahas prinsip dari ketergantungan inversi (berenang). Iniprinsip menyatakan bahwa modul yang merangkum kebijakan tingkat tinggi tidak harus bergantung padamodul-modul yang menerapkan rincian. Sebaliknya, kedua jenis modul harus bergantung padaabstraksi. Agar lebih ringkas dan sederhana, kelas abstrak harus bergantung padabeton kelas; kelas beton harus tergantung pada kelas abstrak. Contoh yang baikprinsip ini adalah TEMPLATEMETHODpattern dari GOF1buku. Dalam pola initinggi tingkat algoritma dikodekan dalam kelas dasar abstrak dan membuat penggunaan murni virtualfungsi untuk menerapkan rinciannya. Kelas turunan menerapkan fungsi virtual yang rinci. Dengan demikian, kelas berisi rincian tergantung pada kelas yang mengandung abstraksi.Dalam artikel ini kita akan meneliti prinsip struktural lain: Interface pemisahan prinsip (ISP). Prinsip ini berkaitan dengan kerugian dari "gemuk" antarmuka.Kelas yang memiliki antarmuka "gemuk" adalah kelas antarmuka yang tidak kohesif. Di lain-lain1. desain pola, Gamma, et. Al. Addison Wesley, 1995Sidebar: Unified notasi 0,8Kelas dasar kelas dasar kelas dasar1 berasal berasal 2DenganReferensiDengan nilaiDigunakan2 antarmuka polusikata-kata, antarmuka kelas dapat dibagi ke dalam kelompok fungsi anggota. Masing-masingkelompok menyajikan kumpulan klien. Dengan demikian beberapa klien menggunakan satu kelompok fungsi anggota, dan klien lain menggunakan kelompok lain.ISP mengakui bahwa ada objek yang memerlukan bebas-kohesif antarmuka;Namun hal ini menunjukkan bahwa klien harus tidak tahu tentang mereka sebagai satu kelas. Sebaliknya, klien harus tahu tentang kelas dasar abstrak yang memiliki antarmuka yang kohesif. Beberapa bahasa merujuk pada kelas dasar ini abstrak sebagai "interface", "protokol" atau "tanda tangan". Dalam artikel ini kita akan membahas kerugian dari "gemuk" atau "polusi" interfacse. Kamiakan menunjukkan bagaimana antarmuka ini bisa dibuat, dan bagaimana desain kelas yang menyembunyikan mereka.Akhirnya kami akan menyajikan sebuah studi kasus di mana antarmuka "gemuk" yang secara alami terjadi, dan kamiakan menggunakan ISP untuk memperbaikinya.Antarmuka polusiPertimbangkan sebuah sistem keamanan. Dalam sistem ini ada objek pintu yang dapat dikunci danterbuka, dan yang tahu apakah mereka terbuka atau tertutup. (Lihat daftar 1).Daftar 1Tempat masukkelas pintu{Umum:Virtual Batal Lock() = 0;Virtual Batal Unlock() = 0;Virtual bool IsDoorOpen() = 0;};Kelas ini abstrak sehingga klien dapat menggunakan benda-benda yang sesuai untuk antarmuka pintu,tanpa harus tergantung pada implementasi tertentu pintu. Sekarang perhatikan bahwa satu penerapan tersebut. TimedDoor kebutuhan untuk membunyikan alarmketika pintu telah dibiarkan terbuka terlalu lama. Untuk melakukan hal ini objek TimedDoorberkomunikasi dengan objek lain yang disebut Timer. (Lihat daftar 2.)Daftar 2Timerkelas Timer{Umum:membatalkan Regsiter (int timeout, TimerClient * klien);};kelas TimerClient{Umum:Virtual Batal TimeOut() = 0;};3: Interface pemisahan prinsipSebuah objek yang ingin diberitahu tentang timeout, itu memanggil fungsi Registertimer. Argumen fungsi ini adalah masa timeout, dan pointer keTimerClient objek yang TimeOut fungsi akan dipanggil ketika batas waktu berakhir.Bagaimana kita bisa mendapatkan kelas TimerClient untuk berkomunikasi dengan kelas TimedDoor jadibahwa kode dalam TimedDoor dapat diberitahu tentang batas? Ada beberapa alternatif. Gambar 1 menunjukkan sebuah solusi umum. Kita memaksa pintu, dan karena itu TimedDoor, untukmewarisi dari TimerClient. Hal ini memastikan bahwa TimerClient dapat mendaftar sendiri dengan Timerdan menerima pesan TimeOut.Meskipun solusi ini umum, hal ini tidak tanpa masalah. Kepala di antara ini adalahbahwa pintu kelas sekarang tergantung pada TimerClient. Tidak semua jenis pintu membutuhkan waktu.Memang, abstraksi pintu asli tidak ada apa pun harus dilakukan dengan waktu. Jika timingfree derivatif pintu dibuat, derivatif tersebut harus menyediakan nol implementasi metode TimeOut. Selain itu, aplikasi yang menggunakan derivatif tersebut akanharus #include definisi kelas TimerClient, meskipun tidak digunakan.Gambar 1 menunjukkan sindrom common desain berorientasi objek languates yang statis diketik seperti C++. Ini adalah sindrom antarmuka polusi. Memiliki antarmuka pintutelah tercemar dengan antarmuka yang tidak memerlukan. Ia telah dipaksa untuk memasukkanantarmuka ini semata-mata untuk kepentingan salah satu sub kelasnya. Jika praktik ini dikejar, kemudiansetiap kali turunan kebutuhan antarmuka baru, antarmuka tersebut akan ditambahkan ke kelas dasar.Ini lebih lanjut akan mencemari antarmuka dari kelas dasar, sehingga "fat". Selain itu, setiap kali antarmuka baru ditambahkan ke kelas dasar, antarmuka tersebut harusdiimplementasikan (atau dibiarkan default) di berasal kelas. Memang, praktek yang terkait adalah untukantarmuka ini menambah kelas dasar sebagai fungsi nilvirtual daripada fungsi virtual yang murni; khusus sehingga kelas turunan tidak dibebani dengan kebutuhan untuk menerapkanmereka. Seperti yang kita pelajari dalam Pasal Kedua kolom ini, seperti praktek yang melanggarLiskov substitusi prinsip (LSP), mengarah ke masalah pemeliharaan dan usabilitas.TimerClientPintuTimedDoorGambar 1TimerClient di atas hirarki4 antarmuka polusiKlien terpisah berarti antarmuka yang terpisah.Pintu dan TimerClient mewakili interface yang digunakan oleh klien yang berbeda complely.Timer menggunakan TimerClient, dan kelas-kelas yang memanipulasi pintu menggunakan pintu. Karena klienterpisah, antarmuka harus tetap terpisah juga. Mengapa? Karena, seperti yang kita lihat diBagian berikutnya, klien mengerahkan pasukan berdasarkan antarmuka server mereka. Mundur pasukan diterapkan oleh klien pada antarmuka.Ketika kita berpikir tentang kekuatan yang menyebabkan perubahan dalam perangkat lunak, kita biasanya berpikir tentang bagaimanaperubahan antarmuka akan mempengaruhi pengguna mereka. Sebagai contoh, kita akan menjadi prihatin tentangperubahan untuk semua pengguna TimerClient, jika antarmuka TimerClient berubah. Namun,ada kekuatan yang beroperasi dalam arah lain. Itu adalah, kadang-kadang itu adalah pengguna yangkekuatan perubahan ke antarmuka. Sebagai contoh, beberapa pengguna timer akan mendaftarkan lebih dari satu permintaan timeout. Pertimbangkan TimedDoor. Ketika mendeteksi bahwa pintu telah dibuka, ia akan mengirimkan daftarpesan untuk Timer, meminta timeout. Namun, sebelum batas waktu yang berakhir pintumenutup; tetap tertutup untuk sementara, dan kemudian membuka lagi. Hal ini menyebabkan kita untuk daftar barupermintaan timeout sebelum lama telah berakhir. Akhirnya, permintaan timeout pertama berakhirdan fungsi TimeOut TimedDoor dipanggil. Dan pintu alarm palsu.Kita dapat memperbaiki situasi ini dengan menggunakan konvensi ditunjukkan dalam daftar 3. Kami menyertakanunik timeOutId kode registrasi timeout masing-masing, dan ulangi bahwa kode dalam batas waktuHubungi TimerClient. Hal ini memungkinkan setiap turunan dari TimerClient untuk mengetahui mana timeoutpermintaan adalah yang menanggapi.Daftar 3Timer dengan IDkelas Timer{Umum:membatalkan Regsiter (int timeout, Int timeOutId, TimerClient* klien);};kelas TimerClient{Umum:Virtual Batal TimeOut (int timeOutId) = 0;};Jelas perubahan ini akan mempengaruhi semua pengguna TimerClient. Kami menerima ini sejakkurangnya timeOutId adalah pengawasan yang memerlukan koreksi. Namun, desain dalam gambar1 juga akan menyebabkan pintu, dan semua klien pintu akan terpengaruh (yaitu setidaknya recompiled) olehmemperbaiki ini! Mengapa bug di TimerClient harus anyaffect pada klien derivatif pintuyang tidak memerlukan waktu? Ini adalah jenis aneh ketergantungan yang menggigil pelanggan5: Interface pemisahan prinsipdan manajer ke tulang. Kapan perubahan dalam salah satu bagian dari program mempengaruhi sepenuhnya unerlated bagian lain dari program, biaya dan dampak dari perubahan menjaditerduga; dan risiko dampak dari perubahan meningkat secara dramatis.Tapi itu hanya mengkompilasi ulang.Benar. Tapi recompiles bisa sangat mahal untuk sejumlah alasan. Pertama-tama mereka mengambilwaktu. Ketika recompiles mengambil terlalu banyak waktu, pengembang mulai mengambil jalan pintas. Mereka mungkinhack perubahan di tempat "salah", daripada insinyur perubahan di tempat yang "benar";karena tempat "benar" akan memaksa penampilan yang besar. Kedua, penampilanberarti modul baru objek. Di hari ini dan usia terkait secara dinamis Perpustakaan dan inkremental loader, menghasilkan modul obyek lebih dari yang diperlukan dapat kerugian yang signifikan. Dll lain yang dipengaruhi oleh perubahan, semakin besar masalahmendistribusikan dan mengelola perubahan.Prinsip pemisahan antarmuka (ISP)CLIENTSSHOULDNOTBEFORCEDTODEPENDUPONINTERFACESTHATTHEYDONOTUSE.Ketika klien terpaksa tergantung pada antarmuka yang mereka tidak menggunakan, maka kliendikenakan perubahan antarmuka tersebut. Hal ini mengakibatkan kopling sengaja antaraSemua klien. Kata lain, ketika klien tergantung pada kelas yang berisi interface yang klien tidak menggunakan, tetapi bahwa klien lain memadamkan, maka klien akanterpengaruh oleh perubahan yang memaksa mereka klien kepada kelas. Kami inginmenghindari kopling seperti mana mungkin, dan sehingga kita ingin memisahkan antarmuka di mana mungkin.Kelas antarmuka vs objek antarmukaPertimbangkan TimedDoor lagi. Di sini adalah sebuah objek yang memiliki dua antarmuka terpisah yang digunakanoleh tw
Being translated, please wait..
Results (Indonesian) 2:[Copy]
Copied!
Copyright (c) 1996 Obyek Mentor, Inc. Semua Hak Dilindungi. 1
Interface Pemisahan
Prinsip
ini adalah keempat saya Teknik Notebookcolumns untuk The C ++ Report. Artikel-artikel
yang muncul di kolom ini fokus pada penggunaan C ++ dan OOD, dan isu-isu alamat rekayasa perangkat lunak. Aku berusaha
untuk artikel yang pragmatis dan langsung berguna untuk
insinyur perangkat lunak dalam
parit. Dalam artikel ini saya
menggunakan Booch dan
Rumbaugh baru bersatu
Modeling Langage (UML
Version 0.8) untuk mendokumentasikan berorientasi objek desain.
Sidebar menyediakan
leksikon singkat notasi ini.
Pendahuluan
di kolom terakhir saya (Mei 96) saya membahas prinsip Ketergantungan inversi (DIP). Ini
prinsip menyatakan bahwa modul yang merangkum kebijakan tingkat tinggi seharusnya tidak bergantung pada
modul yang menerapkan rincian. Sebaliknya, kedua jenis modul harus bergantung pada
abstraksi. Agar lebih ringkas dan sederhana, kelas abstrak tidak harus tergantung pada
kelas beton; kelas beton harus tergantung pada kelas abstrak. Sebuah contoh yang baik dari
prinsip ini adalah TEMPLATEMETHODpattern dari GOF
1
buku. Dalam pola ini, sebuah
algoritma tingkat tinggi dikodekan dalam kelas dasar abstrak dan membuat penggunaan virtual murni
fungsi untuk melaksanakan rinciannya. Kelas turunan melaksanakan fungsi-fungsi maya rinci. Dengan demikian, kelas yang berisi rincian tergantung pada kelas yang berisi abstraksi.
Pada artikel ini kita akan memeriksa lagi prinsip struktural: Interface Pemisahan Prinsip (ISP). Prinsip ini berkaitan dengan kerugian dari "lemak" interface.
Kelas yang memiliki "gemuk" interface kelas yang interface tidak kohesif. Dalam lain
1. Pola desain, Gamma, et. al. Addison Wesley, 1995
Sidebar: Bersatu Notasi 0.8
Base Class Base Class Kelas Basis
Berasal 1 Berasal 2
Telah oleh
Referensi
Harus Dengan Nilai
Digunakan
2 Polusi Antarmuka
kata, antarmuka kelas dapat dipecah menjadi kelompok fungsi anggota. Setiap
kelompok menyajikan satu set yang berbeda dari klien. . Jadi beberapa klien menggunakan satu kelompok fungsi anggota, dan klien lainnya menggunakan kelompok lain
ISP mengakui bahwa ada benda yang membutuhkan antarmuka non-kohesif,
namun menunjukkan bahwa klien tidak harus tahu tentang mereka sebagai satu kelas. Sebaliknya, klien harus tahu tentang kelas dasar abstrak yang memiliki interface kohesif. Beberapa bahasa mengacu pada kelas-kelas dasar abstrak sebagai "interface", "protokol" atau "tanda tangan".
Pada artikel ini kita akan membahas kerugian dari "lemak" atau "tercemar" interfacse. Kami
akan menunjukkan bagaimana antarmuka ini bisa dibuat, dan bagaimana merancang kelas yang menyembunyikan mereka.
Akhirnya kami akan menyajikan sebuah studi kasus di mana sebuah "gemuk" antarmuka alami terjadi, dan kami
akan menggunakan ISP untuk memperbaikinya.
Polusi Antarmuka
Pertimbangkan sistem keamanan. Dalam sistem ini ada benda pintu yang dapat dikunci dan
dibuka, dan yang tahu apakah mereka terbuka atau tertutup. (Lihat Listing 1).
Listing 1
Keamanan Pintu
Pintu class {public: virtual void Lock () = 0; virtual void Aktifkan () = 0; maya IsDoorOpen bool () = 0;}; Kelas ini adalah abstrak sehingga klien dapat menggunakan benda-benda yang sesuai dengan antarmuka Door, tanpa harus bergantung pada implementasi tertentu Door. Sekarang perhatikan bahwa satu implementasi tersebut. TimedDoor perlu membunyikan alarm ketika pintu telah dibiarkan terbuka terlalu lama. Untuk melakukan hal ini objek TimedDoor yang berkomunikasi dengan objek lain yang disebut Timer. (Lihat Listing 2.) Kode 2 Timer Timer class {public: kekosongan regsiter (int timeout, TimerClient * client);}; class TimerClient {public: virtual void TimeOut () = 0;}; 3: The Antarmuka Pemisahan Prinsip Ketika objek ingin diberitahu tentang timeout, itu memanggil fungsi Register dari Timer. Argumen dari fungsi ini adalah saat batas waktu, dan pointer ke objek TimerClient yang fungsinya TimeOut akan dipanggil ketika batas waktu berakhir. Bagaimana kita bisa mendapatkan kelas TimerClient untuk berkomunikasi dengan kelas TimedDoor sehingga bahwa kode di TimedDoor yang dapat diberitahu tentang batas waktu? Ada beberapa alternatif. Gambar 1 menunjukkan solusi umum. Kami memaksa pintu, dan karena itu TimedDoor, untuk mewarisi dari TimerClient. Hal ini memastikan bahwa TimerClient dapat mendaftarkan diri dengan Timer dan menerima pesan TimeOut. Meskipun solusi ini adalah umum, itu bukan tanpa masalah. Kepala di antara ini adalah bahwa kelas Pintu sekarang tergantung pada TimerClient. Tidak semua jenis Pintu perlu waktu. Memang, Pintu abstraksi asli tidak ada apa pun hubungannya dengan waktu. Jika derivatif timingfree Pintu diciptakan, turunan harus menyediakan implementasi nihil untuk metode TimeOut. Selain itu, aplikasi yang menggunakan turunan akan harus # include definisi kelas TimerClient, meskipun tidak digunakan. Gambar 1 menunjukkan sindrom umum desain berorientasi objek di languates statis diketik seperti C ++. Ini adalah sindrom polusi antarmuka. Antarmuka Pintu telah tercemar dengan antarmuka yang tidak memerlukan. Itu telah dipaksa untuk menggabungkan antarmuka ini semata-mata untuk kepentingan salah satu subclass nya. Jika praktek ini dikejar, maka setiap kali derivatif membutuhkan antarmuka baru, antarmuka yang akan ditambahkan ke kelas dasar. Hal ini akan mencemari antarmuka kelas dasar, sehingga "gemuk". Selain itu, setiap kali antarmuka baru ditambahkan ke kelas dasar, antarmuka yang harus dilaksanakan (atau dibiarkan default) di kelas turunan. Memang, praktek terkait adalah dengan menambahkan antarmuka ini untuk kelas dasar sebagai fungsi nilvirtual daripada fungsi virtual murni; khusus sehingga kelas turunan tidak dibebani dengan kebutuhan untuk menerapkan mereka. Seperti yang kita pelajari dalam artikel kedua kolom ini, praktek seperti melanggar Liskov Pergantian Prinsip (LSP), yang mengarah ke pemeliharaan dan usabilitas masalah. TimerClient Pintu TimedDoor Gambar 1 TimerClient di atas hirarki 4 Polusi Antarmuka Klien terpisah berarti Interfaces terpisah. Pintu dan TimerClient mewakili antarmuka yang digunakan oleh complely klien yang berbeda. Timer menggunakan TimerClient, dan kelas yang memanipulasi pintu menggunakan Door. Karena klien terpisah, antarmuka harus tetap terpisah juga. Mengapa? Karena, seperti yang akan kita lihat di bagian berikutnya, klien mengerahkan pasukan pada interface server mereka. Gaya mundur diterapkan oleh klien pada interface. Ketika kita berpikir tentang kekuatan yang menyebabkan perubahan dalam perangkat lunak, kita biasanya berpikir tentang bagaimana perubahan antarmuka akan mempengaruhi mereka pengguna. Sebagai contoh, kita akan khawatir tentang perubahan ke semua pengguna TimerClient, jika antarmuka TimerClient berubah. Namun, ada sebuah kekuatan yang beroperasi di arah lain. Artinya, kadang-kadang adalah pengguna yang memaksa perubahan ke antarmuka. Sebagai contoh, beberapa pengguna Timer akan mendaftarkan lebih dari satu permintaan timeout. Pertimbangkan TimedDoor. Ketika mendeteksi bahwa pintu telah dibuka, ia akan mengirimkan Register pesan ke Timer, meminta timeout. Namun, sebelum batas waktu yang berakhir pintu menutup; tetap tertutup untuk sementara, dan kemudian membuka lagi. Hal ini menyebabkan kita untuk mendaftarkan baru permintaan timeout sebelum yang lama telah berakhir. Akhirnya, permintaan batas waktu pertama berakhir dan fungsi TimeOut dari TimedDoor dipanggil. Dan alarm pintu palsu. Kami dapat memperbaiki situasi ini dengan menggunakan konvensi ditunjukkan pada Listing 3. Kami menyertakan kode timeOutId unik di setiap pendaftaran timeout, dan ulangi kode yang di TimeOut panggilan ke TimerClient. Hal ini memungkinkan setiap turunan dari TimerClient untuk mengetahui batas waktu permintaan sedang merespons. Listing 3 Timer dengan ID Timer class {public: kekosongan regsiter (int timeout, int timeOutId, TimerClient * client);}; class TimerClient {public: virtual void TimeOut (int timeOutId) = 0;}; Jelas perubahan ini akan mempengaruhi semua pengguna TimerClient. Kami menerima ini karena kurangnya timeOutId adalah pengawasan yang perlu koreksi. Namun, desain pada Gambar 1 juga akan menyebabkan pintu, dan semua klien Pintu akan terpengaruh (yaitu minimal dikompilasi ulang) oleh perbaikan ini! Mengapa harus bug di TimerClient memiliki anyaffect pada klien derivatif Pintu yang tidak memerlukan waktu? Ini adalah jenis saling ketergantungan aneh yang menggigil pelanggan 5: The Antarmuka Pemisahan Prinsip dan manajer ke tulang. Ketika perubahan di salah satu bagian dari program mempengaruhi bagian-benar unerlated lain dari program ini, biaya dan dampak dari perubahan menjadi tak terduga; dan risiko dampak dari kenaikan perubahan dramatis. Tapi itu hanya mengkompilasi ulang. Benar. Tapi recompiles bisa sangat mahal untuk sejumlah alasan. Pertama-tama, mereka mengambil waktu. Ketika recompiles mengambil terlalu banyak waktu, pengembang mulai mengambil jalan pintas. Mereka mungkin hack perubahan dalam "salah" tempat, bukan insinyur perubahan yang "benar" tempat; karena yang "benar" tempat akan memaksa kompilasi besar. Kedua, kompilasi ulang sebuah berarti modul objek baru. Di hari ini dan usia perpustakaan terkait secara dinamis dan loader tambahan, menghasilkan lebih modul objek dari yang diperlukan dapat menjadi kerugian yang signifikan. Semakin DLL yang dipengaruhi oleh perubahan, semakin besar masalah mendistribusikan dan mengelola perubahan. Interface Pemisahan Prinsip (ISP) CLIENTSSHOULDNOTBEFORCEDTODEPENDUPONINTERFACES THATTHEYDONOTUSE. Ketika klien dipaksa untuk bergantung pada antarmuka bahwa mereka tidak menggunakan, maka klien-klien yang tunduk perubahan tersebut interface. Hasil ini merupakan kopling sengaja antara semua klien. Kata lain, ketika klien tergantung pada kelas yang berisi antarmuka bahwa klien tidak menggunakan, tapi itu klien lain memadamkan, maka klien akan dipengaruhi oleh perubahan yang mereka klien lain memaksakan kelas. Kami ingin menghindari kopling seperti mana mungkin, dan jadi kami ingin memisahkan interface mana mungkin. Kelas Antarmuka vs Interfaces Object Pertimbangkan TimedDoor lagi. Berikut adalah obyek yang memiliki dua interface yang terpisah digunakan oleh tw














































































































Being translated, please wait..
 
Other languages
The translation tool support: Afrikaans, Albanian, Amharic, Arabic, Armenian, Azerbaijani, Basque, Belarusian, Bengali, Bosnian, Bulgarian, Catalan, Cebuano, Chichewa, Chinese, Chinese Traditional, Corsican, Croatian, Czech, Danish, Detect language, Dutch, English, Esperanto, Estonian, Filipino, Finnish, French, Frisian, Galician, Georgian, German, Greek, Gujarati, Haitian Creole, Hausa, Hawaiian, Hebrew, Hindi, Hmong, Hungarian, Icelandic, Igbo, Indonesian, Irish, Italian, Japanese, Javanese, Kannada, Kazakh, Khmer, Kinyarwanda, Klingon, Korean, Kurdish (Kurmanji), Kyrgyz, Lao, Latin, Latvian, Lithuanian, Luxembourgish, Macedonian, Malagasy, Malay, Malayalam, Maltese, Maori, Marathi, Mongolian, Myanmar (Burmese), Nepali, Norwegian, Odia (Oriya), Pashto, Persian, Polish, Portuguese, Punjabi, Romanian, Russian, Samoan, Scots Gaelic, Serbian, Sesotho, Shona, Sindhi, Sinhala, Slovak, Slovenian, Somali, Spanish, Sundanese, Swahili, Swedish, Tajik, Tamil, Tatar, Telugu, Thai, Turkish, Turkmen, Ukrainian, Urdu, Uyghur, Uzbek, Vietnamese, Welsh, Xhosa, Yiddish, Yoruba, Zulu, Language translation.

Copyright ©2024 I Love Translation. All reserved.

E-mail: