Mengapa kita membutuhkan begitu banyak kelas dalam pola desain?

209

Saya adalah pengembang junior di antara para manula dan saya banyak berjuang dalam memahami pemikiran, alasan mereka.

Saya membaca Domain-Driven Design (DDD) dan tidak dapat memahami mengapa kita perlu membuat banyak kelas. Jika kita mengikuti metode perancangan perangkat lunak kita berakhir dengan 20-30 kelas yang dapat diganti dengan paling banyak dua file dan 3-4 fungsi. Ya, ini bisa berantakan, tetapi jauh lebih mudah dikelola dan dibaca.

Kapan saja saya ingin melihat apa yang dilakukan oleh beberapa jenis EntityTransformationServiceImpl, saya perlu mengikuti banyak kelas, antarmuka, pemanggilan fungsi, konstruktor, kreasi mereka dan sebagainya.

Matematika sederhana:

  • 60 baris kode dummy vs 10 kelas X 10 (misalkan kita memiliki logika yang sangat berbeda) = 600 baris kode berantakan vs 100 kelas + beberapa lagi untuk membungkus dan mengelolanya; jangan lupa untuk menambahkan injeksi ketergantungan.
  • Membaca 600 baris kode berantakan = satu hari
  • 100 kelas = satu minggu, masih lupa yang mana melakukan apa, kapan

Semua orang mengatakan itu mudah dipertahankan, tetapi untuk apa? Setiap kali Anda menambahkan fungsionalitas baru, Anda menambahkan lima kelas lagi dengan pabrik, entitas, layanan, dan nilai-nilai. Saya merasa kode seperti ini bergerak jauh lebih lambat daripada kode yang berantakan.

Katakanlah, jika Anda menulis kode berantakan 50K LOC dalam satu bulan, hal DDD membutuhkan banyak ulasan dan perubahan (saya tidak keberatan dengan tes dalam kedua kasus). Satu tambahan sederhana bisa memakan waktu seminggu jika tidak lebih.

Dalam satu tahun, Anda menulis banyak kode berantakan dan bahkan dapat menulis ulang beberapa kali, tetapi dengan gaya DDD, Anda masih tidak memiliki cukup fitur untuk bersaing dengan kode berantakan.

Tolong jelaskan. Mengapa kita membutuhkan gaya DDD ini dan banyak pola?

