Strategi apa yang Anda gunakan untuk penamaan paket di proyek Java dan mengapa? [Tutup]

88

Saya memikirkan hal ini beberapa waktu yang lalu dan baru-baru ini muncul kembali karena toko saya sedang melakukan aplikasi web Java pertama yang sebenarnya.

Sebagai intro, saya melihat dua strategi penamaan paket utama. (Untuk lebih jelasnya, saya tidak mengacu pada keseluruhan bagian 'domain.company.project' ini, saya berbicara tentang konvensi paket di bawahnya.) Bagaimanapun, konvensi penamaan paket yang saya lihat adalah sebagai berikut:

  1. Fungsional: Memberi nama paket Anda menurut fungsinya secara arsitektural daripada identitasnya menurut domain bisnis. Istilah lain untuk ini mungkin penamaan menurut 'lapisan'. Jadi, Anda akan memiliki paket * .ui dan paket * .domain dan paket * .orm. Paket Anda adalah potongan horizontal, bukan vertikal.

    Ini jauh lebih umum daripada penamaan logis. Sebenarnya, saya tidak percaya saya pernah melihat atau mendengar proyek yang melakukan ini. Ini tentu saja membuat saya curiga (seperti berpikir bahwa Anda telah menemukan solusi untuk masalah NP) karena saya tidak terlalu pintar dan saya berasumsi bahwa setiap orang pasti memiliki alasan yang bagus untuk melakukannya dengan cara yang mereka lakukan. Di sisi lain, saya tidak menentang orang yang hanya merindukan gajah di kamar dan saya tidak pernah mendengar argumen sebenarnya untuk melakukan penamaan paket dengan cara ini. Ini sepertinya menjadi standar de facto.

  2. Logis: Memberi nama paket Anda sesuai dengan identitas domain bisnis mereka dan memasukkan setiap kelas yang berkaitan dengan fungsionalitas vertikal ke dalam paket itu.

    Saya belum pernah melihat atau mendengar ini, seperti yang saya sebutkan sebelumnya, tetapi itu sangat masuk akal bagi saya.

    1. Saya cenderung mendekati sistem secara vertikal daripada horizontal. Saya ingin masuk dan mengembangkan sistem Pemrosesan Pesanan, bukan lapisan akses data. Jelas, ada kemungkinan besar saya akan menyentuh lapisan akses data dalam pengembangan sistem itu, tetapi intinya adalah saya tidak menganggapnya seperti itu. Artinya, tentu saja, adalah ketika saya menerima perintah perubahan atau ingin menerapkan beberapa fitur baru, alangkah baiknya jika tidak perlu mencari-cari di sekumpulan paket untuk menemukan semua kelas terkait. Sebaliknya, saya hanya melihat paket X karena apa yang saya lakukan berkaitan dengan X.

    2. Dari sudut pandang pengembangan, saya melihatnya sebagai kemenangan besar memiliki paket Anda mendokumentasikan domain bisnis Anda daripada arsitektur Anda. Saya merasa domain hampir selalu menjadi bagian dari sistem yang lebih sulit untuk dikuasai dimana arsitektur sistem, terutama pada titik ini, hampir menjadi biasa dalam implementasinya. Fakta bahwa saya bisa datang ke sistem dengan jenis konvensi penamaan ini dan langsung dari penamaan paket tahu bahwa itu berkaitan dengan pesanan, pelanggan, perusahaan, produk, dll tampaknya sangat berguna.

    3. Sepertinya ini akan memungkinkan Anda untuk lebih memanfaatkan pengubah akses Java. Hal ini memungkinkan Anda untuk mendefinisikan antarmuka ke dalam subsistem dengan lebih jelas daripada ke dalam lapisan sistem. Jadi jika Anda memiliki subsistem pesanan yang ingin Anda persisten secara transparan, secara teori Anda tidak boleh membiarkan hal lain tahu bahwa itu persisten dengan tidak harus membuat antarmuka publik ke kelas persistensi di lapisan dao dan sebagai gantinya mengemas kelas dao di dengan hanya kelas-kelas yang ditangani. Jelas, jika Anda ingin mengekspos fungsionalitas ini, Anda dapat menyediakan antarmuka untuk itu atau membuatnya menjadi publik. Sepertinya Anda kehilangan banyak ini dengan memiliki potongan vertikal fitur sistem Anda yang dibagi menjadi beberapa paket.

    4. Saya kira satu kelemahan yang dapat saya lihat adalah hal itu membuat merobek lapisan sedikit lebih sulit. Alih-alih hanya menghapus atau mengganti nama sebuah paket dan kemudian menjatuhkan yang baru dengan teknologi alternatif, Anda harus masuk dan mengubah semua kelas di semua paket. Namun, saya tidak melihat ini masalah besar. Mungkin karena kurangnya pengalaman, tetapi saya harus membayangkan bahwa berapa kali Anda menukar teknologi tidak ada artinya dibandingkan dengan berapa kali Anda masuk dan mengedit potongan fitur vertikal dalam sistem Anda.

