Latar Belakang
Saya sedang mengerjakan proyek C # yang sedang berjalan. Saya bukan programmer C #, terutama programmer C ++. Jadi saya ditugaskan pada dasarnya tugas yang mudah dan refactoring.
Kode ini berantakan. Ini proyek besar. Karena pelanggan kami sering menuntut rilis dengan fitur-fitur baru dan perbaikan bug, semua pengembang lainnya dipaksa untuk mengambil pendekatan brute force saat coding. Kode ini sangat tidak dapat dipelihara dan semua pengembang lain setuju dengannya.
Saya di sini bukan untuk berdebat apakah mereka melakukannya dengan benar. Ketika saya refactoring, saya bertanya-tanya apakah saya melakukannya dengan cara yang benar karena kode refactored saya kelihatannya kompleks! Inilah tugas saya sebagai contoh sederhana.
Masalah
Ada enam kelas: A
, B
, C
, D
, E
dan F
. Semua kelas memiliki fungsi ExecJob()
. Keenam implementasi sangat mirip. Pada dasarnya, pada mulanya A::ExecJob()
ditulis. Kemudian diperlukan versi yang sedikit berbeda yang diterapkan B::ExecJob()
oleh copy-paste-modifikasi A::ExecJob()
. Ketika versi lain yang sedikit berbeda diperlukan, C::ExecJob()
ditulis dan sebagainya. Keenam implementasi memiliki beberapa kode umum, kemudian beberapa baris kode yang berbeda, lalu beberapa kode umum dan seterusnya. Berikut adalah contoh sederhana dari implementasinya:
A::ExecJob()
{
S1;
S2;
S3;
S4;
S5;
}
B::ExecJob()
{
S1;
S3;
S4;
S5;
}
C::ExecJob()
{
S1;
S3;
S4;
}
Di mana SN
sekelompok pernyataan yang sama persis.
Untuk menjadikannya umum, saya telah membuat kelas lain dan memindahkan kode umum dalam suatu fungsi. Menggunakan parameter untuk mengontrol grup pernyataan mana yang harus dieksekusi:
Base::CommonTask(param)
{
S1;
if (param.s2) S2;
S3;
S4;
if (param.s5) S5;
}
A::ExecJob() // A inherits Base
{
param.s2 = true;
param.s5 = true;
CommonTask(param);
}
B::ExecJob() // B inherits Base
{
param.s2 = false;
param.s5 = true;
CommonTask(param);
}
C::ExecJob() // C inherits Base
{
param.s2 = false;
param.s5 = false;
CommonTask(param);
}
Perhatikan bahwa, contoh ini hanya menggunakan tiga kelas dan pernyataan yang terlalu disederhanakan. Dalam praktiknya, CommonTask()
fungsinya terlihat sangat kompleks dengan semua pengecekan parameter dan masih banyak lagi pernyataan. Juga, dalam kode nyata, ada beberapa CommonTask()
fungsi yang tampak.
Meskipun semua implementasi berbagi kode umum dan ExecJob()
fungsi terlihat lebih manis, ada dua masalah yang mengganggu saya:
- Untuk setiap perubahan
CommonTask()
, keenam fitur (dan mungkin lebih banyak di masa depan) perlu diuji. CommonTask()
sudah kompleks. Ini akan menjadi lebih kompleks dari waktu ke waktu.
Apakah saya melakukannya dengan cara yang benar?