Apakah metode berulang mengurangi kompleksitas siklomatik dan meningkatkan daya dukung?

11

Apakah metode berulang seperti yang biasa ditemukan dalam bahasa modern seperti C #, JavaScript, dan (mudah-mudahan) di Java 8 mengurangi dampak kompleksitas siklomatik pada pemahaman dan dukungan kode?

Misalnya dalam C # kita mungkin memiliki kode berikut:

List<String> filteredList = new List<String>();

foreach (String s in originalList){
   if (matches(s)){
      filteredList.add(s);
   }
}

Ini memiliki kompleksitas siklomatik sederhana 2.

Kita dapat dengan mudah menulis ulang ini sebagai:

List<String> filteredList = originalList.where(s => matches(s));

Yang memiliki kompleksitas siklomatik sederhana 0.

Apakah ini benar-benar menghasilkan kode yang lebih dapat didukung? Apakah ada penelitian aktual tentang topik ini?

C. Ross
sumber
2
Judul Anda bertanya tentang pengurangan kompleksitas siklomatik, tetapi teks Anda mengasumsikan pengurangan CC dan bertanya tentang pemeliharaan. Ini berpotensi menjadi pertanyaan yang berharga, dapatkah Anda mengedit judulnya menjadi lebih akurat?
Kilian Foth
@KilianFoth Apakah itu lebih baik?
C. Ross
Saya akan menghubungkan metode berulang dengan metodologi pengembangan berulang. Saya pikir istilah yang lebih baik adalah fungsi tingkat tinggi. (Dan sebagai tambahan, metode tidak memiliki tipe pengembalian / kekosongan sedangkan fungsi mengembalikan sesuatu).
Johannes Rudolph
@JohannesRudolph "metode tidak memiliki tipe pengembalian / kekosongan sedangkan fungsi mengembalikan sesuatu" - dalam bahasa apa ini benar? Saya belum pernah mendengar ini; pada kenyataannya, satu-satunya perbedaan nyata yang pernah saya dengar adalah metode dikaitkan dengan kelas, fungsi tidak.
threed

Jawaban:

14

Dugaan saya adalah bahwa Anda baru saja membagi / memindahkan kompleksitas. Itu menurun karena Anda tidak menghitung implementasi .where()di CC Anda.

CC keseluruhan belum benar-benar bergerak, CC kode Anda sendiri menurun, hanya karena sekarang dipindahkan ke kode kerangka kerja.

Saya akan mengatakan itu lebih mudah dikelola. Ketika itu fitur bahasa, gunakan itu. Ini bukan "ohh, saya mengerti, ini adalah trik pintar" yang Anda gunakan, hanya fungsi inline-like sederhana.

Clement Herreman
sumber
11

Yang Anda lakukan hanyalah menyoroti cacat dalam kompleksitas siklomatik sebagai metrik, kompleksitas kode tidak berubah. Anda memiliki cabang eksplisit dalam contoh pertama dan perlu memahami ada cabang tersirat di yang kedua. Yang kedua lebih jelas dan lebih mudah dipahami asalkan Anda memahami sintaksis, dan karena menggunakan sintaksis yang kurang mendasar yang mungkin menjadi masalah.

Ryathal
sumber
1
Orang bisa berpendapat bahwa kompleksitas siklomatik dari kode sendiri berkurang di sini, karena di wheresini kemungkinan dari suatu kerangka kerja. Saya pikir kompleksitas siklomatik sebagai metrik berguna bahkan di sini karena, sementara memecah fungsi menjadi beberapa tidak mengurangi keseluruhan kompleksitas sistem (memang, itu sering meningkatkannya, jika hanya sedikit), itu membantu Anda menentukan kapan satu sepotong sistem menjadi terlalu rumit dan perlu dipecah.
threed
6

Untuk menjawab pertanyaan secara obyektif, kita perlu semacam metrik untuk pemeliharaan. Kompleksitas siklus itu sendiri bukan merupakan ukuran kemampuan pemeliharaan, tetapi merupakan komponen dari beberapa metrik yang dimaksudkan untuk mengukur kemampuan pemeliharaan. Misalnya, rumus untuk Indeks Maintainability adalah:

MI = 171 - 5.2 * ln(V) - 0.23 * (G) - 16.2 * ln(LOC)

di mana Gkompleksitas cyclomatic dari kode tersebut. Oleh karena itu, mengurangi kompleksitas cyclomatic dari sepotong kode menurut definisi meningkatkan Maintainability Index dan metrik lainnya yang juga menggunakan kompleksitas cyclomatic .

Sulit untuk mengatakan apakah jenis perubahan yang Anda usulkan membuat program tampak lebih dapat dipertahankan oleh programmer; yang mungkin tergantung pada seberapa akrab mereka dengan wheremetode (dalam kasus Anda) .

