강력한 코드는 무엇입니까?


42

교수님은 "강력한"코드를 말할 때이 Java 예제를 계속 언급하고 있습니다.

if (var == true) {
    ...
} else if (var == false) {
    ...
} else {
    ...
}

그는 "강력한 코드"는 프로그램이 모든 가능성을 고려하고 오류와 같은 것이 없다는 것을 의미한다고 주장합니다. 모든 상황은 코드에 의해 처리되어 유효한 상태가되므로 "else"가됩니다.

그러나 나는 의심 스럽다. 변수가 부울 인 경우, 세 번째 상태가 논리적으로 불가능할 때 세 번째 상태를 확인하는 요점은 무엇입니까?

"오류와 같은 것은 없다"는 말도 우스꽝스러워 보인다. Google 애플리케이션조차도 오류를 자동으로 삼키거나 오류를 유효한 상태로 생각하지 않고 사용자에게 직접 오류를 표시합니다. 그리고 그것은 좋은 일입니다-나는 무엇이 잘못되었는지 알고 싶습니다. 그리고 응용 프로그램에 오류가 없다고 주장하는 것은 꽤나 그렇습니다.

그렇다면 "강력한 코드" 의 실제 정의는 무엇 입니까?



4
이것은 강하게 타이핑되지 않은 언어로만 유지됩니다. 강력하게 형식화 된 언어에서 부울 유형의 변수 (부울로 포즈를 취하는 일부 정수는 아님)는 참 또는 거짓 일 수 있으며 세 번째 옵션은 없습니다.
Marjan Venema

23
강력한 코드에는 반드시 테스트가 필요하기 때문에 3 번째 사례에 대한 적용 범위를 테스트하는 방법을 물어보십시오. 3 번째 사례를 테스트 할 수 없다면 거기에 숨어있을 수있는 버그를 찾을 수 없습니다.
gbjbaanb

2
@Marjan-강력하지 않은 언어로 작성하면 대부분 다음과 같이 작성합니다. if (var) {} else {}
kevin cline

2
나는 x와! x가 모두 맞는 언어를 모른다. "if (x == true) ...";를 제안하지 않았습니다. 나는 그런 비교를 싫어한다.
케빈 클라인

답변:


33

세 번째 상태가 논리적으로 불가능할 때 세 번째 상태를 확인하는 요점은 무엇입니까?

참 또는 거짓이 아닌 상태 Boolean?를 허용 하는 어떻습니까? NULL이제 소프트웨어는 어떻게해야합니까? 일부 소프트웨어는 맥박 조정기와 같이 충돌에 강해야합니다. 누군가가 데이터베이스에 열을 추가 Boolean하고 현재 데이터를 NULL초기에 초기화하는 것을 본 적이 있습니까? 내가 봤다는 걸 알아

다음은 소프트웨어 측면에서 강력하다는 의미를 설명하는 몇 가지 링크입니다.

여기에 "견고한"의 정의에 보편적으로 합의 된 것이 있다고 생각되면 행운을 빕니다. 방폭 또는 바보와 같은 동의어가있을 수 있습니다. 덕트 테이프 프로그래머 는 일반적으로 적어도 용어를 이해하면서 강력한 코드를 작성하는 사람의 예입니다.


13
이것이 nullable boolean 인 경우 Java와 c #이 모두 throw되므로 null을 먼저 확인해야합니다.
Esben Skov Pedersen

고양이 나 개가 무엇인지에 대해 보편적으로 합의 된 정의가없는 것 같습니다.
Tulains Córdova

11

내 토론을 위해 Bool은 True 또는 False의 두 가지 상태를 가질 수 있습니다. 다른 것은 프로그래밍 언어 사양에 부적합합니다. 공구 체인이 사양에 맞지 않으면 어떤 작업을 하든지 호스가 연결됩니다. 개발자가 상태가 2 개 이상인 Bool 유형을 만든 경우 코드베이스에서 마지막으로 수행 한 작업입니다.

옵션 A.

if (var == true) {
    ...
} else if (var == false) {
    ...
} else {
    ...
}

옵션 B

if (var == true) {
    ...
} else {
    ...
}

옵션 B가 더 강력하다고 주장합니다 .....

모든 트위트가 예기치 않은 오류를 처리하도록 지시 할 수 있습니다. 그것들은 일단 생각하면 감지하기가 쉽습니다. 당신의 교수가 제시 한 예는 일어날 수있는 것이 아니므로 아주 좋지 않은 예입니다.

복잡한 테스트 하네스 없이는 테스트 할 수 없습니다. 만들 수 없다면 어떻게 테스트하겠습니까? 코드를 테스트하지 않았다면 어떻게 작동하는지 어떻게 알 수 있습니까? 작동하는지 모른다면 강력한 소프트웨어를 작성하지 않은 것입니다. 나는 그들이 아직도 그것을 Catch22라고 부른다고 생각한다.

