개방 / 폐쇄 원칙 명확히


25

내가 설명했듯이, 공개 / 폐쇄 원칙은 한 번 작성된 코드를 수정해서는 안됩니다 (버그 수정 제외). 그러나 비즈니스 규칙이 변경되면 해당 변경을 구현하는 코드를 수정해서는 안됩니까? 나는 그 원리가 나에게 이해되지 않기 때문에 어떻게 그 원리에 대해 이해하지 못한다고 생각합니다.

답변:


22

이것은 아마도 설명하기 가장 견고한 원칙 중 가장 어려운 것입니다. 나 해보자. 완벽하게 작동하고 버그가없는 송장 클래스를 작성했다고 가정하십시오. 송장 PDF를 작성합니다.

그런 다음 누군가가 링크가 포함 된 HTML 송장을 원한다고 말합니다. 이 요청을 충족시키기 위해 송장의 코드를 변경하지 마십시오. 대신 다른 클래스 인 HTMLInvoice를 만들어 원하는대로 만듭니다. 상속을 활용하여 HTMLInvoice에 많은 중복 코드를 작성할 필요가 없습니다.

이전 송장을 사용하던 이전 코드는 손상되거나 실제로 영향을받지 않습니다. 새 코드는 HTMLInvoice를 사용할 수 있습니다. ( 단단한 L 인 Liskov Substitutability 도 수행하는 경우 인보이스 인스턴스를 기대하는 기존 코드에 HTMLInvoice 인스턴스를 제공 할 수 있습니다.) 누구나 행복하게 살아갑니다.

송장은 수정이 마감되고 확장이 열립니다. 그리고 이것이 작동하려면 송장을 올바르게 작성해야합니다.


1
비즈니스 규칙이 변경되면 버그없이 완벽하게 작동한다는 가정이 없으므로 개방 / 폐쇄 원칙이 적용되지 않습니까?
JeffO

나는이 규칙으로 스스로 고투했고 Kate가 제안한 것은 기본적으로 내가 결론을 내린 것입니다. 비즈니스에서는 더 작고 유연한 클래스를 프로그래밍하여 재사용 할 수 있습니다. 제대로 작동하면 수정하고 싶지 않습니다. 그러나 그것들이 완전히 "완료"된 경우는 거의 없으므로 일부 수정이 불가피합니다. 텍스트에는 객체가 아니라 "모듈"이라고 표시되어 있습니다. 나는 한 가지 일을 완벽하게 수행하고 변경할 필요가없는 엄격한 기능으로 종종 기능 수준에서 OCP를 성공적으로 적용합니다.
CodexArcanum

1
@Jeff OI 버그 수정 (코드가 원래 요구 사항을 충족하지 못하고 아무도 원하지 않는 경우)과 요구 사항 변경을 구분합니다. PDF가 필요하고 코드에서 PDF를 작성하는 경우 이제 HTML을 원하지만 버그가 없습니다 (보통 사람들이 아니라 HTML도 원합니다)
Kate Gregory

2
@Winston-이것이 인보이스를 올바르게 작성해야한다고 말했을 때의 의미입니다. 이상적으로는 이미 추상적 인 송장이 있었으며이를 기대하는 PDFInvoice를 상속했습니다. 그렇지 않은 경우 나중에 규칙을 어 기지 않도록 규칙을 한 번 해제해야합니다. 어느 쪽이든, 미래의 변화를 예측하는 것은이 모든 것의 큰 부분입니다. 이것이 바로 "코끼리를 잡아서 자르십시오"부분입니다.
Kate Gregory

1
마지막 진술이 가장 중요합니다. 개방 / 폐쇄는 설계에 이상적이며 설계를 달성하려면 먼저 설계를 시작해야합니다. 모든 것이 개방 / 폐쇄를 만족시킬 필요는 없지만, 그곳에 갈 수 있다면 강력한 도구입니다.
Alex Feinman

13

ObjectMentor에서 Bob 아저씨의 친구들에 의한 공개 폐쇄 원칙 기사 를 읽었 습니까? 나는 그것이 더 나은 설명 중 하나라고 생각합니다.

