Bagaimana cara menjaga produk perangkat lunak yang besar dan kompleks dapat dipelihara selama bertahun-tahun?

156

Saya telah bekerja sebagai pengembang perangkat lunak selama bertahun-tahun sekarang. Sudah pengalaman saya bahwa proyek menjadi lebih kompleks dan tidak dapat dipelihara karena semakin banyak pengembang yang terlibat dalam pengembangan produk.

Tampaknya perangkat lunak pada tahap pengembangan tertentu memiliki kecenderungan untuk menjadi "peretas" dan "peretas" terutama ketika tidak ada anggota tim yang mendefinisikan pekerjaan arsitektur di perusahaan lagi.

Saya merasa frustasi bahwa seorang pengembang yang harus mengubah sesuatu mengalami kesulitan mendapatkan gambaran besar dari arsitektur. Oleh karena itu, ada kecenderungan untuk memperbaiki masalah atau membuat perubahan dengan cara yang bertentangan dengan arsitektur asli. Hasilnya adalah kode yang semakin kompleks dan bahkan lebih sulit untuk dipahami.

Apakah ada saran yang bermanfaat tentang cara menjaga kode sumber benar-benar dapat dipertahankan selama bertahun-tahun?

chrmue
sumber
9
buku yang sangat direkomendasikan: 'Software Project Survival Guide' oleh Steve McConnell, 'Rapid Development' oleh Steve McConnell, 'Refactoring' oleh Martin Fowler
Imran Omar Bukhsh
15
... dan 'Kode Bersih' oleh Paman Bob;) (Robert C. Martin)
Gandalf
34
Tidakkah ini mempertanyakan sesuatu yang telah menghasilkan bacaan berat dan seluruh kursus di universitas selama beberapa dekade?
Detly
17
@Eric Yin - Saya tidak setuju dengan komentarnya. Bagi saya mereka adalah bau kode dan dalam proyek jangka panjang cenderung lebih berbahaya daripada kebaikan karena mereka pasti mendapatkan tanggal dan menjadi menyesatkan.
JohnFx
8
@Eric Yin: berusaha keras untuk mendokumentasikan kode diri. Gunakan komentar dengan niat hanya di mana mereka meningkatkan pemahaman.
Mitch Wheat

Jawaban:

138

Satu-satunya solusi nyata untuk menghindari pembusukan kode adalah kode dengan baik!

Cara kode dengan baik adalah pertanyaan lain. Cukup sulit bahkan jika Anda seorang programmer yang hebat bekerja sendirian. Dalam tim yang heterogen, masih jauh lebih sulit. Dalam proyek (sub) outsourcing ... hanya berdoa.

Praktik baik yang biasa dapat membantu:

  1. Tetap sederhana.
  2. Tetap sederhana. Ini berlaku terutama untuk arsitektur, "gambaran besar". Jika pengembang mengalami kesulitan untuk mendapatkan gambaran besar, mereka yang akan kode menentangnya. Jadi buat arsitekturnya sederhana sehingga semua pengembang mendapatkannya. Jika arsitektur harus kurang dari sederhana, maka pengembang harus dilatih untuk memahami arsitektur itu. Jika mereka tidak menginternalisasi itu, maka mereka tidak boleh kode di dalamnya.
  3. Bertujuan untuk kopling rendah dan kohesi tinggi . Pastikan semua orang di tim memahami ide ini. Dalam sebuah proyek yang terdiri dari bagian-bagian kohesif yang digabungkan secara longgar, jika beberapa bagian menjadi berantakan yang tidak dapat dipelihara, Anda dapat mencabut dan menulis ulang bagian itu. Lebih sulit atau hampir tidak mungkin jika koplingnya kencang.
  4. Bersikaplah konsisten. Standar mana yang mengikuti sedikit hal, tapi tolong ikuti beberapa standar. Dalam sebuah tim, setiap orang harus mengikuti standar yang sama tentunya. Di sisi lain, mudah untuk menjadi terlalu terikat dengan standar dan melupakan yang lain: tolong mengerti bahwa meskipun standar bermanfaat, mereka hanya sebagian kecil dari membuat kode yang baik. Jangan menghasilkan jumlah yang besar.
  5. Ulasan kode mungkin berguna untuk membuat tim bekerja secara konsisten.
  6. Pastikan bahwa semua alat - IDE, kompiler, kontrol versi, sistem bangun, generator dokumentasi, perpustakaan, komputer , kursi , lingkungan keseluruhan dll. - dipelihara dengan baik sehingga pengembang tidak perlu membuang waktu mereka dengan masalah sekunder seperti seperti melawan konflik versi file proyek, pembaruan Windows, kebisingan dan hal-hal sepele apa pun yang menjengkelkan. Harus berulang kali membuang-buang waktu dengan hal-hal yang tidak menarik seperti menurunkan moral, yang setidaknya tidak akan meningkatkan kualitas kode. Dalam tim besar, mungkin ada satu atau lebih orang yang tugas utamanya adalah memelihara alat pengembang.
  7. Saat membuat keputusan teknologi, pikirkan apa yang diperlukan untuk beralih teknologi; keputusan mana yang tidak dapat diubah dan mana yang tidak. Mengevaluasi keputusan yang tidak dapat diubah dengan sangat hati-hati. Misalnya, jika Anda memutuskan untuk menulis proyek di Jawa , itu adalah keputusan yang tidak dapat diubah. Jika Anda memutuskan untuk menggunakan beberapa format biner yang direbus sendiri untuk file data, itu juga merupakan keputusan yang tidak dapat dibalikkan (begitu kode keluar di alam bebas dan Anda harus tetap mendukung format itu). Tapi warna GUI dapat dengan mudah disesuaikan, fitur yang awalnya ditinggalkan dapat ditambahkan kemudian, jadi lebih sedikit menekankan tentang masalah tersebut.