옵션 B는 테스트하기가 쉽지 않습니다.

다음 문제는 교수님에게 "부울이 True도 False도 아닌 경우 어떻게 하시겠습니까?" 그것은 매우 흥미로운 토론으로 이어질 것입니다 .....

대부분의 경우 코어 덤프가 적절하며 최악의 경우 사용자를 성가 시게하거나 많은 비용이 듭니다. 예를 들어, 우주 왕복선 실시간 재진입 계산 시스템 인 경우 어떻게됩니까? 아무리 부정확하더라도 응답은 중단하는 것보다 나빠질 수 없으므로 사용자를 죽일 수 있습니다. 따라서 어떻게해야하는지에 대한 답이 틀렸다는 것을 알고 있다면 50/50으로 가거나 중단하고 100 % 실패로 가십시오. 내가 승무원이라면 50/50을 가져갈 것입니다.

옵션 A는 저를 죽입니다. 옵션 B는 저에게 생존의 기회를줍니다.

그러나 잠깐만 요. 그것은 우주 왕복선 재진입의 시뮬레이션입니다. 그렇다면 무엇입니까? 당신이 그것에 대해 알 수 있도록 중단하십시오. 좋은 생각 같나요? -아닙니다-배송하려는 코드로 테스트해야하기 때문입니다.

옵션 A는 시뮬레이션에 더 좋지만 배포 할 수는 없습니다. 쓸모없는 옵션 B는 배포 된 코드이므로 시뮬레이션은 실제 시스템과 동일하게 수행됩니다.

이것이 유효한 관심사라고 가정 해 봅시다. 더 나은 솔루션은 오류 처리를 응용 프로그램 논리에서 분리하는 것입니다.

if (var != true || var != false) {
    errorReport("Hell just froze over, var must be true or false")
}
......
if (var == true){
 .... 
} else {
 .... 
}

추가 정보 -Therac-25 Xray 머신, Ariane 5 Rocket 실패 및 기타 (링크에 많은 링크가 끊어졌지만 Google에서 도움이되는 정보가 충분 함)


1
".. 예기치 않은 오류. 일반적으로 일단 생각하면 쉽게 알아 차릴 수 있습니다."-생각할 때 더 이상 예상하지 않습니다.
gbjbaanb