UPD 1 : Saya menerima begitu banyak jawaban, bisakah kalian tolong tambahkan komentar di suatu tempat atau edit jawaban Anda dengan tautan untuk daftar bacaan (tidak yakin mulai dari mana, DDD, Pola Desain, UML, Kode Lengkap, Refactoring, Pragmatis,. (begitu banyak buku bagus), tentu saja dengan urutan, sehingga saya juga bisa mulai memahami dan menjadi senior seperti yang Anda lakukan.

pengguna1318496
sumber
81
Saya pikir ada pertanyaan yang bagus di sini tapi itu bersembunyi di balik hiperbola dan frustrasi. @ user1318496, Anda mungkin mendapat manfaat dari mengulangi pertanyaan Anda sedikit.
MetaFight
48
Dengan risiko menginjak kaki, karena bahasa Anda menyebalkan. Jangan menganggapnya lebih dari itu: bahasa yang jelek sering merupakan pilihan teknis yang tepat karena berbagai alasan, tetapi itu tidak membuatnya tidak beruntung. Adapun pertanyaan Anda yang sebenarnya, kebenaran lebih penting daripada keterbacaan. Atau dengan kata lain: pembacaan sangat penting sejauh memungkinkan penalaran tentang kebenaran. Jadi mana yang lebih mudah untuk diuji, 100 kelas Anda atau kelas dewa monolitik Anda? Saya bertaruh 100 kelas sederhana.
Jared Smith
87
"Ya ini bisa berantakan, tetapi jauh lebih mudah dikelola dan dibaca." Jika berantakan, bagaimana bisa dibaca dan dikelola?
Polygnome
37
@ Polygnome: Saya akan mengetik komentar yang sama persis. Karakteristik komentar pilihan lain dari pengembang junior adalah "Saya merasa kode seperti ini bergerak jauh lebih lambat daripada kode yang berantakan." Tidak ada gunanya berlari secepat yang Anda bisa jika Anda menghabiskan setengah waktu berlari ke dinding! Lambat mulus, halus cepat.
Eric Lippert
40
Anda tidak melakukannya, kecuali jika Anda menggunakan Java. Ketika semua yang Anda miliki adalah Java, semuanya tampak seperti kelas.
hobbs

Jawaban:

336

Ini adalah masalah optimisasi

Seorang insinyur yang baik memahami bahwa masalah optimasi tidak ada artinya tanpa target. Anda tidak bisa hanya mengoptimalkan, Anda harus mengoptimalkan untuk sesuatu. Misalnya, opsi kompiler Anda termasuk mengoptimalkan kecepatan dan mengoptimalkan ukuran kode; ini kadang-kadang tujuan yang berlawanan.

Saya ingin memberi tahu istri saya bahwa meja saya dioptimalkan untuk menambah. Itu hanya tumpukan, dan sangat mudah untuk menambahkan barang. Istri saya akan lebih suka jika saya dioptimalkan untuk pengambilan, yaitu mengatur barang saya sedikit sehingga saya dapat menemukan sesuatu. Ini membuatnya lebih sulit, tentu saja, untuk ditambahkan.

Perangkat lunaknya juga sama. Anda tentu dapat mengoptimalkan pembuatan produk - menghasilkan satu ton kode monolitik secepat mungkin, tanpa perlu khawatir mengaturnya. Seperti yang sudah Anda perhatikan, ini bisa sangat, sangat cepat. Alternatifnya adalah mengoptimalkan perawatan - membuat pembuatan sentuhan menjadi lebih sulit, tetapi membuat modifikasi lebih mudah atau kurang berisiko. Itulah tujuan dari kode terstruktur.

Saya menyarankan bahwa produk perangkat lunak yang sukses hanya akan dibuat sekali tetapi dimodifikasi berkali-kali. Insinyur yang berpengalaman telah melihat basis kode yang tidak terstruktur mengambil kehidupan mereka sendiri dan menjadi produk, tumbuh dalam ukuran dan kompleksitas, sampai bahkan perubahan kecil sangat sulit dilakukan tanpa memperkenalkan risiko besar. Jika kode terstruktur, risiko dapat diatasi. Itu sebabnya kami pergi ke semua masalah ini.

Kompleksitas berasal dari hubungan, bukan elemen

Saya perhatikan dalam analisis Anda, Anda melihat kuantitas - jumlah kode, jumlah kelas, dll. Meskipun ini agak menarik, dampak nyata berasal dari hubungan antar elemen, yang meledak secara kombinatorial. Misalnya, jika Anda memiliki 10 fungsi dan tidak tahu yang bergantung pada mana, Anda memiliki 90 kemungkinan hubungan (dependensi) yang harus Anda khawatirkan - masing-masing dari sepuluh fungsi mungkin bergantung pada salah satu dari sembilan fungsi lainnya, dan 9 x 10 = 90. Anda mungkin tidak tahu fungsi mana yang memodifikasi variabel mana atau bagaimana data dilewatkan, jadi pembuat kode memiliki banyak hal yang perlu dikhawatirkan saat menyelesaikan masalah tertentu. Sebaliknya, jika Anda memiliki 30 kelas tetapi mereka diatur dengan cerdik, mereka dapat memiliki sesedikit 29 hubungan, misalnya jika mereka berlapis atau diatur dalam tumpukan.

Bagaimana ini memengaruhi throughput tim Anda? Nah, ada lebih sedikit ketergantungan, masalahnya jauh lebih mudah ditelusuri; coders tidak harus menyulap jutaan hal di kepala mereka setiap kali mereka membuat perubahan. Jadi meminimalkan ketergantungan dapat menjadi dorongan besar bagi kemampuan Anda untuk beralasan tentang masalah secara kompeten. Itulah sebabnya kami membagi berbagai hal ke dalam kelas atau modul, dan variabel ruang lingkup sekencang mungkin, dan menggunakan prinsip SOLID .

John Wu
sumber
103
Saya akan mencatat, bagaimanapun, bahwa meluap-luapnya kelas dan tipuan tidak membantu memahami pemeliharaan NOR. Dan juga kontrol arus yang berbelit-belit (alias, panggilan balik neraka).
Matthieu M.
9
@JohnWu penjelasan ini adalah cara yang terbaik dan lebih mudah untuk memahami yang pernah saya baca.
Adriano Repetti
13
Ditulis dengan baik, tetapi apakah itu mungkin hilang mengapa "dibuat sekali tetapi dimodifikasi berkali-kali" adalah penting? (Jika semua kode ada di dalam EntityTransformationServiceImpl, Anda dipaksa untuk mempelajari bagaimana semuanya bekerja sebelum Anda bisa memperbaikinya - tetapi jika misalnya ada yang salah dengan format dan Formatterkelas yang menangani itu, Anda hanya perlu mempelajari cara kerja bagian itu . Plus membaca kode Anda sendiri setelah ~ 3 bulan seperti membaca kode orang asing.) Saya merasa sebagian besar dari kita secara tidak sadar memikirkan hal ini, tetapi itu mungkin karena pengalaman. Tidak 100% yakin tentang ini.
R. Schmitz
17
Saya akan menggunakan 10 × 10 = 100 penuh untuk kombinatorial: fungsi-fungsi itu bisa saja bersifat rekursif, dan dalam kode yang sangat buruk, tidak terlalu jelas begitu.
KRyan
32
"Alternatifnya adalah mengoptimalkan perawatan - membuat kreasi menjadi lebih sulit, tetapi membuat modifikasi lebih mudah atau kurang berisiko. Itulah tujuan dari kode terstruktur." Saya mengambil masalah dengan gagasan tersirat bahwa lebih banyak kelas = lebih banyak rawatan. Secara khusus, hamburan logika di banyak kelas sering menyulitkan untuk menemukan konsep logis menyeluruh dalam kode (terutama tanpa mata yang sangat disengaja untuk memastikan konsep-konsep tersebut sangat terlihat), yang sangat menurunkan kemampuan pemeliharaan.
jpmc26
67

Yah, pertama-tama, keterbacaan dan pemeliharaan sering di mata yang melihatnya.

Apa yang bisa Anda baca mungkin bukan untuk tetangga Anda.

Maintainability sering bermuara pada kemampuan menemukan (betapa mudahnya suatu perilaku atau konsep ditemukan dalam basis kode) dan kemampuan menemukan adalah hal subjektif lainnya.

DDD

Salah satu cara DDD membantu tim pengembang adalah dengan menyarankan cara spesifik (namun masih subyektif) dalam mengatur konsep dan perilaku kode Anda. Konvensi ini membuatnya lebih mudah untuk menemukan hal-hal, dan karenanya lebih mudah untuk mempertahankan aplikasi.

  • Konsep domain dikodekan sebagai Entitas dan Agregat
  • Perilaku domain berada di Entitas atau Layanan Domain
  • Konsistensi dijamin oleh Root Agregat
  • Kekhawatiran kegigihan ditangani oleh Repositori

Pengaturan ini secara obyektif tidak mudah untuk dipertahankan. Hal ini, bagaimanapun, terukur lebih mudah untuk mempertahankan ketika semua orang mengerti mereka beroperasi dalam konteks DDD.

Kelas

Kelas membantu dengan kemampuan pemeliharaan, keterbacaan, kemampuan menemukan, dll ... karena mereka adalah konvensi terkenal .

Dalam pengaturan Berorientasi Objek, Kelas biasanya digunakan untuk mengelompokkan perilaku yang terkait erat dan untuk merangkum keadaan yang perlu dikendalikan dengan hati-hati.

Saya tahu itu terdengar sangat abstrak, tetapi Anda dapat memikirkannya seperti ini:

Dengan Kelas, Anda tidak perlu tahu bagaimana kode di dalamnya bekerja. Anda hanya perlu tahu untuk apa kelas itu bertanggung jawab.

Kelas memungkinkan Anda untuk mempertimbangkan aplikasi Anda dalam hal interaksi antara komponen yang didefinisikan dengan baik .

Ini mengurangi beban kognitif saat beralasan tentang cara kerja aplikasi Anda. Daripada harus mengingat apa yang dicapai 600 baris kode , Anda dapat berpikir tentang bagaimana 30 komponen berinteraksi.

Dan, mengingat 30 komponen itu mungkin menjangkau 3 lapisan aplikasi Anda, Anda mungkin hanya perlu mempertimbangkan sekitar 10 komponen sekaligus.

Tampaknya itu cukup mudah dikelola.

Ringkasan

Pada dasarnya, apa yang Anda lihat para pengembang senior lakukan adalah ini:

Mereka memecah aplikasi menjadi alasan yang mudah tentang kelas.

Mereka kemudian mengatur ini menjadi alasan yang mudah tentang lapisan.

Mereka melakukan ini karena mereka tahu bahwa, seiring dengan pertumbuhan aplikasi, semakin sulit untuk memikirkannya secara keseluruhan. Memecahnya menjadi Layers dan Kelas berarti bahwa mereka tidak perlu alasan tentang seluruh aplikasi. Mereka hanya perlu beralasan tentang sebagian kecil dari itu.

MetaFight
sumber
5
Selain itu kelas yang lebih kecil lebih mudah untuk diganti / refactor.
Zalomon
12
Overengineering tidak memberikan kode yang lebih mudah dikelola atau dimengerti - justru sebaliknya, terlepas dari apa yang Anda klaim. Siapa yang butuh AddressServiceRepositoryProxyInjectorResolversaat Anda bisa menyelesaikan masalah dengan lebih elegan? Pola desain demi pola desain hanya mengarah pada kompleksitas dan kata kerja yang tidak perlu.
vikingsteve
27
Ya, overengineering itu buruk. Begitu juga membunuh anak anjing. Tak seorang pun di sini yang mengadvokasi keduanya. logicallyfallacious.com/tools/lp/Bo/LogicalFallacies/169/...
MetaFight
5
Juga, "keanggunan" dalam konteks rekayasa perangkat lunak sering kali adalah Weasel Word. en.wikipedia.org/wiki/Weasel_word
MetaFight
11
Hal yang sama dapat dikatakan tentang pendekatan apa pun untuk mengatur kode. Semuanya bergantung pada tim pemeliharaan untuk memahami mengapa kode ini diatur sebagaimana adanya. Itulah inti dari menggunakan konvensi yang mapan dan dipahami.
MetaFight
29

Tolong jelaskan saya, mengapa kita membutuhkan gaya DDD ini, banyak Pola?

Pertama, sebuah catatan: bagian penting dari DDD bukanlah pola , tetapi keselarasan upaya pengembangan dengan bisnis. Greg Young mengatakan bahwa bab-bab dalam buku biru berada di urutan yang salah .

Tetapi untuk pertanyaan spesifik Anda: cenderung ada lebih banyak kelas daripada yang Anda harapkan, (a) karena upaya sedang dilakukan untuk membedakan perilaku domain dari pipa ledeng dan (b) karena upaya ekstra sedang dilakukan untuk memastikan bahwa konsep dalam model domain diekspresikan secara eksplisit.

Terus terang, jika Anda memiliki dua konsep yang berbeda dalam domain, maka mereka harus berbeda dalam model bahkan jika mereka berbagi hal yang sama dalam representasi memori .

Akibatnya, Anda sedang membangun bahasa khusus domain yang menjelaskan model Anda dalam bahasa bisnis, sehingga pakar domain harus dapat melihatnya dan menemukan kesalahan.

Selain itu, Anda melihat sedikit lebih banyak perhatian diberikan pada pemisahan masalah; dan gagasan mengisolasi konsumen dari beberapa kemampuan dari detail implementasi. Lihat DL Parnas . Batas-batas yang jelas memberdayakan Anda untuk mengubah atau memperpanjang implementasi tanpa efek berdesir di seluruh solusi Anda.

Motivasinya di sini: untuk aplikasi yang merupakan bagian dari kompetensi inti bisnis (artinya tempat di mana ia memperoleh keunggulan kompetitif), Anda ingin dapat dengan mudah dan murah mengganti perilaku domain dengan variasi yang lebih baik. Akibatnya, Anda memiliki bagian dari program yang ingin Anda kembangkan dengan cepat (bagaimana status berevolusi dari waktu ke waktu), dan bagian lain yang ingin Anda ubah perlahan-lahan (bagaimana status disimpan); lapisan tambahan abstraksi membantu menghindari secara tidak sengaja menyatukan satu dengan yang lainnya.

Dalam keadilan: beberapa di antaranya juga Kerusakan Otak Berorientasi Objek. Pola-pola yang awalnya dijelaskan oleh Evans didasarkan pada proyek-proyek Jawa yang ia ikuti 15+ tahun yang lalu; keadaan dan perilaku sangat erat dalam gaya itu, yang mengarah pada komplikasi yang Anda mungkin ingin hindari; lihat Persepsi dan Tindakan oleh Stuart Halloway, atau Inlining Code oleh John Carmack.

Apa pun bahasa tempat Anda bekerja, pemrograman dengan gaya fungsional memberikan manfaat. Anda harus melakukannya kapan saja nyaman, dan Anda harus berpikir keras tentang keputusan saat tidak nyaman. Carmack, 2012

VoiceOfUnreason
sumber
2
Saya akan menambahkan jawaban saya sendiri sampai saya membaca ini. Saya akan menekankan paragraf pertama, bahwa tujuannya adalah untuk memodelkan konsep bisnis dalam perangkat lunak untuk menyelaraskan perangkat lunak dengan persyaratan bisnis. Dalam keadilan, analis yang menggerakkan proyek juga harus mengungkapkan berapa banyak waktu pengemudi untuk pengiriman, dan kualitas kode / uji atau kelengkapan harus disesuaikan.
Sentinel
1
John Carmack adalah contoh IMO yang bagus, karena dia terkenal karena menulis kode yang bersih dan mudah dimengerti, selain juga berkinerja baik. Ini terutama terlihat ketika Anda melacak kodenya dengan teknologi canggih - dengan CPU dan memori yang lebih baik, Anda dapat melihat banyak hal didorong dari "ini harus benar-benar singkat" hingga "ini harus benar-benar jelas / terisolasi / ... ". Salah satu programmer paling pragmatis yang saya tahu :)
Luaan
Saya pikir ini adalah jawaban terbaik di sini. Walaupun saya sama sekali tidak dijual di DDD, jawaban ini tentu setidaknya menjelaskan apa itu sebenarnya dan motivasi yang sebenarnya untuk itu, daripada menarik basa-basi umum yang tidak berarti apa-apa.
jpmc26
29

