Pengantar pola desain, Bagian 1: Sejarah dan klasifikasi pola desain

Banyak strategi telah dirancang untuk menyederhanakan dan mengurangi biaya perancangan perangkat lunak, terutama di bidang pemeliharaan. Mempelajari cara mengidentifikasi dan bekerja dengan komponen perangkat lunak yang dapat digunakan kembali (kadang-kadang disebut sebagai sirkuit terintegrasi perangkat lunak ) adalah salah satu strategi. Menggunakan pola desain adalah hal lain.

Artikel ini meluncurkan seri tiga bagian tentang pola desain. Di bagian ini saya akan memperkenalkan kerangka kerja konseptual pola desain dan memandu demonstrasi mengevaluasi pola desain untuk kasus penggunaan tertentu. Saya juga akan membahas sejarah pola desain, dan anti-pola. Terakhir, saya akan mengklasifikasikan dan meringkas pola desain perangkat lunak yang paling banyak digunakan yang telah ditemukan dan didokumentasikan selama beberapa dekade terakhir.

Apa itu pola desain?

Merancang perangkat lunak berorientasi objek yang dapat digunakan kembali yang memodelkan sistem yang ada benar-benar menantang. Pengembang perangkat lunak harus memfaktorkan entitas sistem ke dalam kelas yang antarmuka publiknya tidak terlalu kompleks, membangun hubungan antar kelas, mengekspos hierarki pewarisan, dan banyak lagi. Karena sebagian besar perangkat lunak tetap digunakan lama setelah ditulis, pengembang perangkat lunak juga perlu menangani persyaratan aplikasi saat ini sambil menjaga kode dan infrastruktur mereka cukup fleksibel untuk memenuhi kebutuhan di masa mendatang.

Pengembang berorientasi objek yang berpengalaman telah menemukan bahwa pola desain perangkat lunak memfasilitasi pengkodean sistem perangkat lunak yang stabil dan kuat. Menggunakan kembali pola desain ini daripada terus mengembangkan solusi baru dari awal adalah efisien, dan ini mengurangi beberapa risiko kesalahan. Setiap pola desain mengidentifikasi masalah desain yang berulang dalam konteks aplikasi tertentu, lalu menawarkan solusi umum yang dapat digunakan kembali yang dapat diterapkan pada skenario aplikasi yang berbeda.

" Pola desain mendeskripsikan kelas dan objek yang berinteraksi yang digunakan untuk memecahkan masalah desain umum dalam konteks tertentu."

Beberapa pengembang mendefinisikan pola desain sebagai entitas yang dikodekan kelas (seperti daftar tertaut atau vektor bit), sedangkan yang lain mengatakan bahwa pola desain ada di seluruh aplikasi atau subsistem. Pandangan saya adalah bahwa pola desain menggambarkan kelas dan objek yang berinteraksi yang digunakan untuk memecahkan masalah desain umum dalam konteks tertentu. Secara lebih formal, pola desain ditentukan sebagai deskripsi yang terdiri dari empat elemen dasar:

  1. Sebuah nama yang menggambarkan pola desain dan memberi kita kosakata untuk membahas itu
  2. Sebuah masalah yang mengidentifikasi masalah desain yang perlu dipecahkan bersama dengan konteks di mana masalah terjadi
  3. Sebuah solusi untuk masalah, yang (dalam konteks pola desain perangkat lunak) harus mengidentifikasi kelas dan objek yang berkontribusi terhadap desain bersama dengan hubungan mereka dan faktor lainnya
  4. Penjelasan tentang konsekuensi penggunaan pola desain

Untuk mengidentifikasi pola desain yang tepat untuk digunakan, Anda harus terlebih dahulu mengidentifikasi dengan jelas masalah yang Anda coba selesaikan; di situlah elemen masalah dari deskripsi pola desain membantu. Memilih satu pola desain di atas yang lain juga biasanya melibatkan trade-off yang dapat memengaruhi fleksibilitas aplikasi atau sistem dan pemeliharaan di masa mendatang. Itulah mengapa penting untuk memahami konsekuensi penggunaan pola desain tertentu sebelum Anda mulai menerapkannya.