Caleb
sumber
Peringatan: Angka Ajaib! (>_<)
Izkata
Hanya ada satu masalah kecil dengan Indeks Maintainability. Tiga komponen itu adalah Halstead Volume, Complexity Siklus, dan Lines of Code. Baik Halstead Volume dan Kompleksitas Siklomatik telah terbukti berkorelasi sangat kuat dengan Lines of Code. Ini berarti bahwa persamaan perkiraan alternatif untuk Indeks Maintainability yang bergantung HANYA pada Lines of Code dapat diturunkan yang akan hampir seakurat yang asli, dengan kesulitan komputasi yang jauh lebih sedikit.
John R. Strohm
@ JohnR.Strohm Saya pikir Anda akan mendapatkan hasil yang serupa bahkan jika Anda hanya menggunakan LOC sebagai metrik rawatan. Perubahan OP mengurangi LOC menjadi 1 dari 4, dan perubahan lain yang mengurangi kompleksitas siklomatik juga cenderung mengurangi LOC. Bagaimanapun, itu benar-benar turun ke bagaimana Anda mendefinisikan dan mengukur pemeliharaan.
Caleb
1
@ Caleb: Setuju. Poin yang saya coba sampaikan adalah bahwa orang terlalu sering mencari metrik dan kombinasi metrik yang sangat rumit ini, tidak menyadari bahwa hampir semuanya telah terbukti berkorelasi kuat pada kode nyata dengan Lines Of Code (LOC) lama yang sederhana. , dan karenanya tidak memiliki nilai prediktif atau deskriptif lebih dari LOC.
John R. Strohm
3

Karena telah diperlihatkan bahwa kompleksitas siklomatik (CC) berkorelasi sangat kuat dengan ukuran kode, "sedemikian rupa sehingga CC dapat dikatakan sama sekali tidak memiliki kekuatan penjelasnya sendiri." apa yang sebenarnya Anda tanyakan adalah apakah "metode berulang seperti yang biasa ditemukan dalam bahasa modern seperti C #, JavaScript, dan (mudah-mudahan) di Java 8 mengurangi dampak ukuran kode pada pemahaman dan dukungan kode."

Pada titik itu, orang akan berharap bahwa jawabannya akan jelas. Sudah dikenal selama beberapa dekade bahwa kode yang lebih pendek umumnya lebih mudah dipahami, dipelihara, dan didukung.

John R. Strohm
sumber
2

Jika Anda berbicara tentang stat baku Kompleksitas Cyclomatik, tentu saja. Anda baru saja memindahkannya dari 2 menjadi 0. Jika Anda menggunakan angka, untung murni, semuanya.

Dari perspektif praktis (baca: manusia), saya berpendapat Anda benar-benar telah meningkatkan kompleksitasnya dengan 2. Satu hal yang berasal dari kenyataan bahwa sekarang beberapa programmer lain harus membawa atau mendapatkan pengetahuan tentang LINQ fasih-sintaks untuk memahami ini kode.

Poin lain dari meningkatnya kesulitan berasal dari memahami Ekspresi Lambda; meskipun Lambda cukup mudah dalam hal ini , ada beberapa perubahan paradigma yang harus dilakukan untuk sepenuhnya menghargai mereka.

Kasus ini, menggunakan a.where(x => matches(x, arg))tidak mengerikan, dan dalam semua kejujuran adalah cara yang bagus untuk membuat beberapa rekan kerja melihat dan bekerja dengan ekspresi LINQ dan Lambda untuk pertama kalinya (saya benar-benar mempresentasikan tutorial tentang LINQ / Lambdas kepada beberapa mantan rekan kerja yang menggunakan ini dan set kode lain, untuk efek yang besar.) Namun, penggunaannya memang membutuhkan pengetahuan.

Saya sarankan hati-hati, karena saya telah melihat kasus-kasus di mana refactor LINQ sebenarnya jauh lebih buruk untuk dibaca daripada apa foreachloop itu menjadi.

Andrew Gray
sumber
1

Secara subyektif, itu tergantung pada audiens pengembang, jika mereka memahami ekspresi lambda, maka;

List<String> filteredList = originalList.where(s => matches(s));

lebih cepat dimengerti, dan mungkin sedikit lebih mudah. Saya akan lebih khawatir tentang penggunaan s, dan match (). Baik deskriptif diri, seperti;

List<String> filteredList = 
    originalList.where(stringToBeTested => matchesNameTest(stringToBeTested));

Atau

List<String> filteredList = 
        originalList.where(originalListString => matchesNameTest(originalListString));

memberikan pengembang informasi yang lebih bermakna dan lebih mudah untuk dianalisis, tanpa harus menyelami fungsi pertandingan () untuk menentukan pertandingan apa yang sedang dilakukan.

Maintainability bukan hanya tentang kemampuan untuk memahami kode, tetapi terutama tentang kecepatan dan ketepatan yang dapat digunakan untuk memahami kode.

AceCTO
sumber
2
Hai Ace. Ini adalah contoh, yang tanpa konten semantik untuk menyoroti struktur.
C. Ross