Ada banyak poin bagus di jawaban lain, tetapi saya pikir mereka kehilangan atau tidak menekankan kesalahan konseptual penting yang Anda buat:

Anda membandingkan upaya untuk memahami program yang lengkap.

Ini bukan tugas yang realistis dengan sebagian besar program. Bahkan program sederhana terdiri dari begitu banyak kode sehingga tidak mungkin untuk mengelola semua itu di kepala pada waktu tertentu. Satu-satunya kesempatan Anda adalah menemukan bagian dari sebuah program yang relevan dengan tugas yang ada (memperbaiki bug, mengimplementasikan fitur baru) dan bekerja dengannya.

Jika program Anda terdiri dari fungsi / metode / kelas yang sangat besar, ini hampir mustahil. Anda harus memahami ratusan baris kode hanya untuk memutuskan apakah potongan kode ini relevan dengan masalah Anda. Dengan perkiraan yang Anda berikan menjadi mudah untuk menghabiskan satu minggu hanya untuk menemukan potongan kode yang perlu Anda kerjakan.

Bandingkan dengan basis kode dengan fungsi / metode / kelas kecil bernama dan diorganisasikan ke dalam paket / namespaces yang membuatnya jelas di mana menemukan / meletakkan sepotong logika tertentu. Ketika dilakukan dengan benar dalam banyak kasus, Anda dapat melompat langsung ke tempat yang tepat untuk menyelesaikan masalah Anda, atau setidaknya ke tempat dari mana menjalankan debugger Anda akan membawa Anda ke tempat yang tepat dalam beberapa lompatan.

