많은 소프트웨어 개발자가 개방 / 폐쇄 원칙을 위반하는 이유는 무엇입니까?


74

많은 소프트웨어 개발자 가 업그레이드 후 응용 프로그램을 손상시키는 기능 이름 변경과 같은 여러 가지 사항을 수정 하여 개방 / 폐쇄 원칙 을 위반하는 이유는 무엇 입니까?

이 질문은 React 라이브러리 의 빠른 버전과 지속적인 버전을 마친 후 제 머리로 뛰어 넘습니다 .

짧은 기간마다 구문, 구성 요소 이름 등이 많이 변경되었습니다.

다가오는 React 버전의 예 :

새로운 지원 중단 경고

가장 큰 변화는 React.PropTypes 및 React.createClass를 자체 패키지로 추출한 것입니다. 둘 다 기본 React 오브젝트를 통해 여전히 액세스 할 수 있지만 둘 중 하나를 사용하면 개발 모드에있을 때 사용 중단 경고가 콘솔에 로그됩니다. 이것은 향후 코드 크기 최적화를 가능하게합니다.

이러한 경고는 응용 프로그램의 동작에 영향을 미치지 않습니다. 그러나 특히 console.error를 오류로 처리하는 테스트 프레임 워크를 사용하는 경우 약간의 좌절감을 유발할 수 있습니다.


  • 이러한 변경 사항이 해당 원칙을 위반 한 것으로 간주됩니까?
  • React 와 같은 초보자에게는 라이브러리의 빠른 변화로 어떻게 배울 수 있습니까 (매우 실망 스럽습니까)?

6
이것은 분명히 그것을 관찰 하는 예이며 , '너무 많은'주장은 확실하지 않습니다. Lucene 및 RichFaces 프로젝트는 악명 높은 예이며 Windows COMM 포트 API이지만 다른 프로젝트는 생각할 수 없습니다. 그리고 React는 정말 '큰 소프트웨어 개발자'입니까?
user207421

62
다른 원칙과 마찬가지로 OCP는 그 가치가 있습니다. 그러나 개발자에게는 무한한 예측이 필요합니다. 현실에서는 사람들이 종종 첫 번째 디자인을 잘못 생각합니다. 시간이 지남에 따라, 일부는 호환성을 위해 오래된 실수를 해결하는 것을 선호하고, 다른 하나는 컴팩트하고 부담이없는 코드베이스를 위해 결국 정리하는 것을 선호합니다.
Theodoros Chatzigiannakis

1
"원래 의도 된"객체 지향 언어를 마지막으로 본 시간은 언제입니까? 핵심 원칙은 시스템의 모든 부분을 ​​누구나 확장 할 수 있는 메시징 시스템이었습니다 . 이제 일반적인 OOP와 같은 언어와 비교해보십시오. 기존 방법을 외부에서 얼마나 확장 할 수 있습니까? 얼마나 유용하게 사용할 수 있을까요?
루안

레거시가 짜증납니다. 30 년의 경험을 통해 항상 레거시를 완전히 버리고 새로 시작 해야합니다 . 오늘날 모든 사람은 항상 모든 곳에서 연결되어 있기 때문에 레거시는 오늘날 전혀 관련이 없습니다. 궁극적 인 예는 "Windows와 Mac"입니다. Microsoft는 전통적으로 "레거시 지원"을 시도했지만 여러 가지 방법으로이를 알 수 있습니다. Apple은 항상 레거시 사용자에게 "F---You"라고 말했습니다. (이것은 언어에서 장치, OS에 이르기까지 모든 것에 적용됩니다.) 사실, Apple은 완전히 정확했고 MSFT는 완전히 틀리고 단순하며 단순했습니다.
Fattie

4
실생활에서 100 % 작동하는 "원칙"과 "디자인 패턴"이 정확히 없기 때문입니다.
Matti Virkkunen

답변:


148

IMHO JacquesB의 답변은 많은 진실을 담고 있지만 OCP에 대한 근본적인 오해를 보여줍니다. 공평하게 말하면, 당신의 질문은 이미이 오해를 표현하고 있습니다. 이름을 바꾸는 기능은 이전 버전과의 호환성을 손상 시키지만 OCP는 아닙니다. 호환성을 깨야하는 것 같거나 호환성을 손상시키지 않기 위해 동일한 구성 요소의 두 가지 버전을 유지 관리하는 경우 OCP가 이미 고장난 것입니다!

