Bağlamı bir yöntem zincirinden geçirme modelleri


19

Bağlamını nasıl geçirileceğini: Bu oldukça çok yer geliyormuş gibi görünen bir tasarım kararı olduğu aracılığıyla yapan bir yönteme ihtiyaç olmayan bir yöntemle. Doğru bir cevap var mı yoksa bağlama bağlı mı?

Çözüm gerektiren örnek kod

// needs the dependency
function baz(session) {
  session('baz');
}

// doesn't care about the dependency
function bar() {
  baz();
}

// needs the dependency
function foo(session) {
   session('foo')
   bar();
}

// creates the dependency
function start() {
  let session = new Session();
  foo(session);
}

Muhtemel çözümler

  • threadlocal
  • global
  • bağlam nesnesi
  • bağımlılığı geçmek
  • baz köri ve ilk arg olarak ayarlanan bağımlılık ile çubuğa geçmek
  • bağımlılık enjeksiyonu

Nereye geldiğine dair örnekler

HTTP istek işleme

İstek öznitelikleri biçimindeki bağlam nesneleri sıklıkla kullanılır: bkz. Expressjs, Java Servlets veya .net'in owin'i.

Kerestecilik

Java günlüğü için halk genellikle globals / singletons kullanır. Tipik log4j / ortak günlük / java günlük kalıplarına bakın.

işlemler

İş parçacığı yerlileri, genellikle bunları gerektirmeyen tüm yöntemlere parametre olarak iletmek zorunda kalmamak için bir yöntem çağrısı zinciri ile ilişkili bir işlemi veya oturumu tutmak için kullanılır.


Lütfen daha anlamlı bir örnek kullanın.
Tulains Córdova

Nereye geldiğine dair bazı örnekler ekledim.
Jamie McCrindle

3
Daha anlamlı bir örnek kod demek istedim.
Tulains Córdova

Yanıtlar:


11

Tek adil cevap, programlama paradigmanızın deyimlerine bağlı olmasıdır. OO kullanıyorsanız, yöntemden yönteme bir yönteme bağımlı olmak neredeyse kesinlikle yanlıştır. OO'da bir kod kokusu. Aslında, bu OO'nun çözdüğü sorunlardan biridir - bir nesne bir bağlamı düzeltir . OO'da, doğru (her zaman başka yollar vardır) yaklaşım, bağımlılığı yapıcı veya mülkiyet yoluyla sağlamaktır. Bir yorumcu "Bağımlılık Enjeksiyonu" ndan bahsetmektedir ve bu kesinlikle yasaldır, ancak kesinlikle gerekli değildir. Sadece bağımlılığı sağlayın, böylece foove üyesi olarak kullanılabilir baz.

Körelemeden bahsediyorsun, bu yüzden işlevsel programlamanın söz konusu olmadığını varsayacağım. Bu durumda, nesne bağlamının felsefi bir eşdeğeri kapanmadır. Bir kez daha bağımlılığı düzelten herhangi bir yaklaşım, böylece bağımlılara açıktır. Currying böyle bir yaklaşımdır (ve kulağa akıllı gelmenizi sağlar). Bir bağımlılığı kapatmanın başka yolları olduğunu unutmayın. Bazıları zarif, bazıları korkunç.

En Boy Odaklı programlamayı unutmayın . Son birkaç yıldır gözden düşmüş gibi görünüyor, ancak asıl amacı tam olarak tarif ettiğiniz sorunu çözmek . Aslında, klasik Aspect örneği günlüğe kaydetmektir. AOP'de, bağımlılık diğer kodlar yazıldıktan sonra otomatik olarak eklenir. AOP halkı buna " dokuma " diyor. Ortak yönler, uygun yerlerde koda dokunur. Bu, kodunuzu düşünmeyi kolaylaştırır ve oldukça havalıdır, ancak aynı zamanda yeni bir test yükü ekler. Son eserlerinizin sağlam olduğunu belirlemek için bir yola ihtiyacınız olacak. AOP'nin de cevapları var, bu yüzden korkutmayın.


Parametrelerin OO yöntemleri içinde iletilmesinin bir kod kokusu olduğunu iddia etmek oldukça tartışmalı bir ifadedir. Tam tersini savunuyorum: bir sınıfta karıştırma durumunu ve işlevselliğini teşvik etmek, OO paradigması tarafından yapılan en büyük hatalardan biridir ve bağımlılıkları bir kurucu yerine doğrudan yöntemlere enjekte ederek bunlardan kaçınmak iyi tasarlanmış bir parçanın işaretidir. OO olsun ya da olmasın kodun.
David Arno

3
@DavidArno Nesne durumunun sonucuna varmak yerine farklı bir paradigma kullanılmasını öneririm "OO paradigması tarafından yapılan en büyük hatalardan biri" ve sonra paradigmayı atlatmak. Hemen hemen her yaklaşıma karşı hiçbir şeyim yok ama genellikle yazarın araçlarıyla savaştığı koddan hoşlanmıyorum. Özel devlet, OO'nun ayırt edici bir özelliğidir. Bu özellikten kaçınırsanız, OO'nun gücünün bir kısmını kaybedersiniz.
Scant Roger