Saya telah bekerja di kedua jenis sistem. Perbedaannya dapat dengan mudah menjadi dua urutan besarnya dalam kinerja untuk tugas yang sebanding dan ukuran sistem yang sebanding.

Efeknya terhadap aktivitas lain:

  • pengujian menjadi lebih mudah dengan unit yang lebih kecil
  • konflik penggabungan lebih sedikit karena peluang bagi dua pengembang untuk bekerja pada kode yang sama lebih kecil.
  • duplikasi lebih sedikit karena lebih mudah untuk menggunakan kembali potongan (dan untuk menemukan potongan di tempat pertama).
Jens Schauder
sumber
19

Karena pengujian kode lebih sulit daripada menulis kode

Banyak jawaban telah memberikan alasan yang bagus dari sudut pandang pengembang - bahwa pemeliharaan dapat dikurangi, dengan biaya membuat kode lebih berat untuk ditulis.

Namun, ada aspek lain yang perlu dipertimbangkan - pengujian hanya dapat dipastikan sebagai kode asli Anda.

Jika Anda menulis semuanya dalam monolith, satu-satunya tes efektif yang dapat Anda tulis adalah "diberi input ini, apakah outputnya benar?". Ini berarti setiap bug yang ditemukan, dicakup dalam "suatu tempat di tumpukan kode raksasa".