요 르그 W MITTAG 이미 그의 주석에서 언급 한 바와 같이, 원칙 "은 구성 요소의 동작을 수정할 수 없습니다"말을하지 않습니다 - 그것은 말한다, 하나는해야 시도 하는 방식으로 구성 요소를 설계하는 그들은 재사용에 beeing 오픈 (또는 확장)입니다 여러 가지 방법으로 수정 하지 않아도 됩니다. 이것은 올바른 "확장 점"을 제공하거나 @AntP에서 언급 한대로 "모든 기본 확장 점이 기본적으로 존재하는 지점으로 클래스 / 함수 구조를 분해하여"수행 할 수 있습니다. OCP를 따르는 IMHO는 "이전 버전을 이전 버전과의 호환성을 위해 변경되지 않은 상태로 유지" 와 공통점이 없습니다 ! 또는 아래 @DerekElkin의 의견을 인용하십시오.

OCP는 모듈을 변경하는 것을 절대 허용하지 않는 변경 관리 프로세스를 구현하는 것이 아니라 모듈 [...]을 작성하는 방법에 대한 조언입니다.

훌륭한 프로그래머는 경험을 바탕으로 "올바른"확장 점을 염두에두고 (또는 더 나은 방법으로 인공 확장 점이 필요하지 않은) 구성 요소를 설계합니다. 그러나 불필요한 오버 엔지니어링없이 올바르게 수행하려면 향후 컴포넌트 사용 사례가 어떻게 보일지 미리 알고 있어야합니다. 숙련 된 프로그래머조차도 미래를 바라 볼 수 없으며 모든 향후 요구 사항을 미리 알 수 있습니다. 그렇기 때문에 구성 요소의 확장 포인트 수나 특정 유형의 요구 사항과 관련하여 OCP를 얼마나 잘 준수하는지에 관계없이 때로는 이전 버전과의 호환성 을 위반해야합니다. 수정없이 쉽게 구현할 수없는 요구 사항이 항상 있습니다 구성 요소.


14
IMO가 OCP를 "위반"하는 가장 큰 이유는 OCP 를 올바르게 준수하기 위해 많은 노력이 필요하기 때문입니다. Eric Lippert는 많은 .NET 프레임 워크 클래스가 OCP를 위반하는 이유에 대한 훌륭한 블로그 게시물 을 보유하고 있습니다.
BJ Myers

2
@BJMyers : 링크 주셔서 감사합니다. Jon Skeet은 OCP에 대해 훌륭한 변화를 가져 왔으며 보호 변형에 대한 아이디어와 매우 유사합니다.
Doc Brown

8
이! OCP는 변경하지 않고 변경할 수있는 코드를 작성해야한다고 말합니다! 왜? 따라서 한 번만 테스트, 검토 및 컴파일하면됩니다. 새로운 행동은 새로운 코드에서 나옵니다. 입증 된 오래된 코드를 조이는 것이 아닙니다. 리팩토링은 어떻습니까? 리팩토링은 OCP의 명백한 위반입니다! 그렇기 때문에 가정이 바뀌면 코드를 리팩터링한다고 생각하는 코드를 작성하는 것이 죄가됩니다. 아니! 각 가정을 작은 상자에 넣으십시오. 틀렸을 때 상자를 고치지 마십시오. 새로운 것을 쓰십시오. 왜? 이전으로 돌아 가야 할 수도 있기 때문입니다. 당신이 할 때, 여전히 작동한다면 그것은 좋을 것입니다.
candied_orange

7
@ CandiedOrange : 귀하의 의견에 감사드립니다. 리팩토링과 OCP는 당신이 묘사하는 것과 반대되는 것을 보지 않습니다. OCP를 따르는 컴포넌트를 작성하려면 종종 몇 가지 리팩토링주기가 필요합니다. 목표는 전체 "가족"요구 사항을 해결하기 위해 수정이 필요없는 구성 요소 여야합니다. 그럼에도 불구하고, "경우에 따라"컴포넌트에 임의의 확장 점을 추가해서는 안되며, 이는 너무 쉽게 엔지니어링 할 수 없습니다. 리팩토링의 가능성에 의존하는 것이 많은 경우에 이것에 대한 더 나은 대안이 될 수 있습니다.
Doc Brown

