“요요 문제를 피하십시오”가“원시 강박 관념”을 허용하는 타당한 이유입니까?


42

에 따르면 때 원시 집착하지 않는 코드 냄새입니까? String 객체 대신 우편 번호를 나타내는 ZipCode 객체를 만들어야합니다.

그러나 내 경험상, 나는보고 싶어한다

public class Address{
    public String zipCode;
}

대신에

public class Address{
    public ZipCode zipCode;
}

후자는 프로그램을 이해하기 위해 ZipCode 클래스로 이동해야한다고 생각하기 때문입니다.

그리고 모든 기본 데이터 필드가 클래스로 대체 된 경우 정의를 보려면 많은 클래스간에 이동해야한다고 생각합니다. 요요 문제 (반 패턴)로 고통받는 것처럼 느껴집니다 .

따라서 ZipCode 메소드를 새 클래스로 이동하고 싶습니다. 예를 들면 다음과 같습니다.

낡은:

public class ZipCode{
    public boolean validate(String zipCode){
    }
}

새로운:

public class ZipCodeHelper{
    public static boolean validate(String zipCode){
    }
}

우편 번호를 확인해야하는 사람 만이 ZipCodeHelper 클래스에 의존합니다. 그리고 원시적 인 강박 관념을 유지하는 또 다른 "이점"을 발견했습니다. 클래스가 직렬화 된 양식처럼 보이게합니다 (예 : 문자열 열 zipCode가있는 주소 테이블).

내 질문은 "요요 문제를 피하는 것"(클래스 정의 간 이동)이 "원시적 인 집착"을 허용하는 타당한 이유인가?


9
@ jpmc26 그렇다면 우편 번호 객체가 얼마나 복잡한 지 알 수 있습니다. 그것이 옳다고 말하지는 않지만 존재합니다
Jared Goguen

9
@ jpmc26, 나는 당신이 "복잡한"에서 "나쁜 디자인"으로 어떻게 가는지 보지 못합니다. 복잡한 코드는 종종 단순한 코드가 우리가 원하는 이상적인 세상이 아니라 실제 세계의 복잡성과 접촉하는 결과입니다. "두 페이지 기능으로 돌아갑니다. 예, 저는 창을 표시하는 단순한 기능 일 뿐이지 만 머리카락과 물건이 거의 자라지 않아 아무도 이유를 알지 못합니다. 이유를 알려 드리겠습니다. 그 이유는 버그입니다. 수정. "
Kyralessa

18
@ jpmc26-ZipCode와 같은 객체를 감싸는 요점은 유형 안전입니다. 우편 번호는 문자열이 아니며 우편 번호입니다. 함수가 우편 번호를 요구하면 문자열이 아닌 우편 번호 만 전달할 수 있어야합니다.
Davor Ždralo

4
이것은 언어에 따라 다르며 다른 언어는 여기서 다른 일을합니다. @ DavorŽdralo 같은 범위에서 많은 숫자 유형을 추가해야합니다. "양의 정수만", "짝수 만"은 모두 유형이 될 수 있습니다.
paul23

6
@ paul23 그렇습니다. 그리고 우리 가지고 있지 않은 주된 이유는 많은 언어들이 그것들을 정의하는 우아한 방법을 지원하지 않기 때문입니다. "userAge == currentTemperature"가 넌센스로 감지되도록 "연령"을 "섭씨 온도"와 다른 유형으로 정의하는 것이 합리적입니다.
IMSoP

답변:


116

Address 클래스를 이해하기 위해 ZipCode 클래스를 요요 할 필요 가 없다고 가정 합니다. ZipCode가 잘 디자인되어 있다면 Address 클래스를 읽는 것만으로도 분명합니다.

프로그램은 엔드-투-엔드로 읽히지 않습니다. 일반적으로 프로그램을 구현하기에는 너무 복잡합니다. 프로그램의 모든 코드를 동시에 생각할 수는 없습니다. 따라서 추상화와 캡슐화를 사용하여 프로그램을 의미있는 단위로 "청크"하므로 프로그램에 의존하는 모든 코드를 읽을 필요없이 프로그램의 한 부분 (주소 클래스 등)을 볼 수 있습니다.

예를 들어 코드에서 String을 만날 때마다 String의 소스 코드를 읽지 않아도됩니다.

