Bağımlılık İnversiyon Prensibi ne zaman uygulanmayacaktır?


43

Şu anda SOLID'i anlamaya çalışıyorum. Dolayısıyla, Bağımlılık İnversiyon Prensibi, herhangi bir iki sınıfın doğrudan değil de arayüzlerle iletişim kurması gerektiği anlamına gelir. Örnek: class ABir işaretçiyi türdeki bir nesneye bekleyen bir yönteme sahipse , class Bbu yöntem aslında türden bir nesne beklemelidir abstract base class of B. Bu, Aç / Kapat için de yardımcı olur.

Bunu doğru anlamış olsaydım, sorum şu , bunu tüm sınıf etkileşimlerine uygulamak iyi bir pratik mi olacaktı yoksa katmanlar açısından düşünmeye çalışmalı mıyım?

Şüpheci olmamın nedeni, bu prensibi izlememiz için biraz bedel ödüyor olmamız. Diyelim ki bu özelliği uygulamaya ihtiyacım var Z. Analizden sonra, ben özellik olduğu sonucuna Zişlevsellik oluşur A, Bve C. Ben oluşturmak cephe sınıf Z, yani arayüzleri aracılığıyla, sınıfları kullanır A, Bve C. Ben uygulanmasını kodlama başlar ve bir noktada ben görev biliyoruz Zaslında işlevsellik oluşur A, Bve D. Şimdi Carayüzü, Csınıf prototipini hurdaya ayırmam ve ayrı bir Darayüz ve sınıf yazmam gerekiyor. Arayüzler olmadan sadece sınıfın değiştirilmesi gerekecekti.

Başka bir deyişle, bir şeyi değiştirmek için, değiştirmem gerekiyor 1. arayan 2. arayüz 3. beyanname 4. uygulama. Doğrudan bağlı bir uygulamada bir pitonda sadece uygulamayı değiştirmem gerekecek .


13
Bağımlılık inversiyonu basit bir tekniktir, bu yüzden sadece gerektiğinde uygulanmalıdır ... uygulanabilecek derecesinde bir sınır yoktur, bu yüzden her yere uygularsanız, çöplerle sonuçlanırsınız: her durumda olduğu gibi özel teknik.
Frank Hileman,

Basitçe söylemek gerekirse, bazı yazılım tasarım ilkelerinin uygulanması, gereksinimler değiştiğinde acımasızca yeniden değerlendirebilmeye bağlıdır . Bunlardan, ara yüz kısmının, tasarımın sözleşmesel değişkenlerini en iyi şekilde yakaladığına inanılırken, kaynak kodun (uygulama) daha sık değişikliklere katlanabileceği düşünülmektedir.
rwong