4
이 답변은 (현재) 최상위 답변의 오류를 불러내는 데 도움이됩니다. 개방 / 폐쇄에 성공하는 데있어 중요한 것은 "확장 점"이라는 관점에서 생각 을 멈추고 분해에 대한 생각을 시작하는 것입니다. 클래스 / 함수 구조는 기본적으로 모든 자연 확장 포인트가있는 지점까지입니다. "외부"프로그래밍은이를 달성하는 매우 좋은 방법입니다. 현재 방법 / 기능이 제공하는 모든 시나리오가 외부 인터페이스로 푸시되어 데코레이터, 어댑터 등의 자연스러운 확장 점을 형성합니다.
Ant P

67

개방 / 폐쇄 원칙에는 이점이 있지만 심각한 단점도 있습니다.

이론상 이 원리는 "확장을 위해 개방되었지만 수정을 위해 폐쇄 된"코드를 생성함으로써 이전 버전과의 호환성 문제를 해결합니다. 클래스에 새로운 요구 사항이있는 경우 클래스 자체의 소스 코드를 수정하지 않고 동작 변경에 필요한 해당 멤버 만 재정의하는 하위 클래스를 만듭니다. 따라서 원래 버전의 클래스에 대해 작성된 모든 코드는 영향을받지 않으므로 변경 사항이 기존 코드를 위반하지 않았 음을 확신 할 수 있습니다.

실제로 코드 부풀림과 쓸데없는 클래스의 혼란스러운 혼란으로 쉽게 끝납니다. 확장을 통해 구성 요소의 일부 동작을 수정할 수없는 경우 원하는 동작으로 구성 요소의 새로운 변형을 제공하고 이전 버전과의 호환성을 위해 이전 버전을 변경하지 않아야합니다.

많은 클래스가 상속받는 기본 클래스에서 기본적인 디자인 결함을 발견했다고 가정 해보십시오. 개인 필드의 유형이 잘못되어 오류가 발생했다고 가정하십시오. 멤버를 재정 의하여이 문제를 해결할 수 없습니다. 기본적으로 전체 클래스를 재정의해야합니다. 즉 Object, 대체 기본 클래스를 제공하기 위해 확장 해야합니다. 이제 모든 서브 클래스에 대한 대안을 제공해야하므로 중복 된 오브젝트 계층 구조, 하나의 계층 결함, 하나 개선 . 그러나 결함이있는 계층 구조를 제거 할 수는 없습니다 (코드 삭제가 수정되었으므로). 향후 모든 클라이언트는 두 계층 구조에 모두 노출됩니다.

이제이 문제에 대한 이론적 대답은 "처음으로 올바르게 설계하는 것"입니다. 코드가 결함이나 실수없이 완벽하게 분해되고 향후 가능한 모든 요구 사항 변경을 위해 준비된 확장 점으로 설계된 경우 혼란을 피할 수 있습니다. 그러나 실제로 모든 사람은 실수를 저지르며 미래를 완벽하게 예측할 수있는 사람은 없습니다.

.NET 프레임 워크와 같은 것을 가져보십시오 .10 년 전에 제네릭이 도입되기 전에 설계된 컬렉션 클래스 세트를 계속 사용합니다. 이것은 이전 버전과의 호환성에 도움이되지만 (아무 것도 다시 쓰지 않고도 프레임 워크를 업그레이드 할 수 있음) 프레임 워크를 팽창시키고 개발자에게 단순히 더 이상 사용되지 않는 많은 옵션 세트를 제공합니다.

분명히 React의 개발자들은 개방 / 폐쇄 원칙을 엄격하게 따르는 것이 복잡하고 코드가 큰 비용이 들지 않는다고 생각했습니다.

개방 / 폐쇄에 대한 실질적인 대안은 통제 중단입니다. 단일 릴리스에서 이전 버전과의 호환성을 깨뜨리지 않고 이전 구성 요소는 릴리스주기 동안 유지되지만 클라이언트는 컴파일러 경고를 통해 이전 릴리스가 이후 릴리스에서 제거 될 것이라는 알림을받습니다. 이를 통해 클라이언트는 코드를 수정할 수 있습니다. 이것은이 경우 React의 접근 방식 인 것 같습니다.