Joonas Pulakka
sumber
8
Ini adalah poin yang bagus. Saya harus mengakui bahwa saya berjuang dengan "tetap sederhana". Tampaknya hal itu berbeda artinya bagi orang yang berbeda dalam konteks yang berbeda, yang membuat "sederhana" agak rumit (tetapi kemudian saya memang memiliki kecenderungan alami untuk menyulitkan hal-hal).
Kramii
3
Saya sangat setuju dengan poin Anda, terutama "KIS". Tapi saya melihat kecenderungan bahwa semakin banyak (lebih muda?) Pengembang menggunakan struktur yang agak rumit untuk menggambarkan bahkan konteks yang paling sederhana.
chrmue
10
@ chrmue: Lihat "cara menulis faktorial di Jawa" ;-)
Joonas Pulakka
8
Umm, dan "8. Tetap sederhana".
Dawood ibn Kareem
7
# 6 layak +10.
Jim G.
55

Tes unit adalah teman Anda . Menerapkannya memaksa kopling rendah. Ini juga berarti bahwa bagian-bagian "peretasan" dari program dapat dengan mudah diidentifikasi dan di-refactored. Ini juga berarti bahwa setiap perubahan dapat diuji dengan cepat untuk memastikan mereka tidak merusak fungsi yang ada. Ini harus mendorong pengembang Anda untuk memodifikasi metode yang ada daripada menduplikasi kode karena takut merusak.

Tes unit juga berfungsi sebagai sedikit tambahan dokumentasi untuk kode Anda, menguraikan apa yang harus dilakukan setiap bagian. Dengan tes unit yang luas, programmer Anda tidak perlu mengetahui seluruh arsitektur program Anda untuk membuat perubahan dan menggunakan kelas / metode yang ada.

Sebagai efek samping yang bagus, unit test juga diharapkan akan mengurangi jumlah bug Anda.

Tom Squires
sumber
3
Poin yang sangat penting. Saya mengambil alih sistem warisan, banyak kelas, banyak baris kode, tidak ada dokumentasi, tidak ada tes unit. Setelah dengan rajin membuat unit test untuk semua perbaikan dan peningkatan kode, desain sistem telah berevolusi menjadi kondisi yang lebih bersih dan lebih dapat dipertahankan. Dan kami memiliki "keberanian" untuk menulis ulang bagian inti yang penting (dicakup oleh unit test).
Sam Goldberg
40

Semua orang di sini cepat menyebutkan kode busuk , dan saya benar-benar mengerti dan setuju dengan ini, tetapi masih merindukan gambaran yang lebih besar dan masalah yang lebih besar di sini. Busuk kode tidak terjadi begitu saja. Selanjutnya, tes unit disebutkan mana yang baik, tetapi mereka tidak benar-benar mengatasi masalah tersebut. Seseorang dapat memiliki cakupan tes unit yang baik dan kode relatif bebas bug, namun masih memiliki kode dan desain yang membusuk.

Anda menyebutkan bahwa pengembang yang mengerjakan proyek mengalami kesulitan menerapkan fitur dan melewatkan gambaran yang lebih besar dari keseluruhan arsitektur, dan dengan demikian mengimplementasikan peretasan ke dalam sistem. Di mana kepemimpinan teknis untuk menegakkan dan mempengaruhi desain? Di mana ulasan kode dalam proses ini?

Anda sebenarnya tidak menderita busuk kode, tetapi Anda menderita busuk tim . Faktanya adalah bahwa tidak masalah jika pencipta asli perangkat lunak tidak lagi berada di tim. Jika pemimpin teknis dari tim yang ada sepenuhnya dan benar-benar memahami desain yang mendasarinya dan bagus dalam perannya sebagai pemimpin teknologi, maka ini bukan masalah.

