Rancang pola yang harus dihindari [tertutup]

105

Banyak orang tampaknya setuju, bahwa pola Singleton memiliki sejumlah kekurangan dan beberapa bahkan menyarankan untuk menghindari pola tersebut sepenuhnya. Ada diskusi yang bagus di sini . Harap tujukan komentar apa pun tentang pola Singleton ke pertanyaan itu.

Pertanyaan saya : Apakah ada pola desain lain, yang harus dihindari atau digunakan dengan sangat hati-hati?

Brian Rasmussen
sumber
Saya hanya perlu memperhatikan tentang daftar besar Antipattern Desain deviq.com/antipatterns
Pengembang
@casperOne mengapa Anda menutup pertanyaan? Pertanyaan itu sah.
bleepzter

Jawaban:

149

Polanya rumit

Semua pola desain harus digunakan dengan hati-hati. Menurut pendapat saya, Anda harus melakukan refactor terhadap pola jika ada alasan yang valid untuk melakukannya daripada langsung menerapkan pola. Masalah umum dengan menggunakan pola adalah mereka menambah kompleksitas. Penggunaan pola yang berlebihan membuat aplikasi atau sistem tertentu menjadi rumit untuk dikembangkan dan dipelihara lebih lanjut.

Seringkali, ada solusi sederhana, dan Anda tidak perlu menerapkan pola tertentu. Aturan praktis yang baik adalah menggunakan pola setiap kali potongan kode cenderung diganti atau perlu sering diubah dan bersiaplah untuk mengambil peringatan kode kompleks saat menggunakan pola.

Ingatlah bahwa tujuan Anda haruslah kesederhanaan dan menerapkan pola jika Anda melihat kebutuhan praktis untuk mendukung perubahan dalam kode Anda.

Prinsip di atas pola

Ini mungkin tampak seperti perdebatan untuk menggunakan pola jika mereka ternyata dapat mengarah pada solusi yang direkayasa secara berlebihan dan kompleks. Namun, jauh lebih menarik bagi seorang programmer untuk membaca tentang teknik dan prinsip desain yang meletakkan dasar untuk sebagian besar pola. Faktanya, salah satu buku favorit saya tentang 'pola desain' menekankan hal ini dengan mengulangi prinsip-prinsip apa yang dapat diterapkan pada pola tersebut. Mereka cukup sederhana untuk menjadi berguna daripada pola dalam hal relevansi. Beberapa prinsip cukup umum untuk mencakup lebih dari sekadar pemrograman berorientasi objek (OOP), seperti Prinsip Substitusi Liskov , selama Anda dapat membangun modul kode Anda.

Ada banyak sekali prinsip desain tetapi yang dijelaskan di bab pertama buku GoF cukup berguna untuk memulai.

  • Program ke 'antarmuka', bukan 'implementasi'. (Gang Empat 1995: 18)
  • Lebih menyukai 'komposisi objek' daripada 'warisan kelas'. (Gang Empat 1995: 20)

Biarkan hal itu mempengaruhi Anda untuk sementara waktu. Perlu dicatat bahwa ketika GoF ditulis, antarmuka berarti segala sesuatu yang merupakan abstraksi (yang juga berarti kelas super), jangan bingung dengan antarmuka sebagai tipe di Java atau C #. Prinsip kedua berasal dari penggunaan warisan secara berlebihan yang sayangnya masih umum saat ini .

Dari sana Anda dapat membaca tentang prinsip-prinsip SOLID yang dikemukakan oleh Robert Cecil Martin (alias. Paman Bob) . Scott Hanselman mewawancarai Paman Bob di podcast tentang prinsip-prinsip ini :

  • S perapian di tungku Prinsip Tanggung Jawab
  • Prinsip Tertutup O pena
  • Prinsip Substitusi L iskov
  • Saya nterface Pemisahan Prinsip
  • D ependency Pembalikan Prinsip