(이 원리에 대한 나의 해석은 Robert C. Martin 의 공개 폐쇄 원칙 에 근거합니다 )


37
"원칙은 기본적으로 구성 요소의 동작을 수정할 수 없다고 말합니다. 대신 원하는 동작을 가진 새로운 구성 요소 변형을 제공하고 이전 버전과의 호환성을 위해 이전 버전을 변경하지 않아야합니다." – 나는 이것에 동의하지 않습니다. 원칙에 따르면 원하는 것을 수행하도록 확장 할 수 있으므로 동작을 변경할 필요가 없도록 구성 요소를 설계해야합니다. 문제는, 특히 현재 널리 사용되는 언어를 사용하는 방법을 아직 알지 못했다 는 것입니다. 표현 문제는…의 한 부분입니다.
Jörg W Mittag

8
… 예를 들면. Java 나 C♯ 모두 Expression에 대한 솔루션이 없습니다. Haskell과 Scala는 그 사용자 수는 훨씬 작습니다.
Jörg W Mittag

1
@Giorgio : Haskell에서 솔루션은 타입 클래스입니다. 스칼라에서 솔루션은 암시 적 및 객체입니다. 죄송합니다. 현재 링크가 없습니다. 그렇습니다. 멀티 메소드 (실제로 "멀티"일 필요는 없으며, 필요한 리스프 방법의 "오픈"특성 임)도 가능한 해결책입니다. 일반적으로 논문은 저자가 표현 문제에 제한을 추가하여 현재 존재하는 모든 솔루션이 유효하지 않게 된 다음 자신의 방법을 보여주는 방식으로 작성되기 때문에 표현 문제에 대한 여러 가지 표현이 있습니다.
Jörg W Mittag

1
… 언어는이 "더 어려운"버전을 해결할 수도 있습니다. 예를 들어, Wadler는 원래 표현 문제를 모듈 식 확장뿐만 아니라 정적으로 안전한 모듈 식 확장이라고 표현했습니다. 일반적인 Lisp 다중 방법은 정적으로 안전 하지 않으며 동적으로 만 안전합니다. Odersky는 모듈 식으로 정적으로 안전해야한다고 말함으로써이를 더욱 강화했습니다. 즉, 확장 모듈 만보고 전체 프로그램을 보지 않고도 안전을 정적으로 확인할 수 있습니다. 실제로 Haskell 타입 클래스로는 불가능하지만 Scala로는 가능합니다. 그리고 ...
Jörg W Mittag

2
@Giorgio : 맞습니다. Common Lisp 멀티 메소드가 EP를 해결하게하는 것은 실제로 다중 디스패치가 아닙니다. 방법이 열려 있다는 사실입니다. 일반적인 FP (또는 절차 적 프로그래밍)에서 유형 차별은 기능과 관련이 있습니다. 일반적인 OO에서 메소드는 유형에 연결됩니다. 일반적인 Lisp 메소드는 open 이며, 팩트 후에 그리고 다른 모듈에서 클래스에 추가 될 수 있습니다. 이것이 EP를 해결하는 데 사용할 수있는 기능입니다. 예를 들어 Clojure의 프로토콜은 단일 디스패치이지만 정적 안전을 요구하지 않는 한 EP도 해결합니다.
Jörg W Mittag

20

저는 개방 / 폐쇄 원칙을 이상이라고 부릅니다. 모든 이상과 마찬가지로 소프트웨어 개발의 현실을 거의 고려하지 않습니다. 또한 모든 이상과 마찬가지로 실제로 실제로 달성하는 것은 불가능합니다. 하나는 가능한 한 최선을 다해 그 이상에 접근하려고합니다.

이야기의 다른 측면은 황금 수갑으로 알려져 있습니다. 골든 수갑은 개방 / 폐쇄 원칙에 너무 많이 종속 될 때 얻는 것입니다. 골든 수갑은 과거의 실수가 너무 많아서 이전 버전과의 호환성을 유지하지 못하는 제품이 성장할 수 없을 때 발생합니다.

