Apa cara paling efektif untuk membagikan kode antara aplikasi .NET?

15

Dalam pekerjaan kami, kami memiliki beberapa aplikasi .net yang berbeda yang berbagi banyak fungsi dasar. Kami telah membangun aplikasi ini menggunakan arsitektur n-tier yang bersih, tetapi kami telah mencapai saat di mana kami menyadari bahwa kami telah mengimplementasikan kembali fungsi yang sama beberapa kali berbeda. Jelas ini melanggar KERING, dan kami ingin memperbaikinya. Kami sudah menggunakan Nuget untuk beberapa keberhasilan untuk kode lem umum (memasang IoC, logging, pengaturan), tetapi kami juga ingin berbagi data dan lapisan bisnis antara semua aplikasi kami. Idenya adalah bahwa UI hanya akan berurusan dengan bagian-bagian dari lapisan bisnis yang sebenarnya dibutuhkan.

Ini kelihatannya seperti masalah langsung pada awalnya, tetapi pengembangan yang sedang berlangsung dapat memberikan beberapa jebakan dan kami tidak yakin bagaimana untuk melanjutkan. Katakanlah kita membuat Satu Lapisan Bisnis Kita untuk Mengatur Mereka Semua. Untuk singkatnya, saya akan menyebutnya "Yayasan." Kami port aplikasi kami untuk menggunakan Yayasan, dan semuanya berjalan baik. Yayasan ini didistribusikan ke lapisan UI ringan melalui nuget, dan kami terlihat bagus. Tapi kemudian kami mulai menambahkan fitur ke aplikasi kami, dan kami mengalami masalah.

Katakanlah kita sedang mengerjakan Proyek A dan kami menambahkan fitur baru yang membutuhkan perubahan pada Foundation. Kami membuat perubahan pada fondasi (Foundation-A) dan mendorongnya ke umpan nuget sebagai paket yang tidak stabil. Proyek A mendapatkan paket nuget terbaru, dan semuanya baik-baik saja. Sementara itu, pengembang lain sedang mengerjakan Proyek B. Dia mendapatkan Yayasan terbaru dari kontrol sumber, tetapi mengambilnya dari cabang stabil, sehingga tidak memiliki perubahan Proyek A di dalamnya. Dia membuat perubahan dan menciptakan Foundation-B. Dan semuanya baik-baik saja. Tetapi kemudian kami menemukan bahwa fungsi implementasi Foundation-A dan Foundation-B yang benar-benar dapat membagikan kode, jadi kami menggabungkannya. Sementara itu Foundation-C mengambang di sana dengan perubahannya sendiri. Akhirnya, Foundation-B siap untuk diproduksi, jadi kami mendorongnya. Tapi kemudian kita perlu memperbarui Produksi A, B,

Sepertinya ini bisa berhasil, tetapi kami khawatir tentang bekerja dengan skema basis data yang berbeda dan menjaga semuanya disinkronkan antara berbagai cabang repositori Foundation serta repositori Proyek A, B, dan C. Sepertinya mungkin akan membutuhkan banyak pekerjaan manual, yang membuka kemungkinan kesalahan. Saya ingin ini seotomatis mungkin.

Inilah tumpukan yang kami gunakan: C #, TFS dengan Continuous Integration, Nuget. Aplikasi kami adalah semua jenis aplikasi ASP.NET. Kami bersedia melihat berbagai SCM jika itu akan membuat segalanya lebih mudah.

Saya mencari cara untuk menjaga Nuget tetap waras dengan cabang kode sumber kami yang berbeda. Kami tidak ingin secara tidak sengaja mendorong kode pengembangan ke dalam produksi karena kami merujuk pada Paket Nuget yang salah.

Josh
sumber
Juga, jika ini bukan forum yang bagus untuk diskusi seperti ini, dapatkah seseorang menyarankan yang lebih baik?
Josh

Jawaban:

9

Kami membuat perubahan pada fondasi (Foundation-A) dan mendorongnya ke umpan nuget sebagai paket yang tidak stabil.

Di sinilah masalah Anda dimulai ... Jangan lakukan itu.

Setiap perubahan pada Foundation v1.0 secara inheren harus bernilai bagi semua konsumen Foundation, jika tidak, itu bukan milik Foundation. Jadi, ketika membuat paket nuget, lakukan itu sebagai versi Foundation yang resmi dan stabil (mis. V1.1), atau jangan lakukan itu sama sekali.

Proyek B harus membangun perangkat tambahan Foundation seperti biasanya, tetapi (dengan cara manajemen sumber yang baik) harus menggabungkan perubahan trunk (v1.1) sebelum mendorong Foundation yang stabil (v1.2) ke nuget.

Proyek-proyek lain yang dapat menggunakan perangkat tambahan Foundation dapat memutakhirkan referensi nuget mereka jika perlu, atau tetap menggunakan versi yang lebih lama jika diperlukan.

