Apakah dapat menyalin dan menempelkan kode yang panjang tapi langsung daripada membungkusnya ke dalam kelas atau fungsi?

29

Misalkan saya memiliki segmen kode untuk terhubung ke internet dan menunjukkan hasil koneksi seperti itu:

HttpRequest* httpRequest=new HttpRequest();
httpRequest->setUrl("(some domain .com)");
httpRequest->setRequestType(HttpRequest::Type::POST);
httpRequest->setRequestData("(something like name=?&age=30&...)");
httpRequest->setResponseCallback([=](HttpClient* client, HttpResponse* response){
    string responseString=response->getResponseDataString();
        if(response->getErrorCode()!=200){
            if(response->getErrorCode()==404){
                Alert* alert=new Alert();
                alert->setFontSize(30);
                alert->setFontColor(255,255,255);
                alert->setPosition(Screen.MIDDLE);
                alert->show("Connection Error","Not Found");
            }else if((some other different cases)){
                (some other alert)
            }else
                Alert* alert=new Alert();
                alert->setFontSize(30);
                alert->setPosition(Screen.MIDDLE);
                alert->setFontColor(255,255,255);
                alert->show("Connection Error","unknown error");
            }
        }else{
            (other handle methods depend on different URL)
        }
}

kode panjang, dan umumnya digunakan, tetapi kode di atas tidak memerlukan hal-hal tambahan seperti fungsi kustom dan kelas (HttpRequest dan Alert keduanya disediakan oleh kerangka kerja secara default), dan meskipun segmen kode panjang, itu adalah lugas dan tidak kompleks (panjang hanya karena ada bundel pengaturan seperti url, ukuran font ...), dan segmen kode memiliki sedikit variasi di antara kelas (misalnya: url, data permintaan, kasus kode penanganan kasus, pegangan normal kasing ...)

Pertanyaan saya adalah, apakah dapat menyalin dan menempelkan kode yang panjang tapi langsung daripada membungkusnya dalam suatu fungsi untuk mengurangi ketergantungan kode?

ggrr
sumber
89
Bayangkan Anda memiliki bug dalam kode itu, seperti tidak membebaskan objek yang Anda alokasikan. (Apakah kerangka Anda membebaskan Alertobjek?) Sekarang bayangkan Anda harus menemukan setiap instance kode ini untuk memperbaiki bug. Sekarang bayangkan bukan Anda yang harus melakukannya, tetapi pembunuh kapak gila yang tahu Anda adalah orang yang membuat semua salinan ini di tempat pertama.
Sebastian Redl
8
Dan BTW, pencampuran tampilan jaringan dan kesalahan di satu tempat sudah merupakan tidak-tidak, IMHO.
sleske
11
Tidak pernah. Sepenuhnya tidak dapat diterima. Jika Anda berada di proyek saya, Anda tidak lagi berada di proyek saya dan Anda akan mengikuti program pelatihan atau PIP.
nhgrif
10
Dan datanglah pengawas yang mengatakan "Kotak peringatan di tengah layar saya ini adalah teror absolut. Saya sedang menonton cat jif dan pop-up memblokir pandangan saya setiap kali muncul. Silakan pindahkan ke kanan atas. . " 3 minggu kemudian "Apa yang kamu lakukan ?! Aku tidak bisa lagi menutup jif kucing saya karena pop-up ANDA menutupi X di kanan atas, perbaiki."
MonkeyZeus
11
Saya pikir semua orang di sini tampaknya berpikir ini adalah ide yang buruk. Tetapi untuk membalikkan pertanyaan, mengapa Anda TIDAK menempatkan kode ini di kelas atau fungsi yang terpisah?
Karl Gjertsen

Jawaban:

87

Anda perlu mempertimbangkan biaya perubahan. Bagaimana jika Anda ingin mengubah cara koneksi dibuat? Seberapa mudahkah itu? Jika Anda memiliki banyak kode duplikat, maka menemukan semua tempat yang perlu diubah bisa memakan waktu dan rawan kesalahan.

Anda juga perlu mempertimbangkan kejelasan. Kemungkinan besar, harus melihat 30 baris kode tidak akan semudah dipahami sebagai panggilan tunggal ke fungsi "connectToInternet". Berapa banyak waktu yang hilang ketika mencoba memahami kode ketika fungsi baru perlu ditambahkan?

Ada beberapa kasus langka dimana duplikasi tidak menjadi masalah. Misalnya, jika Anda melakukan percobaan dan kode akan dibuang pada akhir hari. Tetapi secara umum, biaya duplikasi melebihi penghematan waktu yang kecil karena tidak harus menarik kode ke fungsi yang terpisah .

Lihat juga https://softwareengineering.stackexchange.com/a/103235/63172