이것의 유명한 예는 Windows 95 메모리 관리자에 있습니다. Windows 95 마케팅의 일환으로 모든 Windows 3.1 응용 프로그램은 Windows 95에서 작동 할 것이라고 언급되었습니다. Microsoft는 실제로 Windows 95에서 수천 개의 프로그램에 대한 라이센스를 취득하여 Windows 95에서 테스트했습니다. 문제의 사례 중 하나는 Sim City였습니다. Sim City는 실제로 할당되지 않은 메모리에 쓰도록하는 버그가있었습니다. "적절한"메모리 관리자가없는 Windows 3.1의 경우, 이것은 작은 가짜 pas였습니다. 그러나 Windows 95에서는 메모리 관리자가이를 포착하여 세그먼트 화 오류를 발생시킵니다. 해결책? Windows 95에서 응용 프로그램 이름이 simcity.exe인 경우 OS는 실제로 세그먼트 화 오류를 방지하기 위해 메모리 관리자의 제약 조건을 완화합니다!

이 이상적인 배후의 실질적인 문제는 제품과 서비스의 분리 된 개념입니다. 아무도 실제로 하나 또는 다른 것을하지 않습니다. 둘 사이의 회색 영역 어딘가에 모든 것이 줄 지어 있습니다. 제품 지향적 인 접근 방식으로 생각하면 개방 / 폐쇄 사운드가 가장 이상적입니다. 귀하의 제품은 신뢰할 수 있습니다. 그러나 서비스에 관해서는 이야기가 바뀝니다. 개방형 / 폐쇄 형 원칙을 사용하면 팀이 지원 해야하는 기능의 양이 무한대로 무한대에 접근 해야한다는 것을 쉽게 알 수 있습니다. 이전 기능은 정리할 수 없기 때문입니다. 즉, 개발 팀은 매년 점점 더 많은 코드를 지원해야합니다. 결국 당신은 한계에 도달합니다.

오늘날 대부분의 소프트웨어, 특히 오픈 소스는 공개 / 폐쇄 원칙의 일반적인 완화 버전을 따릅니다. 사소한 릴리스에서는 오픈 / 클로즈가 노예로 뒤 따르는 것이 일반적이지만 주요 릴리스에서는 포기되는 것이 매우 일반적입니다. 예를 들어, Python 2.7에는 Python 2.0과 2.1 일의 "나쁜 선택"이 많이 포함되어 있지만 Python 3.0은이 모든 것을 휩쓸 었습니다. (또한 Windows 2000을 출시했을 때 Windows 95 코드베이스에서 Windows NT 코드베이스로의 전환은 모든 종류의 문제를 일으켰지 만, 동작을 결정하기 위해 응용 프로그램 이름을 확인하는 메모리 관리자를 다루지 않아도 됨을 의미 했습니다 !)


SimCity에 관한 아주 좋은 이야기입니다. 소스가 있습니까?
BJ Myers

5
@BJMyers 그것은 오래된 이야기입니다. Joel Spoleky는 이 기사 의 끝 부분에서 이야기합니다 . 원래 몇 년 전에 비디오 게임 개발에 관한 책의 일부로 읽었습니다.
Cort Ammon

1
@BJMyers : 수십 개의 인기있는 응용 프로그램에 대해 유사한 호환성 "해킹"이 있다고 확신합니다.
Doc Brown

3
@BJMyers 이런 것들이 많이 있습니다. 좋은 읽기를 원한다면 Raymond Chen의 The Old New Thing 블로그 로 이동 하여 History 태그를 찾거나 "호환성"을 검색하십시오. 앞서 언급 한 SimCity 사례 와 유사한 주제 포함하여 많은 이야기를 기억합니다. -Addentum : Chen은 이름을 비난하기를 원하지 않습니다.
Theraot

2
95-> NT 전환에서도 아주 적은 일이 발생했습니다. 원래 Windows 용 SimCity는 Windows 10 (32 비트)에서 여전히 잘 작동합니다. 콘솔 하위 시스템이 오디오를 올바르게 처리 할 수 ​​있도록 사운드를 비활성화하거나 VDMSound와 같은 것을 사용하면 DOS 게임도 여전히 완벽하게 작동합니다. Microsoft는 이전 버전과의 호환성을 매우 중요하게 생각하며 "가상 컴퓨터에 넣자"바로 가기도 사용하지 않습니다. 때로는 해결 방법이 필요하지만 특히 상대적인 측면에서 여전히 인상적입니다.
루안

