Memisahkan proyek java

12

Saya punya proyek java yang besar, dan kami menggunakan maven untuk siklus build kami. Proyek yang satu ini digunakan secara luas - dalam proyek lain, dalam berbagai aplikasi, beberapa di antaranya terkandung di dalamnya dan beberapa yang lain ... Sejujurnya, ini sedikit berantakan (berbagai bit ditambahkan pada waktu yang berbeda untuk spesifik tujuan), dan saya ingin membersihkannya sedikit. Juga, itu tidak sepenuhnya diuji (banyak bit telah ditambahkan tanpa unit yang tepat dan pengujian integrasi), dan ada beberapa tes yang membutuhkan waktu lama untuk berjalan atau tidak benar-benar lulus ... (uh-oh) - jadi tes dimatikan dalam siklus pembuatan pakar (sekali lagi, uh-oh).

Saya berpikir untuk memisahkan proyek besar ini menjadi proyek spesifik yang lebih kecil, sehingga sub-proyek 'final' (atau beberapa sub-proyek) akan mengambil berbagai sub-proyek yang diperlukan.

Pemikiran saya adalah sebagai berikut:

  • jika saya memisahkan proyek besar ke dalam berbagai sub proyek, ini menjelaskan apa yang menjadi tanggung jawab masing-masing proyek.
  • dengan memisahkan menjadi sub-proyek, saya kemudian dapat membersihkan pengujian masing-masing sub-proyek secara individual, dan mengaktifkan pengujian untuk sub-proyek dalam siklus pembangunan pakar.

Saya sedikit khawatir tentang apa dampak ini pada waktu pembangunan.

  • Apakah memaksakan struktur pada proyek besar (yaitu menjadi sub proyek yang lebih kecil) memperlambat kompilator?

Juga, saya memiliki sedikit kekhawatiran tentang dampak apa yang mungkin terjadi pada waktu pengeditan dalam IDE (kami terutama menggunakan Intellij). Intellij tampaknya membangun setiap proyek secara bergiliran melalui pohon dependensi - yaitu jika C bergantung pada B bergantung pada A, dan saya mengubah A, ia tidak akan mencoba membangun B kecuali A mengkompilasi, dan seterusnya. Bisa dibilang itu menguntungkan, tetapi saya telah menemukan bahwa jika - misalnya, saya mengubah antarmuka dalam A yang banyak digunakan dalam B dan C, perlu beberapa waktu untuk memperbaiki semua kesalahan dari perubahan itu ...

Pertanyaan lain adalah bagaimana menggunakan kelas pabrik. Beberapa aspek proyek tergantung pada guci eksternal. Kadang-kadang (untungnya tidak sering) ini diperbarui, dan kami harus bermigrasi. Kami cenderung menangani ini dengan menggunakan kelas Pabrik yang menunjuk ke versi yang benar dari kode eksternal (jadi kami tidak harus mengubah semua implementasi di seluruh basis kode).

Saat ini semua ada dalam proyek besar, tetapi saya berpikir bahwa dengan beralih ke sub proyek, saya dapat mengembangkan proyek baru untuk penerapan kode eksternal baru, memastikan bahwa sub-proyek berfungsi penuh dan teruji, dan kemudian alihkan dependensi / kelas pabrik di proyek pengguna. Namun, ini menjadi lebih rumit dengan penggunaan antarmuka yang luas di seluruh proyek besar. Sebagai contoh

  • sub-proyek A - berisi antarmuka
  • sub-proyek B - tergantung pada A untuk antarmuka dan tabung eksternal lama
  • sub-proyek C - tergantung pada B (dan dengan demikian A dan jar eksternal lama), dan berisi kelas Pabrik yang menggunakan implementasi antarmuka B

Jika saya perlu mengganti tabung eksternal B, saya dapat:

  • buat sub-proyek B_ii - lagi tergantung pada A, dan sekarang jar eksternal baru
  • setelah berfungsi penuh, saya dapat menambahkan ketergantungan C ke B_ii, dan mengubah kelas Pabrik untuk menggunakan implementasi antarmuka baru.
  • ketika itu semua berfungsi, saya kemudian dapat menghapus ketergantungan C ke B asli, dan jika diinginkan, hapus sub-proyek B.

  • Apakah itu cara yang masuk akal untuk melakukan ini?

Jadi, secara umum, pertanyaan saya adalah:

  • Apakah ada yang punya pengalaman memecah proyek besar? Apakah ada tips / trik yang ingin Anda bagikan?
  • Apa dampak ini terhadap perkembangan dan waktu pembangunan Anda?
  • Apa saran yang bisa Anda tawarkan untuk menyusun proyek yang seperti itu?
keheranan
sumber
Perhatikan bahwa Anda dapat membuat proyek induk dengan A, B, dan C yang secara terpisah diperiksa bersebelahan. Ini memungkinkan misalnya IntelliJ untuk memiliki ketiganya dalam memori pada saat yang sama, dan melakukan refactoring melintasi batas-batas modul.
Thorbjørn Ravn Andersen

Jawaban:

10

Saya akan mengambil langkah cepat pertama di ini (Q BTW hebat!):

Apakah memaksakan struktur pada proyek besar (yaitu menjadi sub proyek yang lebih kecil) memperlambat kompilator?

Tidak cukup bahwa itu penting, overhead sebenarnya dalam doa Maven.

