Lebih dari kompleksitas

Saya mendengar ungkapan sedemikian rupa sehingga untuk menjadi seorang programmer, Anda harus malas. Tetapi terkadang kemalasan dalam pemrograman menyebabkan hutang teknis yang mengerikan. Dalam artikel saya tentang SRP, saya menyebutkan bahwa melanggar prinsip ini dapat meningkatkan kompleksitas atau bahkan memperbanyaknya. Salah satu kolega saya menghasilkan contoh yang menarik, dan dengan bantuan saya, saya memutuskan untuk menunjukkan tampilannya.



Mari kita putuskan kompleksitas apa yang berlebihan ini. Tetapi pertama-tama, mari kita bicara tentang kebalikannya, tentang kompleksitas persyaratan. Misalnya, ada persyaratan untuk menghitung gaji karyawan dari tarif per jam dan jam kerja. Dan, jika seorang karyawan telah bekerja di perusahaan selama lebih dari lima tahun, dapatkan bonus. Ini "jika" berasal dari persyaratan, dan itu tidak dapat dihindari. Dalam satu bentuk atau yang lain, itu akan menjadi elemen kompleksitas dalam kode aplikasi, kemungkinan besar dalam bentuk operator bersyarat "jika". Tetapi kadang-kadang kompleksitas tidak berasal dari persyaratan, tetapi mengikuti dari pendekatan pengembang untuk memecahkan masalah.

Operator "jika", pola seperti "strategi", metode polimorfik bukan daftar lengkap teknik pemrograman yang dapat mengandung kompleksitas yang berlebihan ini. Secara pribadi, saya, omong-omong, saya selalu menentang penggunaan pola oleh pengembang hanya karena mereka bisa, dan bukan untuk menyelesaikan masalah tertentu.

Ini adalah contoh sederhana. Ini mungkin tampak fiktif, tetapi tidak. Bahkan tidak disederhanakan, dalam bentuk inilah saya bertemu dengannya selama tinjauan kode beberapa tahun yang lalu. Di dua tempat dalam kode ada panggilan ke fungsi yang sama tetapi dengan parameter Boolean yang berbeda:

// first place doSomething(true); // second place doSomething(false); 

Desain serupa selalu terlihat mencurigakan dan fungsi ini tidak mengecewakan saya. Parameter ini diteruskan untuk tujuan tunggal untuk diperiksa di dalam fungsi ini:

 doSomething(flag: boolean): void { if(flag) { // do first thing } else { // do second thing } } 

Pemeriksaan ini dapat digambarkan sebagai "jika saya dipanggil dari tempat A, kami melakukan satu hal, kalau tidak saya dipanggil dari tempat B, kami melakukan hal lain." Bendera ini, "jika" ini adalah tujuan dari seluruh catatan ini. Kompleksitas tidak datang dari persyaratan bisnis. Secara alami, saya merekomendasikan untuk mengubah kode sebagai berikut:

 // first place doFirstThing(); // second place doSecondThing(); //method is split into 2 parts each having their own responsibility doFirstThing(): void { // do first thing } doSecondThing(): void { // do second thing } 

Itu saja, tidak ada lagi kerumitan. Di sinilah pengembang tidak boleh terlalu malas dan menulis tanda tangan fungsi lain.

Di sini Anda dapat berseru: "Tapi ini hanya satu 'jika'", atau: "Pelanggaran ini jelas, siapa yang menulis kode seperti itu?" Dan inilah contoh kedua. Ini menunjukkan bahwa akan lebih sulit untuk melihat pelanggaran, dan juga bahwa biaya pelanggaran ini bisa lebih dari sekadar "jika". Seperti pada contoh pertama, fungsi ini digunakan di dua tempat:

 // first place checkValidity(obj); // second place checkValidity(arrayOfObjs); 

Metode, sebagai berikut dari namanya, memeriksa validitas objek. Namun, tidak jelas bahwa itu juga bisa memeriksa validitas array objek. Saya mengubah nama-nama variabel untuk menekankan pelanggaran ini. Metodenya terlihat seperti ini:

 checkValidity(parm: MyType | MyType[]): void { if(Array.isArray(parm)) { parm.forEach(p => checkValidity(p)); } else { // here the object gets checked // and conditional exception is thrown } } 

Ini dia. Satu jika menjadi banyak jika. Jika array berisi 100 objek, maka "jika" ini akan mengeksekusi 101 kali. Dan pada data nyata, kita bisa memiliki 30 ribu objek di sana, dan ini sudah merupakan kehilangan kinerja yang mengesankan.

Tentunya, dengan mengikuti prinsip tanggung jawab tunggal, metode ini perlu direactored sehingga diperoleh 2 metode:

 checkItemsValidity(parms: MyType[]): void { parms.forEach(p => checkItemValidity(p)); } checkItemValidity(parm: MyType): void { // here the object gets checked // and conditional exception is thrown } 

Sejalan dengan itu, Anda juga perlu menyesuaikan titik panggilan.

Sangat menarik bahwa contoh yang saya berikan dalam artikel tentang SRP menyebabkan peningkatan SLOC, contoh yang sama, sebaliknya, menyebabkan sedikit penurunan di dalamnya, bersama dengan peningkatan yang diharapkan dalam kualitas kode.

Itu saja. Hanya beberapa contoh sederhana untuk menunjukkan prinsip terpenting dari kode yang baik.

Source: https://habr.com/ru/post/id457018/


All Articles