클래스 생성자에 데이터 (행동 대)를 주입한다는 것은 무슨 의미이며, 왜 나쁜 습관으로 간주됩니까?


10

Remo Jansen의 "Learning TypeScript"책을 읽고 있습니다. 한 섹션에서 저자는 Model클래스 를 만드는 방법을 포함하여 매우 간단한 개념 증명 MVC 프레임 워크를 만드는 방법을 설명 하고 다음과 같이 말합니다.

사용하는 웹 서비스의 URL이 모델에 제공되어야합니다. 사용할 서비스의 URL을 설정하기 위해 ModelSettings라는 클래스 데코레이터를 사용할 것입니다. 우리는 생성자를 통해 서비스 URL을 주입 할 수 있지만 클래스 생성자를 통해 (행동이 아닌) 데이터를 주입하는 것은 나쁜 습관으로 간주됩니다 .

나는 그 마지막 문장을 이해하지 못한다. 특히, "데이터 주입"의 의미를 이해하지 못합니다. 지나치게 단순화 된 예제를 사용하는 JavaScript 클래스에 대한 거의 모든 소개에서 매개 변수를 통해 생성자에 데이터가 도입됩니다 ( "주입"?). 예를 들면 다음과 같습니다.

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

필자는 확실히 name행동이 아닌 데이터 라고 생각하며 , 이러한 유형의 예제에는 일반적으로 생성자 매개 변수로 포함되며 이것이 나쁜 습관이라는 언급은 없습니다. 따라서 위의 인용문에서 "데이터"또는 "주입"또는 다른 의미로 잘못 이해하고 있다고 가정합니다.

답은 개념이 내가 추구하는 이해와 밀접하게 관련되어 있다고 생각하기 때문에 JavaScript / TypeScript에서 데코레이터를 언제, 어디서, 어떻게, 왜 사용하는지에 대한 설명을 포함 할 수 있습니다. 그러나 더 중요한 것은 클래스 생성자를 통해 데이터를 주입하는 것이 무엇을 의미하고 왜 나쁜지를 이해하고 싶습니다.


위의 인용문에 더 많은 맥락을 제시하기 위해 상황은 다음 Model과 같습니다.이 예에서는 NASDAQ 용과 NYSE 용으로 증권 거래소 모델을 작성하는 데 사용되는 클래스가 작성됩니다. 각 모델에는 원시 데이터를 제공 할 웹 서비스 또는 정적 데이터 파일의 경로가 필요합니다. 이 책에서는 생성자 매개 변수가 아닌 데코레이터를이 정보에 사용해야한다고 설명합니다.

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

방금 생성자에 대한 매개 변수가 아닌 데코레이터를 통해 서비스 URL을 추가 해야하는 이유를 이해하지 못했습니다.

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

의존성 주입 에 대해 Google에서 빠른 검색을 수행하는 것이 좋습니다 . 이 질문에 대한 올바른 포럼이 아닙니다. :)
toskv 2016 년

1
귀하의 답변을 진심으로 받아 들일 것이지만 Google을 검색하여 의존성 주입에 대해 토론했습니다. "종속성 주입"과 "데이터 주입"이 같은 의미입니까? 또한, "종속성 주입"은 "좋은 것"(또는 적어도 "대체")이라는 느낌이 들었습니다. 반면 제가 제공 한 인용에서 "데이터 주입"에 대한 논의는 "나쁜 것"으로 보입니다. .

의존성 주입과 데이터 주입은 서로 다른 두 가지입니다. 첫 번째는 디자인 원칙이며 두 번째는 공격의 한 유형입니다. 보다 명확한 검색어를 원하면 "제어 역전"을 시도하십시오. 조금 더 넓지 만 더 선명한 그림을 그릴 수 있습니다.
toskv 2016 년

1
"데이터 주입"공격은 인용 된 책의 저자가 "데이터 주입"이라고 말할 때 말하는 것과는 매우 다른 동물이라고 생각합니다. 이것이 Google 검색에 좌절 한 이유 중 하나입니다. 예를 들어 SOLID 원칙을 더 잘 이해해야하더라도 "이름"을 "개인"생성자에 매개 변수로 제공하는 것이 일반적이고 괜찮지 만 "serviceUrl"을 매개 변수로 "모델"에 제공하는 방법을 이해하지 못합니다 생성자가 부적절하거나 "name"/ "Person"예제와 어떻게 다른지.

7
나는 레 모가 잘못 생각합니다. 그가 말한 것에 관계없이 매개 변수 데이터입니다. 항상 주입 된이 데이터 유형을, 그리고 객체 지향 언어의 모든 유형이 어떤 종류의 행동을 가지고있다.
Robert Harvey

답변:


5

필자는 저자에게 의심의 이익을 줄 것이며 아마도 이것이 Typescript와 같은 방식 일 것입니다. 그러나 다른 환경에서는 심각하게 받아 들여서는 안되는 완전히 근거없는 주장입니다.

머릿속에서 생성자를 통해 데이터를 전달하는 것이 좋으며, 중립적이지만 나쁜 것은없는 다양한 상황을 생각할 수 있습니다.

