Sınıf yapıcısına veri (davranış vs) enjekte etmek ne anlama gelir ve bu neden kötü uygulama olarak kabul edilir?


10

Remo Jansen'in "Learning TypeScript" kitabını okuyorum. Bir bölümde yazar, Modelsınıfın nasıl oluşturulacağı da dahil olmak üzere çok basit bir kavram kanıtı MVC çerçevesinin nasıl oluşturulacağını açıklar ve şunları söyler:

Bir modelin, kullandığı web hizmetinin URL'siyle birlikte sağlanması gerekir. Tüketilecek hizmetin URL'sini ayarlamak için ModelSettings adlı bir sınıf dekoratörü kullanacağız. Hizmet URL'sini yapıcısı aracılığıyla enjekte edebiliriz, ancak bir sınıf yapıcısı aracılığıyla veri (bir davranışın aksine) enjekte etmek kötü bir uygulama olarak kabul edilir .

O son cümleyi anlamadım. Özellikle, "veri enjekte etmenin" ne anlama geldiğini anlamıyorum. Bana öyle geliyor ki, aşırı basitleştirilmiş örnekler kullanan JavaScript sınıflarına neredeyse tüm girişlerde, veriler, yapıcıya parametreleri aracılığıyla ("enjekte edildi"?) Örneğin:

class Person {
  constructor(name) {
    this.name = name;
  }
}

Kesinlikle nameveri olarak düşünürüm, davranış olarak değil ve evrensel olarak bu tür bir örneğe bir yapıcı parametresi olarak dahil edilir ve bunun kötü uygulama olduğuna dair hiçbir söz yoktur. Bu nedenle, ya "veri" ya da "enjekte" ya da başka bir şeyle kastedilen, yukarıdaki alıntıdaki bir şeyi yanlış anladığımı varsayıyorum.

Yanıtlarınız, JavaScript / TypeScript'te dekoratörlerin ne zaman, nerede, nasıl ve neden kullanılacağına ilişkin açıklamaları içerebilir, çünkü bu kavramın aradığım anlayışla yakından bağlantılı olduğundan şüpheleniyorum. Ancak, daha da önemlisi, bir sınıf yapıcısı aracılığıyla veri enjekte etmenin ne anlama geldiğini ve bunun neden kötü olduğunu daha iyi anlamak istiyorum.


Yukarıdaki alıntıya daha fazla bağlam vermek için durum budur: ModelBu örnekte, biri NASDAQ diğeri NYSE için borsa modelleri oluşturmak için kullanılacak bir sınıf yaratılır. Her model, ham verileri sağlayacak web hizmetinin veya statik veri dosyasının yolunu gerektirir. Kitap, bir yapıcı parametresi yerine bu bilgi için bir dekoratörün kullanılması gerektiğini belirtir ve aşağıdakilere yol açar:

@ModelSettings("./data/nasdaq.json")
class NasdaqModel extends Model implements IModel {
  constructor(metiator : IMediator) {
    super(metiator);
  }
...
}

Sadece neden hizmet url'sini sadece kurucu için bir parametre olarak değil dekoratör aracılığıyla eklemem gerektiğini anlamıyordum, örn.

