과부하가 개방 / 폐쇄 원칙의 예입니까?


12

위키 백과는 말합니다

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

함수 라는 단어가 눈에 들어 왔고, 이제 메소드에 과부하를 생성하는 것이 개방 / 폐쇄 원리의 예로 간주 될 수 있다고 생각할 수 있는지 궁금합니다.

예를 설명하겠습니다. 거의 1000 곳에서 사용되는 서비스 계층에 메소드가 있다고 가정하십시오. 이 메소드는 userId를 가져오고 사용자가 관리자인지 여부를 판별합니다.

bool IsAdmin(userId)

이제 어딘가에 userId가 아닌 username을 기반으로 사용자가 관리자인지 아닌지를 결정해야합니다. 위에서 언급 한 방법의 서명을 변경하면 1000 개 장소에서 코드가 손상됩니다 (수정을 위해 기능을 닫아야합니다). 따라서 사용자 이름을 얻고, 사용자 이름을 기반으로 userId를 찾거나, 원래의 메소드를 얻기 위해 과부하를 만들 수 있습니다.

public bool IsAdmin(string username)
{
    int userId = UserManager.GetUser(username).Id;
    return IsAdmin(userId);
}

이런 식으로 오버로드를 생성하여 기능을 확장했습니다 (함수는 확장 가능해야 함).

오픈 / 클로즈 원칙 예입니까?

답변:


5

나는 개인적으로 위키 진술을 다음과 같이 개인적으로 해석하려고합니다.

  • 클래스에 대한 : 클래스와 재정을 상속 또는 자유롭게 확장 의 기능을하지만, 원래 클래스가함으로써 해킹하지 않는 변화 가 무엇을.
  • 모듈 (예 : 라이브러리) : 원본을 감싸고, 기능을 사용하기 쉬운 버전으로 병합하거나 추가 기능으로 원본을 확장 하지만 원래 모듈을 변경 하지 않는 새 모듈 / 라이브러리를 작성하십시오 .
  • 함수 (예 : 클래스 메소드가 아닌 정적 함수) : 귀하의 예는 나에게 합리적입니다. 새 IsAdmin (string) 내에서 원래 IsAdmin (int) 함수를 재사용하십시오. 원본은 변경되지 않고 새로운 기능은 기능을 확장합니다.

그러나 코드에서 IsAdmin (int)이있는 'cUserInfo'클래스를 사용하는 경우 규칙을 위반하고 클래스를 변경해야합니다. 새 클래스 cUserWithNameInfo : public cUserInfo 클래스를 만들고 IsAdmin (string) 재정의를 거기에 넣은 경우에만 규칙이 유감스럽게 유지됩니다. 내가 코드베이스를 소유했다면 절대 규칙에 따르지 않을 것입니다. 나는 볼록을 말하고 당신이 제안한 것을 변경합니다.


3

먼저, 귀하의 모범은 불행히도 고안되었습니다. 불필요한 이중 가져 오기를 유발하기 때문에 실제 세계에서는 그렇게하지 않을 것입니다. 또는 더 나쁜 것은 userid와 username이 어느 시점에서 같은 유형이 될 수 있기 때문입니다. 오히려

public bool IsAdmin(int userid)
{
    User user = UserManager.GetUser(userid);
    return user.IsAdmin();
}

public bool IsAdmin(string username)
{
    int userId = UserManager.GetUser(username).Id;
    return IsAdmin(userId);
}

당신은 정말로 그 수업을 확장 해야합니다.

public bool IsAdmin(int userid)
{
    User user = UserManager.GetUserById(userid);
    return user.IsAdmin();
}

public bool IsUsernameAdmin(string username)
{
    User userId = UserManager.GetUserByName(username);
    return user.IsAdmin();
}

일관성을 유지하기 위해 첫 번째 메소드 이름을 추가로 리팩토링하고 IsUserIdAdmin으로 변경할 수 있지만 반드시 그럴 필요는 없습니다. 요점은 새로운 메소드를 추가하고 호출 코드가 깨지지 않도록 보장하면서 클래스가 확장 가능하다는 것을 발견했습니다. 다시 말하면 확장 프로그램을 엽니 다 .

그리고 여기에 닫힌 원칙이 있습니다. 코드의 일부를 확장하고 대신 수정해야 할 때까지 (코드와 함께 제공되는 위험이 증가 할 때까지) 코드 얼마나 잘 준수하는지 수 없습니다 . 그러나 경험이 있으면 예측하는 법을 배웁니다.

으로 삼촌 밥 말한다 (강조 광산) :

폐쇄는 완료 될 수 없으므로 전략적이어야합니다. 즉, 설계자는 설계를 종료 할 변경 종류를 선택해야합니다. 이것은 경험에서 비롯된 어느 정도의 과학을 필요로합니다 . 숙련 된 디자이너는 다양한 종류의 변경 가능성을 판단 할 수있을 정도로 사용자와 업계를 잘 알고 있습니다. 그런 다음 가장 가능성있는 변경에 대해 개방형 원칙이 호출되도록합니다.