Prinsip-prinsip ini adalah awal yang baik untuk membaca dan berdiskusi dengan teman-teman Anda. Anda mungkin menemukan bahwa prinsip-prinsip tersebut terjalin satu sama lain dan dengan proses lain seperti pemisahan masalah dan injeksi ketergantungan . Setelah melakukan TDD untuk beberapa saat, Anda juga mungkin menemukan bahwa prinsip-prinsip ini muncul secara alami dalam praktik karena Anda perlu mengikutinya sampai taraf tertentu untuk membuat pengujian unit yang terisolasi dan berulang .

Spoike
sumber
7
+1 Jawaban yang sangat bagus. Tampaknya setiap programmer (newbie) saat ini mengetahui pola desainnya atau setidaknya tahu bahwa pola itu ada. Tetapi sangat banyak yang tidak pernah mendengar, apalagi menerapkan, beberapa prinsip yang mutlak penting seperti Tanggung Jawab Tunggal untuk mengelola kompleksitas kode mereka.
eljenso
21

Salah satu yang paling dikhawatirkan oleh penulis Design Patterns adalah pola "Pengunjung".

Ini adalah "kejahatan yang diperlukan" - tetapi sering digunakan secara berlebihan dan kebutuhan untuk itu sering kali mengungkapkan kelemahan yang lebih mendasar dalam desain Anda.

Nama alternatif untuk pola "Pengunjung" adalah "Multi-pengiriman", karena pola Pengunjung adalah tujuan akhir Anda saat Anda ingin menggunakan bahasa OO pengiriman jenis tunggal untuk memilih kode yang akan digunakan berdasarkan jenis dua (atau lebih) objek yang berbeda.

Contoh klasiknya adalah Anda memiliki perpotongan antara dua bentuk, tetapi ada kasus yang lebih sederhana yang sering diabaikan: membandingkan persamaan dua objek heterogen.

Bagaimanapun, seringkali Anda berakhir dengan sesuatu seperti ini:

interface IShape
{
    double intersectWith(Triangle t);
    double intersectWith(Rectangle r);
    double intersectWith(Circle c);
}

Masalahnya adalah Anda telah menggabungkan semua implementasi "IShape" Anda. Anda telah menyiratkan bahwa setiap kali Anda ingin menambahkan bentuk baru ke hierarki, Anda juga perlu mengubah semua implementasi "Bentuk" lainnya.

Terkadang, ini adalah desain minimal yang benar - tetapi pikirkan baik-baik. Apakah desain Anda benar-benar mengamanatkan bahwa Anda perlu mengirimkan dua jenis? Apakah Anda bersedia untuk menulis setiap ledakan kombinatorial multi-metode?

Seringkali, dengan memperkenalkan konsep lain, Anda dapat mengurangi jumlah kombinasi yang sebenarnya harus Anda tulis:

interface IShape
{
    Area getArea();
}

class Area
{
    public double intersectWith(Area otherArea);
    ...
}

Tentu saja, itu tergantung - terkadang Anda benar-benar perlu menulis kode untuk menangani semua kasus yang berbeda tersebut - tetapi ada baiknya mengambil jeda dan berpikir sebelum mengambil risiko dan menggunakan Pengunjung. Ini mungkin akan menyelamatkan Anda dari rasa sakit di kemudian hari.

Paul Hollingsworth
sumber
2
Berbicara tentang pengunjung, Paman Bob menggunakannya "sepanjang waktu" butunclebob.com/ArticleS.UncleBob.IuseVisitor
Spoike
3
@Paul Hollingsworth Dapatkah Anda memberikan referensi tentang di mana dikatakan bahwa penulis Pola Desain khawatir (dan mengapa mereka khawatir)?
m3th0dman
16

Singletons - kelas yang menggunakan singleton X memiliki ketergantungan yang sulit dilihat dan sulit diisolasi untuk pengujian.

Mereka sangat sering digunakan karena nyaman dan mudah dipahami, tetapi dapat mempersulit pengujian.

Lihat Singletons are Pathological Liars .

orip
sumber
1
Mereka juga dapat menguji secara sederhana karena mereka dapat memberi Anda satu poin untuk menyuntikkan objek Mock. Semuanya tergantung pada keseimbangan yang benar.
Martin Brown
1
@ Martin: Jika kursus memungkinkan untuk mengubah singelton untuk pengujian (jika Anda tidak menggunakan implementasi singelton standar), tetapi bagaimana itu lebih mudah daripada lulus implementasi pengujian di konstruktor?
orip
14