Mengevaluasi pola desain

Pertimbangkan tugas merancang antarmuka pengguna yang kompleks menggunakan tombol, bidang teks, dan komponen non-penampung lainnya. Pola desain komposit menganggap container sebagai komponen, yang memungkinkan kita menyarangkan container dan komponennya (container dan non-container) di dalam container lain, dan melakukannya secara rekursif. Jika kita memilih untuk tidak menggunakan pola Komposit, kita harus membuat banyak komponen non-penampung khusus (misalnya, satu komponen yang menggabungkan bidang teks kata sandi dan tombol masuk), yang lebih sulit dicapai.

Setelah memikirkan hal ini, kami memahami masalah yang kami coba selesaikan dan solusi yang ditawarkan oleh pola Komposit. Tetapi apa konsekuensi dari menggunakan pola ini?

Menggunakan Composite berarti hierarki kelas Anda akan mencampur komponen container dan non-container. Klien yang lebih sederhana akan memperlakukan komponen kontainer dan non-kontainer secara seragam. Dan akan lebih mudah untuk memperkenalkan jenis komponen baru ke dalam UI. Komposit juga dapat menyebabkan desain yang terlalu umum , sehingga lebih sulit untuk membatasi jenis komponen yang dapat ditambahkan ke wadah. Karena Anda tidak dapat mengandalkan compiler untuk menerapkan batasan tipe, Anda harus menggunakan pemeriksaan tipe runtime.

Apa yang salah dengan pemeriksaan jenis runtime?

Pemeriksaan jenis runtime melibatkan pernyataan if dan instanceofoperator, yang mengarah ke kode rapuh. Jika Anda lupa memperbarui pemeriksaan jenis runtime saat persyaratan aplikasi Anda berkembang, Anda dapat memasukkan bug selanjutnya.

Dimungkinkan juga untuk memilih pola desain yang sesuai dan menggunakannya secara tidak benar. The penguncian ganda Diperiksa pola adalah contoh klasik. Penguncian yang diperiksa dua kali mengurangi overhead perolehan kunci dengan terlebih dahulu menguji kriteria penguncian tanpa benar-benar memperoleh kunci, dan kemudian hanya memperoleh kunci jika pemeriksaan tersebut menunjukkan bahwa penguncian diperlukan. Meskipun terlihat bagus di atas kertas, penguncian yang diperiksa dua kali di JDK 1.4 memiliki beberapa kerumitan tersembunyi. Ketika JDK 5 memperpanjang semantik volatilekata kunci, pengembang akhirnya dapat memperoleh manfaat dari pola penguncian yang diperiksa dua kali.

Lebih lanjut tentang penguncian yang diperiksa dua kali

Lihat "Penguncian yang diperiksa dua kali: Pintar, tetapi rusak" dan "Dapatkah penguncian yang diperiksa dua kali diperbaiki?" (Brian Goetz, JavaWorld) untuk mempelajari lebih lanjut tentang mengapa pola ini tidak berfungsi di JDK 1.4 dan sebelumnya. Untuk mengetahui lebih lanjut tentang menentukan DCL di JDK 5 dan yang lebih baru, lihat "Deklarasi 'Penguncian yang Dicentang Ganda Rusak'" (Departemen Ilmu Komputer Universitas Maryland, David Bacon, dkk.).

Anti-pola

Jika pola desain biasa digunakan tetapi tidak efektif dan / atau kontraproduktif, pola desain tersebut dikenal sebagai anti-pola . Orang mungkin berpendapat bahwa penguncian yang diperiksa dua kali seperti yang digunakan di JDK 1.4 dan sebelumnya adalah anti-pola. Saya akan mengatakan bahwa itu hanyalah ide yang buruk dalam konteks itu. Agar gagasan buruk berkembang menjadi anti-pola, kondisi berikut harus dipenuhi (lihat Sumberdaya).

  • Pola tindakan, proses, atau struktur berulang yang awalnya tampak bermanfaat, tetapi pada akhirnya menghasilkan konsekuensi yang lebih buruk daripada hasil yang bermanfaat.
  • Ada solusi alternatif yang didokumentasikan dengan jelas, terbukti dalam praktik, dan dapat diulang.

