가장 현대적인 프로그래밍 언어에서 계약에 의한 Design에 대한 제한된 지원이 필요한 이유는 무엇입니까?


40

최근에 Design by Contract (DbC)를 발견했으며 코드를 작성하는 데 매우 흥미로운 방법이라고 생각합니다. 무엇보다도 다음을 제공하는 것 같습니다.

  • 더 나은 문서. 계약서가 문서이므로 계약서가 구식이 될 수 없습니다. 또한 계약은 루틴의 기능을 정확하게 지정하므로 재사용을 지원하는 데 도움이됩니다.
  • 더 간단한 디버깅. 계약이 실패하는 순간 프로그램 실행이 중지되므로 오류가 전파 될 수 없으며 위반 된 특정 어설 션이 강조 표시 될 수 있습니다. 이것은 개발 및 유지 보수 동안 지원을 제공합니다.
  • 더 나은 정적 분석. DbC는 기본적으로 Hoare 로직의 구현 일 뿐이며 동일한 원칙이 적용되어야합니다.

이에 비해 비용은 다소 작은 것 같습니다.

  • 여분의 손가락 타이핑. 계약은 철자가되어야하기 때문에.
  • 계약서 작성에 익숙해 지려면 약간의 교육이 필요합니다.

이제 파이썬에 대해 잘 알고 있기 때문에 실제로는 전제 조건을 작성하는 것이 가능하며 (부적절한 입력에 대해 예외를 던짐) 어설 션을 사용하여 특정 사후 조건을 다시 테스트 할 수도 있음을 알고 있습니다. 그러나 궁극적으로 비피 토닉으로 간주되는 추가 마법 없이는 '오래된'또는 '결과'와 같은 특정 기능을 시뮬레이션 할 수 없습니다. (또한 지원을 제공하는 라이브러리가 몇 개 있지만 궁극적으로 대부분의 개발자가하지 않는 것처럼 사용하는 것이 좋지 않은 느낌이 들었습니다.) 나는 다른 모든 언어에서 비슷한 문제라고 가정합니다 (물론 제외) , 에펠).

저의 직감에 따르면 지원 부족이 관행을 거부 한 결과이지만 온라인 검색은 유익하지 않았습니다. 현대의 대부분의 언어가 왜 그렇게 적은 지원을 제공하지 않는지 누군가가 명확히 할 수 있는지 궁금합니다. DbC에 결함이 있거나 지나치게 비쌉니까? 아니면 Extreme Programming 및 기타 방법론으로 인해 더 이상 사용되지 않습니까?


프로그램을 테스트하지 않고도 테스트 중심 프로그래밍을 수행하는 지나치게 복잡한 방법처럼 들립니다.
Dan

3
@Dan은 실제로 유형 시스템의 확장이라고 생각하지 않습니다. 예를 들어, 함수는 정수 인수를 취하는 것이 아니라 계약 적으로 0보다 커야하는 정수를 취합니다.
Carson63000

4
@ 단 코드 계약 은 수행해야 할 테스트 수를 크게 줄입니다.
Rei Miyasaka

24
@ Dan, 나는 오히려 TDD가 가난한 사람의 계약이라고 말하고 싶습니다.
SK-logic

동적 언어에서는 옵션 플래그를 기반으로 계약을 사용하여 오브젝트를 "장식"할 수 있습니다. 환경 플래그 를 사용 하여 기존 오브젝트를 선택적으로 계약으로 원숭이 패치 하는 예제 구현있습니다 . 예, 지원은 기본이 아니지만 쉽게 추가 할 수 있습니다. 테스트 하네스에도 동일하게 적용되며 네이티브는 아니지만 추가 / 쓰기가 쉽습니다.
Raynos

답변:


9

분명히 그들은 거의 모든 프로그래밍 언어에서 지원됩니다.

필요한 것은 "어설 션"입니다.

이들은 "if"문으로 쉽게 코딩됩니다.

if (!assertion) then AssertionFailure();

이를 통해 입력 제약 조건에 대해 이러한 어설 션을 코드 맨 위에 배치하여 계약을 작성할 수 있습니다. 리턴 포인트에있는 것은 출력 제한 조건입니다. 코드 전체에 불변량을 추가 할 수도 있습니다 (실제로는 "설계 계약서"의 일부는 아니지만).

그래서 프로그래머가 코드를 작성하기에는 너무 게으 르기 때문에 널리 퍼지지 않았다고 주장합니다.