좋은 설명 감사합니다. 그러나 1000 회 왕복 또는 1 회 왕복을하는 것이 여기서 중요한 것은 아닙니다. 따라서 현재 성능을 잊어 버리십시오. 그러나 내가 한 일은 동일한 이름이지만 입력 매개 변수가 다른 다른 메소드를 추가했기 때문에 클래스를 확장하는 것입니다. 하지만 밥 삼촌 의 인용에 진심으로 감사드립니다 . +1. ;)
Saeed Neamati

@ SaeedNeamati : 내가하고있는 요점은 기존 방법을 사용하는 방법을 추가 하거나 클래스가 확장에 개방 된 방식으로 완전히 독립적 인 방법을 추가하는 경우 중요하지 않다는 것 입니다. 그러나 기존 메소드 인터페이스를 수정하여이를 달성해야한다면 수정이 필요하지 않습니다.
pdr

2

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

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

  2. 기존 방법을 변경하지 않았으므로 두 번째 규칙을 위반하지 않습니다.

나는 원래의 방법을 바꾸지 못하게하는 것에 관해 다른 사람들의 말을 듣고 싶습니다. 예, 적절한 액세스 수정자를 넣고 캡슐화를 적용 할 수 있지만 다른 작업은 무엇입니까?

참조 : http://www.objectmentor.com/resources/articles/ocp.pdf


1

공개 원칙은 항상 현실이 아니라 목표, 이상적인 경우입니다. 특히 오래된 코드를 리팩토링하려고 할 때 첫 번째 단계는 종종 OCP를 가능하게하기 위해 크게 수정하는 것입니다. 원칙의 근본은 작업 코드가 이미 작동하고 변경하면 버그가 발생할 수 있다는 것입니다. 따라서 가장 좋은 시나리오는 기존 코드를 변경하지 않고 새 코드를 추가하는 것입니다.

그러나이라는 함수가 있다고 가정 해 봅시다 BigContrivedMethod(int1, int2, string1). BigContrivedMethodthing1, thing2 및 thing3의 세 가지 작업을 수행합니다. 이 시점에서 BCM 재사용은 너무 어렵 기 때문에 어려울 수 있습니다. 로 (가능한 경우)를 리팩토링 ContrivedFunction1(int), ContrivedFunction2(int)그리고 ContrivedFunction3(string)더 쉽게 결합 할 수있는 3 개의 작은, 더 집중 방법을 당신에게 제공합니다.

그리고 그것은 방법 / 기능과 관련하여 OCP의 핵심입니다 : 구성. 다른 함수에서 함수를 호출하여 "확장"합니다.

OCP는 5 가지 다른 원칙 인 SOLID 지침의 일부입니다. 첫 번째는 핵심적인 단일 책임입니다. 코드베이스의 모든 것이 하나의 특정 작업 만 수행했다면 코드를 수정할 필요가 없습니다. 새로운 코드를 추가하거나 기존 코드를 새로운 방식으로 결합하기 만하면됩니다. 실제 코드는이 가이드 라인을 거의 따르지 않기 때문에 OCP를 얻기 전에 SRP를 얻기 위해 수정해야 할 경우가 종종 있습니다.


OCP가 아닌 여기에서 단일 책임 원칙에 대해 이야기한다고 생각합니다.
Saeed Neamati

1
SRP 없이는 현실적으로 OCP를 가질 수 없습니다. 너무 많은 코드는 확장 할 수 없으며 재사용 할 수 없습니다. SOLID는 거의 중요한 순서대로 작성되었으며 각 원칙은 실현 가능하기 전에 원칙에 의존합니다.
CodexArcanum

이 답변은 더 많이지지되어야합니다.
Ashish Gupta

0

기존 코드를 변경하지 않고 새 코드를 작성하여 프로그램 동작을 변경하는 경우 공개 원칙을 따르고 있습니다.

가능한 모든 변경에 개방적인 코드를 작성하는 것은 매우 불가능하며 (분석 마비를 입력하기 때문에 원하지 않는 경우) 수정보다는 현재 확장으로 작업중인 모든 다른 동작에 응답하는 코드를 작성합니다.

새로운 행동을 허용하기 위해 단순히 무언가를 변경하는 대신 변경해야 할 무언가에 부딪 치면 변화의 요점이 무엇인지 파악하고, 행동을 변경하지 않고 프로그램을 재구성하여 새로운 코드를 작성하여 그 행동을 바꿀 수 있습니다 .

따라서 이것이 귀하의 경우에 어떻게 적용됩니까?

클래스에 새 함수를 추가하는 경우 클래스가 열리지 않거나 닫히지 않지만 오버로드하는 함수의 클라이언트는 있습니다.

클래스에서 작동하는 새로운 함수를 단순히 추가하는 경우 함수와 함수의 클라이언트가 모두 열리고 닫힙니다.

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