Meskipun penguncian yang diperiksa dua kali di JDK 1.4 memenuhi persyaratan pertama dari anti-pola, itu tidak memenuhi yang kedua: meskipun Anda dapat menggunakan synchronizeduntuk memecahkan masalah inisialisasi malas di lingkungan multithread, hal itu akan mengalahkan alasan untuk menggunakan penguncian yang diperiksa dua kali di tempat pertama.

Kebuntuan anti-pola

Mengenali antipola adalah prasyarat untuk menghindarinya. Baca seri tiga bagian Obi Ezechukwu untuk pengantar tiga anti-pola yang terkenal menyebabkan kebuntuan:

  • Tidak ada arbitrase
  • Agregasi pekerja
  • Penguncian tambahan

Sejarah pola desain

Pola desain tanggal kembali ke akhir 1970-an dengan publikasi A Pattern Language: Towns, Buildings, Construction oleh arsitek Christopher Alexander dan beberapa lainnya. Buku ini memperkenalkan pola desain dalam konteks arsitektural, menyajikan 253 pola yang secara kolektif membentuk apa yang oleh pengarang disebut bahasa pola .

Ironi dari pola desain

Meskipun pola desain yang digunakan untuk desain perangkat lunak dimulai dari A Pattern Language , karya arsitektur ini dipengaruhi oleh bahasa yang muncul saat itu untuk menggambarkan pemrograman dan desain komputer.

Konsep bahasa pola kemudian muncul dalam Desain Sistem Terpusat Pengguna Donald Norman dan Stephen Draper , yang diterbitkan pada tahun 1986. Buku ini menyarankan penerapan bahasa pola untuk desain interaksi , yang merupakan praktik merancang produk digital interaktif, lingkungan, sistem , dan layanan untuk digunakan manusia.

Sementara itu, Kent Beck dan Ward Cunningham mulai mempelajari pola dan penerapannya pada desain perangkat lunak. Pada tahun 1987, mereka menggunakan serangkaian pola desain untuk membantu Tektronix's Semiconductor Test Systems Group, yang mengalami masalah dalam menyelesaikan proyek desain. Beck dan Cunningham mengikuti saran Alexander untuk desain yang berpusat pada pengguna (membiarkan perwakilan pengguna proyek menentukan hasil desain) sambil juga memberi mereka beberapa pola desain untuk mempermudah pekerjaan.

Erich Gamma juga menyadari pentingnya pola desain berulang saat mengerjakan tesis PhD-nya. Dia percaya bahwa pola desain dapat memfasilitasi tugas menulis perangkat lunak berorientasi objek yang dapat digunakan kembali, dan merenungkan bagaimana mendokumentasikan dan mengkomunikasikannya secara efektif. Sebelum Konferensi Eropa 1991 tentang Pemrograman Berorientasi Objek, Gamma dan Richard Helm mulai membuat katalog pola.

Pada lokakarya OOPSLA yang diadakan pada tahun 1991, Gamma dan Helm bergabung dengan Ralph Johnson dan John Vlissides. Ini Gang of Four (GOF), karena mereka kemudian dikenal, melanjutkan untuk menulis populer Pola Desain: Unsur Reusable Object-Oriented Software , yang dokumen 23 pola desain dalam tiga kategori.

Evolusi pola desain modern

Pola desain terus berkembang sejak buku GoF yang asli, terutama karena pengembang perangkat lunak menghadapi tantangan baru terkait dengan perubahan persyaratan perangkat keras dan aplikasi.

Pada tahun 1994, sebuah organisasi nirlaba yang berbasis di AS yang dikenal sebagai Hillside Group meresmikan Pattern Languages ​​of Programs , sebuah grup konferensi tahunan yang bertujuan untuk mengembangkan dan menyempurnakan seni pola desain perangkat lunak. Konferensi yang sedang berlangsung ini telah menghasilkan banyak contoh pola desain khusus domain. Misalnya, pola desain dalam konteks konkurensi.

Christopher Alexander di OOPSLA

