그러나 클라이언트 소프트웨어 충돌은 여전히 좋은 일이 아닙니다.
가장 좋은 방법입니다.
정의되지 않은 시스템은 데이터 손상, 하드 드라이브 포맷, 대통령 위협 이메일 전송 등의 불쾌한 작업을 수행 할 수 있기 때문에 시스템을 정의되지 않은 상태로 두는 것을 원합니다. 시스템을 복구하고 정의 된 상태로 되돌릴 수없는 경우 충돌이 가장 큰 원인입니다. 이것이 우리가 조용히 찢어지지 않고 충돌하는 시스템을 구축하는 이유입니다. 이제 우리는 모두 충돌하지 않는 안정적인 시스템을 원하지만 시스템이 정의 된 예측 가능한 안전 상태를 유지할 때만 원합니다.
제어 흐름과 같은 예외는 심각한 반 패턴으로 간주됩니다.
그것은 절대적으로 사실이지만 종종 오해됩니다. 그들이 예외 시스템을 발명했을 때 그들은 구조화 된 프로그래밍을 깨뜨리는 것을 두려워했습니다. 우리가 왜 구조적 프로그래밍은 for
, while
, until
, break
, 그리고 continue
모든 우리가 필요로 할 때,이 모든 작업을 수행 할 수있다 goto
.
Dijkstra 는 비공식적으로 (즉, 원하는 곳을 뛰어 다니며) 코드를 사용하면 코드를 읽는 것이 악몽이된다고 가르쳤다. 그들이 우리에게 예외 시스템을 주었을 때 그들은 goto를 재발견하는 것을 두려워했습니다. 그래서 그들은 우리가 이해하기를 바라면서 "흐름 제어에 사용하지 말라고 우리에게 말했다. 불행하게도, 우리 중 많은 사람들이 그렇지 않았습니다.
이상하게도, 우리는 goto와 마찬가지로 스파게티 코드를 만들기 위해 예외를 남용하지 않는 경우가 많습니다. 조언 자체가 더 많은 문제를 일으킨 것 같습니다.
근본적으로 예외는 가정을 거부하는 것입니다. 파일 저장을 요청하면 파일을 저장할 수 있고 저장할 수 있다고 가정합니다. 이름이 불법이거나 HD가 가득 찼거나 쥐가 데이터 케이블을 통해 gna 아 먹었 기 때문에 발생할 수없는 예외입니다. 모든 오류를 다르게 처리하거나 모두 같은 방식으로 처리하거나 시스템을 중지시킬 수 있습니다. 코드에는 가정이 맞아야하는 행복한 길이 있습니다. 한 가지 또는 다른 예외로 인해 그 행복한 길을 벗어날 수 있습니다. 엄밀히 말하면, 그것은 일종의 "흐름 제어"이지만 그들이 경고 한 것은 아닙니다. 그들은 다음 과 같이 넌센스 에 대해 이야기 했습니다 .
"예외는 예외적이어야한다". 예외 시스템 설계자가 스택 추적을 빌드 할 시간이 필요하기 때문에이 작은 타우 톨 로지가 탄생했습니다. 뛰어 다니는 것에 비해 느립니다. CPU 시간을 먹는다. 그러나 다음 시스템을 시작하기 전에 시스템을 기록하고 정지 시키거나 현재 시간 집약적 인 처리를 중단하려는 경우 시간을 내야합니다. 사람들이 "흐름 제어를 위해"예외를 사용하기 시작하면 시간에 대한 가정은 모두 창 밖으로 나옵니다. 따라서 성능 예외로 "예외가 예외적이어야합니다"가 실제로 우리에게 주어졌습니다.
그보다 훨씬 더 중요한 것은 우리를 혼동하지 않습니다. 위의 코드에서 무한 루프를 발견하는 데 얼마나 걸렸습니까?
오류 코드를 반환 하지 마십시오 .
... 일반적으로 오류 코드를 사용하지 않는 코드 기반에있을 때는 좋은 조언입니다. 왜? 아무도 반환 값을 저장하고 오류 코드를 확인하는 것을 기억하지 않기 때문입니다. C에있을 때는 여전히 훌륭한 컨벤션입니다.
OneOf
또 다른 규칙을 사용하고 있습니다. 컨벤션을 설정하고 다른 컨벤션과 싸우지 않는 한 괜찮습니다. 동일한 코드베이스에 두 가지 오류 규칙이있는 것이 혼란 스럽습니다. 어떻게 든 다른 규칙을 사용하는 모든 코드를 제거했다면 계속하십시오.
나는 대회 자체를 좋아한다. 그것의 최고의 설명 중 하나는 내가 발견 여기 * :
그러나 내가 좋아하는 한 나는 여전히 다른 규칙과 섞지 않을 것입니다. 하나를 고르세요. 1
1 : 즉, 둘 이상의 컨벤션을 동시에 생각하게하지 마십시오.
후속 생각 :
이 토론에서 현재 내가 취하는 것은 다음과 같습니다.
- 직접 호출자가 예외를 대부분 잡아서 처리하고 다른 경로를 통해 작업을 계속할 것으로 예상되는 경우 아마도 리턴 유형의 일부 여야합니다. 선택적 또는 OneOf가 여기서 유용 할 수 있습니다.
- 직접 호출자가 대부분 예외를 포착하지 않을 것으로 예상되는 경우 예외를 던져 수동으로 스택에 전달하는 어리 석음을 저장하십시오.
- 직접 발신자가 무엇을할지 확실하지 않은 경우 Parse 및 TryParse와 같이 둘 다 제공 할 수 있습니다.
정말 간단하지 않습니다. 이해해야 할 기본 사항 중 하나는 0입니다.
5 월에 며칠이 남았습니까? 0 (5 월이 아니기 때문에 이미 6 월이므로)
예외는 가정을 거부하는 방법이지만 유일한 방법은 아닙니다. 가정을 거부하기 위해 예외를 사용하는 경우 행복한 길을 떠나십시오. 그러나 가정이 단순하지 않다는 신호를 보내는 행복한 길을 보내기 위해 가치를 선택했다면 그 가치를 다룰 수있는 한 그 길을 계속 유지할 수 있습니다. 때로는 0은 이미 무언가를 의미하는 데 사용되므로 아이디어를 거부하는 가정을 매핑 할 다른 값을 찾아야합니다. 당신은이 아이디어가 좋은 대수학 에서 사용됨을 인식 할 수 있습니다 . 모나드는 그것을 도울 수 있지만 항상 모나드 일 필요는 없습니다.
예를 들어 2 :
IList<int> ParseAllTheInts(String s) { ... }
의도적으로 무언가를 던지도록 설계되어야하는 합당한 이유가 있습니까? int를 파싱 할 수 없을 때 얻는 것을 추측하십시오. 난 당신에게 말할 필요가 없습니다.
좋은 이름의 표시입니다. 죄송하지만 TryParse 는 좋은 이름이 아닙니다.
우리는 종종 대답이 동시에 여러 가지 일 수있을 때 아무것도 얻지 못하는 것에 대해 예외를 던지는 것을 피하지만 어떤 대답이 하나의 것이거나 아무것도 아닌 경우 우리에게 하나의 일을 주거나 던지겠다고 고집하는 것에 집착합니다.
IList<Point> Intersection(Line a, Line b) { ... }
평행선이 실제로 예외를 발생시켜야합니까? 이 목록에 둘 이상의 포인트가 포함되지 않으면 실제로 그렇게 나쁩니 까?
어쩌면 의미 상 당신은 그것을 취할 수 없습니다. 그렇다면 유감입니다. 그러나 아마도 임의의 크기가 아닌 Monads List
는 더 나은 느낌을 줄 것입니다.
Maybe<Point> Intersection(Line a, Line b) { ... }
Monads는 특별한 용도로 사용되는 컬렉션이 거의 없으므로 테스트 할 필요가없는 특정 방식으로 사용됩니다. 우리는 그것들이 무엇을 포함하는지에 관계없이 그것들을 다루는 방법을 찾아야합니다. 그렇게하면 행복한 길은 단순하게 유지됩니다. 모든 Monad를 열어서 테스트하고 터치하면 잘못 사용하고 있습니다.
알아, 이상해 그러나 그것은 새로운 도구입니다. 시간을 좀주세요 나사에서 망치 사용을 중지하면 망치가 더 의미가 있습니다.
당신이 나를 탐닉한다면, 나는이 의견을 다루고 싶습니다 :
어떻게 답을 찾지 못하면 모나드가 오류 코드가 아니며 OneOf도 아니 었습니까? 그것들은 근본적으로 다르기 때문에 그 질문은 오해에 근거한 것 같습니다. (수정 된 형식이지만 여전히 유효한 질문입니다.) – Konrad Rudolph 6 월 4 일 18시 14 분 8 초
이것은 절대적으로 사실입니다. 모나드는 예외, 플래그 또는 오류 코드보다 모음에 훨씬 더 가깝습니다. 그들은 현명하게 사용될 때 그러한 것들을 위해 훌륭한 용기를 만듭니다.
Result
;-) 사용