Juga, saya memiliki sedikit kekhawatiran tentang dampak apa yang mungkin terjadi pada waktu pengeditan dalam IDE (kami terutama menggunakan Intellij). Intellij tampaknya membangun setiap proyek secara bergiliran melalui pohon dependensi - yaitu jika C bergantung pada B bergantung pada A, dan saya mengubah A, ia tidak akan mencoba membangun B kecuali A mengkompilasi, dan seterusnya. Bisa dibilang itu menguntungkan, tetapi saya telah menemukan bahwa jika - misalnya, saya mengubah antarmuka dalam A yang banyak digunakan dalam B dan C, perlu beberapa waktu untuk memperbaiki semua kesalahan dari perubahan itu ...

IDE yang berbeda memiliki kekuatan yang berbeda berkaitan dengan binding Maven dan manajemen dependensi. Kondisi permainan saat ini tampaknya sebagian besar hanya bekerja pada Eclipse, Netbeans, dan IntelliJ terbaru - tetapi Anda harus mengajari pengembang Anda tentang double darurat dari "Refresh file sumber dari disk dan membangun kembali semua proyek pakar terkait".

Saya merasa saya harus melakukan itu semakin sedikit hari ini. Memiliki drive SSD membuat perbedaan besar di sini BTW.

paragraf kelas pabrik snip

Manajemen ketergantungan sangat penting, terlepas dari teknologi apa (Maven / Ivy / apa pun) gunakan untuk membantu Anda menerapkannya.

Saya akan mulai dengan mengeluarkan laporan ekstensif dari plugin ketergantungan Maven dan memeriksa apa yang Anda miliki. Secara umum Anda mengatur ketergantungan dalam pengelolaan ketergantungan POM setinggi mungkin dalam rantai makanan, tetapi tidak lebih tinggi. Jadi jika dua submodul Anda menggunakan dependensi eksternal, maka masukkan itu ke POM induknya dan seterusnya dan seterusnya.

Meningkatkan JAR eksternal harus selalu dilakukan sebagai proyek mini yang tepat. Mengevaluasi mengapa Anda meningkatkan, mengubah kode sumber untuk mengambil keuntungan dari semua fitur baru / perbaikan bug dll. Hanya menabrak versi tanpa analisis ini dan pekerjaan akan membuat Anda mendapat masalah.

Jadi, secara umum, pertanyaan saya adalah:

Apakah ada yang punya pengalaman memecah proyek besar? Apakah ada tips / trik yang bersedia Anda bagikan?

  • Antarmuka dan injeksi Ketergantungan adalah teman Anda.
  • Buku Michael Feather tentang cara menangani kode warisan secara efektif adalah wajib dibaca.
  • Tes integrasi adalah teman Anda
  • Memisahkan sub proyek menjadi foo-api (hanya antarmuka!) Dan foo-core dan memiliki modul hanya bergantung pada foo-api membantu banyak dan menegakkan pemisahan
  • Modul Jboss dan / atau OSGi dapat membantu menegakkan pemisahan yang bersih

Apa dampak ini terhadap perkembangan dan waktu pembangunan Anda?

Dampak yang sangat kecil pada waktu pengembangan dan pengembangan - peningkatan besar dalam waktu untuk keseluruhan pipa pengiriman berkelanjutan kami.

Apa saran yang bisa Anda tawarkan untuk menyusun proyek yang seperti itu?

Lakukan hal-hal kecil dengan benar dan hal-hal besar cenderung rontok dengan bersih sesudahnya. Jadi bagilah hal-hal sedikit demi sedikit - jangan melakukan restrukturisasi besar-besaran dari keseluruhan kecuali Anda memiliki persentase cakupan yang tinggi dengan tes integrasi Anda.

Tulis tes integrasi sebelum perpecahan - Anda harus mendapatkan hasil yang kurang lebih sama setelah split.

Gambar diagram modularitas yang Anda miliki sekarang dan di mana Anda ingin pergi. Desain langkah menengah.

Jangan menyerah - beberapa pencukur Yak sekarang membangun fondasi untuk bisa "membangun dan refactor dengan cepat tanpa rasa takut" plug Shameless -> dari Ben and I The Java-Welled Grounded Developer .

Semoga berhasil!

Martijn Verburg
sumber
0

Pendapat saya tentang ini hanya terpisah bila perlu. Namun, itu memunculkan pertanyaan berikutnya: Bagaimana saya menentukan apakah perlu?

  • Ketika artefak berbeda (yaitu jangan membangun EAR, WAR, JAR, tabung pengujian integrasi dalam proyek yang sama).
  • Ketika selama pemisahan Anda melihat bahwa beberapa kode perlu ada di lebih dari satu artefak, refactor mereka menjadi yang baru.
  • Ketika beberapa proyek lain di luar tim Anda ingin menggunakan sesuatu yang Anda miliki dalam proyek Anda.

Salah satu alasannya adalah pengembang harus berurusan dengan banyak proyek dan mencoba mencari tahu selain dari paket Java apa proyek itu seharusnya. Saya telah mengerjakan proyek-proyek di mana ia menjadi sangat anemia dan memiliki proyek yang hanya memiliki empat kelas yang menerapkan satu fungsi hanya karena itulah arahan arsitekturnya. Ini juga kembali sebelum Maven populer sehingga jalur kelas dan apa yang tidak perlu diatur pada skrip IDE dan Ant.

Alasan lainnya adalah Anda akan memiliki lebih banyak bagian yang bergerak untuk ditangani dalam hal menyalurkan file-file di sekitar dan kemungkinan Anda akan memiliki spageti ketergantungan sebelum Anda menyadarinya.

Refactoring juga lebih mudah di dalam proyek daripada lintas proyek.

Jika build time adalah masalah maka cukup sediakan perangkat keras yang lebih baik.

Archimedes Trajano
sumber