@wwong Arabirim, sözleşmeye bağlı değişmezleri, yalnızca sözleşmesel değişmezleri destekleyen bir dil kullanıyorsanız yakalar. Yaygın dillerde (Java, C #), bir arayüz sadece bir API imza setidir. Gereksiz arayüzler eklemek yalnızca bir tasarımı düşürür.
Frank Hileman

Yanlış anladığını söyleyebilirim. DIP, yüksek seviye bileşenin düşük seviye için farklı bir uygulama kullanacağınız diğer bağlamlarda tekrar kullanılmasına izin vermek için "yüksek seviye" bir bileşenden "düşük seviye" bir olana derleme zamanı bağımlılıklarından kaçınmak üzere seviye bileşeni; bu, düşük seviyeli bileşenlerin uyguladığı yüksek düzeyde soyut bir tür yaratılarak yapılır; bu yüzden hem yüksek hem de düşük seviye bileşenler bu soyutlamaya bağlıdır. Sonunda, yüksek ve düşük seviye bileşenler bir arayüz üzerinden iletişim kurar, ancak bu DIP'nin özü değildir .
Rogério

Yanıtlar:


87

Birçok çizgi filmde veya diğer medyada, iyinin ve kötünün güçleri genellikle bir melek ve karakterin omuzlarında oturan bir iblis tarafından gösterilir. Buradaki hikâyemizde, iyilik ve kötülük yerine, bir omuzda SOLID ve diğer tarafta oturan YAGNI'ya (ihtiyacınız olmayacak!).

Maks'a alınan KATI ilkeleri, devasa, karmaşık, ultra yapılandırılabilir işletme sistemleri için en uygun olanıdır. Daha küçük veya daha spesifik sistemler için, her şeyi komik bir şekilde esnek hale getirmek uygun değildir, çünkü işleri soyutlamak için harcadığınız zaman bir yararı olmayacaktır.

Somut sınıflar yerine arayüzleri geçmek bazen örneğin bir ağ akışı için bir dosyadan okumayı kolayca değiştirebileceğiniz anlamına gelir. Ancak, yazılım projelerinin büyük bir miktar için, esneklik bu tür adil değil hiç ihtiyaç olacak ve siz de sadece somut dosya sınıflarını geçmek ve paydos ve beyin hücrelerini yedek olabilir.

Yazılım geliştirme sanatının bir kısmı, zaman geçtikçe neyin değişebileceğinin ve neyin değişmeyeceğine dair iyi bir anlayışa sahip olmaktır. Değişmesi muhtemel şeyler için, arayüzleri ve diğer SOLID kavramlarını kullanın. Olmayacak şeyler için YAGNI kullanın ve sadece somut tipleri geçin, fabrika sınıflarını unutun, tüm çalışma zamanını takmayı ve yapılandırmayı vb. Unutun ve bir çok SOLID soyutlamasını unutun. Tecrübelerime göre YAGNI yaklaşımının, olduğundan çok daha doğru olduğunu ispatladı.


19
SOLID'e ilk girişim 15 yıl önce inşa ettiğimiz yeni bir sistemdi. Hepimiz kool yardımcısını içtik. Herkes bu şey söz ederse kulağa YAGNI gibi, bizler "Pfffft ... plebeian" gibiydiler. Gelecekteki on yılda bu sistemin gelişmesini izleme onuruna (dehşeti?) Sahiptim. Kurucularımız bile olmadı, kimsenin anlayamadığı hantal bir karışıklık oldu. Mimarlar SOLID'i seviyor. Yaşamlarını gerçekten kazanan insanlar YAGNI'yi seviyorlar. İkisi de mükemmel değildir, ama YAGNI mükemmelliğe daha yakın ve ne yaptığınızı bilmiyorsanız varsayılanınız olmalıdır. :-)
Calphool

11
@Ward Evet, bunu bir projede yaptık. Onunla fındık gitti. Artık testlerimiz kısmen alay konusu nedeniyle okunması veya sürdürülmesi mümkün değildir. Bunun da ötesinde, bağımlılık enjeksiyonundan dolayı, bir şeyleri çözmeye çalışırken kodda gezinmek için arka tarafta ağrı var. KATI, gümüş bir kurşun değildir. YAGNI gümüş bir kurşun değildir. Otomatik test, gümüş bir kurşun değildir. Hiçbir şey sizi, ne yaptığınız hakkında düşünmek ve işinize ya da bir başkasının işlerine yardımcı olup olmayacağına dair kararlar almak gibi zor işlerden kurtaramaz .
jpmc26

22
Burada bir çok anti-SOLID duygusu var. KATI ve YAGNI, bir spektrumun iki ucu değildir. Grafikteki X ve Y koordinatları gibiler. İyi bir sistemin çok az gereksiz kodu (YAGNI) vardır ve SOLID ilkelerini izler.
Stephen

31
Meh, (a) SOLID'in = enterprisey olduğuna katılıyorum ve (b) SOLID'in tüm amacı, ihtiyaç duyulacak şey için son derece zayıf tahminciler olma eğiliminde olduğumuzdur. Burada @Stephen ile aynı fikirdeyim. YAGNI, bugün açıkça belirtilmemiş olan gelecekteki gereklilikleri öngörmeye çalışmamamız gerektiğini söylüyor. SOLID, tasarımın zaman içinde değişmesini beklememiz gerektiğini ve bunu kolaylaştırmak için bazı basit teknikleri uygulamamız gerektiğini söylüyor. Bunlar değil birbirini dışlayan; her ikisi de değişen gereksinimlere uyum sağlama teknikleridir. Asıl problemler belirsiz veya çok uzak ihtiyaçlar için tasarlamaya çalıştığınızda meydana gelir.
Aaron

8
"kolayca bir ağ akışı için bir dosyadan okumayı değiştirebilirsin" - bu, DI'nin aşırı basitleştirilmiş bir tanımının insanları saptırmasına yol açan iyi bir örnektir. İnsanlar bazen (aslında) "bu yöntem bir kullanacak File, bu yüzden bunun yerine bir IFileiş alacak " diye düşünürler . Sonra olamaz onlar arayüzü aşırı talep nedeniyle kolayca bir ağ akışı yerine, ve operasyonlar vardır IFilebir soket uygulayamaz böylece, priz için geçerli değildir hatta kullanmaz yöntemi IFile. DI'nin gümüş mermi olmadığı şeylerden biri, doğru soyutlamaları icat etmektir (arayüzler) :-)
Steve Jessop