maple_shaft
sumber
Poin yang sangat bagus, Anda berhasil! Sedih untuk dikatakan, tetapi itulah yang terjadi di sini. Dan tampaknya mustahil untuk mengubah banyak hal tanpa dukungan teknologi ...
chrmue
4
@ Chrmue Persis seperti yang saya kira, tapi saya mulai bosan. Dalam banyak hal saya berharap saya adalah pengembang junior lagi ketika saya tidak begitu menyadari betapa salahnya segala sesuatu di sekitar saya. Sepertinya saya memukul krisis pertengahan karir saya lebih awal. Tapi saya mengoceh ... senang bisa membantu.
maple_shaft
1
@Murph Mengapa Anda tidak harus memiliki pemimpin tim yang tahu segalanya selama fase Pemeliharaan? Setiap bos yang pernah saya harapkan tidak kurang dari pimpinan tim, dan ketika saya menjadi pemimpin tim saya berharap tidak kurang dari saya sendiri.
maple_shaft
1
@maple_shaft karena a) Saya tidak berasumsi bahwa ada pemimpin tim yang didedikasikan untuk satu proyek dan itu lebih atau kurang persyaratan pertama dan b) Saya pikir Anda perlu memahami desain dan implementasi (semuanya) dan itu keras. Di satu sisi kita semua berpendapat bahwa kita seharusnya tidak memiliki font tunggal dari semua pengetahuan tentang proyek-proyek kita, tetapi di sini kita mengatakan bahwa kita harus memilikinya? Itu tidak masuk akal?
Murph
2
@maple_shaft mungkin saya menjadi pemrogram tua yang pemarah (-: Tapi ada masalah karena sering menerapkan "gaya" yang perlu diikuti jauh di dalam basis kode yang ada - dan yang mungkin asing bagi coder dan lead (untuk banyak alasan dunia nyata)
Murph
18

Ada beberapa hal yang bisa kita lakukan:

Berikan satu orang tanggung jawab keseluruhan untuk arsitektur. Ketika memilih orang itu, pastikan mereka memiliki visi dan keterampilan untuk mengembangkan dan memelihara arsitektur, dan bahwa mereka memiliki pengaruh dan wewenang untuk membantu pengembang lain mengikuti arsitektur. Orang itu harus menjadi pengembang berpengalaman yang dipercaya oleh manajemen dan yang dihormati oleh rekan-rekan mereka.

Buat budaya di mana semua pengembang mengambil kepemilikan arsitektur. Semua pengembang perlu dilibatkan dalam proses pengembangan dan pemeliharaan integritas arsitektur.

Mengembangkan lingkungan di mana keputusan arsitektur mudah dikomunikasikan. Dorong orang untuk berbicara tentang desain dan arsitektur - tidak hanya dalam konteks proyek saat ini, tetapi secara umum juga.

Praktik pengkodean terbaik membuat arsitektur lebih mudah dilihat dari kode - luangkan waktu untuk refactor, komentar kode, untuk mengembangkan tes unit, dll. Hal-hal seperti konvensi penamaan dan praktik pengkodean yang bersih dapat banyak membantu dalam berkomunikasi arsitektur, sehingga sebagai tim yang Anda butuhkan meluangkan waktu untuk mengembangkan dan mengikuti standar Anda sendiri.

Pastikan semua dokumentasi yang diperlukan jelas, ringkas, terkini dan mudah diakses. Jadikan diagram arsitektur tingkat tinggi dan rendah agar publik (menyematkannya ke dinding dapat membantu) dan dapat dipertahankan secara publik.

Akhirnya (sebagai perfeksionis alami) saya perlu mengakui bahwa integritas arsitektur adalah aspirasi yang layak, tetapi bahwa ada hal-hal yang lebih penting - seperti membangun tim yang dapat bekerja sama dengan baik dan benar-benar mengirimkan produk yang berfungsi.

Kramii
sumber
1
+1, terutama untuk "membangun tim yang dapat bekerja dengan baik bersama dan benar-benar mengirimkan produk yang berfungsi."
deworde
1
Itu ide yang baik untuk memiliki satu orang menjadi root yang bertanggung jawab untuk arsitektur. Namun Anda memiliki "bau tim" jika tanggung jawab itu sering digunakan: Tim secara alami harus mencapai kesimpulan yang sama, alih-alih mengandalkan satu orang untuk memberikan jawaban. Mengapa? Pengetahuan total dari proyek ini selalu dibagikan, menyematkannya pada satu orang akan menyebabkan masalah yang lebih besar pada akhirnya: Hanya pandangannya yang puas, secara efektif memotong sayap dari seluruh tim. Alih-alih pekerjakan orang-orang terbaik dan biarkan mereka bekerja bersama.
casper
1
@casper: Tepat. Anda mengungkapkan apa yang ada dalam pikiran saya lebih baik daripada saya.
Kramii
18

Cara saya mengatasi masalah ini adalah dengan memotongnya di root:

Penjelasan saya akan menggunakan istilah dari Microsoft / .NET , tetapi akan berlaku untuk platform / kotak alat apa pun:

  1. Gunakan standar untuk penamaan, pengkodean, checkin, aliran bug, aliran proses - pada dasarnya apa saja.
  2. Jangan takut untuk mengucapkan selamat tinggal kepada anggota tim yang tidak mematuhi standar. Beberapa pengembang tidak bisa bekerja dalam standar yang ditentukan dan akan menjadi musuh kolom ke-5 di medan perang untuk menjaga basis kode tetap bersih
  3. Jangan takut untuk mengalokasikan anggota tim berketerampilan rendah untuk pengujian untuk jangka waktu yang lama.
  4. Gunakan setiap alat di gudang Anda untuk menghindari memeriksa kode yang membusuk: ini melibatkan alat khusus, serta tes unit pra-tertulis yang menguji file build, file proyek, struktur direktori, dll.
  5. Dalam tim yang beranggotakan 5-8 orang, suruh lelaki terbaik Anda melakukan refactoring hampir secara konstan - membersihkan kekacauan yang ditinggalkan orang lain. Bahkan jika Anda menemukan spesialis terbaik di bidangnya, Anda masih akan memiliki kekacauan - itu tidak dapat dihindari, tetapi dapat dibatasi oleh refactoring yang konstan.
  6. Apakah menulis unit test dan memeliharanya - JANGAN bergantung pada unit test untuk menjaga proyek tetap bersih, mereka tidak.
  7. Diskusikan semuanya. Jangan takut untuk menghabiskan waktu berjam-jam untuk membahas hal-hal di tim. Ini akan menyebarkan informasi dan akan menghapus salah satu akar penyebab kode buruk: kebingungan tentang teknologi, tujuan, standar, dll.
  8. Berhati - hatilah dengan konsultan yang menulis kode: kode mereka, hampir secara definisi, akan menjadi barang yang menyebalkan.
  9. Lakukan ulasan lebih baik sebagai langkah proses sebelum check-in. Jangan takut untuk mengembalikan komitmen.
  10. Jangan pernah menggunakan prinsip buka / tutup kecuali pada tahap terakhir sebelum rilis: itu hanya menyebabkan kode membusuk dibiarkan berbau.
  11. Setiap kali masalah terjadi, luangkan waktu untuk memahaminya sepenuhnya sebelum menerapkan solusi - kebanyakan kode membusuk berasal dari menerapkan solusi untuk masalah yang tidak sepenuhnya dipahami.
  12. Gunakan teknologi yang tepat. Ini akan sering datang dalam set dan menjadi segar: Lebih baik bergantung pada versi beta dari kerangka kerja Anda memastikan dukungan dari di masa depan, daripada bergantung pada sangat stabil, tetapi kerangka kerja usang, yang tidak didukung.
  13. Pekerjakan orang-orang terbaik.
  14. Memberhentikan sisanya - Anda tidak menjalankan kedai kopi.
  15. Jika manajemen bukan arsitek terbaik dan mereka ikut campur dalam proses pengambilan keputusan - cari pekerjaan lain.
casper
sumber
1
Sekarang, apa yang akan Anda lakukan jika Anda harus mempertahankan dan meningkatkan aplikasi VB6 berusia 12 tahun yang mengerikan dengan 100-an formulir dan kelas sambil mengerjakan C # menulis ulang di 'waktu luang'?
jfrankcarr
7
Tidak setuju dengan # 3. Pengujian tidak harus dilihat sebagai hukuman bagi yang tidak terlatih. Sebenarnya itu harus dilakukan oleh semua pengembang, dan dihitung sama pentingnya dengan pengkodean & desain! Jika Anda memiliki Tuan Yang Tidak Terlatih dalam tim, maka keluarkan dia dari tim untuk beberapa pelatihan !.
NWS
1
"Tidak setuju dengan # 3. Pengujian seharusnya tidak dilihat sebagai hukuman bagi yang tidak terlatih." - Seharusnya tidak dan bukan apa yang saya tulis, izinkan saya menjelaskan: Menguji adalah cara yang baik untuk membiarkan orang yang Anda tidak percaya untuk melakukan perubahan untuk masuk ke kode dia. Penguji terbaik yang saya temukan adalah mereka yang bercita-cita untuk menjadi kontributor kode dan membuktikan kompetensi mereka dengan melihat melalui kode, menjalankan program dan menunjukkan kemampuan untuk mengkorelasikan temuan mereka di runtime dengan kode sumber. Itu bukan hukuman - pelatihannya.
Casper
1
"Tidak setuju dengan # 10 - yang membantu dengan kualitas kode jika dilakukan dengan benar" Ini benar-benar salah dalam pengalaman kerja saya: Kode dikunci tidak dapat di-refactored, artinya akan tetap dalam keadaan saat ini hingga tidak terkunci. Keadaan ini dapat diverifikasi untuk berfungsi pada beberapa tahap, tetapi pada tahap selanjutnya verifikasi ini adalah positif palsu: Semua kode harus dibiarkan terbuka untuk refactoring hingga tahap sebelum pengujian sistem akhir.
Casper
3
@casper: IMHO, Prinsip buka / tutup tidak boleh dipahami sebagai "Anda tidak dapat mengubah sumber", melainkan "mendesain kode seperti itu akan menjadi beku". Pastikan bahwa mungkin untuk memperpanjang kode sebagai nessisary tanpa harus mengubahnya. Hasilnya adalah inheirently lebih longgar digabungkan dan sangat kohesif daripada kode rata-rata. Prinsip ini juga penting ketika mengembangkan perpustakaan untuk digunakan oleh pihak ketiga, karena mereka tidak bisa begitu saja masuk dan memodifikasi kode Anda, sehingga Anda perlu diperluas secara tepat.
Kevin Cathcart
12

Bersihkan kode busuk dengan refactoring, sambil menulis unit test. Bayar (ini) hutang desain pada semua kode yang Anda sentuh, kapan pun Anda:

  • Kembangkan fitur baru
  • Perbaiki masalah

Sangat mempercepat siklus pengembangan tes pertama Anda dengan:

  • Refactoring untuk mengonversi modul kode ke bahasa scripting
  • Gunakan mesin uji berbasis cloud yang cepat

Kode refactor untuk menggunakan kopling rendah (unit yang sangat kohesif secara internal) dengan:

  • Lebih sederhana, (lebih banyak) fungsi (rutin)
  • Modul
  • Objek (dan kelas atau prototipe)
  • Fungsi murni (tanpa efek samping)
  • Lebih suka delegasi, lebih dari warisan
  • Layers (dengan API)
  • Koleksi kecil, program satu arah yang dapat beroperasi bersama

Pertumbuhan organik itu baik; desain muka besar buruk.

Punya pemimpin yang memiliki pengetahuan tentang desain saat ini. Jika tidak, baca kode proyek hingga Anda memiliki pengetahuan.

Baca buku refactoring.

MarkDBlackwell
sumber
1
+1 Jawaban pertama yang bagus, cara sempurna untuk memperkenalkan diri kepada kami!
yannis
11

Jawaban sederhana: Anda tidak bisa .

Itu sebabnya Anda harus bertujuan untuk menulis perangkat lunak kecil dan sederhana . Ini tidak mudah.

Itu hanya mungkin jika Anda berpikir cukup lama tentang masalah Anda yang tampaknya rumit untuk mendefinisikannya sesederhana dan sesingkat mungkin.

Solusi untuk masalah yang benar-benar besar dan kompleks seringkali masih dapat diselesaikan dengan membangun modul-modul kecil dan sederhana.

Dengan kata lain, seperti yang ditunjukkan orang lain, kesederhanaan dan longgar adalah bahan utama.

Jika itu tidak mungkin atau tidak layak, Anda mungkin sedang melakukan penelitian (masalah kompleks tanpa solusi sederhana yang diketahui, atau tidak ada solusi yang diketahui sama sekali). Jangan berharap riset menghasilkan langsung produk yang dapat dipelihara, bukan itu tujuan penelitian.

Joh
sumber
9

Saya bekerja pada basis kode untuk produk yang telah dalam pengembangan berkelanjutan sejak 1999, sehingga Anda dapat membayangkan itu cukup rumit sekarang. Sumber peretasan terbesar dalam basis kode kami adalah dari beberapa kali kami harus memindahkannya dari ASP Classic ke ASP.NET , dari ADO ke ADO.NET, dari postback ke Ajax , beralih perpustakaan UI, standar pengkodean, dll.

Secara keseluruhan kami telah melakukan pekerjaan yang wajar untuk menjaga basis kode tetap terpelihara. Hal-hal utama yang kami lakukan yang berkontribusi pada hal itu adalah:

1) Konstan refactoring - Jika Anda harus menyentuh sepotong kode yang hacky atau sulit dipahami, Anda diharapkan untuk mengambil waktu ekstra untuk membersihkannya dan diberi kelonggaran dalam jadwal untuk melakukannya. Tes unit membuat ini jauh lebih menakutkan, karena Anda dapat menguji terhadap regresi lebih mudah.

