2017-05-09 1 views
1

나는 올바른 방법으로 OOP와 OOD 원칙을 배우려고 노력하고 있습니다. Liskov 치환 원칙과 PRE 및 POST 조건에 대한 설명을 듣고 싶습니다. 일부 주제는 여기에서 읽었으며 일부 기사는 http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod 및 기타 장소에서 읽었습니다.고체 원칙 : LSP 위반

나는 매우 그들에 대한 사전 및 사후 조건에 내 가정 간단한 기본 클래스와 몇 가지 예를 들어 서브 클래스를 작성하고 나는 그들이 올바른 있는지 알고 싶습니다. 댓글 줄은 내가 생각하기에 : PRE 및 POST 조건을 위반하는지 여부입니다.

public abstract class BaseClass 
{ 
    public virtual int GetResult(int x, int y) 
    { 
     if (x > 10 && y < 20) 
     { 
      return y - x; 
     } 
     throw new Exception(); 
    } 
} 

public class LSPExample1 : BaseClass 
{ 
    public override int GetResult(int x, int y) 
    { 
     // PRE: weakened pre condition is ok 
     if (x > 10 && y <= 15) 
     { 
      // POST: Is it ok? because the available result range is narrowed by y <= 15 
      return y - x; 
     } 
     throw new Exception(); 
    } 
} 

public class LSPExample2 : BaseClass 
{ 
    public override int GetResult(int x, int y) 
    { 
     // PRE: Same as base - OK 
     if (x > 10 && y < 20) 
     { 
      // POST: I assume it's bad because of parameters place changed in substraction ? 
      return x-y; 
     } 
     throw new Exception(); 
    } 
} 

public class LSPExample3 : BaseClass 
{ 
    public override int GetResult(int x, int y) 
    { 
     // PRE Condition is bad (Strenghtened) because of (X >5) and (Y>20) ? 
     if (x > 5 && y > 20) 
     { 
      // POST condition is ok because base class do substraction which is weaker than multiplication ? 
      return x * y; 
     } 
     throw new Exception(); 
    } 
} 

정말 시간

답변

5

이 실제로 소스에 갈 수있는 그 멋진 상황 중 하나입니다 감사하겠습니다. 바바라 리 스코프 (Barbara Liskov)의 원저적 인 논문이 있으며 쉽게 읽을 수 있고 쉽게 읽을 수 있습니다. http://csnell.net/computerscience/Liskov_subtypes.pdf

두 개의 정수를 입력으로 받아들이고 정수를 반환하거나 예외를 throw하는 네 가지 방법 모두 GetResult입니다. 이 점에서 그들은 모두 동일한 행동을하므로 LSP가 완전히 만족된다고 말할 수 있습니다. 명시 적 사전/사후 조건 또는 불변 값이없는이 없으면 코드에 대해 실제로 말할 수있는 것은 없습니다.

귀하의 예에서 누락 된 것은 계약입니다. GetResult는 호출자에서은 무엇 필요 않으며, 그것은 생산할 예정 무엇을 보장 는 무엇입니까? 실시 예 2 및 3은 계약 실패 후 x 및 LSP 따라서 휴식 -

예를 들면, 계약이 리턴 값 (Y)와 동일 할 것이 보장 경우

. 그러나 반환 값이 Int 또는 Exception 일 것이라는 유일한 보증이있는 경우 모두 통과합니다.

계약이 보장하고 예외가있는 경우는 X < = 10을 던져 질 경우 || y> = 20 then example 1 & 3 LSP 중단. 메서드가 Int를 반환하거나 Exception을 throw한다는 것이 유일한 보장이면 모두 만족합니다.

코드는 보장이 무엇을 말할 수 없다, 그것은 단지 당신이 코드를 수행하려는 알 수 있습니다.

I가-투표를 많이 받고 있어요 때문에, 나는 예 (의사 코드) 추가 할 것입니다 : 두 함수의 각

class Line { 
    int start 
    int end 
    int length() { return end - start } // ensure: length = end - start 

    void updateLength(int value) { 
     end = start + value 
     // ensure: this.length == value 
    } 
} 

은 "확인"절은 상태에 대한 보장이다 함수가 호출 된 후 Line 객체의 하위 클래스의 보증을 충족하는 한 내 하위 클래스는 LSP를 준수합니다. 따라서 예를 들면 다음과 같습니다.

class Example1: Line { 
    void updateLength(int value) { 
     start = end - value 
    } 
} 

위 항목은 LSP를 만족합니다. 라인의 updateLength 기능도의 보장 조항이있는 경우

는 "this.start 변경"다음 내 서브 클래스는 LSP를 만족하지 않을 것입니다.

+0

요점. 좋은거야. – niksofteng