7
의문 코드가있는 경우에 같은 if (var != true || var != false) {해야한다 &&대신은.

1
나는 사실이 아닌 거짓을 쉽게 생각할 수 있지만 여전히 예상치 못한 것입니다. 부울이 다른 것이 될 수 없다고 말하면, 문자가 숫자 문자인지 확인한 다음 정수 값으로 변환하면 정수 값이 0보다 작거나 9보다 크다는 것을 쉽게 생각할 수 있지만 여전히 예기치 않은.
gnasher729

1
Null 부울은 Java 및 C #에서 지원되며 실제 응용 프로그램이 있습니다. 사람 목록이 포함 된 데이터베이스를 고려하십시오. 잠시 후 성별 (isMale) 필드가 필요하다고 결정합니다. 널 (Null)은 "아무도 묻지 않았다"는 의미입니다. 참은 남자를, 거짓은 여자를 의미합니다. (확인, 트랜스 젠더는 단순화를 위해 생략되었습니다 ...).
kiwiron

@kiwiron : 열거 형 "Male", "Female", "Did Not Ask"를 사용하지 않는 것이 더 좋은 해결책입니다. 열거가 더 좋습니다-필요할 때 확장 될 수 있습니다 (예 : Asexual, Hermaphrodite, "Refused to Answer"가 떠 오릅니다).
mattnz

9

실제로 코드는 더 강력하지 않지만 LESS는 강력합니다. 마지막 else은 테스트 할 수없는 데드 코드입니다.

우주선과 같은 중요한 소프트웨어에서는 데드 코드와 더 일반적으로 테스트되지 않은 코드가 금지됩니다. 우주 광선이 단일 이벤트를 발생시켜 데드 코드가 활성화되면 모든 것이 가능합니다. SEU가 강력한 코드의 일부를 활성화하면 (예기치 않은) 동작이 계속 제어됩니다.


우주선에서 그것을 얻지 못합니다 죽은 코드는 금지되어 있습니까? 즉, 마지막을 쓸 수 없습니까? 당신이 그것을 테스트 할 수 없기 때문에 당신은 그것을 넣을 수 없습니다? 그러나 "SEU가 강력한 코드의 일부를 활성화하면 (예기치 않은) 동작이 제어 상태를 유지합니다."
초라한

5
그렇습니다. 공간에서 중요한 소프트웨어 테스트 범위는 100 % 여야하며 결과적으로 도달 할 수없는 코드 (일명 데드 코드)가 금지됩니다.
mouviciel

7

교수님이 "오류"와 "버그"를 혼동하는 것 같습니다. 강력한 코드에는 버그가 거의 없거나 전혀 없어야합니다. 강력한 코드는 적대적인 환경에서 오류 관리 기능이 우수해야합니다 (예외 처리 또는 엄격한 리턴 상태 테스트).

나는 교수의 코드 예제가 어리석지 만 나만큼 어리석지 않다는 것에 동의합니다.

// Assign 3 to x
var x = 3;
x = 3;   // again, just for sure
while (x < 3 or x > 3) { x = 3; }  // being robust
if (x != 3) { ... }  // this got to be an error!

1
마지막으로 확실하게 트리거된다면 실제로 그렇게 많은 노력이 필요하지 않을 것입니다. 숙련 된 C 프로그래머는 값이 갑자기 변하는 것을 보았습니다. 물론 논리적으로 제어 된 단일 스레드 환경에서는 이런 일이 발생하지 않아야합니다. 실제로 if 내부의 코드는 결국 발생합니다. 유용한 정보가 없다면 그 안에 할 수 있다면 코딩하지 마십시오! (특별한 소프트웨어 개발 중에 재미있는 일이 있었는데, 불가능한 일이 발생했을 때 저주 단어로 예외를 제기했습니다 ... 무슨 일이 일어 났습니까?).
Alex

2
실화 :boolean x = something(); if (x) { x = True // make sure it's really true, ... }
Andres F.

6

Robust Code의 정의에는 동의가 없습니다 . 프로그래밍의 많은 것들이 다소 주관적이므로 ...

교수님의 예는 언어에 따라 다릅니다.

  • Haskell에서는 또는 Boolean중 하나 일 수 있습니다. 세 번째 옵션은 없습니다.TrueFalse
  • C ++에서이 bool될 수있다 true, false또는 (불행히도) 알 수없는 경우에 넣어 몇 가지 의심스러운 캐스트에서 온 ... 이것은 해야 발생하지만,하지 않을 수 있습니다, 이전 오류의 결과로.

그러나 교수가 조언 하는 것은 핵심 프로그램 중간에 발생하지 않아야 할 사건에 대한 불필요한 논리를 도입하여 코드를 모호하게 하므로 대신 방어 프로그래밍으로 안내 합니다.

대학의 경우 계약 별 설계 전략을 채택하여이를 보강 할 수도 있습니다.

  • 클래스에 대한 불변량을 설정합니다 (예 : 목록 size의 항목 수입니다 data).
  • (예를 들어,이 기능이 단지 호출 될 수있는 각 기능에 대해 사전 조건 및 사후 조건들이 a이하 인 10)
  • 각 기능의 시작 및 종료 지점에서 각각을 테스트 하십시오.

예:

class List:
  def __init__(self, items):
    self.__size = len(items)
    self.__data = items

  def __invariant(self):
    assert self.__size == len(self.__data)

  def size(self):
    self.__invariant()

    return self.__size

  def at(self, index):
    """index should be in [0,size)"""
    self.__invariant()
    assert index >= 0 and index < self.__size

    return self.__data[index]

  def pushback(self, item):
    """the subsequent list is one item longer
       the item can be retrieved by self.at(self.size()-1)"""
    self.__invariant()

    self.__data.append(item)
    self.__size += 1

    self.__invariant()
    assert self.at(self.size()-1) == item

그러나 교수는 구체적으로 Java라고 말했으며 var 유형이 무엇인지 구체적으로 말하지 않았습니다. 부울 인 경우 true, false 또는 null 일 수 있습니다. 다른 것이 있으면 true와 false와 같지 않을 수 있습니다. 그렇습니다. 견고하고 방어 적이며 편집증이 겹칩니다.
Andy Canfield

2
C, C ++ 및 Objective-C에서 부울은 다른 유형과 같이 불확실한 값을 가질 수 있지만 할당하면 값이 true 또는 false로 설정되고 다른 값은 설정되지 않습니다. 예를 들어 : bool b = 0; b ++; b ++; b를 true로 설정합니다.
gnasher729

2

교수의 접근 방식은 완전히 잘못된 것입니다.

함수 또는 약간의 코드에는 가능한 모든 입력을 다루는 기능을 나타내는 사양이 있어야합니다. 그리고 그 행동이 스펙과 일치하도록 코드를 작성해야합니다. 이 예에서는 다음과 같이 사양을 매우 간단하게 작성합니다.

Spec: If var is false then the function does "this", otherwise it does "that". 

그런 다음 함수를 작성하십시오.

if (var == false) dothis; else dothat; 

코드가 사양을 충족합니다. 교수님의 말 : var == 42라면? 스펙을보십시오 : 함수가 "그것을"해야한다고 말합니다. 코드를보십시오 : 함수는 "그것"을합니다. 기능이 사양을 충족합니다.

교수의 코드가 문제를 완전히 부실하게 만드는 것은 var가 참이나 거짓이 아닐 때 그의 접근 방식을 사용하면 이전에는 결코 호출되지 않았으며 완전히 테스트되지 않은 코드를 실행하여 전혀 예측할 수없는 결과를 초래한다는 사실입니다.


1

@ gnasher729의 진술에 동의합니다. 교수님의 접근 방식이 완전히 잘못되었습니다.

견고 함은 가정이 거의없고 분리되어 있기 때문에 파손 / 실패에 대한 내성을 의미합니다. 자체 포함, 자체 정의 및 휴대용입니다. 또한 변화하는 요구 사항에 적응할 수있는 것도 포함됩니다. 한마디로, 귀하의 코드는 내구성이 있습니다.

이것은 일반적으로 호출자가 전달한 매개 변수에서 데이터를 가져 오는 간단한 함수와 구체적인 구현 코드가 포함 된 함수가 아닌 소비자를위한 공용 인터페이스 (추상 메서드, 래퍼, 간접, COM 스타일 인터페이스 등)를 사용하는 것으로 해석됩니다.


0

강력한 코드는 단순히 오류를 잘 처리하는 코드입니다. 그 이상도 이하도 아닌.

실패 중에는 잘못된 코드, 불완전한 코드, 예기치 않은 값, 예기치 않은 상태, 예외, 리소스 고갈 등 여러 유형이 있습니다. 강력한 코드가 이러한 문제를 잘 처리합니다.


0

나는 당신이 방어 프로그래밍 의 예로써 (적어도 나는 용어를 사용할 때) 당신이 준 코드를 고려할 것이다 . 방어 프로그래밍의 일부는 나머지 시스템의 동작에 대한 가정을 최소화하는 선택을하는 것입니다. 예를 들어, 다음 중 어떤 것이 더 낫습니다 :

for (int i = 0; i != sequence.length(); ++i) {
    // do something with sequence[i]
}

또는:

for (int i = 0; i < sequence.length(); ++i) {
    // do something with sequence[i]
}

(차이를 보는 데 문제가있는 경우 루프 테스트를 확인하십시오 : 첫 번째 용도 !=, 두 번째 용도 <).

이제 대부분의 상황에서 두 루프는 정확히 같은 방식으로 작동합니다. 그러나 첫 번째 (와 비교 !=)는 i반복 당 한 번만 증가 한다고 가정합니다 . 값 sequence.length()을 건너 뛰면 루프가 시퀀스 경계를 ​​넘어 계속해서 오류가 발생할 수 있습니다.

따라서 두 번째 구현이 더 강력하다는 주장을 할 수 있습니다. 루프 본문이 변경되는지 여부에 대한 가정에 의존하지 않습니다 i(참고 : 실제로 여전히 절대적인 가정 i은 아닙니다).

이러한 가정을 원하지 않는 이유에 대한 동기를 부여하기 위해 루프가 문자열을 스캔하고 텍스트 처리를 수행한다고 가정하십시오. 루프를 작성하면 모든 것이 정상입니다. 이제 요구 사항이 변경되고 텍스트 문자열에서 이스케이프 문자를 지원해야하므로 이스케이프 문자 (예 : 백 슬래시)를 감지하면 이스케이프 i직후에 문자를 건너 뛰도록 증가 합니다. 텍스트의 마지막 문자가 백 슬래시 인 경우 루프 본문이 증가 i하고 루프가 시퀀스 끝을 넘어 계속 진행 하기 때문에 첫 번째 루프에 버그가 있습니다 .


-1

필자는 개인적 으로이 중요한 특성을 가진 '강력한'코드를 설명합니다.

  1. 우리 엄마가 그 앞에 앉아 작업하면 시스템을 깰 수 없어

이제는 시스템을 불안정한 상태로 만들거나 UNHANDLED 예외를 발생시키는 것을 의미 합니다. 때로는 단순한 개념으로 복잡한 정의와 설명을 할 수 있습니다. 그러나 나는 단순한 정의를 선호합니다. 사용자는 강력한 응용 프로그램을 찾는 데 능숙합니다. 응용 프로그램 사용자가 버그, 상태 손실, 직관적이지 않은 워크 플로 등에 대한 많은 요청을 보내면 프로그래밍에 문제가있는 것입니다.

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