컴파일 타임 부울 상수 "확인"을 정의하고 명령문을 약간 수정하여 대부분의 언어에서 이들을 조금 더 효율적으로 만들 수 있습니다.

if (checking & !Assertion) then AssertionFailure();

구문이 마음에 들지 않으면 매크로와 같은 다양한 언어 추상화 기술을 사용할 수 있습니다.

일부 현대 언어는 이에 대한 좋은 구문을 제공합니다. 이것이 "현대 언어 지원"이라는 의미입니다. 그것은 지원이지만 꽤 얇습니다.

현대 언어조차도 대부분 제공하지 않는 것은 "임시"어설 션 (임의의 이전 또는 다음 상태 [임시 연산자 "최종")에 대한 것입니다. 실제로 흥미로운 계약을 작성하려는 경우 필요합니다. IF 문은 도움이되지 않습니다. 당신은 여기에.


어설 션에만 액세스 할 수있는 문제는 사후 조건과 사전 조건을 비교해야하기 때문에 명령에서 사후 조건을 확인하는 효과적인 방법이 없다는 것입니다. .) 파이썬에서이 기능은 데코레이터를 사용하여 간단하게 재현 할 수 있지만 어설 션을 해제 할 때가되면 짧아집니다.
Ceasar Bautista

에펠 탑은 실제로 이전 주에서 얼마를 구합니까? 정지 문제를 해결하지 않고 (함수를 분석하여) 어느 부분에 액세스 / 수정할 수 있는지를 합리적으로 알 수 없기 때문에 전체 기계 상태를 저장하거나 아주 얕은 부분 만 시스템 상태로 저장해야합니다. 나는 후자를 의심한다. 전제 조건 이전의 간단한 스칼라 할당으로 "시뮬레이션"할 수 있습니다. 에펠 탑이 그렇지 않다는 것을 알게되어 기쁩니다.
Ira Baxter

7
... 방금 에펠이 어떻게 작동하는지 확인했습니다. "old <exp>"는 함수 진입시 <exp>의 값이므로 예상대로 함수 입구에서 얕은 복사를 수행하고 있습니다. 그들도 할 수 있습니다. 컴파일러가 pre / post / old에 대한 구문을 구현하는 것이 수동으로 수행하는 것보다 더 편리하다는 점에 동의하지만, 요점은 직접 수작업으로 할 수 있으며 실제로 어렵지는 않습니다. 우리는 게으른 프로그래머로 돌아 왔습니다.
Ira Baxter

계약을 실제 논리와 분리 할 수 ​​있으면 @IraBaxter No. 코드가 더 단순 해집니다. 컴파일러가 떨어져 계약과 코드를 말할 수있는 경우에도, 그것은에 의해 중복을 줄일 수 많은 . 예를 들어 D에서 인터페이스 또는 수퍼 클래스에 대한 계약을 선언 할 수 있으며 어설 션은 해당 함수의 코드에 관계없이 모든 구현 / 확장 클래스에 적용됩니다. 예를 들어 python 또는 Java의 경우 전체 super메소드 를 호출 하고 계약없이 복제를 확인하려는 경우 결과를 버릴 수 있습니다. 이것은 실제로 깨끗한 LSP 호환 코드 구현에 도움이됩니다.
marstato

@ marstato : 나는 언어의 지원이 좋은 것이라고 이미 동의했습니다.
Ira Baxter

15

아시다시피, 계약 의한 디자인 은 에펠 탑의 기능으로, 오랫동안 커뮤니티에서 존경을받지는 않았지만 프로그래밍 언어 중 하나였습니다.

DbC는 주류 프로그래밍 커뮤니티가 코드에 제약 조건 / 예상을 추가하는 것이 프로그래머에게 기대할 수있는 "합리적"이라는 점을 비교적 최근에 받아 들였기 때문에 가장 인기있는 언어는 아닙니다. 프로그래머가 단위 테스트의 가치를 이해하는 것이 일반적이며 프로그래머가 인수를 검증하고 이점을 확인하기 위해 코드를 넣는 것에 더 동의하는 것이 일반적입니다. 그러나 10 년 전, 아마도 대부분의 프로그래머들은 "그것은 당신이 알고있는 것들에 대한 추가 작업이 항상 괜찮을 것"이라고 말할 것입니다.