Tentu saja, Anda kemudian dapat memiliki pengembang duduk dengan debugger dan menemukan di mana masalah dimulai dan bekerja pada perbaikan. Ini membutuhkan banyak sumber daya, dan penggunaan waktu pengembang yang buruk. Bayangkan bug minor yang pernah Anda miliki, menghasilkan pengembang yang perlu men-debug seluruh program lagi.

Solusinya: Banyak tes yang lebih kecil yang menunjukkan masing-masing potensi kegagalan spesifik.

Tes kecil ini (misalnya Tes Unit), memiliki keuntungan memeriksa area spesifik basis kode dan membantu menemukan kesalahan dalam lingkup terbatas. Ini tidak hanya mempercepat debugging ketika sebuah tes gagal, tetapi juga berarti bahwa jika semua tes kecil Anda gagal - Anda dapat lebih mudah menemukan kegagalan dalam tes Anda yang lebih besar (yaitu jika itu tidak dalam fungsi yang diuji spesifik, itu harus dalam interaksi diantara mereka).

Seperti yang seharusnya jelas, untuk membuat tes yang lebih kecil berarti basis kode Anda perlu dipecah menjadi potongan-potongan kecil yang dapat diuji. Cara melakukannya, pada basis kode komersial besar, sering menghasilkan kode yang mirip dengan apa yang Anda kerjakan.

Sama seperti catatan tambahan: Ini bukan untuk mengatakan bahwa orang tidak akan mengambil hal-hal "terlalu jauh". Tetapi ada alasan yang sah untuk memisahkan basis kode menjadi bagian yang lebih kecil / kurang terhubung - jika dilakukan dengan bijaksana.

Bilkokuya
sumber
5
Sementara jawaban Anda hanya membahas pengujian dan pengujian, itu adalah satu-satunya masalah paling penting yang sebagian jawaban lainnya sama sekali diabaikan jadi +1.
skomisa
17

Tolong jelaskan saya, mengapa kita membutuhkan gaya DDD ini, banyak Pola?

Banyak (sebagian besar ...) dari kita benar-benar tidak membutuhkannya . Para ahli teori dan programmer yang sangat maju dan berpengalaman menulis buku tentang teori dan metodologi sebagai hasil dari banyak penelitian dan pengalaman mendalam mereka - itu tidak berarti bahwa semua yang mereka tulis dapat diterapkan untuk setiap programmer dalam praktik sehari-hari mereka.

