쓸모없는 File.Exists 호출을 제거하세요 | Gérald Barré

File.Exists()로 파일 유무를 확인한 후 파일 작업을 시작 하는 패턴은 저 뿐만 아니라 많이 사용하는 패턴일 것 같은데요, 사실은 문제가 발생할 수 있는 코드 입니다. Gérald Barré님이 이에 대해 설명합니다.

5개의 좋아요

우선 흥미로운 주제 주셔서 감사합니다.
생각해봄직한 부분이라 글 자체는 맞는 말인 것 같습니다.

그런데!!!
링크 주신 예시 중 ‘디렉토리 삭제’ 쪽 보면
있는지 확인 후 삭제하기 라는 로직을 구현 할때
try ... catch 를 가지고 구현을 하고 있는데요.
DirectoryNotFoundException에 로직을 넣는게 은근 거부감이 드는건 저만 그럴까요?
exception 구문 안에는 오류처리에 대한 것만 넣어야 할 것 같은 느낌이라고 해야할까요…
혹시 제가 잘못 생각중이거나, 다른 관점이 있다면 가르침 부탁드립니다 (__)

2개의 좋아요

저도 비슷한 감각입니다. 예외자체를 싫어하죠. 그런데 의미적으로는 예외긴 한 것 같습니다.

try / catch 문도 현대식으로 좀 바뀌길 희망합니다.

3개의 좋아요

만약에 파일만 없는경우, 디렉토리만 없는 경우 등등
다 경우의 수를 나눠야 하는데
어떻게보면 엄청 switch문 같은 모양새가 되어버릴 것 같네요;;

수정)
생각 해보니, 파일 생성이 가능한 조건만 flag로 제어해서
정 불편하면 try-exception구문 밑에서 해도 되기는 하겠네요…

2개의 좋아요

저는 파이썬 프로그래밍을 오래 했는데, 파이썬 쪽에서는 대체로 EAFP 스타일이 좀더 선호됩니다. EAFP란 “허락보다 용서를 구하는 게 쉽다”(easier to ask for forgiveness than permission)라는 뜻으로, 일단 연산을 시도하고 문제가 생기면 예외를 처리하는 방식을 뜻합니다. 상반되는 패턴은 LBYL이라고 부르는데, “뛰기 전에 잘 살펴라”(look before you leap)는 뜻입니다.

파이썬 쪽에서 EAFP를 선호하는 데에는 몇 가지 정당화가 존재합니다. 제가 아는 것은 크게 2가지입니다.

  • 여러 스레드·프로세스·프로그램·클라이언트 등으로부터 동시에 접근 가능한 대상을 다룰 때 시간적 빈틈이 없습니다. 파일이 있는지 검사할 때는 파일이 존재했지만, 그 직후 파일을 읽기 전까지의 짧은 순간에 다른 소프트웨어가 파일을 지우면 의도와 다르게 소프트웨어가 고장납니다. 그냥 먼저 냅다 읽으면 그럴 일이 없습니다.
  • 어차피 대부분의 API는 견고성을 위해 안쪽에서 한 번 더 검사를 하기 때문에 쓸데 없이 검사를 하게 됩니다. 파일을 읽는 API도 안에서는 어차피 파일이 있는지 확인을 또 합니다. 이런 여분의 연산을 덜 수 있습니다.

파일을 예로 들었지만 ConcurrentDictionary<TKey, TValue> 같은 자료형이나 RDBMS 등 여러 곳에서 적용 가능한 이야기인 것 같습니다.

5개의 좋아요

오…이런 예외도 하긴 있을 수 있겠습니다.
저같은 경우 HTTP 통신을 주로하는데 예외처리하려다보면 Exception 클래스로 퉁쳐지지 않아서 아래와 같이 처리합니다.

나름 몰랐던 C#의 문법도 써먹어 볼 수 있어서 좋았습니다.
사실 try-finally는 성능상 문제를 주지는 않지만 catch는 overhead를 발생시키기 때문에 디버깅할때만 두고 프로덕션에서는 빼고 하라는 말도 봤었는데, 저는 HTTP 통신을 여러군데 하다보니 사실 뺄 수는 없는 영역같아서 두고 있습니다. 프로그램의 편의성을 위해 성능은 포기해야하는 거라고 보고…사실 그렇게…? overhead를 주장하는 분들의 의견처럼 쌔게 먹는건 아니라고 느낌적인 느낌이 듭니다…ㅎㅎ

5개의 좋아요