Pidato utama OOPSLA 96 disampaikan oleh arsitek Christopher Alexander. Alexander merefleksikan karyanya dan tentang bagaimana komunitas pemrograman berorientasi objek telah mencapai dan meleset dalam mengadopsi dan mengadaptasi idenya tentang bahasa pola ke perangkat lunak. Anda dapat membaca alamat Alexander secara lengkap: "Asal Usul Teori Pola: Teori Masa Depan, Dan Generasi Dunia Hidup".

Pada tahun 1998 Mark Grand merilis Patterns in Java . Buku ini menyertakan pola desain yang tidak ditemukan di buku GoF, termasuk pola konkurensi. Grand juga menggunakan Unified Modeling Language (UML) untuk mendeskripsikan pola desain dan solusinya. Contoh buku itu diungkapkan dan dijelaskan dalam bahasa Jawa.

Pola desain perangkat lunak berdasarkan klasifikasi

Pola desain perangkat lunak modern secara luas diklasifikasikan ke dalam empat kategori berdasarkan penggunaannya: kreasi, struktural, perilaku, dan konkurensi. Saya akan membahas setiap kategori dan kemudian membuat daftar dan menjelaskan beberapa pola yang menonjol untuk masing-masing kategori.

Jenis pola desain lainnya

Jika Anda berpikir bahwa ada lebih banyak jenis pola, Anda benar. Artikel selanjutnya dalam seri ini akan membahas jenis pola desain tambahan: interaksi, arsitektur, organisasi, dan pola komunikasi / presentasi.

Pola penciptaan

Sebuah pola penciptaan abstrak proses Instansiasi, memisahkan bagaimana objek diciptakan, terdiri, dan mewakili dari kode yang bergantung pada mereka. Pola pembuatan kelas menggunakan pewarisan untuk memvariasikan kelas yang dibuat, dan pola pembuatan objek mendelegasikan pembuatan instance ke objek lain.

  • Pabrik abstrak : Pola ini menyediakan antarmuka untuk merangkum sekelompok pabrik individu yang memiliki tema umum tanpa menentukan kelas betonnya.
  • Builder : Memisahkan konstruksi objek yang kompleks dari representasinya, memungkinkan proses konstruksi yang sama untuk membuat berbagai representasi. Abstrak langkah-langkah konstruksi objek memungkinkan implementasi yang berbeda dari langkah-langkah untuk membangun representasi yang berbeda dari objek.
  • Metode pabrik : Mendefinisikan antarmuka untuk membuat objek, tetapi memungkinkan subclass memutuskan kelas mana yang akan dibuat. Pola ini memungkinkan kelas menangguhkan instansiasi ke subkelas. Injeksi ketergantungan adalah pola terkait. (Lihat Sumber.)
  • Inisialisasi malas : Pola ini memberi kita cara untuk menunda pembuatan objek, pencarian database, atau proses mahal lainnya hingga pertama kali hasilnya dibutuhkan.
  • Multiton : Memperluas konsep singleton untuk mengelola peta instance kelas bernama sebagai key-value pair, dan menyediakan titik akses global kepada mereka.
  • Obyek kolam renang : Jauhkan satu set objek diinisialisasi siap untuk digunakan, daripada dialokasikan dan dihancurkan pada permintaan. Tujuannya adalah untuk menghindari perolehan sumber daya yang mahal dan reklamasi dengan mendaur ulang objek yang tidak lagi digunakan.
  • Prototipe : Menentukan jenis objek yang akan dibuat menggunakan contoh prototipe, kemudian membuat objek baru dengan menyalin prototipe ini. Contoh prototipe digandakan untuk menghasilkan objek baru.
  • Akuisisi sumber daya adalah inisialisasi : Pola ini memastikan bahwa sumber daya secara otomatis dan benar diinisialisasi dan diklaim kembali dengan mengikatnya ke masa pakai objek yang sesuai. Sumber daya diperoleh selama inisialisasi objek, ketika tidak ada kemungkinan digunakan sebelum tersedia, dan dilepaskan dengan penghancuran objek yang sama, yang dijamin akan berlangsung bahkan dalam kasus kesalahan.
  • Singleton : Memastikan bahwa kelas hanya memiliki satu instance dan menyediakan titik akses global ke instance ini.