ZipCode에서 ZipCodeHelper로 클래스 이름을 바꾸면 우편 번호와 우편 번호 도우미라는 두 가지 개념이 있습니다. 두 배나 복잡합니다. 이제 유형 시스템은 유형이 동일하므로 임의의 문자열과 유효한 우편 번호를 구별하는 데 도움이되지 않습니다. 이것은 "강박 관념"이 적절한 곳입니다. 당신은 프리미티브 (primitive) 주위에 간단한 래퍼 타입을 피하기 위해 더 복잡하고 덜 안전한 대안을 제안하고 있습니다.

이 특정 유형에 따라 유효성 검사 나 다른 논리가없는 경우 프리미티브 사용이 정당화됩니다. 그러나 로직을 추가하자마자이 로직을 유형으로 캡슐화하면 훨씬 간단합니다.

직렬화에 관해서는 사용중인 프레임 워크의 제한 사항처럼 들립니다. 반드시 ZipCode를 문자열로 직렬화하거나 데이터베이스의 열에 맵핑 할 수 있어야합니다.


2
나는 "의미있는 단위"(main-) 부분에 동의하지만 우편 번호와 우편 번호 유효성 검사가 같은 개념이되는 것은 아닙니다. ZipCodeHelper(나는 오히려 전화 할 것입니다 ZipCodeValidator) 제대로 작동하기 위해 웹 서비스에 대한 연결을 설정할 수 있습니다. 그것은 "우편 번호 데이터를 보유" 하는 단일 책임의 일부가 아닙니다 . ZipCode생성자를 Java의 패키지 전용과 동일 하게 만들고 ZipCodeFactory항상 유효성 검사기를 호출하는 형식으로 호출 하면 형식 시스템에서 유효하지 않은 우편 번호를 허용하지 않을 수 있습니다 .
R. Schmitz

16
@ R.Schmitz : 이것이 단일 책임 원칙의 의미에서 "책임"이 의미하는 것은 아닙니다. 그러나 어떤 경우에도 우편 번호 및 해당 유효성 검사를 캡슐화하는 한 필요한만큼의 클래스를 사용해야합니다. OP는 우편 번호 캡슐화하는 대신 도우미 제안합니다 .
JacquesB

1
나는 정중하게 동의하지 않습니다. SRP는 클래스에 "한 가지 이유 만 변경"해야 함을 의미합니다 ( "zip 코드 구성"과 "확인 방법"변경). 이 특정 사례는 Clean Code : " 객체는 추상화 뒤에 데이터를 숨기고 해당 데이터에서 작동하는 기능을 노출합니다. 데이터 구조는 데이터를 노출하고 의미있는 기능은 없습니다. "- ZipCode"데이터 구조" 와 ZipCodeHelper.에 "객체는 '어떤 경우에도, 나는 우리가 우리가 우편 번호 생성자에 웹 연결을 통과 할 필요가 없습니다 동의합니다 생각합니다.
R. 슈미츠

9
이 특정 유형에 따라 유효성 검사 나 다른 논리가없는 경우 프리미티브 사용이 정당화됩니다. => 동의하지 않습니다. 모든 값이 유효하더라도 프리미티브를 사용하지 않고 의미를 언어로 전달하는 것이 좋습니다. 현재 시맨틱 사용법에 무의미한 기본 유형에서 함수를 호출 할 수있는 경우, 기본 유형이 아니어야하며 적절한 기능 만 정의 된 올바른 유형이어야합니다. (예를 들어, intID로 사용하면 ID에 ID를 곱할 수 있습니다 ...)
Matthieu M.

@ R.Schmitz 나는 우편 번호가 당신의 구별을위한 나쁜 예라고 생각합니다. 자주 변경 뭔가 별도의 후보 수 있습니다 FooFooValidator클래스. 우리는 할 수ZipCode형식의 유효성을 검사 클래스와 ZipCodeValidator일부 웹 서비스를 안타 제대로 포맷이 있는지 확인하기 위해 ZipCode실제로 전류이다. 우편 번호가 변경되는 것을 알고 있습니다. 그러나 실제로, ZipCode또는 일부 로컬 데이터베이스에 캡슐화 된 유효한 우편 번호 목록을 갖게 됩니다.
No U

55

할 수 있다면 :

new ZipCode("totally invalid zip code");

그리고 ZipCode의 생성자는 다음을 수행합니다.

ZipCodeHelper.validate("totally invalid zip code");