Jadi saya kira pertanyaannya akan keluar kepada Anda, bagaimana Anda memberi nama paket Anda dan mengapa? Harap dipahami bahwa saya tidak selalu berpikir bahwa saya telah tersandung pada angsa emas atau sesuatu di sini. Saya cukup baru dalam semua ini dengan sebagian besar pengalaman akademis. Namun, saya tidak bisa menemukan lubang dalam alasan saya jadi saya berharap Anda semua bisa sehingga saya bisa melanjutkan.

Tim Visher
sumber
Apa yang saya dengar sejauh ini sepertinya menunjukkan bahwa itu semacam keputusan pengadilan. Namun, sebagian besar jawaban belum berfokus pada pertimbangan praktis. Itu lebih dari yang saya cari. Terima kasih atas bantuannya sejauh ini!
Tim Visher
Saya tidak berpikir itu adalah keputusan pengadilan. Pertama membagi berdasarkan lapisan, kemudian dengan fungsionalitas jelas merupakan cara yang harus dilakukan. Saya memperbarui jawaban saya.
eljo
@eljenso: sampaikan itu ke Eclipse guys :) Di eclipse, divisi pertama adalah "fitur", yang merupakan unit-unit penerapan dan juga fungsionalitas. Di dalam "fitur", ada "plugin", yang biasanya dibagi berdasarkan lapisan - tetapi plugin dalam "fitur" yang sama harus selalu digunakan bersama. Jika Anda hanya memiliki satu unit penerapan, maka membagi berdasarkan lapisan terlebih dahulu dan baru kemudian menurut fungsionalitas mungkin masuk akal. Dengan beberapa unit penerapan, Anda tidak ingin hanya menerapkan lapisan presentasi - Anda menginginkan fungsionalitas tambahan.
Peter Štibraný
Saya memiliki pertanyaan khusus tentang lapisan bisnis aplikasi, apa yang seharusnya menjadi konvensi penamaan?
Bionix1441

Jawaban:

32

Untuk desain paket, pertama saya bagi berdasarkan lapisan, kemudian dengan beberapa fungsi lainnya.

Ada beberapa aturan tambahan:

  1. lapisan ditumpuk dari yang paling umum (bawah) hingga paling spesifik (atas)
  2. setiap lapisan memiliki antarmuka publik (abstraksi)
  3. sebuah lapisan hanya dapat bergantung pada antarmuka publik dari lapisan lain (enkapsulasi)
  4. sebuah lapisan hanya dapat bergantung pada lapisan yang lebih umum (ketergantungan dari atas ke bawah)
  5. sebuah lapisan sebaiknya bergantung pada lapisan yang berada tepat di bawahnya

Jadi, untuk aplikasi web misalnya, Anda dapat memiliki lapisan berikut di tingkat aplikasi Anda (dari atas ke bawah):

  • lapisan presentasi: menghasilkan UI yang akan ditampilkan di tingkat klien
  • application layer: berisi logika yang dikhususkan untuk aplikasi, stateful
  • lapisan layanan: mengelompokkan fungsionalitas berdasarkan domain, tanpa kewarganegaraan
  • lapisan integrasi: menyediakan akses ke tingkat backend (db, jms, email, ...)

Untuk tata letak paket yang dihasilkan, berikut beberapa aturan tambahan:

  • akar dari setiap nama paket adalah <prefix.company>.<appname>.<layer>
  • antarmuka lapisan selanjutnya dibagi berdasarkan fungsionalitas: <root>.<logic>
  • implementasi privat sebuah layer diawali dengan privat: <root>.private

Berikut adalah contoh tata letak.

Lapisan presentasi dibagi dengan teknologi tampilan, dan secara opsional oleh (kelompok) aplikasi.

com.company.appname.presentation.internal
com.company.appname.presentation.springmvc.product
com.company.appname.presentation.servlet
...

Lapisan aplikasi dibagi menjadi kasus penggunaan.

com.company.appname.application.lookupproduct
com.company.appname.application.internal.lookupproduct
com.company.appname.application.editclient
com.company.appname.application.internal.editclient
...

Lapisan layanan dibagi menjadi domain bisnis, dipengaruhi oleh logika domain di tingkat backend.

com.company.appname.service.clientservice
com.company.appname.service.internal.jmsclientservice
com.company.appname.service.internal.xmlclientservice
com.company.appname.service.productservice
...

Lapisan integrasi dibagi menjadi 'teknologi' dan objek akses.

com.company.appname.integration.jmsgateway
com.company.appname.integration.internal.mqjmsgateway
com.company.appname.integration.productdao
com.company.appname.integration.internal.dbproductdao
com.company.appname.integration.internal.mockproductdao
...

Keuntungan dari memisahkan paket seperti ini adalah lebih mudah untuk mengelola kompleksitas, dan meningkatkan testability dan reusability. Meskipun sepertinya banyak overhead, menurut pengalaman saya itu sebenarnya sangat alami dan semua orang yang mengerjakan struktur ini (atau serupa) mengambilnya dalam hitungan hari.