11

Doc Brown의 답변은 정확에 가장 가깝고 다른 답변은 공개 폐쇄 원칙에 대한 오해를 보여줍니다.

명시 적으로 오해를 명확하게하기 위해, OCP는 이전 버전과 호환되지 않는 변경해서는 안 것을 의미 믿음있을 것 같습니다 (또는 심지어 어떤 이 라인을 따라 변경 또는 무언가를하십시오.) OCP 당신이하지 않도록 구성 요소를 설계에 관한 필요 에 변경 사항이 이전 버전과 호환되는지 여부에 관계없이 기능을 확장하도록 변경하십시오. 기능을 추가하는 것 외에 컴포넌트가 이전 버전과 호환되는지 (예 : 리팩토링 또는 최적화) 또는 이전 버전과 호환되지 않는지 (예 : 기능 사용 중단 및 제거) 구성 요소를 변경할 수있는 다른 많은 이유가 있습니다. 이러한 변경이 구성 요소가 OCP를 위반 한 것을 의미하는 것은 아니다 (확실히 것을 의미하지 않는다 할 수 있다는 것을 당신 OCP를 위반하고 있습니다).

실제로, 그것은 소스 코드에 관한 것이 아닙니다. OCP에 대한보다 추상적이고 관련성있는 진술은 "컴포넌트는 추상화 경계를 위반하지 않고도 확장 할 수 있어야한다"는 것입니다. 더 나아가서보다 현대적인 표현은 "컴포넌트는 추상화 경계를 강화 해야 하지만 확장을 허용 해야한다 "는 것입니다. Bob Martin의 OCP에 실린 기사에서도 "소스 코드가 잘못되었다"고 "수정에 가깝게"설명하는 동안 소스 코드 수정과는 아무런 관련이없는 캡슐화와 추상화와 관련된 모든 것에 대해 이야기하기 시작합니다. 경계.

따라서 문제의 잘못된 전제는 OCP가 코드베이스의 진화에 대한 지침으로 의도된다는 것입니다. OCP는 일반적으로 "컴포넌트는 확장에 개방적이어야하며 소비자가 수정해야하는 폐쇄 형"으로 표시됩니다. 기본적으로 구성 요소 소비자 가 구성 요소 기능 을 추가 하려면 이전 기능 을 추가 기능이있는 새로운 구성 요소로 확장 할 수 있어야하지만 이전 구성 요소 를 변경할 수는 없습니다 .

OCP는 기능을 변경 하거나 제거 하는 구성 요소 작성자 에 대해 아무 말도하지 않습니다 . OCP는 버그 호환성 유지를 옹호하지 않습니다 . 제작자 인 귀하는 구성 요소를 변경하거나 제거하여 OCP를 위반하지 않습니다. 소비자가 구성 요소에 기능을 추가 할 수있는 유일한 방법은 예를 들어 원숭이 패치 등을 통해 변경하는 것만으로도 귀하 또는 귀하가 작성한 구성 요소가 OCP를 위반하는 것입니다.또는 소스 코드에 액세스하여 재 컴파일합니다. 대부분의 경우 이러한 옵션 중 어느 것도 소비자를위한 옵션이 아니며, 구성 요소가 "확장 가능"상태가 아니면 운이 나쁘다는 의미입니다. 그들은 단지 당신의 구성 요소를 그들의 요구에 사용할 수 없습니다. OCP는 최소한 식별 가능한 "확장"클래스와 관련하여 라이브러리의 소비자를이 위치에 두지 말 것을 주장합니다. 소스 코드 또는 소스 코드의 기본 복사본을 수정할 있는 경우에도 그렇게 할 수있는 잠재적 인 부정적인 결과가 많으므로 수정할 수없는 것으로 가장하는 것이 가장 좋습니다.

따라서 귀하의 질문에 답변하십시오 : 아니요, 이는 OCP 위반이 아닙니다. OCP는 변경의 비율이 아니기 때문에 작성자가 변경 한 내용은 OCP를 위반할 수 없습니다. 변화는, 그러나, 수 만들 OCP를 위반, 그들은 코드베이스의 이전 버전에서 OCP의 실패에 의해 좌우 될 수있다. OCP는 코드베이스의 진화 이력이 아닌 특정 코드 조각의 속성입니다.