Saya yakin pola Metode Template umumnya adalah pola yang sangat berbahaya.

  • Seringkali ini menggunakan hierarki warisan Anda karena "alasan yang salah".
  • Kelas dasar memiliki kecenderungan untuk dikotori dengan semua jenis kode yang tidak terkait.
  • Ini memaksa Anda untuk mengunci desain, seringkali di awal proses pengembangan. (Penguncian dini dalam banyak kasus)
  • Mengubah ini pada tahap selanjutnya menjadi semakin sulit.
krosenvold.dll
sumber
2
Saya akan menambahkan bahwa setiap kali Anda menggunakan Metode Template, Anda mungkin lebih baik menggunakan Strategi. Masalah dengan TemplateMethod adalah bahwa ada reentrancy antara kelas dasar dan kelas turunan, yang seringkali terlalu digabungkan.
Paul Hollingsworth
5
@Paul: Metode template sangat bagus bila digunakan dengan benar, yaitu ketika bagian yang bervariasi perlu mengetahui banyak tentang bagian yang tidak. Saya mengambil adalah bahwa strategi harus digunakan ketika kode dasar hanya memanggil kode khusus dan metode template harus digunakan ketika kode khusus secara inheren perlu tahu tentang kode dasar.
dsimcha
ya dsimcha, saya setuju ... selama desainer kelas menyadari hal ini.
Paul Hollingsworth
9

Saya tidak berpikir Anda harus menghindari Design Patterns (DP), dan menurut saya Anda tidak perlu memaksakan diri untuk menggunakan DP ketika merencanakan arsitektur Anda. Kami hanya boleh menggunakan DP ketika mereka muncul secara alami dari perencanaan kami.

Jika kita mendefinisikan sejak awal bahwa kita ingin menggunakan DP tertentu, banyak dari keputusan desain masa depan kita akan dipengaruhi oleh pilihan itu, tanpa jaminan bahwa DP yang kita pilih sesuai dengan kebutuhan kita.

Satu hal yang juga tidak boleh kita lakukan adalah memperlakukan DP sebagai entitas yang tidak berubah, kita harus menyesuaikan pola dengan kebutuhan kita.

Jadi, meringkas, saya tidak berpikir kita harus menghindari DP, kita harus merangkulnya ketika sudah terbentuk dalam arsitektur kita.

Megacan
sumber
7

Menurut saya, Rekaman Aktif adalah pola yang digunakan secara berlebihan yang mendorong percampuran logika bisnis dengan kode persistensi. Itu tidak melakukan pekerjaan yang sangat baik untuk menyembunyikan implementasi penyimpanan dari lapisan model dan mengikat model ke database. Ada banyak alternatif (dijelaskan dalam PoEAA) seperti Table Data Gateway, Row Data Gateway dan Data Mapper yang seringkali memberikan solusi yang lebih baik dan tentunya membantu memberikan abstraksi yang lebih baik ke penyimpanan. Selain itu, model Anda tidak perlu disimpan dalam database; bagaimana dengan menyimpannya sebagai XML atau mengaksesnya menggunakan layanan web? Seberapa mudah untuk mengubah mekanisme penyimpanan model Anda?

Meskipun demikian, Rekaman Aktif tidak selalu buruk dan sempurna untuk aplikasi yang lebih sederhana di mana opsi lain akan berlebihan.

Tim Wardle
sumber
1
Agak benar, tetapi tergantung pada implementasi.
Mike Woodhouse
6

Sederhana saja ... hindari Pola Desain yang tidak jelas bagi Anda atau yang membuat Anda merasa tidak nyaman .

Untuk menyebutkan beberapa ...

ada beberapa pola yang tidak praktis , seperti misalnya:

  • Interpreter
  • Flyweight