오늘 평범한 개발자에게 가서 사후 조건에 대해 이야기한다면, 그들은 열광적으로 고개를 끄덕이며 "OK, 그것은 단위 테스트와 같습니다."라고 생각합니다. 그리고 전제 조건에 대해 이야기한다면, "OK, 그것은 우리가 항상하지는 않지만 매개 변수 유효성 검사와 같습니다.하지만, 괜찮습니다."라고 말하고 불변에 대해 이야기하면 "이봐, 얼마나 많은 오버 헤드가 있는가? 우리가 잡을 더 많은 버그가 있을까?" 기타

따라서 DbC가 널리 채택되기까지 아직 갈 길이 멀다고 생각합니다.


주류 프로그래머 인 OTOH는 한동안 주장을 작성하는 데 사용되었습니다. 가장 현대적인 주류 언어에 사용 가능한 프리 프로세서가 없기 때문에이 방법은 비효율적 이었지만 여전히 C와 C ++에서 일반적입니다. 현재 Microsoft Code Contracts (AFAIK, 릴리스 빌드에 대한 바이트 코드 재 작성 기반)로 복귀하고 있습니다.
SK-logic

8

내 직감에 따르면 지원이 부족하면 실습을 거부 한 결과가 있어야합니다 ...

그릇된.

그것은의 디자인 연습. 코드 (에펠 스타일)로 명시 적으로 구현하거나 암시 적으로 코드 (대부분의 언어) 또는 단위 테스트로 구현할 수 있습니다. 디자인 실습이 존재하고 잘 작동합니다. 언어 지원은 전 세계에 걸쳐 있습니다. 그러나 단위 테스트 프레임 워크에는 여러 언어로 존재합니다.

현대의 대부분의 언어가 왜 그렇게 적은 지원을 제공하지 않는지 누군가가 명확히 할 수 있는지 궁금합니다. DbC에 결함이 있거나 지나치게 비쌉니까?

비싸요. 과. 더 중요한 것은, 입증 할 수없는 몇 가지가 있습니다 주어진 언어. 예를 들어, 루프 터미네이션은 프로그래밍 언어로 입증 될 수 없으며 "고차"증명 기능이 필요합니다. 따라서 어떤 종류의 계약은 기술적으로 표현할 수 없습니다.

아니면 Extreme Programming 및 기타 방법론으로 인해 더 이상 사용되지 않습니까?

아니.

우리는 주로 단위 테스트를 사용하여 DbC가 충족되었음을 보여줍니다.

파이썬에서 언급했듯이 DbC는 여러 곳으로갑니다.

  1. docstring 및 docstring 테스트 결과.

  2. 입력 및 출력을 검증하기위한 어설 션

  3. 단위 테스트.

더욱이.

문해력있는 프로그래밍 스타일 도구를 채택하여 DbC 정보를 포함하고 깨끗한 Python 및 단위 테스트 스크립트를 생성하는 문서를 작성할 수 있습니다. 문해력있는 프로그래밍 접근 방식을 사용하면 계약서와 완전한 출처가 포함 된 훌륭한 문학 작품을 작성할 수 있습니다.


고정 유한 시퀀스 반복과 같은 사소한 루프 종료 사례를 증명할 수 있습니다. 사소하게 종료되는 것으로 보일 수없는 일반화 된 루핑입니다 (수학적 추측에 대한 "관심있는"솔루션을 찾을 수 있기 때문에). 이것이 Halting Problem의 본질입니다.
Donal Fellows

+1. 나는 당신이 가장 중요한 점을 다룬 유일한 사람이라고 생각합니다 there are some things which cannot be proven. 공식 검증은 훌륭하지만 모든 것이 검증 가능한 것은 아닙니다! 이 기능은 실제로 프로그래밍 언어가 실제로 할 수있는 것을 제한합니다!
Dipan Mehta

@DonalFellows : 일반적인 경우를 입증 할 수 없기 때문에 (a) 비싸고 (b) 불완전한 것으로 알려진 여러 기능을 통합하기가 어렵습니다. 이 답변의 요점은 제한 사항이있을 때 이러한 모든 기능을 피하고 공식적인 정확성 증명에 대한 잘못된 기대를 설정하지 않는 것이 더 쉽다는 것입니다. 언어 이외의 디자인 연습으로 많은 증명 기술을 사용할 수 있습니다.
S.Lott

