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..