그런 다음 캡슐화를 중단하고 ZipCode 클래스에 꽤 바보 같은 의존성을 추가했습니다. 생성자 호출 하지 않으면ZipCodeHelper.validate(...) 실제로 시행하지 않고 자체 섬에서 로직을 분리 한 것입니다. 잘못된 우편 번호를 만들 수 있습니다.

validate메소드는 ZipCode 클래스의 정적 메소드 여야합니다. 이제 "유효한"우편 번호에 대한 지식이 ZipCode 클래스와 함께 제공됩니다. 코드 예제가 Java처럼 보이면 ZipCode 생성자는 잘못된 형식이 제공되면 예외를 발생시켜야합니다.

public class ZipCode {
    private String zipCode;

    public ZipCode(string zipCode) {
        if (!validate(zipCode))
            throw new IllegalFormatException("Invalid zip code");

        this.zipCode = zipCode;
    }

    public static bool validate(String zipCode) {
        // logic to check format
    }

    @Override
    public String toString() {
        return zipCode;
    }
}

생성자는 형식을 확인하고 예외를 발생시켜 유효하지 않은 우편 번호가 생성되지 않도록하고 정적 validate코드를 다른 코드에서 사용할 수 있으므로 형식을 확인하는 논리가 ZipCode 클래스에 캡슐화됩니다.

이 ZipCode 클래스 변형에는 "yo-yo"가 없습니다. 적절한 객체 지향 프로그래밍이라고합니다.


또한 ZipCodeFormat 또는 PostalService라는 다른 클래스 (예 : PostalService.isValidPostalCode (...), PostalService.parsePostalCode (...) 등)가 필요할 수있는 국제화도 무시합니다.


28
참고 : @Greg Burkhardt의 접근 방식의 주요 이점은 누군가 누군가 ZipCode 객체를 제공하면 유형과 그것이 성공적으로 생성되었다는 사실이 당신을 다시 확인하지 않고도 유효한 문자열을 포함한다는 것을 신뢰할 수 있다는 것입니다 그 보증. 대신 문자열을 전달한 경우 유효한 우편 번호가 있는지 확인하기 위해 코드의 여러 위치에서 "검증 (zipCode)"을 요구해야하지만 ZipCode 객체가 성공적으로 생성 된 경우 다음을 신뢰할 수 있습니다. 내용은 다시 확인하지 않아도 유효합니다.
일부 사람

3
@ R.Schmitz :이 ZipCode.validate메소드는 예외를 발생시키는 생성자를 호출하기 전에 수행 할 수있는 사전 검사입니다.
Greg Burghardt

10
@ R.Schmitz : vexing 예외가 우려되는 경우 구성에 대한 다른 접근 방식은 ZipCode 생성자를 비공개로 만들고 전달 된 매개 변수의 유효성 검사를 수행하는 공개 정적 팩토리 함수 (Zipcode.create?)를 제공하는 것입니다. 실패하면 null을 반환하고, 그렇지 않으면 ZipCode 객체를 생성하여 반환합니다. 물론 호출자는 항상 null 반환 값을 확인해야합니다. 반면, ZipCode를 생성하기 전에 항상 정규화 (regex? validate? 등)하는 습관을들이는 경우 실제로 예외가 너무 심각하지 않을 수 있습니다.
일부 사람

11
Optional <ZipCode>를 반환하는 팩토리 함수도 가능합니다. 그러면 호출자는 팩토리 기능의 가능한 실패를 명시 적으로 처리 할 수밖에 없습니다. 어쨌든, 오류는 원래 문제와는 거리가 먼 클라이언트 코드에 의해 훨씬 나중에 생성 된 위치 근처에서 발견됩니다.
일부 사람

6
독립적으로 ZipCode의 유효성을 검사 할 수 없으므로 그렇게하지 마십시오. ZipCode / PostCode 유효성 검사 규칙을 조회하려면 Country 개체가 실제로 필요합니다.
조슈아

11

이 질문으로 많은 어려움을 겪고 있다면 사용하는 언어가 그 일에 적합한 도구가 아닐 수 있습니다. 이러한 종류의 "도메인 유형 프리미티브"는 예를 들어 F #으로 표현하기가 쉽습니다.

예를 들어 다음과 같이 작성할 수 있습니다.

type ZipCode = ZipCode of string
type Town = Town of string

