Katmanlı bir yazılım mimarisinde aynı katmandaki nesneler arasında bağımlılık olması sorun yaratır mı?


12

N-katman mimarisine ve bağımlılık enjeksiyonuna sahip orta-büyük bir yazılım göz önüne alındığında, bir katmana ait bir nesnenin alt katmanlardaki nesnelere bağlı olabileceğini, ancak asla daha yüksek katmanlardaki nesnelere bağlı olabileceğini söylemek rahatım.

Ama aynı katmanın diğer nesnelerine bağlı nesneler hakkında ne düşüneceğimi bilmiyorum.

Örnek olarak, üç katman ve görüntüdeki gibi birkaç nesne içeren bir uygulama olduğunu varsayalım. Açıkça yukarıdan aşağıya bağımlılıklar (yeşil oklar) tamam, aşağıdan yukarıya (kırmızı ok) iyi değil, ama aynı katmanın içindeki bağımlılık hakkında ne var (sarı ok)?

resim açıklamasını buraya girin

Dairesel bağımlılık hariç, ortaya çıkabilecek başka herhangi bir konuyu ve bu durumda katmanlı mimarinin ne kadar ihlal edildiğini merak ediyorum.


Döngüleriniz yoksa, horysontal bağlantılara sahip olduğunuz bir katmanda, yalnızca katmanlar arasında bağımlılıkları olan alt katmanlara ayrılır
51'de maks630

Yanıtlar:


10

Evet, bir katmandaki nesneler , bazen döngüsel olanlar arasında doğrudan bağımlılıklara sahip olabilir - aslında, farklı katmanlardaki nesneler arasında doğrudan bağımlılığa izin verilmeyen veya sadece katı bir bağımlılığa izin verilen bağımlılıklar arasındaki temel farkı oluşturan şey budur. yön.

Ancak bu, bu tür bağımlılıklara keyfi bir şekilde sahip olmaları gerektiği anlamına gelmez. Aslında katmanlarınızın neyi temsil ettiğine, sistemin ne kadar büyük olduğuna ve parçaların sorumluluğunun ne olması gerektiğine bağlıdır. "Katmanlı mimari" nin belirsiz bir terim olduğuna dikkat edin, bunun farklı tür sistemlerde gerçekte ne anlama geldiğinin çok büyük bir varyasyonu vardır.

Örneğin, bir veritabanı katmanı, bir iş katmanı ve bir kullanıcı arayüzü (UI) katmanıyla "yatay olarak katmanlı bir sisteminiz" olduğunu varsayalım. UI katmanının en az birkaç düzine farklı iletişim sınıfı içerdiğini söyleyelim.

Diyalog sınıflarının hiçbirinin doğrudan başka bir diyalog sınıfına bağlı olmadığı bir tasarım seçilebilir. "Ana diyalogların" ve "alt diyalogların" bulunduğu bir tasarım seçilebilir ve sadece "ana" dan "alt" diyaloglara doğrudan bağımlılıklar vardır. Veya mevcut herhangi bir UI sınıfının aynı katmandaki diğer UI sınıflarını kullanabileceği / yeniden kullanabileceği bir tasarım tercih edilebilir.

Bunların hepsi olası tasarım seçimleridir, belki de inşa ettiğiniz sistemin türüne bağlı olarak az çok mantıklıdır, ancak hiçbiri sisteminizin "katmanını" geçersiz kılmaz.


UI örneğine devam edersek, iç bağımlılıklara sahip olmanın avantajları ve dezavantajları nelerdir? Kullanılan DI yöntemine bağlı olarak bir sorun olabilecek yeniden kullanımı ve döngüsel bağımlılıkları tanıtmayı kolaylaştırdığını görebiliyorum. Başka herhangi bir şey?
bracco23

@ bracco23: "İç" bağımlılıklara sahip olmanın artıları ve eksileri, keyfi bağımlılıklara sahip olmanın artıları ile aynıdır. "Eksileri", özellikle diğer bileşenlerden ayrı olarak bileşenleri yeniden kullanmayı ve test etmeyi zorlaştırıyorlar. Artıları, açık bağımlılıklar uyum gerektiren şeylerin kullanımını, anlaşılmasını, yönetilmesini ve test edilmesini kolaylaştırır.
Doc Brown