2) Jaga lingkungan pengembangan yang rapi - Waspada tentang menghapus kode yang tidak lagi digunakan, dan jangan meninggalkan salinan cadangan / copy pekerjaan / kode eksperimental yang ada di direktori proyek.

3) Standar pengkodean yang konsisten untuk kehidupan Proyek - Mari kita hadapi itu, pandangan kita tentang standar pengkodean berkembang seiring waktu. Saya sarankan tetap dengan standar pengkodean yang Anda mulai untuk kehidupan proyek kecuali Anda punya waktu untuk kembali dan retrofit semua kode untuk memenuhi standar baru. Sangat menyenangkan bahwa Anda melebihi notasi Hongaria sekarang, tetapi terapkan pelajaran itu ke proyek-proyek baru dan jangan hanya beralih di tengah-tengah proyek baru itu.

JohnFx
sumber
8

Karena Anda telah menandai pertanyaan dengan manajemen proyek, saya telah mencoba menambahkan beberapa poin non-kode :)

  • Rencanakan pergantian - asumsikan bahwa seluruh tim pengembangan akan menghilang pada saat ia mencapai fase pemeliharaan - tidak ada pengembang yang layak garamnya ingin terjebak mempertahankan sistemnya selamanya. Mulailah menyiapkan materi penyerahan segera setelah Anda punya waktu.

  • Konsistensi / keseragaman tidak dapat cukup ditekankan. Ini akan mencegah budaya 'pergi sendiri' dan mendorong pengembang baru untuk bertanya, jika mereka ragu.

  • Tetap mengarusutamakan - teknologi yang digunakan, pola desain dan standar - karena pengembang baru untuk tim (di tingkat apa pun) akan memiliki lebih banyak peluang untuk bangun dan berjalan dengan cepat.

  • Dokumentasi - terutama arsitektur - mengapa keputusan dibuat, dan standar pengkodean. Juga simpan referensi / catatan / peta jalan ke dalam mendokumentasikan domain bisnis - Anda akan kagum betapa sulitnya bagi bisnis perusahaan untuk menjelaskan apa yang mereka lakukan kepada pengembang tanpa pengalaman domain.

  • Tetapkan aturan dengan jelas - tidak hanya untuk tim pengembangan Anda saat ini, tetapi pikirkan tentang pengembang pemeliharaan di masa depan. Jika ini berarti menempatkan hyperlink ke desain yang relevan dan mengkode dokumentasi standar pada setiap halaman, maka jadilah.

  • Pastikan bahwa arsitektur dan terutama lapisan kode dibatasi dengan jelas dan dipisahkan - ini berpotensi memungkinkan untuk penggantian lapisan kode saat teknologi baru datang, misalnya, mengganti UI Formulir Web dengan UI jQuery HTML5 , dll., Yang mungkin beli satu tahun atau lebih dari umur panjang yang ditambahkan.