1
@DavidArno Tüm durum olan ve işlevselliği olmayan bir sınıfın, durumdaki değişmez ilişkileri zorlamak için bir mekanizması yoktur. Böyle bir sınıf hiç OO değildir.
Kevin Krumwiede

@KevinKrumwiede, bir dereceye kadar, yorumuma redükte ad absudium uyguladınız, ancak amacınız hala iyi. Devletteki değişmezlik, "OO'dan devam etmenin" önemli bir parçasıdır. Bu nedenle, karıştırma işlevinden ve durumundan kaçınmak, değişmezliği elde etmek için gereken bir durum nesnesinde yeterli işleve izin vermelidir (yapıcı tarafından ayarlanan ve alıcılar tarafından erişilen kapsüllenmiş alanlar).
David Arno

@ScantRoger, başka bir paradigmanın, yani fonksiyonel paradigmanın kabul edilebileceğini kabul ediyorum. İlginç bir şekilde, en modern "OO" dillerinin giderek artan bir işlevsel özellik listesi vardır ve bu nedenle bu araçlara sadık kalmak ve "araçla savaşmadan" işlev paradigmasını benimsemek mümkündür.
David Arno

10

Eğer barbağımlıysa baz, hangisi gerekiyorsa dependency, doğru kullanmak bariçin dependencyde gerekirbaz . Bu nedenle, doğru yaklaşımlar ya bağımlılığı bir parametre olarak iletmek barya da köri bazalıp bunu iletmek olacaktır bar.

İlk yaklaşımın uygulanması ve okunması daha kolaydır, ancak barve arasında bir bağlantı oluşturur baz. İkinci yaklaşım bu kuplajı kaldırır, ancak daha az net kodla sonuçlanabilir. Hangi yaklaşımın en iyi olduğu bu nedenle muhtemelen her iki fonksiyonun karmaşıklığına ve davranışına bağlı olacaktır. Örneğin, yan etkileri varsa bazveya dependencyvarsa, test kolaylığı muhtemelen çözümün seçildiği büyük bir sürücü olacaktır.

Ben önermek tüm diğer seçenekler doğada hem "hacky" ve hem test hem de izini izlemek zor ile sorunlara yol açabilir öneririz.


1
Neredeyse tamamen katılıyorum. Bağımlılık Enjeksiyonu başka bir "hacky" yaklaşımı olabilir.
Jonathan van de Veen

1
@JonathanvandeVeen, elbette dependencyparametreler üzerinden geçme eylemi bağımlılık enjeksiyonudur?
David Arno

2
@DavidArno Bağımlılık enjeksiyon çerçeveleri bu tür bağımlılıklardan kurtulmaz, sadece onları taşırlar. Sihir, onları sınıflarınızın dışına, testin Başka Birinin Sorunu olduğu bir yere taşımasıdır.
Kevin Krumwiede

Katılıyorum, bağımlılık enjeksiyonu geçerli bir çözümdür. Aslında en sık seçtiğim şey bu.
Jamie McCrindle

1

Felsefi Olarak Konuşma

David Arno'nun endişesine katılıyorum .

OP'yi uygulama çözümleri ararken okuyorum. Ancak, cevap tasarımı değiştirmektir . "Desenler"? OO tasarımı, her şey bağlam hakkındadır. Muhtemelen hamile, geniş, boş bir kağıt.

Mevcut kodla uğraşmak farklı, iyi bir bağlamdır.



Şu anda aynı problem üzerinde çalışıyorum. Eh, sadece bir değer enjekte edilebilir böylece yapılan kod copy-n-paste yüzlerce satır tamir ediyorum.

Kodu modüle etme

600 satır yinelenen kod atıp "A çağrıları B çağrıları C çağrıları D ..." yerine yeniden düzenlendi. "Çağrı A, dönüş, Çağrı B, dönüş, Çağrı C ..." var. Şimdi değeri sadece bu yöntemlerden birine enjekte etmemiz gerekiyor, diyelim ki E yöntemi.

Yapıcıya varsayılan bir parametre ekleyin. Mevcut arayanlar değişmez - "isteğe bağlı" buradaki etkin kelimedir. Bir argüman iletilmezse, varsayılan değer kullanılır. Daha sonra değişkeni yeniden düzenlenmiş, modüler yapıya geçirmek için sadece 1 satır değişir; ve kullanmak için E yönteminde küçük bir değişiklik.


Kapaklar

Bir Programcı iş parçacığı - "Bir program neden bir kapatma kullanıyor?"

Temel olarak, değerlerle özelleştirilmiş bir yöntem döndüren bir yönteme değerler enjekte edersiniz. Bu özelleştirilmiş yöntem daha sonra yürütülür.

Bu teknik, imzasını değiştirmeden mevcut bir yöntemi değiştirmenize izin verir.


Bu yaklaşım tuhaf tanıdık görünüyor ...

Roger zamansal bağlantı (bağlantınız) konusunda @Snowman. Gerekli icra emrinin kapsüllenmesi önemlidir.
radarbob
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.