Son birkaç yılda, yavaş yavaş adım adım ilerleyerek daha iyi yazılmış bir koda geçiyoruz, bir seferde birkaç adım. Sonunda en azından SOLID'e benzeyen bir şeye geçmeye başlıyoruz, ancak henüz tam olarak orada değiliz. Geçiş yaptıktan bu yana, geliştiricilerin en büyük şikayetlerinden biri, daha önce her görevin yalnızca geliştiricinin 5-10 dosyaya dokunmasını gerektirdiği düzinelerce ve düzinelerce dosyayı incelemeye ve geçmeye devam edememeleri.
Geçiş yapmaya başlamadan önce, mimarimiz aşağıdakine benzer şekilde düzenlenmiştir (bir veya iki büyüklük sırası ile daha fazla dosya verilir):
Solution
- Business
-- AccountLogic
-- DocumentLogic
-- UsersLogic
- Entities (Database entities)
- Models (Domain Models)
- Repositories
-- AccountRepo
-- DocumentRepo
-- UserRepo
- ViewModels
-- AccountViewModel
-- DocumentViewModel
-- UserViewModel
- UI
Dosya bilge, her şey inanılmaz derecede doğrusal ve kompakt. Açıkçası çok sayıda kod kopyalama, sıkı bağlantı ve baş ağrısı vardı, ancak herkes onu geçip çözebilirdi. Tamamı acemiler, Visual Studio'yu hiç bu kadar açmayan insanlar, birkaç hafta içinde çözebilirlerdi. Genel dosya karmaşıklığının olmayışı, acemi geliştiricilerin ve yeni işe alınan kişilerin çok fazla rampa süresi olmadan da katkıda bulunmaya başlamalarını nispeten basit hale getiriyor. Ancak, kod stilinin herhangi bir yararı pencereden çıktığında bu oldukça fazla.
Kod tabanımızı daha iyi hale getirmek için yaptığımız her girişimi gönülden onaylıyorum, ancak takımın geri kalanından böyle büyük paradigma kaymaları konusunda bir miktar geri bildirim almak çok yaygın. Şu anda en büyük yapıştırma noktalarından birkaçı:
- Birim Testleri
- Sınıf Sayısı
- Akran Değerlendirmesi Karmaşıklığı
Ünite testleri, zaman kaybı olduklarına inandıkları ve kodlarını her parçadan ayrı olarak bir bütün olarak daha hızlı ele alabildiklerine inandıkları için takıma inanılmaz zor bir satış oldu. Birim testlerini SOLID için bir onay olarak kullanmak, çoğunlukla boşuna olmuştur ve bu noktada çoğunlukla bir şaka haline gelmiştir.
Sınıf sayısı muhtemelen üstesinden gelinmesi gereken en büyük engeldir. 5-10 dosya almak için kullanılan görevler şimdi 70-100 alabilir! Bu dosyaların her biri ayrı bir amaca hizmet etse de, dosyaların büyük bir bölümü ezici olabilir. Takımın tepkisi çoğunlukla inatçı ve kafa çiziciydi. Önceden bir görevin bir veya iki veri havuzu, bir veya iki model, bir mantık katmanı ve bir denetleyici yöntemi gerektirmiş olabilir.
Şimdi, basit bir dosya kaydetme uygulaması oluşturmak için dosyanın var olup olmadığını kontrol etmek için bir sınıfınız var, meta veri yazmak için bir sınıf, soyutlamak için bir sınıf var, DateTime.Now
böylece birim sınaması için zamanlar enjekte edebilir, mantık içeren her dosya için arayüzler, dosyalar Dışarıdaki her sınıf için birim testleri ve DI kabınıza her şeyi eklemek için bir veya daha fazla dosya içerecek şekilde.
Küçük ve orta büyüklükteki uygulamalar için SOLID çok kolay bir satıştır. Herkes fayda ve bakım kolaylığını görür. Bununla birlikte, çok büyük ölçekli uygulamalarda SOLID için iyi bir değer teklifi görmüyorlar. Bu yüzden, bizi artan acıları geçmemiz için organizasyon ve yönetimi iyileştirmenin yollarını bulmaya çalışıyorum.
Yeni tamamlanan bir göreve dayalı olarak, dosya hacminin bir örneğini biraz daha güçlendireceğimi düşündüm. Bir dosya senkronizasyon isteği almak için yeni mikro hizmetlerimizden bazılarında bazı işlevleri uygulama görevi verildi. İstek alındığında, hizmet bir dizi arama yapar ve kontrol eder ve sonunda belgeyi bir ağ sürücüsüne ve 2 ayrı veritabanı tablosuna kaydeder.
Belgeyi ağ sürücüsüne kaydetmek için birkaç özel sınıfa ihtiyacım vardı:
- IBasePathProvider
-- string GetBasePath() // returns the network path to store files
-- string GetPatientFolderName() // gets the name of the folder where patient files are stored
- BasePathProvider // provides an implementation of IBasePathProvider
- BasePathProviderTests // ensures we're getting what we expect
- IUniqueFilenameProvider
-- string GetFilename(string path, string fileType);
- UniqueFilenameProvider // performs some filesystem lookups to get a unique filename
- UniqueFilenameProviderTests
- INewGuidProvider // allows me to inject guids to simulate collisions during unit tests
-- Guid NewGuid()
- NewGuidProvider
- NewGuidProviderTests
- IFileExtensionCombiner // requests may come in a variety of ways, need to ensure extensions are properly appended.
- FileExtensionCombiner
- FileExtensionCombinerTests
- IPatientFileWriter
-- Task SaveFileAsync(string path, byte[] file, string fileType)
-- Task SaveFileAsync(FilePushRequest request)
- PatientFileWriter
- PatientFileWriterTests
Yani bu oldukça basit bir tasarruf sağlamak için toplam 15 ders (POCO ve iskele hariç). Bu sayı, birkaç sistemdeki varlıkları temsil etmek üzere POCO'lar yaratmam gerektiğinde, diğer ORM'lerimizle uyumlu olmayan üçüncü taraf sistemlerle iletişim kurmak için birkaç depo oluşturduğumda ve belirli işlemlerin karmaşıklıklarını ele almak için mantık yöntemleri oluşturduğumda önemli ölçüde yükseldi.