StuartLC
sumber
7

Salah satu properti dari kode yang sangat dapat dipertahankan adalah fungsi kemurnian .

Kemurnian berarti bahwa fungsi harus mengembalikan hasil yang sama untuk argumen yang sama. Artinya, mereka tidak harus bergantung pada efek samping dari fungsi lain. Selain itu, berguna jika mereka tidak memiliki efek samping sendiri.

Properti ini lebih mudah untuk disaksikan dibandingkan dengan properti sambungan / kohesi. Anda tidak harus keluar dari cara Anda untuk mencapainya, dan saya pribadi menganggapnya lebih berharga.

Ketika fungsi Anda murni, tipenya adalah dokumentasi yang sangat bagus dengan sendirinya. Selain itu, menulis dan membaca dokumentasi dalam hal argumen / nilai pengembalian jauh lebih mudah daripada yang menyebutkan beberapa kondisi global (mungkin diakses oleh utas lain O_O).

Sebagai contoh menggunakan kemurnian secara luas untuk membantu pemeliharaan, Anda dapat melihat GHC . Ini adalah proyek besar sekitar 20 tahun di mana refactoring besar sedang dilakukan dan fitur-fitur utama baru masih diperkenalkan.

Terakhir, saya tidak terlalu suka poin "Keep it simple". Anda tidak dapat membuat program Anda sederhana ketika Anda membuat model hal-hal kompleks. Cobalah membuat kompiler sederhana dan kode Anda yang dihasilkan kemungkinan akan berakhir lambat. Tentu, Anda dapat (dan seharusnya) membuat fungsi individu menjadi sederhana, tetapi keseluruhan program tidak akan sesederhana itu.

Rotsor
sumber
2
Nama lain untuk apa yang Anda gambarkan adalah sifat deterministik
jinglesthula
6

Selain jawaban lain, saya akan merekomendasikan layer. Tidak terlalu banyak tetapi cukup untuk memisahkan berbagai jenis kode.

Kami menggunakan model API internal untuk sebagian besar aplikasi. Ada API internal yang terhubung ke database. Kemudian lapisan UI . Orang yang berbeda dapat bekerja pada setiap level tanpa mengganggu atau merusak bagian lain dari aplikasi.

Pendekatan lain adalah membuat semua orang membaca comp.risks dan The Daily WTF sehingga mereka mempelajari konsekuensi dari desain yang buruk dan pemrograman yang buruk, dan mereka akan takut melihat kode mereka sendiri diposting di The Daily WTF .

james
sumber
6

Karena banyak dari jawaban ini tampaknya berfokus pada tim-tim besar, bahkan sejak awal, saya akan menempatkan pandangan saya sebagai bagian dari tim pengembangan dua orang (tiga jika Anda termasuk perancang) untuk sebuah startup.

