문제

면책 조항:나는 평신도 현재 학습 프로그램입니다.지 프로젝트의 일환으며,작성된 이상~500 라인입니다.

나의 질문은:는 방어 프로그램을 위반하지 않는 반복 자신이 원칙이 있습니까?가정 내의 정의는 방어 프로그램이 올바른(을 호출하는 함수 유효성을 입력하는 대신 반대),되지 않을 해로운드?

예를 들어,이런 나쁜:

int foo(int bar)
{
    if (bar != /*condition*/)
    {
        //code, assert, return, etc.
    }
}

int main()
{
    int input = 10;
    foo(input); //doesn't the extra logic
    foo(input); //and potentially extra calls
    foo(input); //work against you?
}   

에 비해 이것:

int main()
{
    if (input == /*condition*/)
    {
        foo(input);
        foo(input);
        foo(input);
    }
}

다시,평신도,내가 얼마나 많이 알고하지 않 간단한 논문에 대한 계산을 마찬가지로 지금까지 성능을 간다,그러나 확실히 방어 프로그래밍에 대 한 좋지 않 프로그램이나 영혼이다.

도움이 되었습니까?

해결책

그것은 모두로 내려진다 계약 인터페이스가 제공합니다. 이에 대한 두 가지 시나리오는 입력 및 출력이 있습니다.

입력-그리고 그에 따라 기본적으로 함수의 매개 변수를 의미합니다. 구현은 일반 규칙으로 점검해야합니다.

출력-반환 결과는 기본적으로 발신자가 기본적으로 신뢰할 수 있어야합니다.

이 모든 것이이 질문에 의해 완화됩니다. 한 당사자가 계약을 끊으면 어떻게됩니까? 예를 들어 인터페이스가 있다고 가정 해 봅시다.

class A {
  public:
    const char *get_stuff();
}

그리고 그 계약은 null 문자열이 반환되지 않을 것을 명시합니다 (최악의 경우 빈 문자열이 될 것입니다). 그러면 안전합니다.

A a = ...
char buf[1000];
strcpy(buf, a.get_stuff());

왜요? 글쎄, 당신이 틀렸고 칼리가 널을 반환하면 프로그램이 충돌합니다. 그게 실제로 괜찮습니다. 일부 물체가 계약을 위반하는 경우 일반적으로 결과는 치명적이어야합니다.

지나치게 방어 적으로 직면하는 위험은 불필요한 코드를 많이 쓰거나 (더 많은 버그를 소개 할 수 있음) 실제로 안해야한다는 예외를 삼켜서 실제로 심각한 문제를 가릴 수 있다는 것입니다.

물론 상황은 이것을 바꿀 수 있습니다.

다른 팁

건조 원칙을 위반하는 것은 다음과 같습니다.

int foo(int bar)
{
    if (bar != /*condition*/)
    {
        //code, assert, return, etc.
    }
}

int main()
{
    int input = 10;
    if (input == /*condition*/)
    {
       foo(input);
       foo(input);
       foo(input);
    }
}

보시다시피, 문제는 프로그램에서 동일한 점검을 두 번 가지고 있다는 것입니다. 따라서 조건이 변경되면 두 곳에서 수정해야하며, 그 중 하나를 잊어 이상한 행동을 일으킬 가능성이 있습니다. 건조는 "같은 코드를 두 번 실행하지 말아야한다"는 의미는 아니지만 "같은 코드를 두 번 쓰지 마십시오"

원칙을 따르는 것이 맹목적으로 맹목적으로 이상적이며 잘못되었다고 말씀 드리겠습니다. 달성하고자하는 것을 달성해야합니다 (예 : 응용 프로그램의 안전). 일반적으로 건조를 위반하는 것보다 훨씬 더 중요합니다. 원칙에 대한 고의적 인 위반은 좋은 프로그래밍에서 가장 자주 필요합니다.

예 : 중요한 단계에서 이중 점검을 수행합니다 (예 : loginservice- LoginService.login을 호출하기 전에 입력을 한 번 유효하게 한 다음 다시 내부). , 일반적으로 단위 테스트를 사용합니다. 때에 따라 다르지.

