방어 코딩을 위해 좋아하는 (영리한) 기술 을 선택해야한다면 그 기술은 무엇입니까? 현재 사용하는 언어는 Java 및 Objective-C (C ++의 배경 지식)이지만 모든 언어로 자유롭게 대답 할 수 있습니다. 여기서 우리 중 70 % 이상이 이미 알고있는 것 이외의 영리한 방어 기술 에 중점 을 둘 것입니다. 이제 트릭을 깊이 파고들 차례입니다.
다시 말해이 흥미없는 예 이외의 다른 것을 생각해보십시오 .
if(5 == x)
대신if(x == 5)
: 의도하지 않은 할당을 피하기 위해
다음은 흥미로운 방어 적 프로그래밍 방법에 대한 몇 가지 예입니다 (언어 별 예는 Java로되어 있음).
-변수를 변경해야 할 때까지 변수를 잠그십시오.
즉, 변수 를 변경해야한다는 것을 알 때까지 모든 변수를 선언 할 수 있으며이 final
시점에서을 제거 할 수 있습니다 final
. 일반적으로 알려지지 않은 사실은 이것이 메소드 매개 변수에도 유효하다는 것입니다.
public void foo(final int arg) { /* Stuff Here */ }
-나쁜 일이 생길 때는 증거를 남기십시오
예외가있을 때 수행 할 수있는 여러 가지 작업이 있습니다. 명백하게 기록하고 정리를 수행하는 것은 몇 가지 일 것입니다. 그러나 증거의 흔적을 남길 수도 있습니다 (예 : “UNABLE TO LOAD FILE”또는 99999와 같은 센티넬 값으로 변수를 설정하면 예외 catch
블록을 넘어서 버릴 경우 디버거에서 유용 할 수 있습니다 ).
-일관성에 관해서 : 악마는 세부 사항에 있습니다.
사용중인 다른 라이브러리와 일관성을 유지하십시오. 예를 들어 Java에서 값 범위를 추출하는 메소드를 작성하는 경우 하한을 포함 하고 상한을 독점으로 설정하십시오 . 이것은 String.substring(start, end)
같은 방식으로 작동하는 것과 같은 방법과 일치하게합니다 . Sun JDK에서 이러한 유형의 모든 메소드는 배열이 일치하는 요소의 반복을 포함하여 다양한 작업을 수행하므로 인덱스가 0 ( 포함 )부터 배열의 길이 ( 독점 ) 까지 다양한 방식으로 작동하므로 이러한 방식으로 작동합니다 .
그렇다면 가장 좋아하는 수비 관행은 무엇입니까?
업데이트 : 아직하지 않은 경우 자유롭게 차임하십시오. 공식 답변을 선택하기 전에 더 많은 답변을 드리겠습니다.
답변
c ++에서는 펜스 포스트 오류를 포착하기 위해 여분의 메모리를 제공하기 위해 새로운 재정의를 한 번 좋아했습니다.
현재 저는 테스트 주도 개발 (Test Driven Development)을 선호하는 방어 적 프로그래밍을 피하는 것을 선호합니다 . 오류를 신속하고 외부 적으로 포착하는 경우 방어적인 조작으로 코드를 어지럽 힐 필요가 없으며 코드가 건조 되어 방어해야 할 오류가 줄어 듭니다.
방어 프로그래밍을 피하고 대신 빨리 실패하십시오.
방어 적 프로그래밍이란 데이터의 일부 실패를 보상하는 코드 작성, 호출자가 호출자와 서브 루틴 간의 계약을 준수하지 않는 데이터를 제공 할 수 있고 서브 루틴이 어떻게 든 대처해야한다고 가정하는 코드 작성 습관을 의미합니다. 그것으로.
답변
SQL
데이터를 삭제해야 할 때
select *
--delete
From mytable
Where ...
내가 그것을 실행할 때, where 절을 잊어 버렸는지 알 수 있습니다. 안전이 있습니다. 모든 것이 괜찮다면 ‘-‘주석 토큰 다음에있는 모든 것을 강조 표시하고 실행합니다.
편집 : 많은 데이터를 삭제하는 경우 * 대신 count (*)를 사용합니다.
답변
응용 프로그램이 시작될 때 합리적인 메모리 덩어리를 할당하십시오. Steve McConnell은 이것을 Code Complete 의 메모리 낙하산 이라고 부릅니다 .
심각한 문제가 발생하여 종료해야하는 경우에 사용할 수 있습니다.
이 메모리를 미리 할당하면 여유 공간을 확보 한 후 사용 가능한 메모리를 사용하여 다음을 수행 할 수 있으므로 안전망이 제공됩니다.
- 모든 영구 데이터 저장
- 적절한 파일을 모두 닫습니다
- 로그 파일에 오류 메시지 쓰기
- 사용자에게 의미있는 오류를 제시
답변
기본 사례가없는 모든 switch 문에서 오류 메시지와 함께 프로그램을 중단하는 사례를 추가합니다.
#define INVALID_SWITCH_VALUE 0
switch (x) {
case 1:
// ...
break;
case 2:
// ...
break;
case 3:
// ...
break;
default:
assert(INVALID_SWITCH_VALUE);
}
답변
열거 형 (C #)의 다양한 상태를 처리 할 때 :
enum AccountType
{
Savings,
Checking,
MoneyMarket
}
그런 다음, 일상 안에서 …
switch (accountType)
{
case AccountType.Checking:
// do something
case AccountType.Savings:
// do something else
case AccountType.MoneyMarket:
// do some other thing
default:
--> Debug.Fail("Invalid account type.");
}
언젠가이 열거 형에 다른 계정 유형을 추가하겠습니다. 그리고 내가 할 때, 나는이 스위치 문장을 고치는 것을 잊을 것이다. 따라서이 Debug.Fail
사실에주의를 끌기 위해 디버그 모드에서 끔찍하게 충돌이 발생합니다. 을 추가하면 case AccountType.MyNewAccountType:
다른 계정 유형을 추가하고 여기에서 사례를 업데이트하는 것을 잊을 때까지 끔찍한 충돌이 중지됩니다.
(예, 다형성이 아마도 더 좋을 수도 있지만 이것은 단지 내 머리 꼭대기의 예일뿐입니다.)
답변
문자열 (특히 사용자 입력에 따라 다름)과 함께 오류 메시지를 인쇄 할 때 항상 작은 따옴표를 사용합니다 ''
. 예를 들면 다음과 같습니다.
FILE *fp = fopen(filename, "r");
if(fp == NULL) {
fprintf(stderr, "ERROR: Could not open file %s\n", filename);
return false;
}
%s
파일 이름이 빈 문자열이거나 공백 또는 무언가이기 때문에 따옴표 가 부족합니다 . 인쇄 된 메시지는 물론 다음과 같습니다.
ERROR: Could not open file
따라서 항상하는 것이 좋습니다.
fprintf(stderr, "ERROR: Could not open file '%s'\n", filename);
그런 다음 최소한 사용자에게 다음이 표시됩니다.
ERROR: Could not open file ''
최종 사용자가 제출 한 버그 보고서의 품질 측면에서 큰 차이가 있습니다. 일반적인 소리가 아닌 이와 같은 재미있는 오류 메시지가있는 경우 “내 파일을 열지 않습니다”라고 쓰지 않고 복사 / 붙여 넣기 할 가능성이 훨씬 높습니다.
답변
SQL 안전
데이터를 수정할 SQL을 작성하기 전에 롤백 트랜잭션으로 전체를 래핑합니다.
BEGIN TRANSACTION
-- LOTS OF SCARY SQL HERE LIKE
-- DELETE FROM ORDER INNER JOIN SUBSCRIBER ON ORDER.SUBSCRIBER_ID = SUBSCRIBER.ID
ROLLBACK TRANSACTION
이렇게하면 잘못된 삭제 / 업데이트를 영구적으로 실행할 수 없습니다. 또한 모든 것을 실행하고 합리적인 레코드 수를 확인하거나 SELECT
SQL과 사이 에 문을 추가 하여 ROLLBACK TRANSACTION
모든 것이 올바르게 표시되도록 할 수 있습니다.
완전히있을 때 확실히 당신이 기대했던의 변경 않습니다 ROLLBACK
에 COMMIT
와 진짜 실행합니다.