Jelas, desain dan solusi sederhana adalah yang terbaik, tetapi ketika Anda memiliki orang yang benar-benar membayar gaji Anda, Anda tidak perlu punya waktu untuk memikirkan solusi yang paling elegan, sederhana dan dapat dipelihara. Dengan mengingat hal itu, poin besar pertama saya adalah:

Dokumentasi Bukan komentar, kode sebagian besar harus didokumentasikan sendiri, tetapi hal-hal seperti dokumen desain, hierarki dan dependensi kelas, paradigma arsitektur, dll. Apa pun yang membantu programmer baru, atau bahkan yang sudah ada, untuk memahami basis kode. Juga, mendokumentasikan pseudo-library aneh yang muncul pada akhirnya, seperti "menambahkan kelas ini ke elemen untuk fungsi ini" dapat membantu, karena itu juga mencegah orang dari menulis ulang fungsionalitas.

Namun, bahkan jika Anda memiliki batas waktu yang berat, saya menemukan bahwa hal baik yang perlu diingat adalah:

Hindari peretasan dan perbaikan cepat. Kecuali jika perbaikan cepat adalah perbaikan aktual, selalu lebih baik untuk mencari tahu masalah yang mendasarinya untuk sesuatu, dan kemudian memperbaikinya. Kecuali Anda benar-benar memiliki skenario "buat ini berfungsi dalam 2 menit, atau Anda dipecat", melakukan perbaikan sekarang adalah ide yang lebih baik, karena Anda tidak akan memperbaiki kode nanti, Anda hanya akan pindah ke tugas berikutnya yang Anda miliki.

Dan tip favorit pribadi saya lebih dari kutipan, meskipun saya tidak dapat mengingat sumbernya:

"Kode seolah-olah orang yang datang setelahmu adalah psikopat pembunuh yang tahu di mana kau tinggal"

Aatch
sumber
Saya selalu menemukan komentar fungsi dan kelas untuk membantu bahkan jika hanya untuk menyediakan pemisahan segmen kode pada fungsi dan lokasi kelas dengan menggunakan penyorotan sintaksis. Saya sangat jarang memasukkan komentar ke dalam kode fungsi, tetapi saya menulis baris untuk setiap kelas dan fungsi, seperti /** Gets the available times of a clinic practitioner on a specific date. **/atau /** Represents a clinic practitioner. **/.
Nick Bedford
5

Satu prinsip yang belum disebutkan tetapi yang saya anggap penting adalah prinsip terbuka / tertutup .

Anda tidak boleh memodifikasi kode yang telah dikembangkan dan diuji: setiap potongan kode tersebut disegel. Sebagai gantinya, perluas kelas yang ada dengan subkelas, atau gunakan mereka menulis pembungkus, kelas dekorator atau menggunakan pola apa pun yang Anda rasa cocok. Tetapi jangan mengubah kode kerja .

Hanya 2 sen saya.

Giorgio
sumber
Bagaimana jika persyaratan bisnis yang dinyatakan dalam perubahan kode kerja? Jangan-sentuh pada kode yang tidak diperhitungkan dengan baik tetapi secara teknis 'berfungsi' dapat melukai Anda dalam jangka panjang, terutama ketika tiba saatnya untuk melakukan perubahan yang diperlukan.
jinglesthula
@jinglesthula: Buka untuk ekstensi berarti Anda dapat menambahkan fungsionalitas baru sebagai implementasi baru (misalnya kelas) dari antarmuka yang ada. Tentu saja, kode yang terstruktur dengan buruk tidak memungkinkan ini: harus ada abstraksi seperti antarmuka yang memungkinkan kode untuk "berubah" dengan menambahkan kode baru alih-alih dengan memodifikasi kode yang ada.
Giorgio
5
  • Jadilah pengintai . Selalu tinggalkan kode lebih bersih daripada yang Anda temukan.

  • Perbaiki jendela yang rusak . Semua komentar itu "berubah dalam versi 2.0" saat Anda menggunakan versi 3.0.

  • Ketika ada peretasan besar, rancang solusi yang lebih baik sebagai sebuah tim dan lakukan itu. Jika Anda tidak dapat memperbaiki retasan sebagai sebuah tim, maka Anda tidak memahami sistem dengan cukup baik. "Minta bantuan orang dewasa." Orang-orang tertua di sekitar mungkin pernah melihat ini sebelumnya. Cobalah menggambar atau mengekstraksi diagram sistem. Cobalah menggambar atau mengekstraksi kasus penggunaan yang terutama hacky sebagai diagram interaksi. Ini tidak memperbaikinya, tetapi setidaknya Anda bisa melihatnya.

  • Asumsi apa yang tidak lagi benar yang mendorong desain ke arah tertentu? Mungkin ada refactoring kecil yang bersembunyi di balik beberapa kekacauan itu.

  • Jika Anda menjelaskan cara kerja sistem (bahkan hanya satu kasus penggunaan) dan mendapati diri Anda harus meminta maaf atas suatu subsistem berulang kali, itu masalahnya. Apa yang akan menjadikan sisa sistem lebih sederhana (tidak peduli seberapa sulit untuk diterapkan dibandingkan dengan apa yang ada). Subsistem klasik untuk ditulis ulang adalah subsistem yang mencemari setiap subsistem lainnya dengan semantik dan implementasinya. "Oh, Anda harus groz nilai sebelum Anda memasukkannya ke dalam subsistem froo, maka Anda un-groz lagi ketika Anda mendapatkan output dari froo. Mungkin semua nilai harus groz'ed ketika dibaca dari pengguna & penyimpanan, dan sisanya dari sistem ini salah? Ini menjadi lebih menarik ketika ada dua atau lebih grozifikasi yang berbeda.

  • Habiskan seminggu sebagai tim menghapus peringatan sehingga masalah nyata terlihat.

  • Format ulang semua kode ke standar pengkodean.

  • Pastikan sistem kontrol versi Anda terkait dengan pelacak bug Anda. Ini berarti perubahan di masa depan adalah baik dan dapat dipertanggungjawabkan, dan Anda dapat bekerja MENGAPA.

  • Lakukan arkeologi. Temukan dokumen desain asli dan tinjau. Mereka mungkin berada di PC lama di sudut kantor, di ruang kantor yang ditinggalkan atau di lemari arsip yang tidak pernah dibuka oleh siapa pun.

  • Publikasikan ulang dokumen desain pada wiki. Ini membantu melembagakan pengetahuan.

  • Tulis prosedur seperti daftar periksa untuk rilis dan build. Ini menghentikan orang untuk berpikir, sehingga mereka dapat berkonsentrasi untuk menyelesaikan masalah. Automate build sedapat mungkin.

  • Coba integrasi terus menerus . Semakin cepat Anda mendapatkan bangunan yang gagal, semakin sedikit waktu proyek dapat menghabiskan dari rel.

  • Jika pemimpin tim Anda tidak melakukan hal-hal ini, baik itu buruk bagi perusahaan.

  • Cobalah untuk memastikan semua kode baru mendapatkan pengujian unit yang tepat dengan cakupan terukur. Jadi masalahnya tidak bisa lebih buruk.

  • Coba uji unit beberapa bit lama yang tidak diuji unit. Ini membantu mengurangi ketakutan akan perubahan.

  • Otomatiskan tes integrasi dan regresi Anda jika Anda bisa. Setidaknya punya daftar periksa. Pilot cerdas dan mendapat banyak bayaran dan mereka menggunakan daftar periksa. Mereka juga mengacaukan sangat jarang.