Mengapa menurut saya pendekatan vertikal tidak begitu baik?

Dalam model berlapis, beberapa modul tingkat tinggi yang berbeda dapat menggunakan modul tingkat yang lebih rendah yang sama. Misalnya: Anda dapat membangun beberapa tampilan untuk aplikasi yang sama, beberapa aplikasi dapat menggunakan layanan yang sama, beberapa layanan dapat menggunakan gateway yang sama. Triknya di sini adalah ketika berpindah melalui lapisan, tingkat fungsionalitas berubah. Modul di lapisan yang lebih spesifik tidak memetakan 1-1 pada modul dari lapisan yang lebih umum, karena tingkat fungsionalitas yang mereka ekspresikan tidak memetakan 1-1.

Saat Anda menggunakan pendekatan vertikal untuk desain paket, yaitu Anda membagi berdasarkan fungsionalitas terlebih dahulu, kemudian Anda memaksa semua blok penyusun dengan tingkat fungsionalitas yang berbeda ke dalam 'jaket fungsionalitas' yang sama. Anda mungkin merancang modul umum Anda untuk yang lebih spesifik. Tetapi ini melanggar prinsip penting bahwa lapisan yang lebih umum seharusnya tidak mengetahui tentang lapisan yang lebih spesifik. Misalnya, lapisan layanan tidak boleh dimodelkan setelah konsep dari lapisan aplikasi.

eljenso
sumber
"Keuntungan dari memisahkan paket seperti ini adalah lebih mudah untuk mengelola kompleksitas, dan meningkatkan testability dan reusability." Anda benar-benar tidak membahas alasan mengapa demikian.
mangoDrunk
1
Anda tidak membahas alasan mengapa tidak demikian. Tapi bagaimanapun ... aturan pengorganisasiannya cukup jelas dan lugas, sehingga mengurangi kompleksitas. Ini lebih dapat diuji dan digunakan kembali karena organisasi itu sendiri. Semua orang bisa mencobanya, dan setelah itu kita bisa setuju atau tidak setuju. Saya menjelaskan secara singkat beberapa kelemahan dari pendekatan vertikal, secara implisit memberikan alasan mengapa menurut saya pendekatan horizontal lebih mudah.
eljo
8
Artikel ini menjelaskan dengan cukup baik mengapa lebih baik menggunakan paket-demi-fitur daripada paket-demi-lapisan .
Tom
@eljenso "Anda tidak membahas alasan mengapa tidak demikian", mencoba mengalihkan beban pembuktian? Saya rasa artikel yang diposting oleh Tom menjelaskan dengan sangat baik mengapa paket-demi-fitur lebih baik dan saya kesulitan menjawab, "Menurut saya ini bukan keputusan yang tepat. Pertama membagi berdasarkan lapisan, kemudian menurut fungsionalitas sudah pasti caranya untuk pergi "dengan serius.
pka
18

Saya menemukan diri saya berpegang teguh pada prinsip desain paket Paman Bob . Singkatnya, kelas-kelas yang akan digunakan kembali bersama-sama dan diubah bersama-sama (untuk alasan yang sama, misalnya perubahan ketergantungan atau perubahan kerangka kerja) harus diletakkan dalam paket yang sama. IMO, kerusakan fungsional akan memiliki peluang yang lebih baik untuk mencapai tujuan ini daripada kerusakan vertikal / khusus bisnis di sebagian besar aplikasi.

Misalnya, potongan horizontal objek domain dapat digunakan kembali oleh berbagai jenis front-end atau bahkan aplikasi dan potongan horizontal front-end web kemungkinan besar akan berubah bersama ketika kerangka web yang mendasarinya perlu diubah. Di sisi lain, mudah untuk membayangkan efek riak dari perubahan ini di banyak paket jika kelas di berbagai area fungsional dikelompokkan dalam paket tersebut.

Jelas, tidak semua jenis perangkat lunak itu sama dan perincian vertikal mungkin masuk akal (dalam hal mencapai tujuan dapat digunakan kembali dan dapat ditutup-untuk-berubah) dalam proyek tertentu.

Buu Nguyen
sumber
Terima kasih, ini sangat jelas Seperti yang saya katakan dalam pertanyaan, saya merasa berapa kali Anda akan menukar teknologi jauh lebih sedikit daripada Anda bergeser di sekitar irisan fungsionalitas vertikal. Bukankah ini pengalaman Anda?
Tim Visher
Ini bukan hanya tentang teknologi. Poin # 1 dari posting asli Anda hanya masuk akal jika potongan vertikal adalah aplikasi / layanan independen yang berkomunikasi satu sama lain melalui beberapa antarmuka (SOA, jika Anda mau). lebih lanjut di bawah ...
Buu Nguyen
Sekarang saat Anda beralih ke detail dari setiap aplikasi / layanan yang memiliki gui / bisnis / datanya sendiri, saya hampir tidak dapat membayangkan bahwa perubahan dalam potongan vertikal, baik itu tentang teknologi, ketergantungan, aturan / alur kerja, logging , keamanan, gaya UI, dapat sepenuhnya diisolasi dari potongan lainnya.
Buu Nguyen
Saya akan tertarik dengan umpan balik Anda tentang jawaban saya
i3ensays
@BuuNguyen Tautan ke prinsip desain paket rusak.
johnnieb
5