특정 클래스가 유효한 상태에 있고 제대로 실행되기 위해 특정 데이터 조각에 의존하는 경우 생성자에서 해당 데이터를 요구하는 것이 좋습니다. 직렬 포트를 나타내는 클래스는 포트 이름, 파일 객체는 파일 이름, 해상도가 필요한 그리기 캔버스 등을 필요로 할 수 있습니다. 생성자에서 데이터를 전달하지 않으면 객체가 잘못된 상태에있을 수 있습니다. 보고 확인해야합니다. 그렇지 않으면 객체 인스턴스화에서만 확인할 수 있으며 그 후에는 대부분 작동한다고 가정합니다. 저자들은 그 유리한 상황을 불가능하게 만든다고 주장합니다.

또한 생성자에서 데이터 전달을 금지하기로 결정하면 사실상 모든 불변 개체가 불가능합니다. 불변의 객체는 많은 상황에서 다양한 이점을 가지고 있으며, 모든 것은 저자의 정책으로 버려 질 것입니다.

변경 가능한 객체가 원하는 경우에도이 나쁜 습관은 어떻습니까?

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

찬성 :

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

저자는 실제로 첫 번째 방법이 좋지 않다고 생각하고 항상 옵션 2를 사용해야합니까? 나는 그것이 미친 이야기라고 생각합니다.

그래서, 나는이 책이 없어서 어쨌든 읽지 않을 것이기 때문에,이 시점에서 그 진술과 그에 대한 거의 모든 일반적인 진술을 상당히 의심하게 여길 것입니다.


토론 해 주셔서 감사합니다. 당신이 말하는 것은, 특히 Rectangle의 예를 들었을 때 나에게 "냄새가 난다". 저자가 클래스에 필요한 데이터와 클래스의 각 인스턴스에 필요한 데이터를 구분하고 있는지 궁금합니다. 그러나 나는 그 책이 묘사하는 프로젝트가 그것을 명확히하기에 충분한 깊이로 들어가는 것으로 생각하지 않습니다. 참고로, 귀하의 답변은 객체 불변성에 대한 초기 조사에서 저를 보냈지 만 원래 질문과 관련이 있거나 관련이 없으므로 감사합니다!
Andrew Willems

0

나는 그것이 어떤 종류의 모델에서 논의되고 있는지에 따라 상황에 달려 있다고 생각합니다. Remo의 책은 없지만 모델은 일종의 서비스 모델이며 원격 웹 서비스에서 데이터를 검색해야한다고 생각합니다. 이 경우 웹 서비스 모델 인 경우 웹 서비스의 메소드에서 인수로 필요한 모든 데이터를 전달하여 서비스를 무 상태로 만드는 것이 좋습니다.

상태 비 저장 서비스에는 몇 가지 장점이 있습니다. 예를 들어 서비스 메서드 호출을 읽는 사람은 서비스가 호출 된 서비스의 세부 정보를 찾기 위해 구성 될 때 조회 할 필요가 없습니다. 모든 세부 사항은 메소드 호출에 사용 된 인수에 표시됩니다 (원격 URL 제외).


그렇습니다. 모델은 데이터를 검색해야합니다 (결국 제안한대로 원격 웹 서비스에서 가져 오지만 책에서는 데모 일 뿐이므로 처음에는 직접 인라인으로 코딩 된 데이터를 모의합니다). "웹 서비스의 메소드에서"인수로 데이터를 전달하는 것에 대한 귀하의 제안을 이해하고 있지 않습니다. 생성자에 대한 매개 변수 (1)와 데코레이터에 대한 (2)로 데이터를 전달하는 것의 차이점에 대해 묻고있었습니다. 웹 서비스의 메소드에 대한 매개 변수 / 인수로 데이터를 전달하는 등 세 번째 옵션을 제안하는 것 같습니다. 요점을 놓치고 있습니까?
Andrew Willems

0

그냥 추측.

'데이터가 아닌 행동을 주입하십시오'라고 귀를 기울이면이 대신에 생각할 것입니다.

(의사 코드의 예는 죄송합니다) :

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

이것을하기 위해:

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())
  }
}

이렇게하면 항상 잡음의 동작을 변경하고 하나의 내부 변수에 따라 무작위로 만들 수 있습니다 ...

나는 그것이 '상속적인 선호보다 상속'규칙에 관한 것이라고 생각합니다. 어느 것이 좋은 규칙인지, 나는 말해야한다.

이것은 이름이 순수한 비즈니스 데이터이기 때문에 이름을 '개인'개체에 '주입'할 수 없다는 것을 의미하지는 않습니다. 그러나 웹 서비스에서 제공하는 예에서 URL은 어떻게 든 서비스를 연결하는 무언가를 생성하는 데 필요한 것 입니다. 즉 어떻게 든 행동입니다 : 만약 당신이 URL을 분사하면 분사 '데이터'그 경우는 사용되는 행동 외부 준비가 주입을하는 것이 좋습니다 그래서에서하는 '행동'을 구축하는 데 필요한 : 대신 URL의 분사 주입 사용 가능한 연결 또는 사용 가능한 연결 작성기

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.