Pertimbangkan metode ini:
public List<Employee> GetAllEmployees()
{
using (Entities entities = new Entities())
{
return entities.Employees.ToList();
}
}
public List<Job> GetAllJobs()
{
using (Entities entities = new Entities())
{
return entities.Jobs.ToList();
}
}
public List<Task> GetAllTasksOfTheJob(Job job)
{
using (Entities entities = new Entities())
{
return entities.Tasks.Where(t => t.JobId == job.Id).ToList();
}
}
Penggunaan blok sama dan telah diulang 3 kali di sini (tentu saja, lebih dari 100 kali dalam aplikasi nyata). Bagaimana mungkin menerapkan prinsip DRY (Don't Repeat Yourself) untuk using
blok? Apakah itu dianggap sebagai pelanggaran prinsipal KERING sama sekali?
Pembaruan: Saya tidak berbicara tentang apa yang telah diterapkan di dalam using
blok. Apa yang sebenarnya saya maksud di sini, adalah using (Entities entities = new Entities())
. Baris ini diulang 100 kali atau lebih.
c#
design-patterns
dry
Saeed Neamati
sumber
sumber
Jawaban:
Satu ide adalah untuk membungkusnya dengan fungsi yang membutuhkan
Func
.Sesuatu seperti ini
Maka kode Anda di atas menjadi
Saya membuat
Entities
param tipe juga, karena saya berasumsi Anda memiliki lebih dari satu tipe yang Anda lakukan dengan ini. Jika tidak, Anda bisa menghapusnya dan cukup menggunakan param jenis untuk jenis kembali.Sejujurnya meskipun kode semacam ini tidak membantu keterbacaan sama sekali. Dalam pengalaman saya, semakin banyak rekan kerja Jr yang mengalami kesulitan juga.
Perbarui Beberapa variasi tambahan tentang pembantu yang mungkin Anda pertimbangkan
sumber
Entities
.IEnumerable
fungsi jika ada non-IEnumerable
properti T yang diinginkan pemanggil dikembalikan, tetapi Anda benar, itu akan sedikit membersihkannya. Mungkin memiliki pembantu untuk Single danIEnumerable
hasilnya akan bagus. Yang mengatakan, saya masih berpikir itu memperlambat pengakuan tentang apa yang dilakukan kode, terutama untuk seseorang yang tidak terbiasa menggunakan banyak obat generik dan lambda (mis. Rekan kerja Anda yang TIDAK pada SO :))WithEntities
, gunakanFunc<T,IEnumerable<K>>
sebagai gantiFunc<T,K>
, dan beri "WithEntities" nama yang lebih baik (seperti SelectEntities). Dan saya tidak berpikir "Entitas" perlu menjadi parameter umum di sini.where T : IDisposable, new()
, seperti yangusing
diperlukanIDisposable
untuk bekerja.Bagi saya ini akan seperti mengkhawatirkan tentang mencari koleksi yang sama beberapa kali: itu hanya sesuatu yang perlu Anda lakukan. Setiap upaya untuk abstrak lebih lanjut akan membuat kode tersebut jauh lebih mudah dibaca.
sumber
foreach
koleksi yang sangat besar atau logika dalamforeach
loop memakan waktu misalnya. Sebuah motto yang saya adopsi: Jangan terobsesi tetapi selalu perhatikan pendekatan AndaSepertinya Anda mengacaukan prinsip "Once and Only Once" dengan prinsip KERING. Prinsip KERING menyatakan:
Namun prinsip Once dan Only Once sedikit berbeda.
Prinsip KERING biasanya digunakan dalam konteks logika aktual, tidak terlalu berlebihan menggunakan pernyataan:
Sumber
sumber
Saya gagal melihat penggunaan di
using
sini:Bagaimana tentang:
Atau bahkan lebih baik, karena saya pikir Anda tidak perlu membuat objek baru setiap saat.
Adapun untuk melanggar KERING: KERING tidak berlaku pada tingkat ini. Sebenarnya tidak ada prinsip yang benar-benar berlaku, kecuali keterbacaan. Mencoba menerapkan KERING pada tingkat itu benar-benar hanya mikro-optimasi arsitektur, yang seperti semua mikro-optimasi hanya sepeda-shedding dan tidak mendapatkan masalah diselesaikan, tetapi bahkan risiko untuk memperkenalkan yang baru.
Dari pengalaman saya sendiri, saya tahu bahwa jika Anda mencoba mengurangi redundansi kode pada level itu, Anda membuat dampak negatif pada kualitas kode, dengan mengaburkan apa yang benar-benar jelas dan sederhana.
Sunting:
Oke. Jadi masalahnya sebenarnya bukan statemen using, masalahnya adalah ketergantungan pada objek yang Anda buat setiap waktu. Saya sarankan menyuntikkan konstruktor:
sumber
using (CustomTransaction transaction = new CustomTransaction())
blok kode dalam kode kita untuk mendefinisikan ruang lingkup transaksi. Itu tidak dapat digabungkan menjadi satu objek dan di setiap tempat Anda ingin menggunakan transaksi, Anda harus menulis blokir. Sekarang bagaimana jika Anda ingin mengubah jenis transaksi dariCustomTransaction
menjadiBuiltInTransaction
dalam lebih dari 500 metode? Bagi saya ini merupakan tugas yang berulang dan contoh pelanggaran prinsipal KERING.using
(dalam konteks ini) masih merupakan "sintaksis yang nyaman"? Mengapa sangat menyenangkan untuk menggunakan =)Tidak hanya menggunakan kode duplikat (dengan cara itu adalah kode duplikat dan benar-benar membandingkan dengan coba..catch .. pernyataan terakhir) tetapi toList juga. Saya akan memperbaiki kode Anda seperti ini:
sumber
Karena tidak ada logika bisnis apa pun di sini kecuali yang terakhir. Ini tidak benar-benar KERING, menurut saya.
Yang terakhir tidak memiliki KERING di blok menggunakan tapi saya kira klausa di mana harus berubah di mana pun itu digunakan.
Ini adalah pekerjaan khas untuk pembuat kode. Tulis dan tutup pembuat kode dan biarkan menghasilkan untuk setiap jenis.
sumber
using (Entities entities = new Entities())
blok. Maksud saya, baris kode ini diulang 100 kali dan semakin berulang.Karena Anda membuat dan menghancurkan objek sekali pakai yang sama berulang-ulang, kelas Anda sendiri merupakan kandidat yang baik untuk menerapkan pola IDisposable.
Ini membuat Anda hanya perlu "menggunakan" saat membuat instance kelas Anda. Jika Anda tidak ingin kelas bertanggung jawab untuk membuang objek, maka Anda bisa membuat metode menerima ketergantungan sebagai argumen:
sumber
Sepotong sihir favoritku yang tak bisa dipercaya!
Wrap
ada hanya untuk abstrak itu atau sihir apa pun yang Anda butuhkan. Saya tidak yakin saya akan merekomendasikan ini sepanjang waktu tetapi mungkin untuk digunakan. Gagasan "yang lebih baik" adalah dengan menggunakan wadah DI, seperti StructureMap, dan hanya lingkup kelas Entitas ke konteks permintaan, menyuntikkannya ke dalam pengontrol, dan kemudian membiarkannya mengurus siklus hidup tanpa perlu pengontrol Anda.sumber
Func
cukup saya harus.