Sebagai pengembang junior, ada baiknya membaca buku seperti yang Anda sebutkan untuk memperluas perspektif Anda, dan membuat Anda sadar akan masalah tertentu. Ini juga akan menyelamatkan Anda dari rasa malu dan bingung ketika kolega senior Anda menggunakan terminologi yang tidak Anda kenal. Jika Anda menemukan sesuatu yang sangat sulit dan tampaknya tidak masuk akal atau tampak bermanfaat, jangan bunuh diri karena itu - simpan saja di kepala Anda bahwa ada konsep atau pendekatan seperti itu.

Dalam perkembangan Anda sehari-hari, kecuali jika Anda seorang akademisi, tugas Anda adalah menemukan solusi yang bisa diterapkan dan dapat dikelola. Jika ide-ide yang Anda temukan di buku tidak membantu Anda mencapai tujuan itu, maka jangan khawatir tentang itu sekarang, selama pekerjaan Anda dianggap memuaskan.

Mungkin ada saatnya ketika Anda akan menemukan bahwa Anda dapat menggunakan sebagian dari apa yang Anda baca tetapi tidak terlalu "mengerti" pada awalnya, atau mungkin tidak.

Vektor
sumber
12
Sementara pada level murni ini benar, kedengarannya seperti DDD dan Pola lainnya hanya teori. Mereka bukan. Mereka adalah alat penting untuk mencapai kode yang dapat dibaca dan dipelihara.
Jens Schauder
9
@PeteKirkham dilema OPs adalah pola desain yang terlalu sering digunakan . Apakah Anda benar-benar membutuhkan AccountServiceFacadeInjectResolver(contoh nyata saya baru saja menemukan dalam suatu sistem di tempat kerja) - jawabannya kemungkinan besar tidak.
vikingsteve
4
@vikingsteve OP bukan guru pemrograman yang mengomentari penggunaan pola desain yang terlalu umum. OP adalah seorang magang dan berpikir mereka terlalu sering digunakan di tokonya . Saya tahu bahwa pemula-saya akan memikirkan hal yang sama tentang kode yang saya tulis saat ini, tetapi pemula-saya memiliki banyak proyek pribadi yang gagal karena akhirnya terlalu berbelit-belit.
R. Schmitz
3
@ R.Schmitz Yang mengatakan, pemula saya punya banyak proyek pribadi gagal karena mereka berusaha terlalu keras untuk membuat hal-hal yang dirancang dengan baik, terorganisir, terstruktur, OOP ... Semua ini adalah alat. Mereka perlu dipahami dan digunakan dengan benar, dan Anda hampir tidak dapat menyalahkan palu karena miskin dalam mengacaukan. Anehnya, tampaknya butuh banyak wawasan dan pengalaman untuk memahami hal sederhana ini :)
Luaan
3
@Luaan Jika Anda sudah peduli tentang yang dirancang dengan baik, terorganisir, terstruktur, OOP, saya tidak akan menyebut itu pemula-Anda, tapi ya terlalu sering itu buruk. Namun, pertanyaannya lebih lanjut tentang bagaimana OP tidak benar-benar memahami masalah mana yang dipecahkan. Jika Anda tidak tahu alasannya, sepertinya tidak ada alasan - tetapi sebenarnya, Anda belum tahu.
R. Schmitz
8

Karena pertanyaan Anda mencakup banyak alasan, dengan banyak asumsi, saya akan memilih subjek pertanyaan Anda:

Mengapa kita membutuhkan begitu banyak kelas dalam pola desain

Kita tidak. Tidak ada aturan yang berlaku umum yang mengatakan bahwa harus ada banyak kelas dalam pola desain.

Ada dua panduan utama untuk memutuskan di mana menempatkan kode, dan cara memotong tugas Anda menjadi unit kode yang berbeda:

  • Kohesi: setiap unit kode (baik itu paket, file, kelas atau metode) harus dimiliki bersama . Yaitu, metode spesifik apa pun harus memiliki satu tugas, dan melakukannya dengan baik. Setiap kelas harus bertanggung jawab atas satu topik yang lebih besar (apa pun itu). Kami ingin kohesi yang tinggi.
  • Coupling: setiap dua unit kode harus bergantung sesedikit mungkin pada satu sama lain - seharusnya tidak ada dependensi melingkar. Kami ingin kopling rendah.