Biasanya ada kedua tingkat pembagian. Dari atas, ada unit penyebaran. Ini dinamai 'secara logis' (dalam istilah Anda, pikirkan fitur Eclipse). Di dalam unit penerapan, Anda memiliki divisi fungsional paket (pikirkan plugin Eclipse).

Misalnya, fitur adalah com.feature, dan terdiri dari com.feature.client, com.feature.coredan com.feature.uiplugin. Di dalam plugin, saya hanya memiliki sedikit pembagian ke paket lain, meskipun itu juga tidak biasa.

Pembaruan: Btw, ada pembicaraan bagus oleh Juergen Hoeller tentang organisasi kode di InfoQ: http://www.infoq.com/presentations/code-organization-large-projects . Juergen adalah salah satu arsitek Spring, dan tahu banyak tentang hal ini.

Peter Štibraný
sumber
Saya kurang mengikuti. Biasanya Anda mungkin melihat com.apache.wicket.x di mana x berfungsi atau logis. Saya biasanya tidak melihat com.x. Saya kira Anda mengatakan bahwa Anda akan menggunakan struktur com.company.project.feature.layer? Apakah kamu punya alasan?
Tim Visher
Alasannya adalah bahwa "com.company.project.feature" adalah unit penerapan. Pada level ini, beberapa fitur bersifat opsional, dan dapat dilewati (yaitu tidak diterapkan). Namun, fitur di dalam, hal-hal tidak opsional, dan Anda biasanya menginginkan semuanya. Di sini lebih masuk akal untuk membagi berdasarkan lapisan.
Peter Štibraný
4

Sebagian besar proyek java yang saya kerjakan mengiris paket java secara fungsional terlebih dahulu, lalu secara logis.

Biasanya bagian-bagiannya cukup besar sehingga dipecah menjadi artefak bangunan yang terpisah, di mana Anda dapat menempatkan fungsionalitas inti ke dalam satu toples, apis ke yang lain, barang frontend web ke dalam warfile, dll.

Ben Hardy
sumber
Seperti apa kelihatannya? domain.company.project.function.logicalSlice?
Tim Visher
kurang lebih! egdcpweb.profiles, dcpweb.registration, dcpapis, dcppersistence dll umumnya bekerja dengan cukup baik, jarak tempuh Anda mungkin berbeda. tergantung juga jika Anda menggunakan pemodelan domain - jika Anda memiliki beberapa domain, Anda mungkin ingin membagi berdasarkan domain terlebih dahulu.
Ben Hardy
Saya pribadi lebih suka sebaliknya, logis kemudian fungsional. apples.rpc, apples.model, lalu banana.model, banana.store
mP.
Ada lebih banyak nilai dalam mengelompokkan semua barang apel daripada mengelompokkan semua barang web menjadi satu.
mP.
3

Paket harus dikompilasi dan didistribusikan sebagai satu kesatuan. Saat mempertimbangkan kelas apa yang termasuk dalam sebuah paket, salah satu kriteria utamanya adalah ketergantungannya. Apa paket lain (termasuk pustaka pihak ketiga) yang bergantung pada kelas ini. Sistem yang terorganisir dengan baik akan mengelompokkan kelas dengan dependensi serupa dalam sebuah paket. Ini membatasi dampak perubahan dalam satu pustaka, karena hanya beberapa paket yang terdefinisi dengan baik yang akan bergantung padanya.

Sepertinya logis, sistem vertikal Anda mungkin cenderung "mencoreng" ketergantungan di sebagian besar paket. Artinya, jika setiap fitur dikemas sebagai potongan vertikal, setiap paket akan bergantung pada setiap pustaka pihak ketiga yang Anda gunakan. Setiap perubahan pada perpustakaan kemungkinan besar akan mempengaruhi seluruh sistem Anda.

erickson
sumber
Ah. Jadi satu hal yang dilakukan oleh melakukan irisan horizontal adalah melindungi Anda dari peningkatan aktual di perpustakaan yang Anda gunakan. Saya pikir Anda benar bahwa irisan vertikal mengotori setiap ketergantungan yang dimiliki sistem Anda di setiap paket. Mengapa ini menjadi masalah besar?
Tim Visher
Untuk sebuah "fitur", ini bukan masalah besar. Mereka cenderung lebih tidak stabil dan memiliki lebih banyak ketergantungan. Di sisi lain, kode "klien" ini cenderung memiliki kegunaan ulang yang rendah. Untuk sesuatu yang Anda inginkan menjadi perpustakaan yang dapat digunakan kembali, mengisolasi klien dari setiap perubahan kecil adalah investasi yang bagus.
erickson
3

Saya pribadi lebih suka mengelompokkan kelas secara logis kemudian di dalamnya termasuk sub-paket untuk setiap partisipasi fungsional.

