Manakah dari desain ini yang lebih baik? Apa pro dan kontra dari masing-masing? Yang mana yang akan Anda gunakan? Saran lain tentang cara menangani metode seperti sangat dihargai.
Masuk akal untuk mengasumsikan bahwa Draw () adalah satu-satunya tempat dari mana metode draw lainnya dipanggil. Ini perlu diperluas ke lebih banyak metode Draw * dan Tampilkan * properti, bukan hanya tiga yang ditampilkan di sini.
public void Draw()
{
if (ShowAxis)
{
DrawAxis();
}
if (ShowLegend)
{
DrawLegend();
}
if (ShowPoints && Points.Count > 0)
{
DrawPoints();
}
}
private void DrawAxis()
{
// Draw things.
}
private void DrawLegend()
{
// Draw things.
}
private void DrawPoints()
{
// Draw things.
}
Atau
public void Draw()
{
DrawAxis();
DrawLegend();
DrawPoints();
}
private void DrawAxis()
{
if (!ShowAxis)
{
return;
}
// Draw things.
}
private void DrawLegend()
{
if (!ShowLegend)
{
return;
}
// Draw things.
}
private void DrawPoints()
{
if (!ShowPoints || Points.Count <= 0))
{
return;
}
// Draw things.
}
Jawaban:
Saya tidak berpikir Anda dapat memiliki aturan selimut untuk hal semacam ini, itu tergantung pada situasinya.
Dalam hal ini, saya akan menyarankan memiliki klausa if di luar metode karena nama-nama metode Draw menyiratkan bahwa mereka hanya menggambar hal-hal tanpa syarat khusus.
Jika Anda menemukan bahwa Anda harus melakukan cek sebelum memanggil metode di banyak tempat, maka Anda mungkin ingin memasukkan cek di dalam metode dan mengganti nama mereka untuk mengklarifikasi bahwa ini terjadi
sumber
Saya katakan yang kedua.
Metode harus memiliki tingkat abstraksi yang sama.
Dalam contoh kedua, tanggung jawab
Draw()
metode adalah bertindak seperti pengontrol, memanggil masing-masing metode menggambar individu. Semua kode dalamDraw()
metode ini memiliki tingkat abstraksi yang sama. Pedoman ini mulai digunakan dalam skenario penggunaan ulang. Misalnya, jika Anda tergoda untuk menggunakan kembaliDrawPoints()
metode ini dalam metode publik lain (sebut sajaSketch()
), Anda tidak perlu mengulangi klausa penjaga (pernyataan if memutuskan apakah akan menggambar poin).Dalam contoh pertama,
Draw()
metode ini bertanggung jawab untuk menentukan apakah akan memanggil masing-masing metode individu, dan kemudian memanggil metode-metode tersebut.Draw()
memiliki beberapa metode tingkat rendah yang berfungsi, namun mendelegasikan pekerjaan tingkat rendah lainnya ke metode lain, dan karenanyaDraw()
memiliki kode pada berbagai tingkat abstraksi. Dalam rangka untuk digunakan kembaliDrawPoints()
diSketch()
, Anda akan perlu untuk meniru penjaga klausul dalamSketch()
juga.Ide ini dibahas dalam buku Robert C. Martin "Clean Code", yang sangat saya rekomendasikan.
sumber
DrawAxis()
et. Al. untuk menunjukkan bahwa eksekusi mereka adalah kondisional, mungkinTryDrawAxis()
. Kalau tidak, Anda perlu menavigasi dariDraw()
metode ke setiap submetode individu untuk mengkonfirmasi perilakunya.Pendapat saya tentang subjek ini cukup kontroversial, tapi tetaplah, karena saya percaya hampir semua orang setuju pada hasil akhirnya. Saya hanya punya pendekatan berbeda untuk sampai ke sana.
Dalam artikel saya Function Hell , saya menjelaskan mengapa saya tidak suka metode pemisahan hanya demi menciptakan metode yang lebih kecil. Saya hanya membagi mereka ketika saya tahu , mereka akan digunakan kembali, atau tentu saja, ketika saya bisa menggunakannya kembali.
OP menyatakan:
Ini membawa saya ke opsi ketiga (menengah) yang tidak disebutkan. Saya membuat 'blok kode' atau 'paragraf kode' yang orang lain akan buat fungsinya.
OP juga menyatakan:
... jadi metode ini akan tumbuh sangat besar dengan cepat. Hampir semua orang setuju ini mengurangi keterbacaan. Menurut pendapat saya solusi yang tepat tidak hanya memecah menjadi beberapa metode, tetapi memecah kode menjadi kelas yang dapat digunakan kembali. Solusi saya mungkin akan terlihat seperti ini.
Argumen Ofcourse masih perlu disahkan dan semacamnya.
sumber
Untuk kasus-kasus ketika Anda memeriksa bidang yang mengontrol apakah akan menggambar atau tidak, masuk akal untuk memilikinya
Draw()
. Ketika keputusan itu menjadi lebih rumit, saya cenderung memilih yang terakhir (atau membaginya). Jika Anda akhirnya membutuhkan lebih banyak fleksibilitas, Anda selalu dapat mengembangkannya.Perhatikan metode tambahan dilindungi yang memungkinkan subclass untuk memperluas apa yang mereka butuhkan. Ini juga memungkinkan Anda untuk memaksa menggambar untuk pengujian atau apa pun alasan lain yang mungkin Anda miliki.
sumber
DrawPointsIfItShould()
metode yang pintasif(should){do}
:)Dari dua alternatif itu, saya lebih suka versi pertama. Alasan saya adalah saya ingin metode untuk melakukan apa yang tersirat namanya, tanpa ada dependensi tersembunyi. DrawLegend harus menggambar legenda, bukan mungkin menggambar legenda.
Jawaban Steven Jeuris lebih baik daripada dua versi dalam pertanyaan.
sumber
Alih-alih memiliki
Show___
properti individual untuk setiap bagian, saya mungkin akan mendefinisikan bidang bit. Itu akan menyederhanakannya menjadi:Selain itu, saya akan cenderung memeriksa visibilitas dalam metode luar, bukan dalam. Lagi pula, itu
DrawLegend
bukanDrawLegendIfShown
. Tapi itu tergantung pada anggota kelas lainnya. Jika ada tempat lain yang memanggilDrawLegend
metode itu dan mereka perlu memeriksaShowLegend
juga, saya mungkin hanya memindahkan cek keDrawLegend
.sumber
Saya akan pergi dengan opsi pertama - dengan "jika" di luar metode. Ini lebih baik menjelaskan logika yang diikuti, ditambah memberi Anda pilihan untuk benar-benar menggambar sumbu, misalnya, dalam kasus ketika Anda ingin menggambar satu terlepas dari pengaturan. Plus itu menghilangkan overhead panggilan fungsi tambahan (dengan asumsi itu tidak inline), yang dapat terakumulasi jika Anda ingin kecepatan (contoh Anda sepertinya hanya menggambar grafik di mana itu mungkin bukan faktor, tetapi dalam animasi atau game bisa jadi).
sumber
Secara umum, saya lebih suka memiliki tingkat kode yang lebih rendah menganggap prasyarat terpenuhi dan melakukan pekerjaan apa pun yang seharusnya mereka lakukan, dengan pemeriksaan yang dilakukan lebih tinggi di tumpukan panggilan. Ini memiliki keuntungan samping dari menghemat siklus dengan tidak melakukan pemeriksaan berlebihan, tetapi itu juga berarti Anda dapat menulis kode yang bagus seperti ini:
dari pada:
Dan tentu saja ini menjadi lebih nastier jika Anda memaksakan keluar tunggal, memiliki memori yang Anda butuhkan untuk bebas, dll.
sumber
Itu semua tergantung pada konteks:
sumber