7장. 고급 루틴
목차
- 7.1 루틴을 작성하는 이유
- 7.2 루틴 수준의 설계
- 7.3 좋은 루틴 이름
- 7.4 루틴은 얼마나 길어야 할까?
- 7.5 루틴 매개변수 처리
- 7.6 함수를 사용할 때 특별히 고려해야 할 사항
- 7.7 매크로 루틴과 인라인 루틴
루틴 : 한 가지 목적을 위해서 호출할 수 있는 개별 메서드나 프로시저
7.1 루틴을 작성하는 이유
- 복잡성을 줄인다.
- 이해하기 쉬운 중간 단계의 추상화를 도입한다.
- 중복 코드를 피한다.
- 서브 클래싱을 지원한다.
- 코드의 실행 순서를 감춘다.
- 포인터 연산을 감춘다.
- 이식성을 높인다.
- 복잡한 불린 테스트를 단순화한다.
- 성능을 개선하기 쉽다.
'한 줄 또는 두 줄 정도로 된 짧은 코드를 루틴으로 작성하는 것이 효율적일까?' 라는 질문에 이 책은 충분히 효율적이라고 대답한다. 그 이유는
- 코드를 수정해야 할 때, 여러 군데에서 사용하고 있을 때 한 부분만 수정해도 되기 때문에
- 이름을 설정할 수 있어서 가독성을 높일 수 있기 때문에
이와 같다.
추가로 클래스를 작성하는 이유의 대부분이 루틴을 작성하는 이유가 될 수 있다.
7.2 루틴 수준의 설계
응집성이 높을수록 코드의 오류가 적다.
기능적 응집성은 루틴이 오직 하나의 연산만 처리하는 경우처럼 강하고 바람직한 응집성이다. 응집성이 높은 루틴의 예로는 sin(), getCustomerNmae(), earseFile() 등이 있다.
순차적 응집성, 통신적 응집성 등등 여러가지 이름의 응집성이 있지만 가장 중요한 것은 루틴이 기능적 응집성을 가지도록 설계하는 것이다.
sin() 루틴과 conAndtan() 루틴을 비교했을 때 sin()이 더 깔끔하고, 오류가 발생할 확률도 적을 것이다.
한가지 기능을 수행하는 루틴을 작성할 수 있도록 설계하고 구현해야 한다.
7.3 좋은 루틴 이름
루틴 이름을 짓기 위한 규칙
- 루틴이 하는 모든 것을 표현하라.
- 의미가 없거나 모호하거나 뚜렷한 특징이 없는 동사를 사용하지 ㅏㅁㄹ라.
- 루틴 이름을 숫자로 구분하지 말라.
- 루틴 이름의 길이에 신경 쓰지 마라.
- 함수의 이름을 지을 때는 리턴 값에 관해서 설명하라.
- 프로시저의 이름을 지을 때 확실한 의미가 있는 동사를 객체 이름과 함께 사용하라.
- 반의어를 정확하게 사용하라.
루틴 이름을 숫자로 구분해왔던 버릇을 고쳐야겠다. 그동안 part1, part2와 같은 이름을 사용한 경우가 많았는데 이는 보는 사람에게 어떤 정보도 제공하지 않기 때문에 더 타당한 이름을 설계해야겠다.
사실 코딩을 할 때, 이름 짓는 것이 가장 힘들다고 느껴진다. 혼자 볼 코드라면 아무렇게나 지어도 상관없겠지만, 팀 단위로 프로젝트를 진행할 때 협업을 하게되는데, 이 때 누가봐도 알 수 있는 이름을 짓는 것이 너무 힘들다. 위의 규칙들을 마음에 새겨 좋은 이름을 짓는 작명사가 돼야겠다.
7.4 루틴의 길이에 대한 문제
특별한 경우가 아니면 200줄 내로 루틴을 작성하는 것이 좋다. 200줄이 넘어가면 오류 발생률도 높아지고, 가독성도 떨어지게 된다.
7.5 루틴 매개변수 처리
매개변수의 순서를 통일하는 것이 좋다. 보통 in, modify, out 순으로 매개변수를 준다. 유사한 동작을 하는 루틴의 경우 특히 매개변수 순서를 통일하는 것이 도움이 된다. 만약 다르다면 루틴을 사용할 때마다 매뉴얼을 찾아봐야하는 번거로움이 생길 수 있다.
매개변수를 선언했다면 반드시 사용하는 것을 추천한다.
마지막으로 루틴의 매개변수를 연산을 위한 변수로 사용하지 말아야 한다. 이는 하단 코드로 설명하겠다.
int sum(int v1, int v2) {
v1 += v2;
return v1;
}
위의 코드는 v1 매개변수의 값이 변경된다. 이럴 경우 루틴의 동작중에는 외부에서 v1을 사용할 수 없는 문제가 발생할 수 있다. 매개변수를 변경시키지 않기 위해 아래와 같이 새로운 변수를 하나 더 두어서 루틴을 작성하는 것이 좋다.
int sum(int v1, int v2) {
int result = v1 + v2;
return v2;
}
이렇게 작성하면 외부에서 v1을 사용해도 문제가 발생하지 않을 것이다.
7.6 함수를 사용할 때 특별히 고려해야 할 사항
함수와 프로시저의 차이점을 먼저 설명하겠다. 함수는 값을 리턴하는 것이 함수이고, 특별한 값을 리턴하지 않는 경우 함수다. c++에서 void로 선언하는 루틴은 보통 함수라고 부르지만 실제로는 프로시저다.
루틴의 일차적인 목적이 함수의 이름에서 가리키고 있는 값을 반환하는 것이라면 함수를 사용하고 그렇지 않다면 프로시저를 사용하라.
함수값 리턴 설정
- 가능한 모든 리턴 경로를 검사하라.
- 지역 데이터에 대한 참조나 포인터를 리턴하지 말라.
7.7 매크로 루틴과 인라인 루틴
매크로로 루틴을 표현하는 것은 권장되지 않는 사항이므로 이에 대해서는 딱히 설명하지 않겠다. 책에 설명된 매크로 루틴의 대체 방법은 다음과 같다.
- 상수 값을 선언하기 위한 const
- 인라인 코드로 컴파일 될 함수를 정의하기 위한 inline
- min, max 등과 같은 표준 연산을 타입에 맞게 안전한 방법으로 처리하기 위한 template
- 열거형을 정의하기 위한 enum
- 간단하게 새로운 타입을 정의하기 위한 typedef
인라인 루틴
C++는 inline 키워드를 지원한다. 인라인 루틴을 이용하면 개발자가 코드를 작성할 때는 코드를 루틴처럼 다룰 수 있지만, 컴파일러가 컴파일하면서 해당 루틴을 인라인 코드로 변환할 것이다. 이론적으로 인라인은 루틴 호출 시 발생하는ㄴ 부하를 줄임으로써 효율적인 코드를 작성하는데 도움이 될 수 있다.
인라인 루틴을 자주 사용하지 않는 것을 추천한다. 인라인 루틴은 해당 루틴이 호출될 때마다 루틴의 전체 코드를 생성시키기 때문에 코드의 크기를 즈악시킬 위험이 있다. 따라서 무분별한 사용 대신 사용 전후의 성능 측정을 한 후 확실한 경우 사용해야 한다.