Tujuan pengemasan

Bagaimanapun, paket adalah tentang pengelompokan hal-hal bersama - gagasan menjadi kelas terkait hidup berdekatan satu sama lain. Jika mereka tinggal di paket yang sama, mereka dapat memanfaatkan paket pribadi untuk membatasi visibilitas. Masalahnya adalah menggabungkan semua tampilan dan ketekunan Anda ke dalam satu paket dapat menyebabkan banyak kelas tercampur menjadi satu paket. Hal selanjutnya yang perlu dilakukan adalah membuat view, persistance, sub paket util dan kelas refactor yang sesuai. Sayangnya protected and package private scoping tidak mendukung konsep paket dan subpaket saat ini karena ini akan membantu dalam menegakkan aturan visibilitas tersebut.

Saya sekarang melihat nilai dalam pemisahan melalui fungsionalitas karena nilai apa yang ada untuk mengelompokkan semua hal yang terkait tampilan. Hal-hal dalam strategi penamaan ini menjadi terputus dengan beberapa kelas dalam tampilan sementara yang lain dalam ketekunan dan seterusnya.

Contoh struktur kemasan logis saya

Untuk tujuan ilustrasi, mari beri nama dua modul - saya akan menggunakan modul nama sebagai konsep yang mengelompokkan kelas di bawah cabang tertentu dari pohon pacckage.

apple.model apple.store banana.model banana.store

Keuntungan

Seorang klien yang menggunakan Banana.store.BananaStore hanya dihadapkan pada fungsionalitas yang ingin kami sediakan. Versi hibernate adalah detail implementasi yang tidak perlu mereka ketahui, mereka juga tidak harus melihat class ini saat menambahkan clutter ke operasi penyimpanan.

Keuntungan Logis v Fungsional lainnya

Semakin jauh ke root semakin luas cakupannya dan hal-hal yang termasuk dalam satu paket mulai menunjukkan semakin banyak ketergantungan pada hal-hal yang termasuk dalam modulnya. Jika seseorang harus memeriksa, misalnya modul "banana", sebagian besar dependensi akan dibatasi di dalam modul itu. Nyatanya kebanyakan pembantu di bawah "banana" tidak akan dirujuk sama sekali di luar cakupan paket ini.

Mengapa fungsionalitas?

Nilai apa yang dicapai seseorang dengan menggabungkan berbagai hal berdasarkan fungsionalitas. Sebagian besar kelas dalam kasus seperti itu tidak bergantung satu sama lain dengan sedikit atau tidak perlu memanfaatkan metode atau kelas privat paket. Memfaktorkannya kembali menjadi sub-paket mereka sendiri tidak banyak berguna tetapi membantu mengurangi kekacauan.

Pengembang mengubah sistem

Ketika pengembang ditugaskan untuk membuat perubahan yang lebih dari sepele, tampaknya konyol bahwa mereka memiliki potensi perubahan yang menyertakan file dari semua area pohon paket. Dengan pendekatan terstruktur yang logis, perubahan mereka lebih lokal dalam bagian yang sama dari pohon paket yang sepertinya benar.

mP.
sumber
"Ketika pengembang [...] file dari semua area pohon paket." Anda benar ketika Anda mengatakan ini tampak konyol. Karena inilah titik pelapisan yang tepat: perubahan tidak mempengaruhi seluruh struktur aplikasi.
eljo
Terima kasih atas sarannya. Saya tidak yakin saya memahami Anda dengan jelas. Saya yakin Anda mencoba berdebat untuk paket Logis, saya tidak begitu jelas mengapa. Bisakah Anda mencoba membuat jawaban Anda sedikit lebih jelas, mungkin merekam ulang? Terima kasih!
Tim Visher
3

Baik pendekatan fungsional (arsitektural) dan logis (fitur) untuk pengemasan memiliki tempat. Banyak contoh aplikasi (yang ditemukan di buku teks dll.) Mengikuti pendekatan fungsional menempatkan presentasi, layanan bisnis, pemetaan data, dan lapisan arsitektur lainnya ke dalam paket terpisah. Dalam aplikasi contoh, setiap paket seringkali hanya memiliki sedikit atau hanya satu kelas.

Pendekatan awal ini baik-baik saja karena contoh yang dibuat-buat sering berfungsi untuk: 1) secara konseptual memetakan arsitektur kerangka kerja yang disajikan, 2) dilakukan dengan satu tujuan logis (misalnya menambah / menghapus / memperbarui / menghapus hewan peliharaan dari klinik) . Masalahnya banyak pembaca yang menganggap ini sebagai standar yang tidak ada batasnya.

Saat aplikasi "bisnis" berkembang untuk menyertakan lebih banyak fitur, mengikuti pendekatan fungsional menjadi beban. Meskipun saya tahu di mana harus mencari tipe berdasarkan layer arsitektur (misalnya pengontrol web di bawah paket "web" atau "ui", dll.), Mengembangkan fitur logis tunggal mulai membutuhkan lompatan bolak-balik di antara banyak paket. Ini rumit, paling tidak, tapi lebih buruk dari itu.