Tim Williscroft
sumber
4

Baca dan baca kembali Kode Lengkap oleh Steve McConnell. Ini seperti Alkitab penulisan perangkat lunak yang baik, dari desain proyek awal hingga satu baris kode dan semua yang ada di antaranya. Yang paling saya sukai tentang hal ini adalah didukung oleh data padat selama beberapa dekade; bukan hanya gaya pengkodean terbaik berikutnya.

dwenaus
sumber
3

Saya datang untuk menyebutnya "Efek Rumah Misteri Winchester". Seperti rumah, itu dimulai cukup sederhana, tetapi selama bertahun-tahun banyak pekerja yang berbeda menambahkan begitu banyak fitur aneh tanpa rencana keseluruhan sehingga tidak ada yang benar-benar mengerti lagi. Mengapa tangga ini tidak menuju ke mana-mana dan mengapa pintu itu hanya terbuka satu arah? Siapa tahu?

Cara untuk membatasi efek ini adalah mulai dengan desain bagus yang dibuat di mana cukup fleksibel untuk menangani ekspansi. Beberapa saran telah ditawarkan untuk hal ini.

Tetapi, sering kali Anda akan mengambil pekerjaan di mana kerusakan sudah terjadi, dan sudah terlambat untuk desain yang baik tanpa melakukan desain ulang dan menulis ulang yang mahal dan berpotensi berisiko. Dalam situasi itu, yang terbaik adalah mencoba menemukan cara untuk membatasi kekacauan sambil merangkulnya sampai batas tertentu. Mungkin mengganggu kepekaan desain Anda bahwa semuanya harus melalui kelas 'manajer' tunggal yang besar, jelek, tunggal atau lapisan akses data digabungkan erat ke UI, tetapi belajarlah untuk menghadapinya. Kode pertahanan dalam kerangka itu dan mencoba untuk mengharapkan yang tak terduga ketika 'hantu' programmer masa lalu muncul.

jfrankcarr
sumber
2

Refactoring kode dan pengujian unit sangat baik. Tetapi karena proyek jangka panjang ini berjalan ke peretasan, ini berarti bahwa manajemen tidak meletakkan kakinya untuk membersihkan busuk. Tim diminta untuk memperkenalkan hacks, karena seseorang tidak mengalokasikan sumber daya yang cukup untuk melatih orang dan menganalisis masalah / permintaan.

Mempertahankan proyek yang berjalan lama adalah tanggung jawab manajer proyek seperti halnya pengembang individu.

Orang tidak memperkenalkan retasan karena mereka menyukainya; mereka dipaksa oleh keadaan.

Peter Mortensen
sumber
Dipaksa oleh keadaan? Orang-orang memperkenalkan peretasan karena (a) mereka tidak tahu lebih baik => perlu pelatihan, (b) mereka tidak melihat gambaran yang lebih besar => komunikasi, dokumentasi dan disiplin yang dibutuhkan, (c) mereka pikir mereka lebih pintar => itulah yang terbesar rintangan untuk mengatasi (d) dipaksa oleh keadaan => perbaikan terbaru cepat ok ketika di bawah tekanan waktu, tetapi seseorang harus mengambil tanggung jawab dan membersihkan kode setelah itu. "Keadaan" lainnya hanyalah BS . Ada pengecualian untuk aturan praktis itu, tetapi pengecualian yang paling disebut mantra "malas".
JensG
2

Saya hanya ingin menempatkan masalah non-teknis dan pendekatan pragmatis (mungkin).

Jika manajer Anda tidak peduli dengan kualitas teknis (kode yang dapat dikelola, arsitektur sederhana, infrastruktur yang andal, dan sebagainya), menjadi sulit untuk meningkatkan proyek. Dalam hal ini perlu untuk mendidik manajer tersebut dan meyakinkan untuk "menginvestasikan" upaya ke dalam pemeliharaan dan mengatasi utang teknis .

Jika Anda bermimpi dengan kualitas kode yang ditemukan dalam buku-buku itu, Anda juga memerlukan atasan yang peduli akan hal ini.