객체 지향 디자인과 관련된 많은 휴리스틱이 있습니다. 예를 들어, "모든 구성원 변수는 개인용이어야합니다"또는 "전역 변수는 사용하지 않아야합니다"또는 "RTTI (런타임 유형 식별) 사용은 위험합니다". 이러한 휴리스틱의 소스는 무엇입니까? 무엇이 사실입니까? 그들은 항상 사실입니까? 이 칼럼에서는 이러한 휴리스틱의 기초가되는 디자인 원칙 인 개방형 원칙을 조사합니다.

Ivar Jacobson은 다음과 같이 말했습니다.“모든 시스템은 수명주기 동안 변경됩니다. 첫 번째 버전보다 오래 지속될 것으로 예상되는 시스템을 개발할 때이 점을 염두에 두어야합니다.”변화에 안정적이고 첫 번째 버전보다 오래 지속되는 디자인을 어떻게 만들 수 있습니까? 베르트랑 메이어 (Bertrand Meyer)는 1988 년 그가 지금 유명한 공개 폐쇄 원칙을 만들었을 때부터 우리에게 지침을주었습니다. 그를 역어 :

소프트웨어 엔티티 (클래스, 모듈, 기능 등)는 연장을 위해 열어야하지만 수정을 위해 닫혀 있어야합니다.

프로그램을 한 번 변경하면 종속 모듈이 연속적으로 변경 될 때 해당 프로그램은 "나쁜"디자인과 관련하여 원하지 않는 속성을 나타냅니다. 프로그램은 깨지기 쉽고 단단하며 예측할 수 없으며 재사용 할 수 없게됩니다. 공개 폐쇄 원칙은이를 매우 간단하게 공격합니다. 절대 변하지 않는 모듈을 설계해야한다고 말합니다 . 요구 사항이 변경되면 이미 작동하는 이전 코드를 변경하지 않고 새 코드를 추가하여 해당 모듈의 동작을 확장합니다.

기술

공개 폐쇄 원칙을 따르는 모듈에는 두 가지 주요 속성이 있습니다.

  1. 그것들은“확장을위한 개방”입니다.
    이는 모듈의 동작이 확장 될 수 있음을 의미합니다. 애플리케이션의 요구 사항이 변경되거나 새로운 애플리케이션의 요구를 충족시키기 위해 모듈이 새롭고 다양한 방식으로 작동하도록 할 수 있습니다.
  2. "수정 마감"입니다.
    그러한 모듈의 소스 코드가 위배됩니다. 아무도 소스 코드를 변경할 수 없습니다.

이 두 속성은 서로 상충되는 것 같습니다. 모듈의 동작을 확장하는 일반적인 방법은 해당 모듈을 변경하는 것입니다. 변경할 수없는 모듈은 일반적으로 고정 된 동작을하는 것으로 생각됩니다. 이 두 가지 반대되는 속성을 어떻게 해결할 수 있습니까?

추상화가 핵심이다 ...


3
이것은 추상화를 설명하는 좋은 기사입니다. 하지만 고려해야 할 근본적인 점이 있는데, 이것이 처음에는 좋은 추상 디자인이었습니다. 많은 상점에는 기존 코드가 많이 있으며 이를 변경 하는 유일한 방법은 "확장"이 아니라 "수정"입니다. 이 경우 변경을 시도해야하지만 변경 될 때까지 코드를 수정해야합니다.
Michael K

@Chris, cool-이런 종류의 것을 좋아한다면 Bob 아저씨의 "깨끗한 코드"책을 추천합니다.
Martijn Verburg

@Michael-테스트에 이상적인 코드를 만들기 위해 코드를 리팩터링해야하는 것과 거의 같습니다.
Martijn Verburg

이 기사는 추상화의 중요성을 아주 잘 보여줍니다. 그러나 추상화 사이의 연결을 파악하지 않고 모듈을 작성한 후에는 절대 모듈을 수정하려고하지 않습니다. 추상화는 모듈 Y를 수정하지 않고 모듈 X를 수정할 수 있음을 의미합니다. 그러나 그렇게 할 필요가 없어서 필요한 경우 모듈 X 또는 모듈 Y를 수정할 수 있습니까?
Winston Ewert

1
와우. 코드가 위반됩니까? 나는 밥 삼촌을 좋아 한 적이 없습니다. 이 교장은 비현실적이며 실용적이지 않으며 현실과의 연결이 제한되어 있습니다.
user949300

12