14

Bir katmana ait bir nesnenin alt katmanlardaki nesnelere bağlı olabileceğini söylemek rahatım

Dürüst olmak gerekirse, bu konuda rahat olmanız gerektiğini düşünmüyorum. Önemsiz bir sistemden başka bir şeyle uğraşırken, tüm katmanların yalnızca diğer katmanlardan soyutlamalara bağlı olmasını sağlamayı amaçlıyorum; hem düşük hem de yüksek.

Yani, örneğin, Obj 1bağımlı olmamalıdır Obj 3. Örneğe bağımlı IObj 3olmalı ve bu soyutlamanın hangi uygulamasının çalışma zamanında çalışacağı söylenmelidir. Söyleyen şey, işin bu bağımlılıkları haritalamak olduğu için herhangi bir seviyeyle ilgisi olmamalıdır. Bu bir IoC kapsayıcısı olabilir, örneğin mainsaf DI kullanan tarafından çağrılan özel kod . Ya da bir itme ile bir servis bulucu bile olabilir. Ne olursa olsun, katmanlar arasında bu eşleme sağlanana kadar bağımlılıklar mevcut değildir.

Ama aynı katmanın diğer nesnelerine bağlı nesneler hakkında ne düşüneceğimi bilmiyorum.

Doğrudan bağımlılıkların olması gereken tek zaman budur . Bu katmanın iç işleyişinin bir parçasıdır ve diğer katmanları etkilemeden değiştirilebilir. Yani zararlı bir bağlantı değil.


Cevap için teşekkürler. Evet, katman nesneleri değil, arayüzleri açığa çıkarmalıdır, biliyorum ama basitlik uğruna dışarıda bıraktım.
bracco23

4

Buna pratik olarak bakalım

resim açıklamasını buraya girin

Obj 3artık Obj 4var olduğunu biliyor . Ne olmuş yani? Neden önemsiyoruz?

DIP diyor

"Yüksek seviyeli modüller, düşük seviyeli modüllere bağlı olmamalı. Her ikisi de soyutlamalara bağlı olmalıdır."

Tamam ama, tüm nesnelerin soyutlamaları değil mi?

DIP ayrıca

"Soyutlamalar detaylara, detaylar soyutlamalara bağlı olmalıdır."

Tamam ama, nesnem düzgün bir şekilde kapsüllenmişse, bu herhangi bir ayrıntıyı gizlemiyor mu?

Bazı insanlar her nesnenin bir anahtar kelime arayüzüne ihtiyaç duyduğunu körü körüne ısrar etmeyi sever. Ben onlardan biri değilim. Eğer onları şimdi kullanmayacaksanız, daha sonra onlar gibi bir şeye ihtiyaç duymak için bir plana ihtiyacınız olduğunu körü körüne ısrar etmek istiyorum.

Kodunuz her sürümde tamamen yeniden oluşturulabiliyorsa, daha sonra ihtiyacınız olduğunda arayüzleri ayıklayabilirsiniz. Yeniden derlemek istemediğiniz bir kod yayınladıysanız ve kendinizi bir arayüz üzerinden konuşmak istediğinizi düşünüyorsanız, bir plana ihtiyacınız olacaktır.

Obj 3Obj 4var olduğunu bilir . Ama somut Obj 3olup olmadığını biliyor Obj 4mu?

İşte bu yüzden, newher yere yayılmaması çok güzel . Eğer somut Obj 3olup olmadığını bilmiyorsa Obj 4, muhtemelen yaratmadığı için, o zaman daha sonra Obj 4sokulur ve soyut bir sınıfa Obj 3dönerseniz umursamazsınız.

Eğer bunu yapabilirseniz, o zaman Obj 4boyunca tamamen soyut oldu. Başından itibaren aralarında bir arayüz oluşturan tek şey, birisinin yanlışlıkla şu Obj 4anda somut olan kodu veren kod eklemeyeceğinin güvencesidir . Korumalı inşaatçılar bu riski azaltabilir, ancak bu başka bir soruya yol açar:

Obj 3 ve Obj 4 aynı pakette mi?

Nesneler genellikle bir şekilde gruplandırılır (paket, ad alanı vb.). Akıllıca gruplandırıldığında, gruplar arasında değil, bir grup içindeki olası etkiler daha olasıdır.

Özelliğe göre gruplamayı seviyorum. Eğer Obj 3ve Obj 4aynı grupta ve katmanda vardır o bir tane yayınlanmış ve sadece diğeri değiştirmeye gerek ederken refactor istiyorum gelmiş olacak çok düşüktür. Bu, bu nesnelerin, açık bir ihtiyacı olmadan aralarına bir soyutlama getirmekten yararlanma olasılıklarının daha düşük olduğu anlamına gelir.

Bir grup sınırını geçiyorsanız, her iki taraftaki nesnelerin bağımsız olarak değişmesine izin vermek iyi bir fikirdir.

Bu kadar basit olmalı, ancak ne yazık ki hem Java hem de C #, bunu karmaşıklaştıran talihsiz seçimler yaptı.

C # 'da her anahtar kelime arabirimini bir Iönekle adlandırmak geleneğidir . Bu, istemcileri bir anahtar kelime arayüzüyle konuştuklarını bilmeye zorlar. Bu yeniden düzenleme planına karışıyor.

Java'da daha iyi bir adlandırma kalıbı kullanmak geleneği vardır: FooImple implements FooAncak, Java yalnızca anahtar kelime arabirimlerini farklı bir ikili dosyaya derlediğinden, bu yalnızca kaynak kodu düzeyinde yardımcı olur. Bu, somuttan Foosoyut kodlara değiştiğinizde, tek bir kod karakterine ihtiyaç duymadığınızda, hala derlenmelidir.

İnsanların gerçekten ihtiyaç duyuncaya kadar resmi soyutlamayı ertelemelerini engelleyen bu belirli dillerde bu HATALAR. Hangi dili kullandığınızı söylemediniz, ancak bu sorunları olmayan bazı diller olduğunu anladınız.

Hangi dili kullandığınızı söylemediniz, bu yüzden her yerde anahtar kelime arayüzleri olacağına karar vermeden önce dilinizi ve durumunuzu dikkatlice analiz etmenizi tavsiye edeceğim.

YAGNI prensibi burada kilit bir rol oynamaktadır. Ama "Lütfen kendimi ayağımı vurmayı zorlaştır".


0

Yukarıdaki cevaplara ek olarak, farklı bakış açılarından bakmanıza yardımcı olabilir.

Örneğin, Bağımlılık Kuralı açısından. DR, Robert C. Martin tarafından ünlü Temiz Mimarisi için önerilen bir kuraldır .

Diyor ki

Kaynak kodu bağımlılıkları yalnızca içeriye, daha üst düzey politikalara işaret etmelidir.

By üst düzey politikaları , O demektir üst seviyede bir soyutlama. Örneğin, somut sınıflar veya veri yapılarının aksine arayüzler veya soyut sınıflar gibi uygulama ayrıntılarına sızan bileşenler.

Mesele şu ki, kural katmanlar arası bağımlılıkla sınırlı değildir. Sadece ait oldukları yere veya katmana bakılmaksızın kod parçaları arasındaki bağımlılığa işaret eder.

Yani hayır, aynı katmanın elemanları arasında bağımlılıkların doğasında yanlış olan hiçbir şey yoktur. Bununla birlikte, bağımlılık, kararlı bağımlılık ilkesine uymak için hala uygulanabilir .

Başka bir bakış açısı SRP'dir.

Ayrıştırma, zararlı bağımlılıkları kırmanın ve bağımlılık inversiyonu (IoC) gibi bazı en iyi uygulamaları aktarmanın yoludur. Bununla birlikte, değişme nedenlerini paylaşan unsurlar birbirinden ayrılma nedenleri vermezler, çünkü aynı nedenden dolayı değişime neden olan elementler aynı anda değişecektir (büyük olasılıkla) ve aynı zamanda da konuşlandırılacaktır. Arasındaki durum buysa Obj3ve Obj4ardından bir kez daha doğal olarak yanlış bir şey yok.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.