Karena jenis yang terkait secara logis tidak dikemas bersama, API dipublikasikan secara berlebihan; interaksi antara tipe yang terkait secara logis dipaksa menjadi 'publik' sehingga tipe dapat mengimpor dan berinteraksi satu sama lain (kemampuan untuk meminimalkan ke default / visibilitas paket hilang).

Jika saya membangun perpustakaan kerangka kerja, tentu saja paket saya akan mengikuti pendekatan pengemasan fungsional / arsitektural. Konsumen API saya bahkan mungkin menghargai bahwa pernyataan impor mereka berisi paket intuitif yang diberi nama sesuai dengan arsitekturnya.

Sebaliknya, saat membangun aplikasi bisnis saya akan mengemas berdasarkan fitur. Saya tidak memiliki masalah dalam menempatkan Widget, WidgetService, dan WidgetController dalam paket " com.myorg.widget. " Yang sama dan kemudian memanfaatkan visibilitas default (dan memiliki lebih sedikit pernyataan impor serta dependensi antar-paket).

Namun, ada kasus yang saling silang. Jika WidgetService saya digunakan oleh banyak domain logis (fitur), saya mungkin membuat paket " com.myorg.common.service. ". Ada juga peluang bagus bahwa saya membuat kelas dengan maksud agar dapat digunakan kembali di seluruh fitur dan berakhir dengan paket seperti " com.myorg.common.ui.helpers. " Dan " com.myorg.common.util. ". Saya bahkan mungkin akhirnya memindahkan semua kelas "umum" ini kemudian dalam proyek terpisah dan memasukkannya ke dalam aplikasi bisnis saya sebagai ketergantungan myorg-commons.jar.

i3ensays
sumber
2

Itu tergantung pada granularitas proses logis Anda?

Jika mereka berdiri sendiri, Anda sering memiliki proyek baru untuk mereka di kontrol sumber, bukan paket baru.

Proyek yang saya jalani saat ini salah terhadap pemisahan logis, ada paket untuk aspek jython, paket untuk mesin aturan, paket untuk foo, bar, binglewozzle, dll. Saya sedang mencari pengurai khusus XML / writers untuk setiap modul dalam paket itu, daripada memiliki paket XML (yang telah saya lakukan sebelumnya), meskipun masih akan ada paket XML inti tempat logika bersama digunakan. Namun satu alasan untuk ini adalah bahwa itu mungkin dapat diperluas (plugin) dan karenanya setiap plugin juga perlu menentukan kode XML (atau database, dll), sehingga memusatkan ini dapat menimbulkan masalah di kemudian hari.

Pada akhirnya, tampaknya itulah cara yang paling masuk akal untuk proyek tertentu. Saya pikir mudah untuk mengemas sepanjang garis diagram berlapis proyek yang khas. Anda akan mendapatkan campuran kemasan logis dan fungsional.

Yang dibutuhkan adalah ruang nama yang diberi tag. Pengurai XML untuk beberapa fungsionalitas Jython dapat diberi tag baik Jython maupun XML, daripada harus memilih satu atau yang lain.

Atau mungkin aku goyah.

JeeBee
sumber
Saya tidak sepenuhnya memahami maksud Anda. Saya pikir apa yang Anda katakan adalah bahwa Anda harus melakukan apa yang paling masuk akal untuk proyek Anda dan untuk Anda itu logis dengan sedikit fungsionalitas. Apakah ada alasan praktis khusus untuk ini?
Tim Visher
Seperti yang saya katakan, saya akan memiliki plugin untuk menambah fungsionalitas bawaan. Sebuah plugin harus dapat mengurai dan menulis XML-nya (dan akhirnya ke dalam DB) serta menyediakan fungsionalitas. Oleh karena itu, apakah saya memiliki com.xx.feature.xml atau com.xx.xml.feature? Yang pertama tampak lebih rapi.
JeeBee
2

Saya mencoba merancang struktur paket sedemikian rupa sehingga jika saya menggambar grafik ketergantungan, akan mudah untuk mengikuti dan menggunakan pola yang konsisten, dengan referensi melingkar sesedikit mungkin.

Bagi saya, ini jauh lebih mudah untuk dipertahankan dan divisualisasikan dalam sistem penamaan vertikal daripada horizontal. jika component1.display memiliki referensi ke component2.dataaccess, yang mengeluarkan lebih banyak lonceng peringatan daripada jika display.component1 memiliki referensi ke dataaccess. komponen2.

Tentu saja, komponen yang dibagikan oleh keduanya masuk dalam paketnya sendiri.

levand
sumber
Seperti yang saya pahami, Anda akan menganjurkan konvensi penamaan vertikal. Saya pikir inilah gunanya paket * .utils, ketika Anda membutuhkan kelas di beberapa irisan.
Tim Visher
2