Vaughn Cato
sumber
19
... dan siapa yang tahu apakah 30 baris ini benar-benar sama dengan yang lainnya yang pernah Anda lihat sebelumnya atau jika seseorang beralih ke port atau alamat IP yang berbeda dalam salinannya dengan alasan apa pun. Asumsi implisit bahwa " sekelompok 30 baris yang dimulai dengan HttpRequestsemuanya sama " adalah mudah untuk membuat kesalahan.
null
@null Sempurna. Saya pernah bekerja pada kode di mana ada koneksi koneksi database disalin dan ditempel di seluruh, tetapi beberapa memiliki perbedaan yang halus dalam pengaturan. Saya tidak tahu apakah ini penting, perubahan yang disengaja, atau hanya perbedaan acak
user949300
54

Tidak.

Bahkan, bahkan kode "sederhana" Anda harus dipecah menjadi beberapa bagian yang lebih kecil. Setidaknya dua.

Satu untuk membuat koneksi dan menangani respon 200 normal. Misalnya, bagaimana jika Anda mengubah dari POST ke PUT dalam beberapa kasus? Bagaimana jika Anda membuat zillions koneksi ini dan memerlukan multi-threading atau koneksi-pooling? Memiliki kode di satu tempat, dengan argumen untuk metode ini, akan membuat ini lebih mudah

Demikian pula yang lain untuk menangani kesalahan. Misalnya, jika Anda mengubah warna atau ukuran font peringatan. Atau Anda mengalami masalah dengan koneksi terputus-putus dan ingin mencatat kesalahan.

pengguna949300
sumber
Anda juga dapat mengutip SRP: memiliki blok kode yang hanya memiliki satu tujuan membuatnya jauh lebih mudah untuk dipahami dan dipelihara ..
Roland Tepp
Ini adalah satu kasus di mana KERING dan SRP benar-benar sejajar. Terkadang tidak.
user949300
18

apakah dapat menyalin dan menempel ...

Tidak.

Bagi saya, argumen yang menentukan adalah argumen ini:

... itu biasa digunakan ...

Jika Anda menggunakan sepotong kode di lebih dari satu tempat maka, ketika itu berubah, Anda harus mengubahnya di lebih dari satu tempat atau Anda mulai mendapatkan ketidakkonsistenan - "hal-hal aneh" mulai terjadi (yaitu Anda memperkenalkan Bug).

itu mudah dan tidak rumit ...

Dan seharusnya semuanya menjadi lebih mudah direvisi menjadi suatu fungsi.

... ada bundel pengaturan seperti url, ukuran font ...

Dan apa yang suka diubah pengguna ? Font, ukuran font, warna, dll., Dll.

Sekarang; di berapa banyak tempat Anda harus mengubah potongan kode yang sama untuk mendapatkan mereka semua warna / font / ukuran yang sama lagi? (Jawaban yang disarankan: hanya satu ).

... segmen kode memiliki sedikit variasi di antara kelas (misalnya: url, meminta data, menangani kasus kode kesalahan, kasus menangani normal ...)

Variasi => parameter fungsi.

Phill W.
sumber
"Dan apa yang suka diubah pengguna? Font, ukuran font, warna, dll." Begitulah masalahnya. Apakah Anda benar-benar ingin mengubahnya di banyak lokasi?
Dan
8

Ini tidak benar-benar ada hubungannya dengan salin dan tempel. Jika Anda mengambil kode dari tempat lain, di kedua Anda mengambil kode itu Anda kode dan Anda bertanggung jawab, jadi apakah itu disalin atau ditulis benar-benar sendiri tidak membuat perbedaan.

Di peringatan Anda, Anda membuat beberapa keputusan desain. Kemungkinan keputusan desain serupa harus dibuat untuk semua peringatan. Jadi kemungkinan Anda harus memiliki metode di suatu tempat "ShowAlertInAStyleSuitableForMyApplication" atau mungkin sedikit lebih pendek, dan itu harus dipanggil.

Anda akan memiliki banyak permintaan http dengan penanganan kesalahan serupa. Anda seharusnya tidak menduplikasi penanganan kesalahan lagi dan lagi dan lagi tetapi mengekstrak penanganan kesalahan umum. Terutama jika penanganan kesalahan Anda menjadi sedikit lebih rumit (bagaimana dengan kesalahan batas waktu, 401, dan sebagainya).

gnasher729
sumber
6

Duplikasi OK dalam beberapa keadaan. Tapi tidak untuk yang ini. Metode itu terlalu rumit. Ada batas yang lebih rendah, ketika duplikasi lebih mudah daripada "memfaktorkan" metode.

Sebagai contoh:

def add(a, b)
    return a + b
end

bodoh, lakukan a + b.

Tetapi ketika Anda hanya mendapatkan sedikit, sedikit lebih kompleks, maka Anda biasanya melewati batas.

foo.a + foo.b

harus menjadi

foo.total
def foo
    ...
    def total
        return self.a + self.b
    end
end