11

Layman'ın sözleriyle:

DIP'yi uygulamak hem kolay hem de eğlencelidir . Tasarımı ilk denemede doğru yapmamak, DIP'den tamamen vazgeçmek için yeterli bir neden değildir.

  • Genellikle IDE'ler bu tür yeniden yapılandırma işlemlerini yapmanıza yardımcı olur, hatta bazıları zaten uygulanmış bir sınıfın dışını açmanıza izin verir
  • Tasarımı ilk seferinde doğru yapmak neredeyse imkansız
  • Normal iş akışı, geliştirmenin ilk aşamalarında arayüzlerin değiştirilmesini ve yeniden düşünülmesini içerir.
  • Gelişme geliştikçe olgunlaşır ve arayüzleri değiştirmek için daha az nedeniniz olur.
  • İleri bir aşamada arayüzler (tasarım) olgunlaşacak ve neredeyse hiç değişmeyecek
  • O andan itibaren, uygulamanız yükseltilmeye açık olduğundan, avantajlardan yararlanmaya başlarsınız.

Öte yandan, arayüzler ve OOD ile programlama, neşeyi bazen eski programlama programına geri getirebilir.

Bazı insanlar bunun karmaşıklık kattığını söylüyorlar ancak bence opossite doğru. Küçük projeler için bile. Test etmeyi / alay etmeyi kolaylaştırır. Herhangi bir caseifade veya iç içe geçmişse , kodunuzun daha az olmasını sağlar ifs. Siklomatik karmaşıklığı azaltır ve yeni şekillerde düşünmenizi sağlar. Programlamayı gerçek dünya tasarım ve imalatına daha benzer kılar.


5
OP tarafından hangi dillerin veya IDE'lerin kullanıldığını bilmiyorum, ancak VS 2013'te arayüzlere karşı çalışmak, arayüzleri ayıklamak ve uygulamak gülünç derecede basittir ve TDD kullanılıyorsa kritiktir. Bu ilkeleri kullanarak geliştirme için ek bir ek yükü yoktur.
stephenbayer

Soru DIP ile ilgiliyse, bu cevap neden DI hakkında konuşuyor? DIP 1990'lardan bir kavramdır, DI 2004'ten itibarendir. Çok farklıdır.
Rogério

1
(Önceki yorumum başka bir cevap için yapılmıştı; görmezden gelindi.) “Arayüzlere programlama” DIP'den çok daha genel bir konu değil, ancak her sınıfın ayrı bir arayüz oluşturmasıyla ilgili değil. Ve sadece test / alay aletleri ciddi sınırlamalardan muzdarip olursa "test / alay" işlemini kolaylaştırır.
Rogério

@ Rogério Genellikle DI kullanırken, her sınıf ayrı bir arayüz uygulamaz. Bir arayüz birkaç sınıf tarafından uygulanmaktadır.
Tulains Córdova

@ Rogério Cevabımı düzelttim, DI'den her bahsettiğimde DIP demek istedim.
Tulains Córdova

9

Mantıklı olan yerde bağımlılık inversiyonunu kullanın .

Aşırı bir karşı örnek, birçok dilde bulunan "string" sınıfıdır. Temelde bir dizi karakter olan ilkel bir kavramı temsil eder. Bu çekirdek sınıfı değiştirebileceğinizi varsayalım, DI'yi burada kullanmanın bir anlamı yoktur, çünkü dahili durumu asla başka bir şeyle değiştirmek zorunda kalmazsınız.

Dahili olarak başka modüllere maruz kalmayan veya herhangi bir yerde tekrar kullanılmayan bir modülde kullanılan bir nesne grubunuz varsa, muhtemelen DI kullanma çabalarına değmez.