대조적으로, 이전 버전과의 호환성은 코드 변경 의 속성입니다 . 일부 코드가 이전 버전과 호환되거나 호환되지 않는다고 말하는 것은 의미가 없습니다. 오래된 코드 와 관련하여 일부 코드의 이전 버전과의 호환성에 대해서만 이야기하는 것이 합리적 입니다. 따라서 일부 코드의 첫 번째 컷이 이전 버전과 호환되는지 여부에 대해 이야기하는 것은 의미가 없습니다. 코드의 첫 번째 컷은 OCP를 만족 시키거나 만족시키지 못할 수 있으며, 일반적으로 우리는 코드의 이전 버전을 참조하지 않고 일부 코드가 OCP를 만족하는지 여부를 결정할 수 있습니다.

마지막 질문에 관해서는, 일반적으로 의견을 기반으로하는 것은 일반적으로 StackExchange의 주제는 아니지만 논란의 여지가 있지만 기술과 특히 JavaScript는 지난 몇 년 동안 기술 한 현상이 JavaScript 피로 라고 불리는 JavaScript에 환영 받습니다. ( 여러 가지 관점에서 이에 대해 이야기하는 풍자적 인 다양한 기사를 찾으 려면 Google 에 자유롭게 문의하십시오.)


3
"창조자로서 구성 요소를 변경하거나 제거하여 OCP를 위반하지 않습니다." -이것에 대한 참조를 제공 할 수 있습니까? 내가 본 원리의 정의 중 어느 것도 "창조자"(그것이 무엇이든간에)가 원칙에서 면제된다고 언급하지 않았다. 게시 된 구성 요소를 제거하는 것은 분명히 중요한 변경 사항입니다.
JacquesB

1
@JacquesB 사람과 코드 변경조차도 OCP를 위반하지 않으며 구성 요소 (예 : 실제 코드)는 OCP를 위반하지 않습니다. (그리고 명확하게 말하면, 구성 요소가 다른 구성 요소의 OCP를 위반하는 것이 아니라 OCP 자체에 의존하지 못한다는 것을 의미합니다.) 제 대답의 요점은 OCP가 코드 변경에 대해 이야기하지 않는다는 것입니다 깨지거나 그렇지 않으면. 구성 요소는 확장 개방 및 수정 폐쇄하거나, 또는 방법이 될 수있다처럼 그것은, 아니다 private여부. 저자가 나중에 private방법을 만든다고 public해서 액세스 제어를 위반 한 것은 아닙니다. (1/2)
Derek Elkins

2
...이 방법이 실제로 private이전 이 아니었다는 의미는 아닙니다 . "게시 된 구성 요소를 제거하는 것은 명백히 중요한 변경 사항입니다."는 중요하지 않습니다. 새 버전의 구성 요소가 OCP를 충족 시키거나 그렇지 않은 경우이를 결정하기 위해 코드베이스 기록이 필요하지 않습니다. 당신의 논리에 의해, 나는 OCP를 만족시키는 코드를 작성할 수 없었습니다. 코드 속성 인 OCP를 통해 이전 버전과의 호환성, 코드 속성 변경 사항을 혼동하고 있습니다. 귀하의 의견은 quicksort가 이전 버전과 호환되지 않는다는 것만 큼 의미가 있습니다. (2/2)
Derek Elkins 12

3
@JacquesB 먼저, 이것은 OCP를 따르는 모듈 에 관한 것 입니다. OCP는 모듈 을 작성 하는 방법에 대한 조언 이므로 소스 코드를 변경할 수 없다는 제약 조건 이 있으면 모듈을 확장 할 수 있습니다. 이 문서의 앞부분에서 그는 모듈을 변경할 수없는 변경 관리 프로세스를 구현하는 것이 아니라 변경되지 않는 모듈을 디자인 하는 것에 대해 이야기 합니다. 답변 편집을 참조하면 모듈 코드를 수정하여 "OCP를 중단"하지 않습니다. 대신, 모듈을 "확장" 하려면 소스 코드를 수정 해야 합니다. (1/3)
Derek Elkins

2
"OCP는 코드베이스의 진화 이력이 아닌 특정 코드의 속성입니다." -훌륭합니다!
Doc Brown
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.