Saya setuju dengan @Giedrius ; bagi saya ini tampaknya lebih sebagai masalah kontrol sumber / percabangan dalam arti bahwa jika percabangan / penggabungan Yayasan ditangani dengan benar, masalah manajemen paket menjadi diperdebatkan.

Eric King
sumber
Ya, ini masuk akal. Masalahnya ada di aplikasi praktis. Saat Anda melakukan pembaruan untuk Foundation untuk v1.1 Anda ingin menggunakan perubahan itu di Project B saat Anda sedang mengembangkan. Jika cara Anda membagikan kode tersebut adalah melalui nuget, maka opsi Anda adalah: 1) Publikasikan paket nuget baru, atau 2) Secara manual salin dll. Tak satu pun dari ini sepertinya pilihan yang baik.
Josh
Beberapa di antaranya dapat dikurangi dengan memiliki rangkaian uji yang efektif, tetapi masih akan bolak-balik saat Anda menambahkan fitur.
Josh
@Josh Ya, pembaruan untuk Foundation harus lengkap dan dapat diuji, terlepas dari bagaimana Proyek B akan menggunakannya (karena mereka pergi ke perpustakaan bersama), jadi 'publikasikan paket nuget baru' adalah cara alami untuk pergi. Jangan impor dan gunakan Foundation v.Berikutnya di Project B sampai paket stabil di nuget. Dibutuhkan sedikit disiplin, tetapi jauh lebih baik daripada kekacauan melakukannya sebaliknya.
Eric King
1
Saya benar-benar mengerti apa yang Anda katakan, tetapi saya pikir itu tidak realistis. Ketika Anda mengembangkan fitur, bahkan jika Anda memiliki semua logika bisnis dan lapisan akses data sepenuhnya diuji, akan ada modifikasi sebelum didorong ke produksi. Mungkin Anda menyadari bahwa Anda perlu menambahkan properti lain ke logika bisnis, atau pemilik produk kembali dengan perubahan atau klarifikasi. Mungkin beberapa asumsi penyederhanaan Anda salah. Ini adalah hal-hal yang terjadi setiap saat. Jika Anda terbatas untuk mengunci logika basis Anda, sepertinya memang sangat terbatas.
Josh
2
Karena kami telah melakukan ini selama beberapa bulan, ini pada dasarnya adalah apa yang kami setujui. Saya pikir saya terlalu khawatir memiliki proses formal. Begitu kami mulai benar-benar mengerjakannya, segalanya berakhir dengan sangat lancar. Terima kasih atas masukan Anda.
Josh
4

Ubah kode duplikat Anda menjadi fungsi yang berlaku secara lebih abstrak, dan masukkan ke pustaka atau kerangka kerja mereka sendiri. Buat mereka longgar digabungkan dan arsitektur-agnostik, dan Anda seharusnya tidak pernah memiliki masalah. Jika Anda membutuhkan inspirasi, pelajari bagaimana .NET framework mengabstraksi konsep menggunakan hal-hal seperti antarmuka, generik, dan pola perangkat lunak seperti Dispose().

Juga, ingat bahwa tidak semua kode duplikat benar-benar digandakan; beberapa di antaranya adalah kode lem atau kode yang jika tidak diperlukan untuk mempertahankan arsitektur, jadi jangan terobsesi menjadi terlalu KERING.

Robert Harvey
sumber
Mungkin saya tidak sejelas mungkin dalam pertanyaan saya. Ini tentang apa yang terjadi selanjutnya. Anda telah melakukan semua itu, dan sekarang Anda perlu membagikan kode Anda secara efektif di antara berbagai proyek Anda. Seseorang berkata "cukup gunakan nuget untuk itu" dan kedengarannya hebat sampai Anda masuk ke detail dan mengalami masalah - seperti cara menyinkronkan perubahan yang berbeda dari berbagai cabang dan aplikasi.
Josh
Ya, saya setuju dengan Eric King. Kode fondasi harus didorong sebagai versi stabil, bukan yang tidak stabil. Kuncinya adalah mempertahankan API yang stabil: jika Anda tahu tanda tangan metode pondasi Anda tidak akan berubah, Anda dapat dengan aman mendorong metode-metode tersebut ke Foundation dan melakukan refactor nantinya tanpa merusak apa pun.
Robert Harvey
4

Penggunaan Kembali Kode