Kate Gregory대답 은 매우 좋지만 기존 Invoice클래스 의 상대적으로 작은 변화로 새로운 요구 사항을 충족시킬 수있는 다른 상황을 고려하십시오 . 예를 들어, 새 필드를 송장 PDF에 추가해야한다고 가정합니다. OCP에 따르면 몇 줄의 코드를 변경하여 기존 구현에 새 필드를 추가 할 수있는 경우에도 새 서브 클래스를 작성해야합니다.

내 이해에 따르면, OCP는 80 년대와 90 년대 초의 현실을 반영합니다. 프로젝트는 종종 버전 제어를 사용하지 않았고, 자동 회귀 테스트 나 정교한 리팩토링 도구의 이점이 훨씬 적었습니다. OCP는 수동으로 테스트하여 프로덕션 환경에 넣은 코드를 깨뜨릴 위험을 피하기위한 시도였습니다. 오늘날에는 작동중인 소프트웨어 (버전 제어 시스템, TDD 및 자동화 된 테스트, 리팩토링 도구)가 손상 될 위험을 관리하는 더 좋은 방법이 있습니다.


2
그렇습니다. 실제로 모든 방법을 보호하지 않으면 (O / C보다 훨씬 중요한 YAGNI 원칙을 빨고 위반하지 않는 한) 가능한 모든 미래에 맞게 확장 할 수있는 클래스를 만들 수 없기 때문에 디토).
Martin Wickman

"OCP에 따르면 몇 줄의 코드를 변경하여 기존 구현에 새 필드를 추가 할 수있는 경우에도 새로운 하위 클래스를 작성해야합니다.": 정말? 왜 새로운 필드 나 새로운 메소드를 추가하지 않습니까? 중요한 점은 추가하거나 확장하고 이미 존재하는 것을 변경하지 않는 것입니다.
조르지오

표준 라이브러리 / 프레임 워크를 다룰 때 원칙이 합리적이라고 생각합니다. 잘 설정된 코드를 열고 수정하고 싶지 않습니다. 그렇지 않으면 그것은 지속적인 리팩토링과 테스트, 테스트, 테스트에 관한 것입니다.
mastaBlasta

@Giorgio 물론이 새 필드 나 메소드를 추가하는 것입니다 나는 대부분의 경우에, 추천 할 것입니다 무엇. 그러나 그것은 확장 이 아니라 "수정"입니다. OCP의 요점은 코드가 "확장을 위해 열려있는"동안 "수정을 위해 닫아야합니다"(즉, 기존 소스 파일을 변경하지 않아야 함)해야한다는 것입니다. OCP의 확장은 구현 상속을 통해 달성됩니다.
Rogério

@ Rogério : 클래스 레벨에서 확장과 수정 사이의 경계를 정의하는 이유는 무엇입니까? 특별한 이유가 있습니까? 메서드 수준에서 설정하고 싶습니다. 메서드를 변경하면 응용 프로그램의 동작이 변경되고 (공용) 메서드를 추가하면 인터페이스가 확장됩니다.
조르지오

6

개인적으로 저는이 원리를 소금 한 덩어리로 가져와야한다고 생각합니다. 코드는 유기적이며 시간이 지남에 따라 비즈니스 요구에 따라 비즈니스가 변경되고 코드가 변경됩니다.

추상화가 핵심이라는 사실을 이해하기가 매우 어렵다는 것을 알게되었습니다. 추상화가 원래 잘못 되었다면 어떻게 될까요? 비즈니스 기능이 크게 변경된 경우 어떻게해야합니까?

이 원칙은 본질적으로 디자인의 원래 의도와 행동이 절대 변하지 않도록 보장합니다. 퍼블릭 API를 가지고 있고 클라이언트가 새로운 릴리스 및 다른 일부 사례를 따라 잡는 데 어려움이있는 사람들에게 효과적 일 수 있습니다. 그러나 회사가 모든 코드를 소유하고 있다면이 원칙에 도전합니다.

코드를 잘 테스트하면 코드 기반 리팩토링이 쉬워집니다. 그것은 물건을 잘못 얻는 것이 괜찮다는 것을 의미합니다. 테스트는 더 나은 디자인으로 안내하는 데 도움이됩니다.

테스트가 없다면이 원칙은 건전합니다.

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