ada juga beberapa yang lebih sulit untuk dipahami , seperti misalnya:

  • Abstract Factory - Pola pabrik abstrak penuh dengan kumpulan objek yang dibuat tidak semudah kelihatannya
  • Bridge - Bisa menjadi terlalu abstrak, jika abstraksi dan implementasi dibagi menjadi subpohon, tetapi pola yang sangat berguna dalam beberapa kasus
  • Visitor - Pemahaman mekanisme pengiriman ganda benar-benar HARUS

dan ada beberapa pola yang terlihat sangat sederhana , tetapi pilihannya tidak begitu jelas karena berbagai alasan terkait dengan prinsip atau penerapannya:

  • Singleton - tidak benar-benar pola yang buruk, hanya TERLALU digunakan secara berlebihan (sering kali ada, di tempat yang tidak cocok)
  • Observer - pola yang bagus ... hanya membuat kode lebih sulit untuk dibaca dan di-debug
  • Prototype - memperdagangkan pemeriksaan kompiler untuk dinamisme (yang bisa baik atau buruk ... tergantung)
  • Chain of responsibility - terlalu sering didorong secara paksa / artifisial ke dalam desain

Untuk "yang tidak praktis" itu, orang harus benar-benar memikirkannya sebelum menggunakannya, karena biasanya ada solusi yang lebih elegan di suatu tempat.

Untuk yang "lebih sulit dipahami" ... mereka sangat membantu, ketika digunakan di tempat yang sesuai dan ketika diterapkan dengan baik ... tetapi mereka adalah mimpi buruk, ketika digunakan dengan tidak benar.

Sekarang, apa selanjutnya ...

Marcel Toth
sumber
Pola kelas terbang adalah suatu keharusan kapan saja Anda menggunakan sumber daya, seringkali berupa gambar, lebih dari sekali. Itu bukanlah sebuah pola, ini sebuah solusi.
Cengiz Kandemir
5

Saya harap saya tidak akan dipukuli terlalu banyak untuk ini. Christer Ericsson menulis dua artikel ( satu , dua ) tentang topik pola desain di blog deteksi tabrakan waktu nyata miliknya . Nada suaranya agak kasar, dan mungkin sedikit provokatif, tetapi pria itu tahu barang-barangnya, jadi saya tidak akan menganggapnya sebagai ocehan orang gila.

falstro
sumber
Bacaan yang menarik. Terima kasih untuk tautannya!
Bombe
3
Orang bodoh menghasilkan kode yang buruk. Apakah orang bodoh dengan pola menghasilkan kode yang lebih buruk daripada orang bodoh yang tidak pernah melihat pola? Saya tidak berpikir mereka melakukannya. Bagi orang pintar, pola memberikan kosakata terkenal, yang memudahkan pertukaran ide. Solusinya: Pelajari pola dan hanya berurusan dengan pemrogram cerdas.
Martin Brown
Saya rasa tidak mungkin bagi orang bodoh sejati untuk menghasilkan kode yang lebih buruk - tidak peduli alat apa yang mereka gunakan
1800 INFORMATION
1
Saya pikir teladannya dengan ujian perguruan tinggi hanya membuktikan bahwa orang-orang yang membenci domain masalah mereka dan keengganan untuk mempelajarinya selama lebih dari beberapa jam selama satu akhir pekan akan menghasilkan jawaban yang salah ketika mencoba untuk memecahkan masalah.
scriptocalypse
5

Beberapa orang mengatakan bahwa pencari lokasi adalah pola anti.