type Adress = {
  zipCode: ZipCode
  town: Town
  //etc
}

let adress1 = {
  zipCode = ZipCode "90210"
  town = Town "Beverly Hills"
}

let faultyAdress = {
  zipCode = "12345"  // <-Compiler error
  town = adress1.zipCode // <- Compiler error
}

이것은 다른 엔티티의 ID를 비교하는 것과 같은 일반적인 실수를 피하는 데 실제로 유용합니다. 이러한 유형의 프리미티브는 C # 또는 Java 클래스보다 훨씬 가볍기 때문에 실제로 사용하게됩니다.


흥미로운-검증을 원한다면 ZipCode어떻게 보일까요?
헐크

4
@Hulk F #으로 OO 스타일을 작성하고 형식을 클래스로 만들 수 있습니다. 그러나 ZipCode = private ZipCode 유형의 문자열을 선언하고 create 함수를 사용하여 ZipCode 모듈을 추가하는 기능 스타일을 선호합니다. 여기에 몇 가지 예가 있습니다. gist.github.com/swlaschin/54cfff886669ccab895a
Guran

@ Bent-Tranberg 편집 해 주셔서 감사합니다. 당신은 옳습니다. 간단한 유형 약어는 컴파일 시간 유형 보안을 제공하지 않습니다.
Guran

당신이 내가 삭제 한 첫 번째 의견을 우송 한 경우, 그 이유는 내가 당신의 출처를 처음 오해했기 때문입니다. 나는 그것을 충분히 읽지 못했습니다. 내가 그것을 컴파일하려고했을 때, 나는 마침내 당신이 실제로 이것을 정확하게 설명하려고한다는 것을 깨달았습니다. 그래서 나는 그것을 올바르게 얻기 위해 편집하기로 결정했습니다.
벤트 트랜 버그

네. 내 원본 소스는 유감스럽게도 유감스럽게도 지원되지 않는 예를 포함하여 유효했습니다. 도! 직접 코드를 입력하는 대신 Wlaschin에 연결해야합니다. :) fsharpforfunandprofit.com/posts/…
Guran

6

답은 우편 번호로 실제로하고 싶은 것에 전적으로 달려 있습니다. 두 가지 극단적 인 가능성이 있습니다.

(1) 모든 주소는 단일 국가에 있어야합니다. 전혀 예외는 없습니다. (예 : 외국 고객이 없거나 외국 고객을 위해 일하는 동안 개인 주소가 해외에있는 직원이 없습니다.)이 국가에는 우편 번호가 있으며 심각한 문제가 없을 것으로 예상 할 수 있습니다 (예 : 자유 형식 입력이 필요하지 않음) "현재 D4B 6N2이지만 2 주마다 변경됩니다"). 우편 번호는 주소 지정뿐만 아니라 지불 정보의 검증 또는 유사한 목적으로 사용됩니다. -이러한 상황에서 우편 번호 클래스는 의미가 있습니다.

(2) 주소는 거의 모든 국가에있을 수 있으므로 우편 번호가 있거나없는 수십 또는 수백 개의 주소 지정 체계 (수천 가지의 예외 및 특수 사례 포함)가 적합합니다. "ZIP"코드는 우편 번호를 제공하는 것을 잊지 않는 국가에서 온 사람들에게 상기시켜 줄 것을 요청합니다. 주소는 누군가가 자신의 계정에 액세스 할 수없고 이름과 주소를 증명할 수있는 경우에만 액세스가 복원되도록 사용됩니다. -이러한 상황에서 모든 관련 국가의 우편 번호 클래스는 엄청난 노력이 될 것입니다. 다행히도 그들은 전혀 필요하지 않습니다.


3

다른 답변은 OO 도메인 모델링 및 더 풍부한 유형을 사용하여 가치를 나타내는 것에 대해 이야기했습니다.

나는 당신이 게시 한 예제 코드를 감안할 때 동의하지 않습니다.

그러나 그것이 실제로 귀하의 질문에 대한 답변인지 궁금합니다.

다음 시나리오를 고려하십시오 (실제로 진행중인 프로젝트에서 가져 왔습니다).