Dalam kasus Anda, saya melihat empat "metode". Mungkin di kelas yang berbeda. Satu untuk membuat permintaan, satu untuk mendapatkan respons, satu untuk menampilkan kesalahan, dan semacam panggilan balik untuk dipanggil setelah respons kembali untuk memproses respons. Saya pribadi mungkin akan menambahkan semacam "pembungkus" di atas itu juga untuk membuat panggilan lebih mudah.

Pada akhirnya, untuk membuat permintaan web saya ingin panggilan terlihat seperti:

Web.Post(URI, Params, ResponseHandler);

Baris itu adalah apa yang saya miliki di seluruh kode saya. Kemudian ketika saya perlu melakukan perubahan pada "bagaimana saya mendapatkan barang" saya dapat dengan cepat melakukannya, dengan usaha yang jauh lebih sedikit.

Ini juga membuat kode KERING dan membantu dengan SRP .

kapas
sumber
0

Dalam suatu proyek dengan berbagai ukuran / kompleksitas, saya ingin dapat menemukan kode ketika saya membutuhkannya untuk tujuan berikut:

  1. Perbaiki saat rusak
  2. Ubah fungsionalitasnya
  3. Gunakan kembali.

Bukankah menyenangkan, untuk bergabung dengan proyek yang sedang berjalan atau terus mengerjakan proyek selama beberapa tahun dan ketika permintaan baru untuk "terhubung ke internet dan menunjukkan hasil koneksi" ada di beberapa lokasi yang mudah ditemukan karena memiliki desain yang bagus daripada mengandalkan melakukan pencarian di seluruh kode untuk httprequest? Mungkin lebih mudah ditemukan dengan Google.

Jangan khawatir, saya orang baru dan saya akan memperbaiki blok kode ini karena saya sangat kesal karena bergabung dengan tim yang tidak mengerti ini dengan basis kode yang buruk atau saya sekarang berada di bawah banyak tekanan seperti yang lainnya. Anda dan hanya akan menyalin dan menempelnya. Setidaknya itu akan menjaga bos dari punggungku. Kemudian ketika proyek benar-benar diidentifikasi sebagai bencana, saya akan menjadi yang pertama merekomendasikan kami menulis ulang dengan menyalin dan menempel versi dalam kerangka terbaru dan terhebat yang tidak ada di antara kita yang mengerti.

JeffO
sumber
0

Kelas dan / atau fungsi lebih baik, setidaknya menurut saya. Untuk sekali, itu membuat file lebih kecil yang merupakan keuntungan yang sangat berat jika Anda berurusan dengan aplikasi web atau aplikasi untuk perangkat dengan sedikit penyimpanan (IoT, ponsel lama, dll.)

Dan jelas poin terbaiknya adalah bahwa jika Anda memiliki sesuatu untuk diubah karena protokol baru, dll. Anda hanya mengubah konten fungsi dan tidak terhitung berapa kali Anda meletakkan fungsi ini di suatu tempat yang bahkan mungkin dalam file yang berbeda membuat mereka lebih sulit untuk temukan dan ubah.

Saya menulis seluruh penerjemah SQL sehingga saya bisa beralih lebih baik dari MySQL ke MySQLi di PHP, karena saya hanya perlu mengubah juru bahasa saya dan semuanya berfungsi, meskipun itu sedikit contoh yang ekstrem.

My1
sumber
-1

Untuk memutuskan apakah suatu kode harus digandakan atau dipindahkan ke suatu fungsi yang disebut dua kali, cobalah untuk menentukan mana yang lebih mungkin:

  1. Penting untuk mengubah kedua penggunaan kode dengan cara yang sama.

  2. Penting untuk mengubah setidaknya satu penggunaan kode sehingga mereka berbeda.

Dalam kasus pertama, kemungkinan akan lebih baik untuk memiliki satu fungsi menangani kedua penggunaan; dalam kasus terakhir, kemungkinan akan lebih baik untuk memiliki kode terpisah untuk dua penggunaan.

Dalam memutuskan apakah sepotong kode yang akan digunakan sekali harus ditulis in-line atau ditarik ke fungsi lain, cari tahu bagaimana seseorang akan sepenuhnya menggambarkan perilaku yang diperlukan fungsi. Jika deskripsi lengkap dan akurat tentang perilaku yang diperlukan fungsi akan lebih panjang atau lebih lama dari kode itu sendiri, memindahkan kode ke fungsi yang terpisah dapat membuat hal-hal lebih sulit untuk dipahami daripada lebih mudah. Mungkin masih layak dilakukan jika ada kemungkinan besar bahwa penelepon kedua akan perlu menggunakan fungsi yang sama, dan setiap perubahan di masa depan pada fungsi tersebut akan perlu memengaruhi kedua penelepon, tetapi jika tidak ada pertimbangan seperti itu, keterbacaan akan mendukung pemisahan. ke tingkat di mana kode dan deskripsi perilaku yang diperlukan akan sama-sama panjang.

supercat
sumber