Arnis Lapsa
sumber
Juga penting untuk dicatat bahwa terkadang pencari lokasi diperlukan. Misalnya, ketika Anda tidak memiliki kontrol yang tepat atas instansiasi objek (misalnya atribut dengan parameter non-konstan di C #). Tapi itu juga mungkin untuk menggunakan pelacak layanan DENGAN injeksi ctor.
Sinaesthetic
2

Saya percaya pola pengamat memiliki banyak jawaban, ini berfungsi dalam kasus yang sangat umum, tetapi karena sistem menjadi lebih kompleks, itu menjadi mimpi buruk, membutuhkan pemberitahuan OnBefore (), OnAfter (), dan sering memposting tugas asinkron untuk menghindari pengulangan pintu masuk. Solusi yang jauh lebih baik adalah mengembangkan sistem analisis ketergantungan otomatis yang melengkapi semua akses objek (dengan hambatan baca) selama penghitungan dan secara otomatis membuat tepi dalam grafik ketergantungan.

Jesse Pepper
sumber
4
Saya mengerti semua dalam jawaban Anda sampai kata "A"
1800 INFORMATION
Anda mungkin perlu memperluas atau menautkan ke analisis ketergantungan otomatis yang Anda bicarakan ini. Juga dalam delegasi / acara NET digunakan sebagai pengganti pola pengamat.
Spoike
3
@Spoike: delegasi / acara adalah implementasi dari pola pengamat
orip
1
Dendam pribadi saya terhadap Observer adalah bahwa hal itu dapat membuat kebocoran memori dalam bahasa pengumpulan sampah. Ketika Anda telah selesai dengan suatu objek, Anda perlu mengingat bahwa objek tersebut tidak akan dibersihkan.
Martin Brown
@orip: ya, itulah mengapa Anda menggunakan delegasi / acara. ;)
Spoike
2

Sebuah pelengkap untuk posting Spoike, Refactoring to Patterns adalah bacaan yang bagus.

Adeel Ansari
sumber
Saya sebenarnya telah menautkan ke katalog buku di Internet. :)
Spoike
Oh! Saya tidak repot-repot mengarahkannya. Sebenarnya, tepat setelah menyelesaikan pertanyaan, buku ini muncul di benak saya, dan kemudian saya melihat jawaban Anda. Saya tidak bisa menahan diri untuk mempostingnya. :)
Adeel Ansari
0

Iterator adalah satu lagi pola GoF yang harus dihindari, atau setidaknya digunakan hanya jika tidak ada alternatif yang tersedia.

Alternatifnya adalah:

  1. untuk setiap loop. Konstruksi ini ada di sebagian besar bahasa arus utama dan dapat digunakan untuk menghindari iterator di sebagian besar kasus.

  2. penyeleksi à la LINQ atau jQuery. Mereka harus digunakan jika untuk masing-masing tidak sesuai karena tidak semua objek dari wadah harus diproses. Tidak seperti iterator, penyeleksi memungkinkan untuk memanifestasikan di satu tempat jenis objek yang akan diproses.

Volodymyr Frolov
sumber
Saya setuju dengan penyeleksi. Foreach adalah sebuah iterator, sebagian besar bahasa OO menyediakan antarmuka iterable yang Anda terapkan untuk memungkinkan foreach.
Neil Aitken
Dalam beberapa bahasa untuk setiap konstruksi dapat diimplementasikan melalui iterator, tetapi konsepnya sebenarnya lebih tinggi dan lebih dekat dengan penyeleksi. Saat menggunakan for-each developer menyatakan secara eksplisit bahwa semua elemen dari container harus diproses.
Volodymyr Frolov
Iterator adalah pola yang bagus. Anti-pola akan mengimplementasikan IEnumerable / IEnumerator tanpa iterator. Saya yakin LINQ dimungkinkan melalui yielditerator. Eric White memiliki beberapa diskusi hebat tentang ini di C # 3.0: blogs.msdn.com/b/ericwhite/archive/2006/10/04/… . Juga, periksa diskusi Jeremy Likness tentang coroutine dengan iterator: wintellect.com/CS/blogs/jlikness/archive/2010/03/23/… .
@Ryan Riley, iterator adalah objek tingkat rendah dan karenanya harus dihindari dalam desain dan kode tingkat tinggi. Detail implementasi iterator dan berbagai jenis penyeleksi tidak menjadi masalah di sini. Selektor, tidak seperti Iterator, memungkinkan pemrogram untuk mengekspresikan secara eksplisit apa yang ingin mereka proses dan agar levelnya tinggi.
Volodymyr Frolov
Fwiw, alternatifnya, sintaks F # mirip LINQ adalah `List.map (fun x -> x.Value) xs`, yang sepanjang pemahaman daftar.