•
이 장은 매우 중요한 과정인 클래스와 메소드를 작성하는 과정을 매우 구체적으로 설명하고 있다.
•
설계와 문서 작성 시 해야하는 작업을 줄여주고 품질을 향샹시키는 의사코드 프로그래밍 프로세스(PPP)에 대해서 설명한다.
1. 클래스 및 메소드 개발 단계 요약
•
클래스는 다양한 방법으로 구현할 수 있지만 보통은 클래스를 일반적인 형태로 설계하고 클래스 내의 구체적인 메소드를 열거, 구현, 검증하는 과정을 반복한다.
클래스 생성 단계
•
클래스에 대한 일반적인 설계를 작성한다.
◦
클래스의 구체적인 책임을 정의하고 클래스가 숨겨야할 정보를 무엇인지 정의한다.
•
클래스 내에 각 메소드를 구현한다.
◦
클래스의 주요 메소드를 식별했다면 각 메소드를 구현해야 한다.
◦
이 과정에서 추가로 다른 메소드가 필요하다는 것을 알게 되며 그러한 추가적인 메소드를 작성하면서 생기는 문제가 전체적인 클래스에 영향을 끼치기도 한다.
•
클래스를 전체적으로 검토하고 테스트한다.
◦
클래스의 개별적인 메소드 수준에서 각 기능들을 테스트한다.
메소드를 작성하는 단계
•
메소드에는 접근자 메소드, 다른 객체의 메소드에 대한 직접 호출 메소드 등이 있으며 설계, 설계 검사, 코드 작성, 코드 점검의 과정을 거쳐 작성된다.
2. 전문가를 위한 의사코드
•
의사코드란 알고리즘이나 메소드, 클래스, 프로그램이 어떻게 동작할지를 기술하는 표기법을 가리킨다.
•
의사코드는 자연어와 비슷해서 생각을 정리하기 위해 충분한 설명이 가능하다. 다음은 의사코드를 사용하는 특히나 더 유용한 방법들이다.
◦
구체적인 연산을 정확하게 기술하기 위해 자연어 문장과 같은 형태의 명령문을 사용한다.
◦
특정 프로그래밍 언어의 요소를 피한다. 의사코드는 추상화 수준이 더 높은 설계가 가능하다.
3. PPP를 이용한 메소드 구현
메소드를 설계한다
•
먼저, 선행 조건을 검사한다. 메소드 자체에 대한 작업을 수행하기 전에 메소드가 해야 할 일이 잘 정의되었고 클래스에 어울리는지 검사한다.
•
메소드가 해결할 문제를 정의한다. 메소드가 해결할 문제를 당장 해결할 수 있을 정도로 자세히 기술한다.
•
메소드의 좋은 이름을 짓는다.
•
메소드를 어떻게 테스트할 것인지 결정한다.
•
표준 라이브러리에서 가져다 쓸만한 기능이 있는지 조사한다.
•
오류 처리에 대해서 생각한다.
•
효율성에 대해서 생각한다.
◦
메소드가 자원과 속도의 목표를 달성할 수 있도록 설계한다.
•
알고리즘과 데이터형을 조사한다.
•
의사코드를 작성한다.
•
데이터에 대해 생각한다.
•
의사코드를 검사한다.
•
의사코드 상태에서 여러 변형을 시도해보고 가장 좋은 방법을 선택한다.
메소드를 구현한다
•
메소드의 선언부를 작성한다.
•
의사코드를 자연어 주석으로 변환한다.
•
각 주석 아래에 코드를 채운다.
◦
각 코드 블록은 주석에 담긴 생각을 완전하게 구현해야 한다. 각 주석은 일반적으로 2줄에서 10줄 정도의 코드로 확장된다.
•
코드를 더 나눠야 하는지 검사한다.
◦
주석 아래에 있는 코드가 10줄 이상의 거대한 코드 블록일 경우, 나눠야하는지 확인한다. 이때 다음 두가지 과정중 하나를 고려하라.
▪
주석 아래에 있는 코드를 새로운 메소드로 나눈다. 의사 코드 한 줄이 예상했던 것보다 많은 코드로 확장되었다면 해당 코드를 별도의 메소드로 나눌 수 있다.
▪
PPP를 재귀적으로 적용한다. 의사코드 한 줄 아래에 20줄이 넘는 코드를 작성하는 대신, 원래 있던 의사코드를 여러 줄의 의사코드로 분해한다.
코드를 검사한다
•
메소드를 설계하고 구현한 후, 세 번째로 해야할 일은 구현한 코드가 정확한지 확인하기 위해 코드 검사를 하는 것이다.
•
이 단계에서 놓친 오류는 나중에 테스트할 때까지 발견되지 않기 때문에 최대한 이 단계에서 오류를 찾아낼 수 있도록 해야한다.
•
머릿속에서 메소드의 오류를 검사한다.
◦
코드를 이해하려고 노력해야 한다. 보통 오류는 코드에 존재한다.
◦
작동하는 메소드만으로는 충분하지 않다. 왜 작동하는지를 모른다면 알 때까지 이해하려고 시도해야 한다.
•
메소드를 컴파일한다.
•
코드를 디버거에서 한 단계씩 살펴본다.
•
코드를 테스트한다.
◦
메소드를 개발할 때, 계획했거나 작성했던 테스트 케이스를 사용해 코드를 테스트한다.
•
메소드에 있는 오류를 제거한다.
◦
오류가 발견되었다면 오류를 제거해야 한다. 이 시점에 개발 중인 메소드에 버그가 많다면 앞으로도 버그가 많을 가능성이 높다.
◦
메소드에 버그가 많다면 처음부터 다시 작성한다.
나머지를 정리한다
•
코드 점검이 끝났다면 일반적인 특성들을 검사한다. 메소드의 품질이 자신의 기준에 적합한지 확인하기 위해 여러 단계로 이뤄진 정리 작업을 수행할 수 있다.
•
메소드의 인터페이스를 검사한다. 모든 입력과 출력 데이터를 확인하고 모든 매개변수가 사용되었는지 확인한다.
•
일반적인 설계 품질을 검사한다. 메소드가 하나의 책임만 가지며 그 책임을 잘 처리하는지 확인하고 다른 협력자들과 느슨하게 결합되어 있는지 확인한다.
•
메소드의 변수를 검사한다. 부정확한 변수 이름이나 사용되지 않은 매개변수, 선언되지 않은 변수, 부적절하게 초기화된 객체 등을 검사한다.
•
메소드의 명령문과 논리적인 구조를 검사한다. 무한 루프나 적절하지 않은 중첩, 자원 누수 등을 검사한다.
•
메소드의 레이아웃을 검사한다. 메소드와 표현식, 매개변수 목록의 논리적인 구조가 명확하도록 공백을 사용해 구분했는지 확인한다.
•
메소드의 문서화를 검사한다. 주석에서 변환된 의사코드가 정확한지 확인한다. 알고리즘 설명, 인터페이스와 불명확한 의존성에 대한 문서 등에 대한 정당성을 검사한다.
•
불필요한 주석을 제거한다.
필요한 만큼 반복한다
•
메소드의 품질이 좋지 않다면 의사코드 단계로 돌아간다. 좋은 프로그래밍은 반복적인 프로세스이니 주저하지 말고 돌아가자.
4. PPP 대안
•
여기서는 PPP의 몇몇 대안이 되는 방법들을 설명한다.
•
테스트 주도 개발
◦
테스트 주도 개발은 코드를 작성하기 전에 테스트 케이스를 작성하는 유명한 개발 방법이다.
•
리팩토링
◦
리팩토링은 논리적인 구조를 유지하며 변경하는 과정을 통해서 코드를 향상하는 개발 방법이다.
◦
개발자는 나쁜 코드의 패턴을 사용하거나 개선할 필요가 있는 코드 영역을 코드 스멜로 정의한다.
•
계약에 의한 설계
◦
이는 각 메소드가 선행 조건과 후행 조건을 갖고 이싸독 생각하는 개발 방법ㅇ디ㅏ.
요점 정리
•
클래스와 메소드의 구현은 반복적인 경향이 있다. 특정한 메소드를 구현하면서 얻는 내용이 클래스의 설계에 영향을 끼칠 수 있다.
•
훌륭한 의사코드를 작성하기 위해서는 이해할 수 있는 자연어를 사용하고 특정 프로그래밍 언어에 특화된 기능을 사용하지 않고 자연어 수준에서 설명해야 한다.
•
의사코드 프로그래밍 프로세스는 상셰 설계에 유용한 도구이며 코드 작성을 쉽게 해준다. 의사코드는 곧바로 주석으로 변환되며 이렇게 변환된 주석은 정확하고 유용하다.
•
첫 설계가 완벽한 설계가 아니다. 반복적으로 설계를 개선해나가자.
•
각 단계에서 작업 내용을 검사하고 다른 사람도 검사하게 한다. 그렇게하면 가장 적은 노력을 들여 실수를 바로 잡을 것이다.