계약 빌드가 릴리스 빌드에서 컴파일되는 C ++과 같은 언어에서는 전혀 비싸지 않습니다. 그리고 DBC를 사용하면 프로그램이 합법적 인 상태에 대해 런타임 검사를 적게하기 때문에보다 가벼운 빌드 코드를 릴리스하는 경향이 있습니다. 나는 수많은 함수들이 불법 테스트 된 빌드 빌드에서 그 상태에 있지 않아야 할 때 수많은 함수들이 불법 상태를 검사하고 거짓을 반환하는 것을 보았던 엄청나게 많은 코드베이스의 수를 잃어 버렸다.
Kaitain

6

그냥 추측. 어쩌면 그것이 인기가없는 이유의 일부는 "Design by Contract"가 Eiffel에 의해 상표권을 받았다는 것입니다.


3

한 가지 가설은 충분히 큰 복잡한 프로그램, 특히 대상이 움직이는 프로그램의 경우 계약 자체가 프로그램 코드보다 버그가 많고 디버그하기가 어려울 수 있다는 것입니다. 다른 패턴과 마찬가지로, 감소 된 수익률을 넘어서서 사용량이 많을 수 있으며,보다 표적화 된 방식으로 사용될 때 분명한 이점이있을 수 있습니다.

또 다른 가능한 결론은 "관리 언어"의 인기가 선택된 관리 기능 (계약에 의한 배열 범위 등)에 대한 계약 별 설계 지원의 현재 증거라는 것입니다.


> 계약서 자체는 버그가 많고 디버그하기 어려워 질 수 있습니다.
Kaitain

2

대부분의 주류 언어가 언어에 DbC 기능을 가지고 있지 않은 이유는 언어 구현 자에게 언어를 구현할 때의 이점에 대한 비용이 높기 때문입니다.

이것의 한쪽은 이미 다른 답변, 단위 테스트 및 기타 런타임 메커니즘 (또는 템플릿 메타 프로그래밍이있는 일부 컴파일 시간 메커니즘)에서 이미 살펴 보았으므로 이미 DbC의 장점을 많이 얻을 수 있습니다. 따라서 이점이 있지만 상당히 겸손한 것으로 보입니다.

다른 쪽은 비용이며, 기존 언어에 DbC를 다시 맞추는 것은 너무 큰 변화이며 부팅하기가 매우 복잡합니다. 오래된 코드를 깨지 않고 언어에 새로운 구문을 도입하는 것은 어렵습니다. 이렇게 광범위한 변경을 사용하도록 기존 표준 라이브러리를 업데이트하면 비용이 많이 듭니다. 따라서 기존 언어로 DbC 기능을 구현하는 데 비용이 많이 든다는 결론을 내릴 수 있습니다.

나는 또한 그주의 것 개념 꽤 템플릿에 대한 많은 계약입니다, 따라서 다소 DBC 관련, 심지어 작업들이 여전히 필요 년 추정 그들에 일 년 후 같은 최신 C ++ 표준에서 제외되었다. 이러한 종류의 크고 광범위한 언어 변경은 구현하기가 너무 어렵습니다.


2

DbC는 계약을 위반 한 프로그램을 실행할 수 없도록 컴파일 타임에 계약을 확인할 수있는 경우 더 광범위하게 사용됩니다.

컴파일러 지원이 없으면 "DbC"는 "불변 / 가정 확인 및 위반시 예외 발생"의 또 다른 이름입니다.


이것이 멈추는 문제에 빠지지 않습니까?
Ceasar Bautista

@Ceasar 그것은 다릅니다. 일부 가정은 확인할 수 있지만 다른 가정은 확인할 수 없습니다. 예를 들어 빈 목록을 인수로 전달하지 않거나 반환 할 수있는 형식 시스템이 있습니다.
Ingo

Bertrand Meyer가 "프로그래밍 마스터스 (Masterminds of Programming)"부분에서 랜덤 클래스 생성 시스템과 계약 위반 여부를 확인하는 시스템을 언급했지만 좋은 점 (+1)입니다. 이 혼합 컴파일 시간 / 런타임 접근 방식,하지만 난 의심 그래서이 기술은 모든 상황에서 작동
Maksee

