함수를 만들때 사용자에게 어느정도까지 허용해야할지..

gurugio의 이미지

예를 들어 파일 이름을 넘겨주면 파일 이름에 .exe를 붙여주는 함수가 있다고 했을때

1. 함수 안에서 이미 .exe가 있는지 확인한다.
2. 함수 사용자가 알아서 .exe가 있는지 확인하고 함수를 호출한다.

함수가 어떤 기능을 할때, 미리 전제조건들이 있을텐데
이런 조건들을 모두(혹은 최대한) 함수에서 검사해야할지
아니면 함수의 사용 조건에 명시해서 사용자가 스스로 검사해야할지 고민됩니다.

어떤게 더 좋을까요?

ktd2004의 이미지

프로그램을 작성할 때 항상하게 되는 고민인것 같네요...

해당하는 함수가 해야할 일과
예외적인 상황에서 어떻게 대처해야할까?

1. 일단은 함수가 해야할 일만 작성합니다.
* 주어진 문제를 가장 빨리 해결할 수 있겠죠.

2. 예외적인 상황이 발생하거나 나중에 시간이 남는 경우에
* 예외적인 상황을 처리하도록 한다.
* DEBUG상태에서만 체크되도록 한다.
* RELEASE에서도 예외상황을 체크하게 하면 쓸데없는 부하가 추가되겠죠.

저는 이런식으로 작업하는 것 같네요..

koreteck의 이미지

함수 단위든, 클래스 단위든 혼자 작업하는 것이면 상관없겠지만 그런 경우가 아니라면
항상 고민하게 되는 문제네요.
저도 KTD님과 비슷하게 진행하고 있습니다.
조금 더 추가하자면 합수의 입출력 방법을 통일하고 어느 정도 수준까지 함수가 처리할지에 대해
팀 또는 프로젝트 별로 기준을 설정하는 것도 하나의 방법이 되지 않을까 합니다.

ymir의 이미지

라이브러리 작성시에 많이 고민되는 문제네요..

하나의 함수는 가급적 최소한의 단위 기능을 갖도록 작성하는 것이 좋겠죠.
이 함수들을 이용해서 로직을 구성하는 것이 응용 프로그램이 해야 할 일이구요.

그래서 저 같은 경우는 주로 appl -> appl lib -> primitive lib 정도로 참조 관계를 구성합니다.
appl lib 은 모듈의 용도에 맞게 primitive lib 를 wrapping 해서 작성하구요..

bool check_ext(const char *file, const char *ext);
char *paste_ext(char *file, const char *ext);

두 기능을 제공하는 라이브러리를 제공한다고 한다면..
응용프로그램에서는 이 단위 기능을 이용해서..자신의 로직을 구성합니다.

위의 라이브러리를 wrapping 해서 특목적의 라이브러리로 생성해도 되구요..

char *lib_paste_ext(file, ext, bool check)
{
  if (check && check_ext(...))
     return file;
  else
     return paste_ext(...);
}

char *app1_paste_ext(file, ext)
{
    return lib_paset_ext(file, ext, true);
}
char *app2_paste_ext(file, ext)
{
    return lib_paste_ext(file, ext, false);
}

여러명이 작업하는 경우에도 구현 범위를 정하고, prototype 을 먼저 작성하면..
모듈 작업자 간에 동시 구현도 가능할 겁니다. (현실은 독고다이... _orz..)

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

cynicjj의 이미지

다른 사람이 사용할 함수면 함수 내부에서 검사하는게 당연하고요

자기만 쓸 함수라면 그때 그때 알아서...

hongminhee의 이미지

2번에 해당하는 함수를 만들고, 1번에 해당하는 함수 안에서 앞서 만든 함수를 호출하는 형식으로요. 클라이언트 코드 쪽에서 신경쓰지 않으면 좋겠지만, 만약 중복된 파일이 확실히 존재하지 않는 상황에서는 중복 검사를 하지 않는 함수를 사용할 수 있도록요.

홍민희 (VLAAH, LangDev)

winner의 이미지

우선 적정한 문서를 만들어야 할 것 같아요.
그리고 .so나 .dll 같은 경우의 외부 노출 기능들은 가급적 예외처리를 하는게 좋을 것 같고요.
예외처리비용과 각 단위가 가지는 동작비용을 고려하여 하는게 좋을 것 같습니다.
예를 들어 성능에 민감하지 않는 정렬함수를 작성한다면

internal_sort(arr);
for (int i = 0; i + 1 < arr_len; ++i)
{
    assert(arr[i] <= arr[i+1];
}

정도는 해도 좋을 것 같고요.
chadr의 이미지

그럴 경우에는 저는 그냥 옵션으로 처리하게 합니다. 함수 인자로 옵션을 받게 해서
호출하는 측에서 하고 싶은데로 하게 합니다.
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

sangheon의 이미지

제가 생각하는 함수의 원칙입니다.

말씀하신 예에서 1번은 하나의 함수가 두가지 일을 하는 경우입니다.

1. exe 파일이 존재하는지는 검사한다
2. 파일 이름에 exe 확장자를 붙인다

두 가지 일이 필요하다면 두 개의 함수를 만들어야 합니다.

이렇게 하는데는 두가지 이유가 있습니다.

1. 개발자에게 상황에 따른 자유를 제공한다.

이미 exe가 100% 존재하는 상황(영역)에서도 1번 방식은 exe 파일이 존재하는지 검사하게 됩니다. 이건 낭비입니다.

2. 함수의 결합도를 낮추어 수정의 범위를 축소시킬 수 있다.

2가지 기능을 함으로서 훗날 exe 파일 존재 확인하는 기능만을 필요로 하게 되거나, exe 파일 존재를 검사하는
방법이 바뀐 경우 엉뚱하게도 파일 이름에 exe 확장자를 붙이는 함수를 고쳐야 합니다. 뭔가 깔끔하지 않죠?

어떤 개발자들은 1 번의 방식을 사용하기도 하는데 이는 어떤 절차에 대해서 사용자가 알지 못더라도
그냥 단순히 호출만 하여 사용 가능케 하기 위해 이렇게 만들기도 합니다.

그러나 저는 자동화된 절차는 랩핑이나 OOP라면 상속 등을 통해서 이런 문제를 얼마든지 해결 가능하며
함수(또는 메소드)는 오직 아주 단순한 한 가지의 기능만을 포함해야 한다고 보는 편입니다.

또한 어떤 함수를 사용하는 사람들은 개발 지식이 부족한 사람들이 아니라 충분히 숙련된 개발자들입니다.
이 정도 문제는 다들 잘 알아서 해결 가능하시지요.

만약 API 처럼 다양한 배경의 개발자들이 이용해야 하는 라이브러리라면 세세히 나누어진 함수와 이를 묶어
랩핑하여 편리하고 자동화된 함수를 둘 다 제공하는 것이 좋습니다.

--

B/o/o/k/w/o/r/m/

--

Minimalist Programmer