Mengapa keduanya harus penting?

  • Kohesi: metode yang melakukan banyak hal (misalnya, skrip CGI kuno yang melakukan GUI, logika, akses DB, dll. Semuanya dalam satu kode yang panjang berantakan) menjadi sulit digunakan. Pada saat penulisan ini, sangat menggoda untuk memasukkan pemikiran Anda ke dalam metode yang panjang. Ini berfungsi, mudah disajikan dan semacamnya, dan Anda dapat melakukannya. Masalah muncul kemudian: setelah beberapa bulan, Anda mungkin lupa apa yang Anda lakukan. Baris kode di bagian atas mungkin berjarak beberapa layar dari garis di bagian bawah; mudah untuk melupakan semua detail. Setiap perubahan di mana pun dalam metode ini dapat merusak sejumlah perilaku dari hal yang kompleks. Akan sangat sulit untuk refactor atau menggunakan kembali bagian dari metode ini. Dan seterusnya.
  • Coupling: kapan saja Anda mengubah unit kode, Anda berpotensi menghancurkan semua unit lain yang bergantung padanya. Dalam bahasa ketat seperti Java, Anda mungkin mendapatkan petunjuk selama waktu kompilasi (yaitu, tentang parameter, pengecualian yang dinyatakan, dan sebagainya). Tetapi banyak perubahan tidak memicu seperti itu (yaitu perubahan perilaku), dan bahasa lain yang lebih dinamis, tidak memiliki kemungkinan seperti itu. Semakin tinggi kopling, semakin sulit untuk mengubah apa pun, dan Anda mungkin berhenti, di mana penulisan ulang yang lengkap diperlukan untuk mencapai beberapa tujuan.

Kedua aspek ini adalah "driver" dasar untuk setiap pilihan "di mana harus meletakkan apa" dalam bahasa pemrograman apa pun, dan paradigma apa pun (tidak hanya OO). Tidak semua orang secara eksplisit menyadarinya, dan butuh waktu, seringkali bertahun-tahun, untuk mendapatkan perasaan yang benar-benar tertanam dan otomatis tentang bagaimana perangkat lunak ini memengaruhi.

Jelas, kedua konsep itu tidak memberi tahu Anda apa yang sebenarnya harus dilakukan . Beberapa orang keliru dalam hal terlalu banyak, yang lain terlalu sedikit. Beberapa bahasa (memandang Anda di sini, Jawa) cenderung memihak banyak kelas karena sifatnya yang sangat statis dan pedantik dari bahasa itu sendiri (ini bukan pernyataan nilai, tetapi itu adalah apa adanya). Ini menjadi sangat nyata ketika Anda membandingkannya dengan bahasa yang lebih dinamis dan lebih ekspresif, misalnya Ruby.

Aspek lain adalah bahwa beberapa orang berlangganan pendekatan tangkas dari hanya menulis kode yang diperlukan saat ini , dan untuk melakukan refactor berat nanti, bila perlu. Dalam gaya pengembangan ini, Anda tidak akan membuat interfaceketika Anda hanya memiliki satu kelas pelaksana. Anda cukup mengimplementasikan kelas konkret. Jika, nanti, Anda membutuhkan kelas dua, Anda akan refactor.

Beberapa orang tidak bekerja seperti itu. Mereka membuat antarmuka (atau, lebih umum, kelas dasar abstrak) untuk apa pun yang pernah dapat digunakan secara lebih umum; ini menyebabkan ledakan kelas dengan cepat.

Sekali lagi, ada argumen untuk dan melawan, dan tidak masalah yang saya, atau Anda, sukai. Dalam hidup Anda sebagai pengembang perangkat lunak, Anda akan menghadapi semua hal yang ekstrem, mulai dari metode spaghetti yang panjang, hingga desain kelas yang tercerahkan, cukup besar, hingga skema kelas yang sangat meledak-ledak yang terlalu banyak direkayasa. Ketika Anda semakin berpengalaman, Anda akan tumbuh lebih banyak menjadi peran "arsitektur", dan dapat mulai memengaruhi ini ke arah yang Anda inginkan. Anda akan menemukan tengah emas untuk diri sendiri, dan Anda masih akan menemukan bahwa banyak orang akan tidak setuju dengan Anda, apa pun yang Anda lakukan.

Oleh karena itu, menjaga pikiran terbuka adalah hal yang paling penting, di sini, dan itu akan menjadi saran utama saya untuk Anda, melihat bahwa Anda tampaknya sangat kesakitan tentang masalah ini, menilai dari sisa pertanyaan Anda ...

AnoE
sumber
7

Coders berpengalaman telah belajar:

  • Karena program-program bertubuh kecil dan kelas-kelas mulai tumbuh, terutama yang sukses. Pola-pola sederhana yang bekerja pada level sederhana tidak berskala.
  • Karena mungkin terasa membebani harus menambahkan / mengubah beberapa artefak untuk setiap penambahan / perubahan tetapi Anda tahu apa yang harus ditambahkan dan mudah untuk melakukannya. 3 menit mengetik ketukan 3 jam pengkodean pintar.
  • Banyak kelas kecil tidak "berantakan" hanya karena Anda tidak mengerti mengapa overhead sebenarnya adalah ide yang bagus
  • Tanpa pengetahuan domain yang ditambahkan, kode 'jelas bagi saya' sering kali misterius bagi rekan satu tim saya ... ditambah masa depan saya.
  • Pengetahuan suku dapat membuat proyek menjadi sangat sulit untuk menambah anggota tim dengan mudah dan sulit agar mereka menjadi produktif dengan cepat.
  • Penamaan adalah salah satu dari dua masalah sulit dalam komputasi yang masih benar dan banyak kelas dan metode sering merupakan latihan yang intens dalam penamaan yang banyak ditemukan manfaat besar.