Bence DI'nin otomatik olarak kullanılması gereken iki yer var:

  1. Uzatma için tasarlanmış modüllerde . Bir modülün tüm amacı onu genişletmek ve davranışı değiştirmek ise, DI'yi en baştan pişirmek çok mantıklıdır.

  2. Yeniden kullanım amacıyla yeniden modüle ettiğiniz modüllerde. Belki bir sınıfı yapmak için bir sınıfa kodladınız, daha sonra bir refactor ile bu kodu başka bir yerde kaldırabileceğinizi ve bunun için bir ihtiyaç olduğunu anlayın . Bu, DI ve diğer genişletilebilirlik değişiklikleri için harika bir aday.

Buradaki anahtarlar , ihtiyaç duyulan yerde kullanırlar çünkü ekstra karmaşıklık getirecektir ve bunun gerek teknik gerekliliklerle (birinci nokta) veya kantitatif kod incelemesiyle (ikinci nokta) ölçtüğünden emin olun .

DI harika bir araçtır, ancak herhangi bir * araç gibi, fazla veya yanlış kullanılabilir.

* Yukarıdaki kuralın istisnası: pistonlu testere, herhangi bir iş için mükemmel bir araçtır. Sorununuzu çözmezse, sorunu çözecektir. Kalıcı.


3
Ya "senin sorunun" duvardaki bir delikse? Bir testere onu çıkarmaz; daha da kötüleşirdi. ;)
Mason Wheeler

3
@MasonWheeler, kullanımı kolay ve güçlü bir testere ile, "duvardaki delik" kullanışlı bir varlık olan "giriş" e dönüşebilir :-)

1
Delik için bir yama yapmak için testereyi kullanamaz mısın?
JeffO