중앙 서버와 통신하는 필드 장치에 원격 응용 프로그램이 있습니다. 장치 항목의 DB 필드 중 하나는 필드 장치가있는 주소의 우편 번호입니다. 우편 번호 (또는 그 문제에 대한 나머지 주소)는 신경 쓰지 않습니다. 그것에 관심이있는 모든 사람들은 HTTP 경계의 반대편에 있습니다. 당신은 데이터의 단일 진실 소스가됩니다. 도메인 모델링에는 자리가 없습니다. 당신은 그것을 기록하고, 유효성을 검사하고, 저장하고, 요청시 JSON 블롭에서 다른 곳으로 셔플합니다.

이 시나리오에서 SQL 정규식 제약 (또는 ORM에 해당)에 삽입을 확인하는 이상 아무것도 많이하고있는 것은 아마도 과잉 YAGNI의 다양한.


6
SQL 정규식 제한 조건은 규정 된 유형으로 볼 수 있습니다. 데이터베이스 내에서 우편 번호는 "VarChar"로 저장되지 않지만 "VarChar는이 규칙에 의해 제한됩니다". 일부 DBMS에서는 해당 유형 + 제약 조건에 재사용 가능한 "도메인 유형"이라는 이름을 쉽게 지정할 수 있으며 데이터에 의미있는 유형을 제공하는 권장 위치로 돌아 왔습니다. 나는 원칙적으로 귀하의 답변에 동의하지만 그 예가 일치한다고 생각하지 않습니다. 더 좋은 예는 데이터가 "원시 센서 데이터"이고 가장 의미있는 유형이 "바이트 배열"인 경우 데이터의 의미를 모릅니다.
IMSoP

@IMSoP 재미있는 포인트. 그래도 동의하지는 않습니다 : 정규 표현식을 사용하여 Java (또는 다른 언어)로 문자열 우편 번호를 확인할 수는 있지만 더 풍부한 유형 대신 문자열로 처리 할 수 ​​있습니다. 도메인 로직에 따라 추가 조작이 필요할 수 있습니다 (예 : 우편 번호가 정규식으로 확인하기 어렵거나 불가능한 상태와 일치하는지 확인).
Jared Smith

당신 은 할 수 는 있지만 그렇게하자마자 도메인 특정 행동을하게 될 것입니다. 인용 된 기사에서 말하는 것은 바로 커스텀 유형의 생성으로 이어질 것입니다. 문제는 하나의 스타일로 또는 다른 스타일로 할 있는지 여부가 아니라 프로그래밍 언어가 선택할 수 있다고 가정 해야한다는 것 입니다.
IMSoP

RegexValidatedString문자열 자체와 문자열을 검증하는 데 사용되는 정규 표현식을 포함하는 것과 같은 것을 모델링 할 수 있습니다. 그러나 모든 인스턴스에 고유 한 정규식이 없으면 (가능하지만 거의 불가능합니다) 약간 어리 석고 낭비되는 메모리 (및 정규식 컴파일 시간)로 보입니다. 따라서 정규 표현식을 별도의 테이블에 넣고 각 인스턴스에서 조회 키를 남겨 두어 찾아서 (간접으로 인해 더 나쁠 수 있음) 규칙을 공유하는 각 일반적인 유형의 값 공유에 대해 한 번 저장하는 방법을 찾습니다. -예. IMSoP가 말한 것처럼 도메인 유형의 정적 필드 또는 동등한 방법.
Miral

1

ZipCode귀하의 경우 추상화는 의미를 만들 수있는 Address클래스도하지 않은 TownName속성을. 그렇지 않으면 절반의 추상화가 있습니다. 우편 번호는 도시를 지정하지만이 두 가지 관련 정보는 다른 클래스에 있습니다. 이치에 맞지 않습니다.

그러나 그럼에도 불구하고 여전히 원시적 인 강박 관념에 대한 올바른 응용 (또는 오히려 해결책)이 아닙니다. 내가 이해하는 것처럼 주로 두 가지에 중점을 둡니다.

  1. 특히 프리미티브 콜렉션이 필요한 경우 메소드의 입력 (또는 출력) 값으로 프리미티브를 사용합니다.
  2. 시간이 지남에 따라 추가 속성을 키우는 클래스는 이들 중 일부를 자체 하위 클래스로 그룹화해야하는지 여부를 다시 고려하지 않습니다.

귀하의 경우도 마찬가지입니다. 주소는 명확하게 필요한 속성 (거리, 번호, 우편 번호, 도시, 주, 국가 등)이 포함 된 잘 정의 된 개념입니다. 지구상의 위치 지정이라는 단일 책임 이 있기 때문에이 데이터를 분해 할 이유가 거의 없습니다 . 주소를 이해하려면 이러한 모든 필드가 필요 합니다 . 주소의 절반은 의미가 없습니다.