constructor(metiator : IMediator, serviceUrl : string) {...

Google'da bağımlılık enjeksiyonu hakkında hızlı bir arama yapmanızı öneririm . Bu, bu soruyu sormak için doğru forum değil. :)
toskv

1
Kalbinize cevabınızı alacağım, ancak google'da arama yaptım ve bağımlılık enjeksiyonuyla ilgili tartışmalarla karşılaştım. "Bağımlılık enjeksiyonu" ve "veri enjeksiyonu" aynı şeyi mi ifade ediyor? Ayrıca, "bağımlılık enjeksiyonunun" "iyi bir şey" (veya en azından "alternatif bir şey") olduğu izlenimim varken, sağladığım alıntıdaki "veri enjeksiyonu" tartışmasının "kötü bir şey" gibi görünmesini sağlıyor .

Bağımlılık enjeksiyonu ve veri enjeksiyonu 2 farklı şeydir. birincisi bir tasarım prensibi, ikincisi bir saldırı türüdür. Daha net bir arama terimi istiyorsanız "kontrolün ters çevrilmesi" ni deneyin. Biraz daha geniştir ancak daha net bir resim çizmeye yardımcı olur.
toskv

1
"Veri enjeksiyonu" saldırıları, inanıyorum ki alıntılanan kitabın yazarının "veri enjekte et" derken konuştuğu şeyden çok farklı bir hayvandır. Bu konuda Google arama ile sinirli olmanın nedenlerinden biri budur. Anlamak gerekirse bile, örneğin SOLID ilkeleri daha iyi, bir "Kişi" yapıcı için bir parametre olarak bir "isim" sağlamak normal ve Tamam ama bir "Model" için bir parametre olarak "serviceUrl" sağlamak anlamıyorum yapıcı uygunsuzdur veya "name" / "Person" örneğinden bile farklıdır.

7
Bence Remo yanılıyor. Parametreler ne derse desin , verilerdir. Enjekte edilen verilerin her zaman bir türü vardır ve nesne yönelimli dillerdeki tüm türlerin bir çeşit davranışı vardır.
Robert Harvey

Yanıtlar:


5

Yazara şüpheden faydalanacağım ve belki de işler böyle yazmalı, ancak diğer ortamlarda ciddiye alınmaması gereken tamamen asılsız bir iddia.

Başımın üstünden, yapıcı aracılığıyla veri aktarmanın iyi, bazıları nötr olan, ancak kötü olduğu hiçbir durum düşünemiyorum.

Belirli bir sınıf, geçerli bir durumda olmak ve düzgün bir şekilde çalışmak için belirli bir veri parçasına bağlıysa, bu verileri yapıcıda talep etmek mantıklıdır. Seri bağlantı noktasını temsil eden bir sınıf bağlantı noktası adını alabilir, bir dosya nesnesi dosya adını, çözünürlüğünü gerektiren bir çizim tuvalini vb. Gerektirebilir. Verileri yapıcıya aktarmazsanız, nesnenin geçersiz bir durumda olması mümkündür. izlenmeli ve kontrol edilmelidir. Aksi takdirde, yalnızca nesne somutlaştırmasında kontrol edebilir ve daha sonra çoğunlukla çalıştığını varsayabilirsiniz. Yazarlar iddia bu yararlı durumu imkansız hale getirir.

Ek olarak, bir kurucuya veri aktarımını yasaklamaya karar vermek, neredeyse tüm değişmez nesneleri imkansız hale getirir. Değişmez nesnelerin birçok durumda çeşitli yararları vardır ve bunların hepsi yazarın politikası ile atılacaktır.

Değişken nesneler istediğiniz gibi olsa bile, bu kötü uygulama nasıl olur:

var blah = new Rectangle(x,y,width,height);

lehine:

var blah = new Rectangle();
blah.X = x;
blah.Y = y;
blah.Width = width;
blah.Height = height;

Yazar gerçekten ilkinin kötü uygulama olduğunu düşünüyor mu ve ben her zaman 2. seçenekle devam etmeliyim? Bence bu çılgınca konuşma.

Yani, kitabım olmadığı için ve okumasam bile yine de okumadığım için, bu ifadeyi ve hemen hemen tüm genel ifadeleri önemli bir şüphe ile görecektim.


Tartışmanız için çok teşekkürler. Bana “doğru kokuyor” dediğiniz şey, özellikle Dikdörtgen örneğini verdiğinizde. Hala yazarın sınıf için gereken veriler ile sınıfın her örneği arasında bir ayrım yapıp yapmadığını merak ediyorum. Ancak kitabın açıkladığı projenin bunu açıklığa kavuşturmak için yeterince derinliğe girdiğini sanmıyorum. Bir yan not olarak, cevabınız bana nesne değişmezliğinin ilk soruşturmasını gönderdi, ancak orijinal sorumla ilgisi yok veya ilgisi yok, bu yüzden bunun için teşekkürler!
Andrew Willems

0

Burada ne tür bir modelin tartışıldığı bağlama bağlı olduğunu düşünüyorum. Remo'nun kitabım yok, ancak modelin uzak bir web servisinden veri alması gereken bir tür hizmet modeli olduğunu tahmin ediyorum. Bu durumda, bir web hizmeti modeli olarak, hizmeti vatansız hale getirerek web hizmetinin yöntemlerinde bağımsız değişken olarak gerekli olan tüm verileri iletmek daha iyidir.

Durum bilgisi olmayan hizmetin çeşitli avantajları vardır, örneğin, bir hizmet yöntemi çağrısını okuyan herkes, hizmetin adı verilen hizmetin ayrıntılarını bulmak için yapılandırıldığında arama yapmasına gerek yoktur. Tüm ayrıntılar, yöntem çağrısında kullanılan bağımsız değişkenlerde gösterilir (uzak url hariç).


Evet, modelin verileri alması gerekiyor (sonunda önerdiğiniz gibi uzak bir web hizmetinden, ancak kitapta bu sadece bir demo, bu yüzden başlangıçta doğrudan doğrudan kodlanmış sahte veriler). Verileri "web hizmetinin yöntemlerinde" bağımsız değişken olarak geçirmeyle ilgili önerinizi anlamıyorum. Bir yapıcı için verileri (1) ile bir dekoratör (2) için parametre (1) olarak geçirme arasında ayrım yapmayı soruyordum. 3. bir seçenek öneriyor gibi, yani veri web hizmeti yöntemi için parametre / bağımsız değişken olarak iletilmesi gibi. Demek istediğim eksik mi?
Andrew Willems

0

Sadece tahmin ediyorum.

Ben 'veri değil davranış enjekte' kulak, ben bunu yapmak yerine, düşünürdüm:

(Sözde koddaki örnek için üzgünüm):

class NoiseMaker{
  String noise;
  NoiseMaker(String noise){
     this.noise = noise;
  }
  void soNoise(){
    writeToOutput(noise)
  }
}

Bunu yapmak için:

interface Noise{
  String getAudibleNoise();
}

class PanicYell implements Noise{
   String getAudibleNoise(){
       return generateRandomYell();
   }
   .....
}



class WhiteNoise implements Noise{
   String getAudibleNoise(){
       return generateNoiseAtAllFrequences();
   }
   .....
}

class NoiseMaker{
  Noise noise;
  NoiseMaker(Noise noise){
     this.noise = noise;
  }
  void soNoise(){
    writeToOutput(noise.getAudibleNoise())
  }
}

Bu şekilde gürültünün davranışını her zaman değiştirebilir, rastgele hale getirebilir, bir iç değişkene bağlı olarak ...

Bence her şey 'miras üzerinde iyilik kompoziti' kuralıyla ilgili. Bu harika bir kural, söylemeliyim.

Bu, 'Kişi' Nesnesine adı 'enjekte edemeyeceğiniz' DEMEKTİR, çünkü bu isim tamamen iş verisidir. Ancak, web hizmetinde verdiğiniz örnekte, URL bir şekilde bir hizmeti bağlayan bir şey oluşturmak için ihtiyacınız olan bir şeydir . Bu bir şekilde bir davranıştır: URL'yi enjekte ederseniz, bir 'davranış' oluşturmak için gerekli 'verileri' enjekte edersiniz, bu durumda davranışı dışarıda yapmak ve kullanılmaya hazır enjekte etmek daha iyidir: Bunun yerine bir URL enjekte etmek kullanılabilir bir bağlantı veya kullanılabilir bir bağlantı oluşturucu.

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.