Saya benar-benar mengikuti dan mengusulkan organisasi logis ("menurut fitur")! Sebuah paket harus mengikuti konsep "modul" sedekat mungkin. Organisasi fungsional dapat menyebarkan modul ke suatu proyek, menghasilkan enkapsulasi yang lebih sedikit, dan rentan terhadap perubahan dalam detail implementasi.

Mari kita ambil plugin Eclipse sebagai contoh: meletakkan semua tampilan atau tindakan dalam satu paket akan menjadi berantakan. Sebagai gantinya, setiap komponen fitur harus masuk ke paket fitur, atau jika ada banyak, ke subpaket (featureA.handlers, featureA.preferences, dll.)

Tentu saja, masalahnya terletak pada sistem paket hierarkis (yang dimiliki antara lain Java), yang membuat penanganan masalah ortogonal tidak mungkin atau setidaknya sangat sulit - meskipun terjadi di mana-mana!

thSoft
sumber
1

Saya pribadi akan memilih penamaan fungsional. Alasan singkatnya: ini menghindari duplikasi kode atau mimpi buruk ketergantungan.

Izinkan saya menjelaskan sedikit. Apa yang terjadi jika Anda menggunakan file jar eksternal, dengan pohon paketnya sendiri? Anda secara efektif mengimpor kode (dikompilasi) ke dalam proyek Anda, dan dengannya pohon paket (terpisah secara fungsional). Apakah masuk akal untuk menggunakan dua konvensi penamaan pada saat yang bersamaan? Tidak, kecuali itu disembunyikan dari Anda. Dan ya, jika proyek Anda cukup kecil dan memiliki satu komponen. Tetapi jika Anda memiliki beberapa unit logis, Anda mungkin tidak ingin menerapkan ulang, katakanlah, modul pemuatan file data. Anda ingin membaginya di antara unit logis, tidak memiliki ketergantungan buatan antara unit yang secara logis tidak terkait, dan tidak harus memilih unit mana yang akan Anda gunakan untuk meletakkan alat bersama tersebut.

Saya rasa inilah mengapa penamaan fungsional paling banyak digunakan dalam proyek yang menjangkau, atau dimaksudkan untuk mencapai, ukuran tertentu, dan penamaan logis digunakan dalam konvensi penamaan kelas untuk melacak peran tertentu, jika ada dari setiap kelas dalam a paket.

Saya akan mencoba menanggapi dengan lebih tepat setiap poin Anda tentang penamaan logis.

  1. Jika Anda harus memancing di kelas lama untuk mengubah fungsionalitas saat Anda memiliki perubahan rencana, itu pertanda abstraksi yang buruk: Anda harus membangun kelas yang menyediakan fungsionalitas yang terdefinisi dengan baik, yang dapat didefinisikan dalam satu kalimat pendek. Hanya beberapa, kelas tingkat atas yang harus mengumpulkan semua ini untuk mencerminkan kecerdasan bisnis Anda. Dengan cara ini, Anda akan dapat menggunakan lebih banyak kode, memiliki perawatan yang lebih mudah, dokumentasi yang lebih jelas, dan masalah ketergantungan yang lebih sedikit.

  2. Itu terutama tergantung pada cara Anda menyelesaikan proyek Anda. Jelas, pandangan logis dan fungsional bersifat ortogonal. Jadi jika Anda menggunakan satu konvensi penamaan, Anda perlu menerapkan yang lain ke nama kelas untuk menjaga beberapa urutan, atau bercabang dari satu konvensi penamaan ke yang lain pada kedalaman tertentu.

  3. Pengubah akses adalah cara yang baik untuk mengizinkan kelas lain yang memahami pemrosesan Anda mengakses bagian dalam kelas Anda. Hubungan logis tidak berarti pemahaman tentang batasan algoritmik atau konkurensi. Fungsional mungkin, meski tidak. Saya sangat lelah dengan pengubah akses selain publik dan pribadi, karena mereka sering menyembunyikan kurangnya arsitektur dan abstraksi kelas yang tepat.

  4. Dalam proyek besar dan komersial, perubahan teknologi terjadi lebih sering daripada yang Anda kira. Misalnya, saya sudah 3 kali mengganti XML parser, 2 kali teknologi caching, dan 2 kali software geolocalisation. Untung saya telah menyembunyikan semua detail berpasir dalam paket khusus ...

Varkhan
sumber
1
Maafkan saya jika saya salah, tetapi bagi saya sepertinya Anda lebih banyak berbicara tentang mengembangkan kerangka kerja yang dimaksudkan untuk digunakan oleh banyak orang. Saya pikir aturan berubah antara jenis pengembangan dan pengembangan sistem pengguna akhir. Apakah aku salah?
Tim Visher
Saya pikir untuk kelas umum yang digunakan oleh banyak irisan vertikal, masuk akal untuk memiliki sesuatu seperti utilspaket. Kemudian, setiap kelas yang membutuhkannya dapat bergantung pada paket itu.
Tim Visher
Sekali lagi, ukuran penting: ketika sebuah proyek menjadi cukup besar, maka perlu didukung oleh beberapa orang, dan semacam spesialisasi akan terjadi. Untuk memudahkan interaksi, dan mencegah kesalahan, membagi proyek menjadi beberapa bagian menjadi perlu dengan cepat. Dan paket utils akan segera menjadi sangat besar!
Varkhan
1