Atau jika Anda hanya ingin menjinakkan "proyek Frankenstein" ini adalah tips saya:

  • Atur dan sederhanakan
  • Mempersingkat fungsi
  • Prioritaskan keterbacaan di atas efisiensi (jika tentu saja dapat diterima, dan beberapa keuntungan efisiensi terlalu menyedihkan untuk disimpan)

Dalam pengalaman saya, pemrograman lebih entropis daripada muncul (setidaknya dalam paradigma imperatif-terstruktur populer). Ketika orang menulis kode untuk "hanya bekerja" kecenderungannya adalah kehilangan organisasinya. Sekarang pengorganisasian kode membutuhkan waktu, kadang-kadang lebih dari membuatnya berfungsi.

Di luar implementasi fitur dan perbaikan bug, luangkan waktu Anda untuk pembersihan kode.

Eric.Void
sumber
"... proyek ini hancur" - dalam pengalaman saya, ini belum tentu demikian. Alternatifnya adalah dengan mendidik manajer tersebut dan meyakinkan untuk "menginvestasikan" upaya dalam pemeliharaan dan mengatasi utang teknis
nyamuk
Maaf, saya tidak dapat menahan diri untuk menulis itu karena saya sudah memiliki pengalaman ketika manajer mengabaikan semua saran saya tentang hutang teknis. Tapi saya pikir Anda benar: sekitar satu tahun setelah saya menyerahkan proyek itu, manajer kehilangan semua wewenangnya atas tim teknologi karena ketidakmampuannya untuk mengelolanya.
Eric. Batal
1

Saya terkejut menemukan bahwa tidak satu pun dari banyak jawaban yang menyoroti yang jelas: membuat perangkat lunak terdiri dari banyak perpustakaan kecil dan independen. Dengan banyak perpustakaan kecil, Anda dapat membangun perangkat lunak yang besar dan kompleks. Jika persyaratan berubah, Anda tidak perlu membuang seluruh basis kode atau menyelidiki cara mengubah basis kode klakson besar untuk melakukan sesuatu yang lain daripada apa yang sedang dilakukan. Anda hanya memutuskan perpustakaan mana yang masih relevan setelah persyaratan berubah dan bagaimana menggabungkannya untuk memiliki fungsi baru.

Gunakan teknik pemrograman apa pun di perpustakaan yang membuat penggunaan perpustakaan mudah. Perhatikan bahwa mis. Setiap pointer fungsi pendukung bahasa yang tidak berorientasi objek mendukung sebenarnya pemrograman berorientasi objek (OOP). Jadi, misalnya dalam C, Anda dapat melakukan OOP.

Anda bahkan dapat mempertimbangkan untuk berbagi perpustakaan kecil dan independen di antara banyak proyek (git submodules adalah teman Anda).

Tidak perlu dikatakan, setiap perpustakaan kecil dan independen harus diuji unit. Jika perpustakaan tertentu tidak dapat diuji unit, Anda melakukan sesuatu yang salah.

Jika Anda menggunakan C atau C ++ dan tidak menyukai gagasan memiliki banyak file .so yang kecil, Anda dapat menautkan semua pustaka menjadi file .so yang lebih besar, atau Anda dapat melakukan tautan statis. Hal yang sama berlaku untuk Java, cukup ubah .so menjadi .jar.

ahli hukum agama
sumber
Ini tampaknya agak terlalu teoritis dari sudut pandang saya. Tentu saja proyek yang saya sebutkan dalam pertanyaan saya dibangun dari beberapa perpustakaan dan modul. Pengalaman saya dalam 26 tahun terakhir pengembangan perangkat lunak adalah bahwa semakin lama proyek tersebut mendapatkan organisasi awal
chrmue
0

Sederhana: kurangi biaya perawatan sebagian besar kode Anda menjadi nol sampai Anda memiliki jumlah komponen yang dapat dipelihara. Kode yang tidak perlu diubah tanpa dikenakan biaya perawatan. Saya sarankan bertujuan untuk membuat kode benar-benar memiliki biaya pemeliharaan nol , tidak mencoba untuk mengurangi biaya lebih dari iterasi refactoring kecil dan cerewet. Buat biaya nol segera.

Oke, harus diakui itu jauh, jauh lebih sulit daripada kedengarannya. Tetapi tidak sulit untuk memulai. Anda dapat mengambil sebagian dari basis kode, mengujinya, membangun antarmuka yang bagus di atasnya jika desain antarmuka berantakan, dan mulai menumbuhkan bagian-bagian dari basis kode yang dapat diandalkan, stabil (seperti tidak ada alasan untuk mengubah), sementara secara bersamaan menyusut bagian-bagian yang tidak dapat diandalkan dan tidak stabil. Basis kode yang terasa seperti mimpi buruk untuk dipertahankan sering tidak membedakan bagian yang bergerak yang perlu diubah dari bagian yang tidak, karena semuanya dianggap tidak dapat diandalkan dan cenderung berubah.

Saya benar-benar merekomendasikan untuk memisahkan organisasi basis kode Anda menjadi bagian "stabil" dan "tidak stabil", dengan bagian stabil menjadi PITA besar untuk dibangun kembali dan diubah (yang merupakan hal yang baik, karena mereka tidak perlu perlu diubah dan dibangun kembali jika mereka benar-benar termasuk dalam bagian "stabil").

Ini bukan ukuran basis kode yang membuat pemeliharaan sulit. Ini ukuran basis kode yang perlu dipertahankan. Saya bergantung pada jutaan baris kode setiap kali saya, katakanlah, menggunakan API sistem operasi. Tetapi itu tidak berkontribusi pada biaya pemeliharaan produk saya, karena saya tidak harus mempertahankan kode sumber sistem operasi. Saya hanya menggunakan kode dan itu berfungsi. Kode yang hanya saya gunakan dan tidak perlu memelihara tidak ada biaya pemeliharaan pada saya.

user204677
sumber