내가 자주 겪는 문제는 다음과 같습니다. Product 클래스가있는 웹 상점 프로젝트가 있습니다. 사용자가 제품에 리뷰를 게시 할 수있는 기능을 추가하고 싶습니다. 그래서 제품을 참조하는 Review 클래스가 있습니다. 이제 제품에 대한 모든 리뷰를 나열하는 방법이 필요합니다. 두 가지 가능성이 있습니다.
(ㅏ)
public class Product {
...
public Collection<Review> getReviews() {...}
}
(비)
public class Review {
...
static public Collection<Review> forProduct( Product product ) {...}
}
코드를 살펴보면 (A)를 선택합니다. 정적이 아니며 매개 변수가 필요하지 않습니다. 그러나 (A)는 단일 책임 원칙 (SRP) 및 공개 폐쇄 원칙 (OCP)을 위반하지만 (B)는 그렇지 않다는 것을 알고 있습니다.
(SRP) 제품에 대한 리뷰가 수집되는 방식을 변경하려면 제품 클래스를 변경해야합니다. 그러나 Product 클래스를 변경해야하는 이유는 한 가지뿐입니다. 그리고 그것은 확실히 리뷰가 아닙니다. 제품의 제품과 관련이있는 모든 기능을 포장하면 곧 엉망이 될 것입니다.
(OCP)이 기능으로 확장하려면 제품 클래스를 변경해야합니다. 이것이 원칙의 '변화에 대한 폐쇄'부분을 위반한다고 생각합니다. 고객의 검토 구현 요청을 받기 전에 제품을 완성 된 것으로 간주하고 "닫았습니다".
더 중요한 것은 SOLID 원칙을 따르거나 더 간단한 인터페이스를 갖는 것입니까?
아니면 내가 여기서 뭔가 잘못하고 있습니까?
결과
와우, 당신의 모든 위대한 답변에 감사드립니다! 공식 답변으로 하나를 선택하기는 어렵습니다.
답변에서 주요 주장을 요약하겠습니다.
- pro (A) : OCP는 법이 아니며 코드의 가독성도 중요합니다.
- pro (A) : 엔티티 관계는 탐색 가능해야합니다. 두 클래스 모두이 관계에 대해 알고있을 것입니다.
- pro (A) + (B) : 둘 다 수행하고 (A)에서 (B)로 위임하여 제품이 다시 변경 될 가능성이 줄어 듭니다.
- 프로 (C) : 파인더 메소드를 정적이 아닌 3 급 (서비스)에 넣습니다.
- 콘트라 (B) : 테스트에서 조롱을 방해합니다.
직장 내 대학에서 제공 한 몇 가지 추가 사항 :
- pro (B) : ORM 프레임 워크는 (B)에 대한 코드를 자동으로 생성 할 수 있습니다.
- pro (A) : ORM 프레임 워크의 기술적 이유로 파인더가가는 곳과는 독립적으로 "닫힌"엔터티를 변경해야합니다. 어쨌든 항상 SOLID를 고수 할 수는 없습니다.
- 대조 (C) : 많은 소란 ;-)
결론
현재 프로젝트에 위임과 함께 (A) + (B)를 모두 사용하고 있습니다. 그러나 서비스 지향 환경에서는 (C)를 사용하겠습니다.
Assert(5 = Math.Abs(-5));
Abs()
는 문제가 아니며, 그것에 의존하는 것을 테스트하는 것입니다. 모의를 사용하기 위해 종속 코드 테스트 (CUT)를 분리하기위한 이음새가 없습니다. 즉, 원자 단위로 테스트 할 수 없으며 모든 테스트는 단위 논리를 테스트하는 통합 테스트가됩니다. 테스트 실패는 CUT 또는 Abs()
종속 코드 에있을 수 있으며 단위 테스트의 진단 이점을 제거합니다.