이렇게하면 더 이상 세분화 할 필요가 없다는 것을 알 수 있습니다. 더 이상 세분화하면 Address클래스 의 기능적 의도가 손상됩니다 . 마찬가지로, 사람이 연결 되지 않은 상태가 도메인에서 의미있는 개념이 아니라면 클래스 Name에서 하위 클래스를 사용할 필요가 없습니다 . (보통) 그렇지 않습니다. 이름은 사람을 식별하는 데 사용되며 일반적으로 가치가 없습니다.PersonName


1
@RikD : 대답에서 : " 이름이 (사람이 첨부 되지 않은 ) 도메인에서 의미있는 개념이 아니라면 클래스 Name에서 서브 클래스를 사용할 필요가 없습니다 ." Person이름에 대한 사용자 정의 유효성 검사가 있으면 이름이 도메인에서 의미있는 개념이되었습니다. 하위 유형을 사용하는 유효한 유스 케이스로 명시 적으로 언급했습니다. 둘째, 우편 번호 확인을 위해 특정 국가의 형식을 따라야하는 우편 번호와 같은 추가 가정을 소개합니다. 당신은 OP의 질문의 의도보다 훨씬 더 광범위한 주제를 파산하고 있습니다.
Flater

5
" 주소는 명확하게 필요한 속성 (거리, 번호, 우편 번호, 도시, 주, 국가)을 가진 잘 정의 된 개념입니다. "- 그건 분명 잘못입니다. 이를 처리하는 좋은 방법은 Amazon의 주소 양식을 참조하십시오.
R. Schmitz

4
@Flater 글쎄요, 허위의 전체 목록을 읽지 않았다고 비난하지는 않습니다. 왜냐하면 그것은 꽤 길기 때문입니다. 그러나 문자 그대로 "주소에 거리가있을 것입니다", "주소는 도시와 국가가 필요합니다" 인용 된 문장의 내용과 반대되는 우편 번호 "등이 있습니다.
R. Schmitz

8
@GregBurghardt "우편 번호는 미국 우편 서비스를 전제로하며 우편 번호에서 도시 이름을 찾을 수 있습니다. 도시는 여러 개의 우편 번호를 가질 수 있지만 각 우편 번호는 1 개의 도시에만 연결되어 있습니다." 이것은 일반적으로 올바르지 않습니다. 이웃 도시에 주로 사용되는 우편 번호가 있지만 거주지가 없습니다. 우편 번호가 정부의 경계와 항상 일치하는 것은 아닙니다. 예를 들어 42223에는 TN 및 KY의 카운티가 포함 됩니다 .
JimmyJames

2
오스트리아에는 독일에서만 접근 할 수있는 계곡이 있습니다 ( en.wikipedia.org/wiki/Kleinwalsertal ). 이 지역에 대한 특별 조약이 있으며,이 지역의 주소에는 오스트리아 및 독일 우편 번호가 모두 포함되어 있습니다. 따라서 일반적으로 주소에 유효한 우편 번호가 하나만 있다고 가정 할 수 없습니다.)
Hulk

1

기사에서 :

보다 일반적으로, 요요 문제는 또한 사람이 개념을 이해하기 위해 다른 정보원 사이를 계속 넘겨야하는 모든 상황을 지칭 할 수있다.

소스 코드는 작성된 것보다 훨씬 자주 읽습니다 . 따라서 많은 파일간에 전환해야하는 요요 문제가 우려됩니다.

그러나, 어떤 (서로 사이에 앞뒤로 전화) 깊이 상호 의존적 인 모듈 또는 클래스를 처리 할 때, 요요 문제는 훨씬 더 관련 느낀다. 이것들은 읽을만한 특별한 종류의 악몽이며 요요 문제의 창시자가 생각한 것입니다.

그러나 - , 추상화의 너무 많은 레이어를 피하는 것이 중요합니다!

사소한 추상화는 어느 정도 누설됩니다. -새는 추상화의 법칙.