Michael Durrant
sumber
5
Tetapi apakah overhead itu perlu? Dalam banyak kasus yang saya lihat, pola desain terlalu sering digunakan. Hasil dari overcomplexity adalah meningkatnya kesulitan dalam memahami, memelihara, menguji dan men-debug kode. Ketika Anda memiliki 12 kelas dan 4 modul pakar di sekitar satu kelas layanan sederhana (contoh nyata yang baru saja saya lihat), dengan cepat menjadi kurang dapat dikelola daripada yang Anda kira.
vikingsteve
4
@vikingsteve Anda tetap merujuk pada satu contoh implementasi yang cacat dengan harapan hal itu akan membuktikan bahwa kode terstruktur, secara umum, adalah ide yang buruk. Itu tidak melacak.
MetaFight
2
@MetaFight OP tidak berbicara tentang kode struktur. Dia berbicara tentang, apa yang dia lihat, terlalu banyak abstraksi. Jika Anda memiliki terlalu banyak abstraksi, saya berpendapat, Anda dengan cepat mendapatkan kode yang sangat tidak terstruktur dan banyak bagian yang hampir identik, hanya karena orang tidak dapat mengatasi jumlah barang yang harus mereka tangani.
jelas
4
@Clearer Saya cukup yakin semua orang di sini setuju bahwa kesalahan penerapan kode terstruktur adalah hal yang buruk. OP mengatakan mereka Junior. Itu sebabnya orang berasumsi dia tidak terbiasa dengan manfaat kode terstruktur dan mengulanginya.
MetaFight
2

Sejauh ini jawabannya, semuanya baik, dimulai dengan asumsi yang masuk akal bahwa si penanya kehilangan sesuatu, yang juga diakui si penanya. Mungkin juga penanya pada dasarnya benar, dan ada baiknya membahas bagaimana situasi ini bisa terjadi.

Pengalaman dan praktik sangat kuat, dan jika para senior mendapatkan pengalaman mereka dalam proyek-proyek besar dan kompleks di mana satu-satunya cara untuk menjaga hal-hal di bawah kendali adalah dengan banyak hal EntityTransformationServiceImpl, maka mereka menjadi cepat dan nyaman dengan pola desain dan kepatuhan yang dekat dengan DDD. Mereka akan jauh lebih efektif menggunakan pendekatan yang ringan, bahkan untuk program kecil. Sebagai yang aneh, Anda harus beradaptasi dan itu akan menjadi pengalaman belajar yang hebat.

Meskipun beradaptasi, Anda harus menganggapnya sebagai pelajaran dalam keseimbangan antara mempelajari satu pendekatan secara mendalam, sampai pada titik Anda dapat membuatnya bekerja di mana saja, dibandingkan tetap fleksibel dan mengetahui alat apa yang tersedia tanpa harus menjadi ahli dengan salah satu dari mereka. Ada keuntungan untuk keduanya dan keduanya dibutuhkan di dunia.

Josh Rumbut
sumber
-4

Membuat lebih banyak kelas dan fungsi sesuai penggunaan akan menjadi pendekatan yang bagus untuk menyelesaikan masalah dengan cara tertentu yang membantu di masa depan untuk menyelesaikan masalah apa pun.

Banyak kelas membantu mengidentifikasi sebagai pekerjaan dasar mereka dan setiap kelas dapat dipanggil kapan saja.

Namun jika Anda memiliki banyak kelas dan fungsi dari nama yang dapat diperoleh, mereka mudah dipanggil dan dikelola. Ini disebut kode bersih.

Sanjeev Chauhan
sumber
9
Maaf, tapi apa yang kamu katakan?
Deduplicator
@Dupuplikator mari kita ambil contoh di java jika kita mendesain kita menggunakan utas dan kelas jframes untuk warisannya. Dari hanya satu kelas kita tidak dapat menggunakan beberapa karya java untuk desain jadi kita perlu membuat lebih banyak kelas
Sanjeev Chauhan
2
Jawaban ini perlu menyajikan gagasan yang dimaksudkan untuk disajikan dalam bahasa Inggris yang lebih jelas. Sepertinya ide inti dalam jawabannya adalah bahwa kelas yang lebih kecil, masing-masing dengan satu fungsi yang terdefinisi dengan baik, adalah ide yang bagus, tetapi tata bahasa yang buruk membuatnya hampir mustahil untuk dipahami. Juga, dengan sendirinya, pernyataan ini mungkin tidak cukup.
talonx