Ada beberapa pendekatan untuk menggunakan kembali kode yang mendapat dukungan selama bertahun-tahun. Setiap pendekatan memiliki tempatnya, dan yang lebih penting adalah masalahnya , tetapi cara yang layak untuk menggunakan kembali kode di .NET adalah:

  1. Perpustakaan Umum. Kode yang diperlukan di lebih dari satu tempat dimasukkan ke dalam perpustakaan umum, dan semua bagian lain dari basis kode kemudian memiliki referensi tunggal untuk kode ini. Kelemahan prinsipnya adalah bahwa Anda berakhir dengan sebagian besar proyek Anda tergantung pada perpustakaan ini yang berisi banyak fungsi yang tidak terkait. Ini adalah ide yang buruk dari aspek jaminan kualitas.

  2. Kode Sumber Umum. Kode yang diperlukan di lebih dari satu tempat dituliskan sekali dan ditempatkan di file sumber dalam struktur direktori umum. Semua proyek yang memerlukan kode ini kemudian memasukkan file ini sebagai salah satu file sumbernya. Ini memberikan penggunaan kembali kode, dan keuntungan menulis sekali, gunakan banyak. Namun. Kelemahannya adalah menjadi mungkin untuk memiliki bagian-bagian berbeda dari proyek yang dikompilasi dengan versi berbeda dari kode ini - yang dapat memperkenalkan beberapa cacat halus yang bisa sangat sulit untuk dideteksi dan diidentifikasi dengan jaminan kualitas.

  3. Layanan. Kode umum diimplementasikan sebagai layanan, yang dapat diakses oleh aspek lain. Ini memiliki keuntungan bahwa akan ada satu layanan dalam penyebaran, dan menghindari ketergantungan. Namun itu akan memperkenalkan latensi dan kegagalan. Pendekatan semacam ini bekerja dengan baik pada produk-produk yang didistribusikan besar di mana ketersediaan tinggi dan toleransi kesalahan sudah dipahami dan dikelola.

Mengelola NuGET

Di sini Anda memiliki masalah yang jauh lebih menarik. Mengelola banyak konfigurasi. Saran saya di sini adalah untuk tidak mengelola basis pelanggan yang beragam dengan versi kode yang berbeda, tetapi dengan file konfigurasi. Setidaknya ada 3 lapisan data konfigurasi untuk dikelola. Konfigurasi produk dasar (internal) yang tidak pernah dilihat pelanggan. Opsi konfigurasi default yang dapat diubah pelanggan Anda dan lapisan terakhir opsi konfigurasi yang telah diubah pelanggan Anda. Dengan memisahkan lapisan-lapisan yang berbeda ini Anda akan dapat meluncurkan peningkatan tanpa merusak konfigurasi pelanggan Anda.

Michael Shaw
sumber
1

Saya pikir masalahnya bukan pada nuget / kontrol sumber / percabangan, tetapi dalam apa yang tergelincir ke dalam kode lem.

Robert memiliki jawaban yang bagus, hanya untuk melihat gambaran keseluruhannya, saya sarankan untuk memikirkan dependensi apa yang akan dibawa utilitas umum ini ke dalam setiap proyek:

http://ayende.com/blog/3986/let-us-burn-all-those-pesky-util-common-libraries http://blog.jordanterrell.com/post/CommonUtility-Libraries-Dead.aspx

Cara terbaik untuk menghindari neraka yang Anda alami adalah dengan membuka kode lem Anda. Sedemikian rupa Anda akan mulai peduli, bahwa tidak ada logika bisnis yang akan dipublikasikan, sehingga tidak ada ketergantungan proyek konkret akan tergelincir ke dalam kode lem, bahwa itu akan cukup abstrak untuk digunakan kembali oleh siapa pun, bahkan di luar perusahaan Anda - dan jika itu melekat kode akan cukup baik - Anda juga akan mendapat masukan dari komunitas.

Giedrius
sumber
Saya tidak berbicara tentang mengelola kode lem. Kami sudah punya solusi untuk itu dan berfungsi dengan baik. Saya berbicara tentang berbagi logika bisnis. Misalnya, aplikasi kami berurusan dengan mengelola organisasi dan orang. Jadi, kita perlu buat seseorang, dan ada banyak aturan bisnis yang terkait dengan bagaimana seseorang harus dibuat. Daripada membuatnya beberapa kali, kami ingin memiliki satu paket yang menangani semuanya, mulai dari membangun objek hingga bertahan, yang kami bagikan di antara berbagai proyek yang berbeda yang perlu menciptakan manusia
Josh
0

Solusinya sederhana: buat proyek terpisah untuk itu, dan kelola sebagai hal yang terpisah: itu persyaratan sendiri, pengujian, konvensi, dokumentasi, perencanaan, orang, dll. Dengan cara ini, Anda memastikan bahwa kualitas tetap tinggi dan kemungkinan perubahan yang merusak akan didapat dievaluasi terlebih dahulu sebelum mereka membuat masalah.

Atau bahkan lebih baik: jadikan "sumber terbuka" di dalam organisasi Anda. Jadi siapa pun dapat mengubah kode, tetapi hanya beberapa orang terpilih yang memiliki hak komit penuh. Dan orang-orang itu akan bertanggung jawab untuk memastikan kualitas dan fitur yang benar.

Euforia
sumber