그래도 나는 이중 상태 검사를 통해 결코 일을하지 않았다. 다른 한편으로는 전적으로 그들을 잊어 버리는 것은 일반적으로 여러 가지 크기가 더 나쁘다 :)

방어 프로그래밍은 일종의 나쁜 랩을 얻는다. 왜냐하면 그것은 단어가 없어지는 소리가없고, 더 이상한 코드를 포함하고, 더 크게 오류에 대한 종이를하는 것이기 때문이다.

대부분의 사람들은 오류가 발생할 때 프로그램이 빠르게 실패해야한다는 데 동의하지만, 미션 크리티컬 시스템은 바람직하지 않게 실패하지 않아야하며 대신 오류 상태에 직면하여 계속해서 많은 노력을 기울여야합니다.

물론 그 진술에 문제가 있습니다. 물론 프로그램, 심지어 미션 비평가 어떻게 일관성이없는 상태에있을 때 계속 진행할 수 있습니까? 물론 실제로는 할 수 없습니다.

당신이 원하는 것은 이상한 일이 있더라도 프로그램이 올바른 일을하기 위해 모든 합리적인 단계를 수행하는 것입니다. 동시에 프로그램은 불만을 제기해야합니다. 큰 소리로, 그것이 이상한 상태를 만날 때마다. 그리고 볼 수없는 오류가 발생하는 경우 일반적으로 발행을 피해야합니다. HLT 지시, 오히려 우아하게 실패해야합니다. 시스템을 안전하게 차단하거나 백업 시스템을 사용할 수있는 경우 일부 백업 시스템을 활성화해야합니다.

단순화 된 예에서는 두 번째 형식이 바람직 할 것입니다.

그러나 이는 실제로 더 크고 복잡하고 현실적인 프로그램에는 적용되지 않습니다.

"FOO"가 어디에서 또는 어떻게 사용되는지 미리 알 수 없으므로 입력을 검증하여 FOO를 보호해야합니다. 입력이 발신자에 의해 검증 된 경우 (예 : 예제에서 "메인") "메인"은 유효성 검사 규칙을 알고 적용해야합니다.

실제 프로그래밍에서 입력 검증 규칙은 상당히 복잡 할 수 있습니다. 발신자가 모든 유효성 검사 규칙을 알고 올바르게 적용하도록하는 것은 적절하지 않습니다. 어딘가에 일부 발신자는 검증 규칙을 잊어 버리거나 잘못된 규칙을 수행 할 것입니다. 따라서 반복적으로 호출 되더라도 "foo"내부에 검증을하는 것이 좋습니다. 이것은 발신자에서 칼리로 부담을 바꾸어 발신자가 "foo"의 세부 사항에 대해 덜 생각하고 추상적이고 신뢰할 수있는 인터페이스로 더 많이 사용하도록 해석합니다.

"FOO"가 동일한 입력으로 여러 번 호출되는 패턴이있는 경우, 한 번 유효성 검사를 수행하는 래퍼 함수와 검증을 측정하는 보호되지 않은 버전을 제안합니다.

void RepeatFoo(int bar, int repeatCount)
{
   /* Validate bar */
   if (bar != /*condition*/)
   {
       //code, assert, return, etc.
   }

   for(int i=0; i<repeatCount; ++i)
   {
       UnprotectedFoo(bar);
   }
}

void UnprotectedFoo(int bar)
{
    /* Note: no validation */

    /* do something with bar */
}

void Foo(int bar)
{
   /* Validate bar */
   /* either do the work, or call UnprotectedFoo */
}

알렉스는 다음과 같이 말했다,그것은 상황에 따라,예를 들어,거의 항상 유효성을 입력의 모든 단계에서 로그인 과정입니다.

다른 곳에서 당신은 필요하지 않습니다.

그러나,예를 했다면,두 번째 예에서,당신은 하나 이상의 입력으니 그렇지 않으면 될 것이 중복되는 동일한 함수를 호출하 3 회는 동일한 입력하는 방법에 대해 알아보십시오를 작성해야의 조건 3 번입니다.지금은 중복입니다.

만약 입력 항상 확인할 수 있만에 포함 기능입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top