Olmayan bir kullanıcı genişletilebilir sahip olmanın bazı avantajları olsa da Stringtürünü, örneğin bir belirli bir kısmına bir alt kopyalamak (tip sanal operasyonlar iyi bir dizi olsaydı Diğer gösterimler yararlı olacaktır pek çok vaka vardır short[]bir olsun, raporu Subring yalnızca ASCII içeriyor veya içerebilir, yalnızca ASCII'yi belirtilen bir kısma ASCII içerdiğine inanılan bir alt byte[]diziyi kopyalamaya çalışın.) Dizeleri , herhangi bir yararlı dizeyle ilgili arayüz uygulamamak çok kötü çerçevelerdir.
supercat

1
Soru DIP ile ilgiliyse, bu cevap neden DI hakkında konuşuyor? DIP 1990'lardan bir kavramdır, DI 2004'ten itibarendir. Çok farklıdır.
Rogério

5

Bana öyle geliyor ki, asıl sorunun DIP noktasının bir parçası eksik.

Şüpheci olmamın nedeni, bu prensibi izlememiz için biraz bedel ödüyor olmamız. Söyleyin, Z özelliğini uygulamam gerekiyor. Analizden sonra, Z özelliğinin A, B ve C işlevlerinden oluştuğu sonucuna varıyorum. Z arayüzlü bir Z sınıfı oluşturuyorum. Arabirimler aracılığıyla A, B ve C sınıflarını kullanıyor. uygulama ve bir noktada Z görevinin aslında A, B ve D işlevselliğinden oluştuğunu anlıyorum. Şimdi C arabirimini, C sınıfı prototipini hurdalaştırmam ve ayrı D arabirimi ve sınıfı yazmam gerekiyor. Arayüzler olmadan, yalnızca sınıfın değiştirilmesi gereken dalga olacaktır.

DIP'den gerçekten faydalanmak için önce Z sınıfını oluşturacak ve (henüz geliştirilmemiş olan) A, B ve C sınıflarının işlevselliğini çağırmasını sağlayabilirsiniz. Bu size A, B ve C sınıfları için API verir. Sonra A, B ve C sınıflarını yaratıp ayrıntıları doldurursunuz. Z sınıfını oluştururken, tamamen Z sınıfının ihtiyaç duyduğu şeyi temel alarak ihtiyaç duyduğunuz soyutlamaları etkili bir şekilde oluşturmalısınız. A, B veya C sınıfları bile yazılmadan önce Z sınıfının etrafında testler bile yazabilirsiniz.

DIP’nin “Yüksek seviyeli modüllerin düşük seviyeli modüle bağlı olmamalı, her ikisinin de soyutlamaya bağlı olması gerektiğini” söylediğini unutmayın.

Z sınıfının neye ihtiyacı olduğunu ve ne istediğini almak istediğini belirledikten sonra, ayrıntıları doldurabilirsiniz. Elbette, bazen Z sınıfında değişiklik yapılması gerekebilir, ancak zamanın% 99'u bu şekilde olmaz.

Asla bir D sınıfı olmayacak çünkü Z'nin yazılmadan önce A, B ve C'ye ihtiyacı olduğunu belirlediniz. Gereksinimlerdeki bir değişiklik, tamamen farklı bir hikaye.


5

Kısa cevap "neredeyse asla" dır, ancak aslında DIP'nin anlam ifade etmediği birkaç yer vardır:

  1. İşi nesneler yaratmak olan fabrikalar veya inşaatçılar. Bunlar temel olarak IoC'yi tamamen kucaklayan bir sistemdeki "yaprak düğümleri" dir. Bir noktada, bir şey aslında nesnelerinizi yaratmalı ve bunun için başka hiçbir şeye bağlı olamaz. Birçok dilde, bir IoC konteyneri sizin için yapabilir, ancak bazen eski moda bir şekilde yapmanız gerekebilir.

  2. Veri yapılarının ve algoritmalarının uygulamaları. Genel olarak, bu durumlarda, optimize ettiğiniz belirgin özellikler (çalışma süresi ve asimptotik karmaşıklık gibi) kullanılan belirli veri türlerine bağlıdır. Bir karma tablosu uyguluyorsanız, bağlantılı bir liste değil, depolama için bir dizi ile çalıştığınızı bilmeniz gerekir ve yalnızca tablonun dizileri nasıl düzgün şekilde tahsis edeceğini bilir. Ayrıca değişken bir diziye geçmek istemezsiniz ve arayanın içeriği ile uğraşarak karma masanızı kırmasını istemediğinizden de emin olursunuz.

  3. Etki alanı modeli sınıfları. Bunlar, iş mantığınızı uygular ve (çoğu zaman) yalnızca bir uygulamaya sahip olmanız mantıklıdır, çünkü (çoğu zaman) yazılımı yalnızca bir işletme için geliştirirsiniz. Bazı etki alanı modeli sınıfları, diğer etki alanı modeli sınıfları kullanılarak oluşturulmuş olsa da, bu genellikle durum bazında olacaktır. Etki alanı modeli nesneleri, yararlı bir şekilde taklit edilebilecek herhangi bir işlevsellik içermediğinden, DIP'ye test edilebilirlik veya bakım kolaylığı sağlamaz.

  4. Harici bir API olarak sağlanan ve uygulama ayrıntılarını herkese açık olarak göstermek istemediğiniz diğer nesneleri oluşturması gereken nesneler. Bu, "kütüphane tasarımı uygulama tasarımından farklıdır" genel kategorisine girer. Bir kütüphane veya çerçeve DI'yi liberal bir şekilde kullanabilir, ancak sonunda gerçek bir çalışma yapmak zorunda kalacak, aksi halde çok kullanışlı bir kütüphane değildir. Bir ağ kütüphanesi geliştirdiğinizi varsayalım; Eğer gerçekten do not tüketicinin bir soket kendi uygulamasını sağlamak isterler. Dahili olarak bir soketin soyutlamasını kullanabilirsiniz, ancak arayanlara maruz bıraktığınız API kendi soketlerini oluşturacak.

  5. Birim testleri ve test iki katına çıkar. Sahte ve saplamalar bir şey yapmalı ve basitçe yapmalı. Bağımlılık enjeksiyonunu yapıp yapmama konusunda endişelenecek kadar karmaşık bir sahtekarsanız, o zaman muhtemelen çok karmaşıktır (belki de çok karmaşık bir arayüz uygulamasından dolayıdır).

Daha fazlası olabilir; bunlar biraz sıkça gördüğüm şeyler .


"Dinamik bir dilde çalıştığınız zaman" hakkında ne düşünüyorsunuz?
Kevin,

Hayır? JavaScript'te çok fazla iş yapıyorum ve hala orada eşit derecede geçerli. SOLID'deki "O" ve "I", biraz bulanık olabilir.
Aarona,

Huh ... Python'un ördek sınıflandırma ile birleştirilmiş birinci sınıf tiplerinin daha az gerekli olmasını sağladığını biliyorum.
Kevin,

DIP'nin kesinlikle tip sistemiyle hiçbir ilgisi yoktur. Ve hangi şekilde "birinci sınıf" python için benzersizdir? İzole edilmiş bir şeyi test etmek istediğinizde, bağımlılıkları için test ikilisini kullanmanız gerekir. Bu sınama çiftleri, bir arabirimin alternatif uygulamaları olabilir (statik olarak yazılmış dillerde) veya bunlar üzerinde aynı yöntemlere / işlevlere sahip olan anonim nesneler veya alternatif türler olabilir (ördek yazma). Her iki durumda da, bir örneği gerçekten değiştirmenin bir yoluna ihtiyacınız var.
Aarona,

1
@Kevin python, dinamik yazma ya da gevşek alaylara sahip olan ilk dildi. Aynı zamanda tamamen alakasız. Soru, bir nesnenin türünün ne olduğu değil, o nesnenin nasıl / nerede yaratıldığıdır. Bir nesne kendi bağımlılıklarını yarattığında, genel API'nin bahsetmediği sınıfların kurucularını bastırmak gibi korkunç şeyler yaparak uygulama detaylarının ne olması gerektiğini birim testine zorlarsınız. Test etmeyi, karışma davranışını ve nesne yapısını unutmayı basitçe sıkı bir şekilde birleştirmeye yol açar. Ördek yazarak bu sorunlardan birini çözmez.
Aaron

2

Bazı işaretler DIP'yi çok düşük bir seviyede mikro değerde uyguladığınız, değer sağlamadığı durumlar:

  • Bir C / CImpl veya IC / C çiftine sahip olursunuz, sadece bu arabirimin tek bir uygulaması ile
  • Arayüzünüzdeki ve uygulamanızdaki imzalar bire bir eşleşiyor (DRY ilkesini ihlal ediyor)
  • C ve CImpl'i aynı anda sık sık değiştirirsiniz.
  • C projenizin içindedir ve projeniz dışında bir kütüphane olarak paylaşılmaz.
  • sizi gerçek sınıf yerine arabirime götüren Visual Studio'daki Eclipse / F12'deki F3 ile sinirli oluyorsunuz

Gördüğünüz şey buysa, doğrudan Z çağrısı C ye girip arayüzü atlamanız daha iyi olabilir.

Ayrıca, bağımlılık enjeksiyon / dinamik proxy çerçevesiyle (Spring, Java EE) yöntem dekorasyonunu gerçek SOLID DIP ile aynı şekilde düşünmüyorum - bu daha çok yöntem dekorasyonunun bu teknoloji yığında nasıl çalıştığını gösteren bir uygulama detayı gibi. Java EE topluluğu , eskisi gibi Foo / FooImpl çiftlerine ihtiyaç duymadığınız bir gelişme olarak görür ( başvuruda ). Buna karşılık, Python birinci sınıf dil özelliği olarak işlev dekorasyonunu destekler.

Ayrıca bu blog gönderisine bakın .


0

Her zaman bağımlılıklarınızı tersine çevirirseniz, tüm bağımlılıklarınız altüst olur. Bunun anlamı, dağınık kodla bir bağımlılık düğümü ile başlarsanız, hala (gerçekten) sahip olduğunuz şeydir, tam tersine çevirdiniz. Bir uygulamadaki her değişikliğin kendi arayüzünü de değiştirmesi gereken sorunu nerede elde edersiniz.

Bağımlılık inversiyonunun amacı, işleri karışık yapan bağımlılıkları seçmeli olarak tersine çeviriyor olmanızdır . A'dan B'ye C'ye gitmesi gerekenler hala öyle, C'den A'ya gidenler, şimdi A'dan C'ye gidenler.

Sonuç, döngü içermeyen bir bağımlılık grafiği olmalıdır - bir DAG. Orada çeşitli araçlar bu özelliği işaretleyin ve grafik çekecektir.

Daha ayrıntılı bir açıklama için bu makaleye bakın :

Bağımlılık İnversiyon Prensibi'ni doğru uygulamanın özü şudur:

İstediğiniz kodu / hizmeti /… bir arayüze ve uygulamaya bölün. Arabirim, onu kullanan kodun jargonundaki bağımlılığı yeniden yapılandırır, uygulama onu altta yatan teknikleri açısından uygular.

Uygulama olduğu yerde kalır. Ancak, arayüzün şu anda farklı bir işlevi vardır (ve farklı bir jargon / dil kullanır), kullanım kodunun yapabileceği bir şeyi tarif eder. Onu bu pakete taşıyın. Arabirimi ve uygulamayı aynı pakete yerleştirmeyerek, bağımlılığın yönü (kullanıcı yönü) kullanıcı → uygulamadan uygulama → kullanıcıya ters çevrilir.

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.