Ini adalah eksperimen yang menarik untuk tidak menggunakan paket sama sekali (kecuali untuk paket root.)

Pertanyaan yang muncul kemudian adalah, kapan dan mengapa masuk akal untuk memperkenalkan paket. Agaknya, jawabannya akan berbeda dari apa yang akan Anda jawab di awal proyek.

Saya berasumsi bahwa pertanyaan Anda muncul sama sekali, karena paket seperti kategori dan terkadang sulit untuk memutuskan salah satunya. Terkadang tag akan lebih bermanfaat jika dikomunikasikan bahwa kelas dapat digunakan dalam banyak konteks.

pengguna53682
sumber
0

Dari sudut pandang murni praktis, konstruksi visibilitas java ini memungkinkan kelas dalam paket yang sama dengan metode akses dan properti dengan protecteddan defaultvisibilitas, sertapublic orang-orang. Menggunakan metode non-publik dari lapisan kode yang sama sekali berbeda pasti akan menjadi bau kode yang besar. Jadi saya cenderung menempatkan kelas dari lapisan yang sama ke dalam paket yang sama.

Saya tidak sering menggunakan metode dilindungi atau default ini di tempat lain - kecuali mungkin dalam pengujian unit untuk kelas - tetapi ketika saya melakukannya, itu selalu dari kelas pada lapisan yang sama

Bill Michell
sumber
Bukankah itu sesuatu yang alami dari sistem berlapis-lapis untuk selalu bergantung pada lapisan berikutnya ke bawah? Misalnya, UI bergantung pada lapisan layanan Anda yang bergantung pada lapisan domain Anda, dll. Mengemas potongan vertikal bersama-sama tampaknya melindungi dari ketergantungan antar paket yang berlebihan, bukan?
Tim Visher
Saya hampir tidak pernah menggunakan metode yang dilindungi dan default. 99% publik atau swasta. Beberapa pengecualian: (1) visibilitas default untuk metode yang digunakan hanya oleh pengujian unit, (2) metode abstrak terlindungi yang hanya digunakan dari kelas dasar abstrak.
Esko Luontola
1
Tim Visher, ketergantungan antar paket tidak menjadi masalah, selama ketergantungan selalu menunjuk ke arah yang sama dan tidak ada siklus dalam grafik ketergantungan.
Esko Luontola
0

Tergantung. Dalam pekerjaan saya, terkadang kami membagi paket berdasarkan fungsi (akses data, analitik) atau berdasarkan kelas aset (kredit, ekuitas, suku bunga). Cukup pilih struktur yang paling nyaman untuk tim Anda.

quant_dev
sumber
Apakah ada alasan untuk pergi ke kedua arah tersebut?
Tim Visher
Pemisahan menurut kelas aset (lebih umum: menurut domain bisnis) memudahkan orang baru untuk menemukan jalan mereka melalui kode. Membagi menurut fungsi bagus untuk enkapsulasi. Bagi saya, akses "paket" di Java mirip dengan "teman" di C ++.
quant_dev
@quant_dev Saya tidak setuju dengan ".. oleh fungsi baik untuk enkapsulasi". Saya pikir maksud Anda kebalikannya adalah benar. Selain itu, jangan hanya memilih "kenyamanan". Ada kasus untuk masing-masing (lihat jawaban saya).
i3ensays
-3

Dari pengalaman saya, penggunaan kembali menciptakan lebih banyak masalah daripada pemecahan. Dengan prosesor dan memori terbaru & murah, saya lebih suka duplikasi kode daripada mengintegrasikan secara erat untuk digunakan kembali.

Raghu Kasturi
sumber
5
Penggunaan kembali kode bukanlah tentang harga perangkat keras tetapi tentang biaya pemeliharaan kode.
pengguna2793390
1
Setuju, tetapi memperbaiki sesuatu dalam modul sederhana seharusnya tidak memengaruhi seluruh kode. Apa biaya perawatan yang Anda bicarakan?
Raghu Kasturi
1
Perbaikan bug dalam modul akan mempengaruhi seluruh aplikasi. Mengapa Anda ingin memperbaiki bug yang sama beberapa kali?
pengguna2793390
Apakah Anda harus mempertahankan kode itu bertahun-tahun setelah Anda menulisnya? Saya mengutuk mereka yang datang sebelum saya yang mengambil pendekatan lesu untuk pemrograman komputer. Menghabiskan waktu saya untuk memperbaiki kode Anda beberapa kali karena duplikat tidak efisien dan menjengkelkan. Saya harus mengerjakan kode saya sendiri 18 tahun setelah saya menulisnya dan setiap kesalahan bahasa yang saya buat membuat hidup saya jauh lebih sulit. redundansi adalah salah satu kesalahan mengerikan yang saya bayar pada akhirnya.
David Rector