예를 들어, 나는 mmmaaa의 대답 에서 " 주소 클래스를 이해하기 위해 ZipCode 클래스를 [(방문)] 할 필요 가 없다 " 는 가정에 동의 하지 않습니다 . 내 경험에 따르면 당신 적어도 처음 몇 번은 코드를 읽었습니다. 다른 사람이 언급 한 그러나, 거기에 있습니다 경우가 ZipCode클래스가 적합하다.

YAGNI (나중에 않을거야 필요 그것은) (너무 많은 레이어 코드) 라자냐 코드를 방지하기 위해 따라야하는 더 좋은 패턴이다 - 추상화, 같은 종류의 같은과 클래스는 프로그래머가 도움을, 그리고 그들이하지 않는 한 사용되어서는 안 된다 원조.

나는 개인적으로 "코드 줄 저장"(그리고 관련 "파일 / 모듈 / 클래스 저장"등)을 목표로합니다. 나는 "원초적인 집착"이라는 표현을 나에게 적용 할 사람이 있다고 확신한다. 레이블, 패턴, 반 패턴에 대해 걱정하는 것보다 추론하기 쉬운 코드를 갖는 것이 더 중요하다 . 함수, 모듈 / 파일 / 클래스 생성 또는 공통 위치에 함수를 배치 할시기를 올바르게 선택하는 것은 매우 상황이 좋지 않습니다. 나는 대략 3-100 개의 라인 함수, 80-500 개의 라인 파일, 그리고 재사용 가능한 라이브러리 코드에 대한 "1, 2, n"을 목표로한다 ( SLOC- 주석 또는 상용구를 포함하지 않음; 나는 일반적으로 필수 라인 당 최소 1 개의 추가 SLOC를 원한다) 상용구).

가장 긍정적 인 패턴은 개발자가 필요할 때 정확히 그렇게함으로써 발생 합니다 . 동일한 문제를 해결하지 않고 패턴을 적용하는 것보다 읽기 쉬운 코드를 작성하는 방법을 배우는 것이 훨씬 중요합니다. 모든 훌륭한 개발자는 문제에 적합한 드문 경우에 팩토리 패턴을 미리 보지 않고도 구현할 수 있습니다. 팩토리 패턴, 옵저버 패턴 및 아마도 수백 개를 그 이름을 알지 못하고 사용했습니다 (즉, "가변 할당 패턴"이 있습니까?). 재미있는 실험을 위해-JS 언어에 몇 개의 GoF 패턴이 내장되어 있는지 확인하십시오 -2009 년 12-15 년 후에 다시 계산을 중단했습니다. 팩토리 패턴은 JS 생성자에서 객체를 반환하는 것만 큼 간단합니다. WidgetFactory.

그래서 - , 가끔 ZipCode 좋은 클래스입니다. 그러나, , 요요 문제는 엄격하게 관련되지 않습니다.


0

요요 문제는 앞뒤로 뒤집어 야하는 경우에만 관련이 있습니다. 하나 또는 두 가지 (때로는 둘 다)로 인해 발생합니다.

  1. 이름이 잘못되었습니다. 우편 번호는 괜찮은 것 같습니다. ZoneImprovementPlanCode는 대부분의 사람들 (그리고 감명을받지 않는 소수의 사람들)의 모습을 요구할 것입니다.
  2. 부적절한 커플 링. ZipCode 클래스에 지역 코드 조회가 있다고 가정하십시오. 편리하기 때문에 이치에 맞다고 생각할 수도 있지만 실제로 우편 번호와 관련이 없으며 그것을 삽입하면 사람들이 어디로 갈 것인지 알 수 없습니다.

이름을보고 그 기능을 합리적으로 생각할 수 있고 메서드와 속성이 합리적으로 명백한 일을하는 경우 코드를 보지 않아도됩니다. 그것은 처음부터 클래스의 요점입니다. 즉, 독립적으로 사용하고 개발할 수있는 모듈 식 코드입니다. 클래스가 수행하는 작업을보기 위해 API 이외의 다른 것을 살펴보아야 할 경우 이는 부분적으로 실패하는 것입니다.


-1

은 총알이 없다는 것을 기억하십시오. 크롤링해야하는 매우 간단한 앱을 작성하는 경우 간단한 문자열로 작업을 수행 할 수 있습니다. 그러나 98 %의 시간 에 Eric Evans가 DDD에서 설명한 Value Object 는 완벽하게 적합 할 것입니다. Value 객체가 제공하는 모든 이점을 쉽게 읽을 수 있습니다.

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