예외가 아닌 치명적인 실패 여야하지만 어느 정도는 사실입니다 (아래 참조). DBC의 주요 장점은 실제로보다 나은 프로그램을 설계 할 수있는 방법론과 주어진 방법이 시작시 합법적 인 상태에 있어야한다는 보장으로 많은 내부 논리를 단순화합니다. 일반적으로 계약 위반시 예외를 처리하는 업무를 수행해서는 안됩니다. 프로그램이 LEGALLY가 ~ X 상태에있을 수있는 경우 예외를 사용해야하며 클라이언트 코드가이를 처리해야합니다. 계약은 ~ X는 단순히 불법이라고 말합니다.
Kaitain

1

나는 간단한 설명을했습니다. 프로그래머를 포함한 대부분의 사람들은 필요한 것을 보지 않으면 추가 작업을 원하지 않습니다. 안전이 매우 중요하다고 여겨지는 Avionics 프로그래밍 나는 그것 없이는 대부분의 프로젝트를 보지 못했습니다.

그러나 웹 사이트, 데스크톱 또는 모바일 프로그래밍을 고려하는 경우 충돌 및 예기치 않은 동작은 때때로 버그를보고 할 때 추가 작업을 피하고 나중에 버그를 수정하여 버그를 수정하는 것으로 충분하다고 생각되는 경우가 종종 있습니다.

아마도 Ada는 멋진 언어이지만 더 많은 코딩 작업이 필요하고 신뢰할 수있는 시스템을 구축하려는 경우 작업에 가장 적합한 언어입니다. 에이다에 근거한 언어).

C #의 계약 라이브러리 별 디자인은 Microsoft에서 실험 한 것으로 신뢰할 수있는 소프트웨어를 구축하는 데 매우 유용하지만 시장에서 모멘텀을 선택하지 않았습니다. 그렇지 않으면 핵심 C # 언어의 일부로 볼 수 있습니다.

주장은 이전 / 이후 조건과 불변에 대한 완전한 기능적 지원과는 다릅니다. 에뮬레이션을 시도 할 수는 있지만 적절한 지원을 제공하는 언어 / 컴파일러는 '추상 구문 트리'분석을 수행하고 단순히 어설 션이 수행 할 수없는 논리 오류를 확인합니다.

편집 : 나는 검색을했고 다음은 도움이 될 수있는 관련 토론입니다 : https : //.com/questions/4065001/are-there-any-provable-real-world-languages-scala


-2

대부분 이유는 다음과 같습니다.

  1. 인기가없는 언어로만 제공됩니다
  2. 기존 프로그래밍 언어에서 동일한 작업을 실제로 수행하려는 사람이 다른 방식으로 수행 할 수 있으므로 불필요합니다.
  3. 이해하고 사용하기가 어렵습니다. 제대로하기 위해서는 전문 지식이 필요합니다.
  4. 프로그래머는 많은 양의 코드가 필요합니다.
  5. 장점은 없습니다-가치있는 버그를 찾을 수 없습니다.

1
당신의 대답은 잘 논쟁되지 않았습니다. 당신은 단순히 장점이 없으며, 많은 양의 코드가 필요하며, 기존 언어로 수행 할 수 있기 때문에 불필요하다고 의견을 말하고 있습니다 (OP 가이 문제를 구체적으로 해결했습니다!).
Andres F.

나는 어설 션 등을 대체하는 것으로 생각하지 않습니다. 기존 언어로하는 올바른 방법은 아닙니다 (예 : 아직 해결되지 않았습니다)
tp1

@ tp1, 프로그래머가 실제로 타이핑을 최소화하기를 원한다면 결코 자바처럼 장황하고 웅장한 것으로 빠지지 않을 것입니다. 그리고 그렇습니다. 프로그래밍 자체에는 "적절한 지식을 얻기 위해"전문 지식 "이 필요합니다. 그러한 지식을 가지고 있지 않은 사람들은 코딩을해서는 안됩니다.
SK-logic

@ Sk-logic : 음, 반 세계가 멤버 함수에서 데이터 멤버의 멤버 함수로 전달 함수를 작성하고 싶지 않기 때문에 OO가 잘못하고있는 것 같습니다. 내 경험상 큰 문제입니다. 이것은 쓸 문자 수를 최소화함으로써 직접 발생합니다.
tp1

@ tp1, 사람들이 실제로 타이핑을 최소화하고 싶다면 OO를 만지지 않아도됩니다. OOP는 스몰 토크와 같은 최상의 구현에서도 자연스럽게 웅변입니다. 나는 그것이 나쁜 재산이라고 말하고 싶지 않으며, 웅변은 때때로 도움이됩니다.
SK-logic
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.