클래스 설계 초급편 초보자를 대상으로 클래스 설계와 관련된 내용을 알아보자. 클래스 설계는 경험이 필요하다. 일단 객체 지향 설계 원칙을 의식하는 것부터 시작해보자. 대략적인 클래스 조사 대상의 문제가 어떤 클래스로 이루어 졌는지 떠오르는 대로 적어 보자. 그리고 클래스 이름만으로 간단한 클래스 다이어그램을 작성해서 클래스의 관계를 구성한다. 여러 사람과 함께 토론하는 것이 혼자서 생각하는 것보다 훨씬 효율적이다. 처음부터 완전한 설계를 할 수 없다. 대략 적인 설계가 끝나면 코드를 작성하면서 진행하자. 코드를 작성하면서 재설계를 하면 된다. 초기 단계의 설계에 너무 집착하지 말자. 초기 설계를 버릴 각오를 하는 편이 좋다. 어느 정도 코드 작성이 진행될 떄까지는 문제의 본질이 잘 보이지 않을 수 있다...
어떻게 클래스를 설계하면 좋은지 알아보자. 또한 객체 지향 설계의 기본 개념과 원칙을 중심으로 사고하는 요령에 관해 설명하겠다. 클래스 설계의 기본 클래스 설계는 현실 세계의 업무 분담과 비슷하다. 각 클래스의 역할을 정하고 업무 책임을 분담하는 작업이라고 할 수 있다. 클래스의 이름은 담당하는 역할을 나타낸다. 1개의 클래스는 1개의 역할을 해야 한다. 객체 지향에 익숙하지 않는 사람은 자료구조와 알고리즘 중심으로 프로그램을 생각한다. 하지만 객체 지향 프로그래밍에서는 자료구조와 알고리즘은 객체를 작동시키기 위한 수단에 지나지 않는다. 클래스를 사용하는 관점에서 자료구조와 알고리즘보다는 어떤 역할과 책임이 있는지가 훤씬 중요하다. 클래스의 역할 설계 의도를 명확하게 하려면 어느 정도의 역할 분담을 정해..
SOLID 객체 지향 설계시 사용되는 SOLID라는 원칙이 있다. 각 원칙의 첫글자를 따서 만든 SOLID에 대해서 알아보자. 단일 책임 원칙 단일 책임 원칙(SRP, Single Responsibility Principle)은 클래스를 변경해야 할 이유는 한 가지여야 한다는 원칙이다. 간단히 말하면 하나의 클래스는 하나의 책임만 가져야 한다라는 원칙이다. 개방 폐쇄 원칙 개방 폐쇄 원칙(OCP, Open Closed Principle)은 소프트웨어 구성 요소는 확장에 관해서는 열려 있어야 하고, 변경에 대해서는 닫혀 있어야 한다라는 원칙이다. 간단히 말하면 변하지 않는 부분(닫힌 부분)과 변하는 부분(열린부분)을 분리하자는 것이다. 개방 폐쇄 원칙은 상속과 이양을 이용해서 구현할 수 있다. 리스코프 치..
클래스를 만드는 사고방식과 원칙을 알아보자. 원칙은 참고로 삼고 너무 집착하지는 말자. 캡슐화, 응집도, 결합도 캡슐화, 응집도, 결합도는 보수성이 높은 클래스를 설계하는데 사용하는 기본 요소이다. 이 3가지를 의식하기만 해도 코드 품질은 매우 좋아진다. 캡슐화 객체 내부의 변수 또는 구현 상세를 사용자로부터 은폐하는 것을 캡슐화라고 한다. 클래스 사용자 입장에서 클래스가 어떤 멤버 변수를 가지며 어떤 방식으로 구현되는지 다 알 필요가 없다. 사용자에게는 꼭 필요한 부분만 제공하는 것이 좋다. 부모-자식 관계라도 꼭 필요한 부분만 protect로 하고 나머지는 private가 좋다. 추상 인터페이스를 사용하면 좋은 캡슐화를 실현할 수 있다. 추상 인터페이스란 순수 가상 함수만으로 구성된 추상 클래스를 의..
클래스화 요령 클래스화도 반복적인 부분을 정리한다는 목적에서 생각해보면 함수화와 거의 비슷하다. 프로그램 설계의 요령은 문제를 작게 나누는 것이다. 코드를 작은 클래스로 나눠 조합하면 전체가 크더라도 각각의 부분은 단순해진다. 큰 함수를 분할 클래스화하기 위한 사전 준비로 일단 큰 함수를 작은 함수로 나눈다. 클래스를 찾아 내기 위해서 작은 함수로 만들어야 한다. 함수 이름을 기반으로 클래스 이름 정하기 함수 이름을 기반으로 클래스 후보를 쉽게 찾을 수 있다. 함수 이름 뒤에 붙는 명사가 클래스 후보들이다. 예를 들어 update_player, draw_player등의 함수 이름이 있다면 player를 클래스로 작성할 수 있다. 이처럼 큰 함수를 나누고 적절한 함수 이름을 붙이면 클래스 후보를 쉽게 찾을..
함수 함수화 기술은 보수성 높은 코드를 작성하는 기본이다. 복잡한 코드도 함수화가 잘 되어 있으면 쉽게 보수할 수 있다. 함수의 기본 원칙 함수를 만들 때 도움이 되는 기본 원칙이 있다. 1개의 함수에는 1개의 역할만 한다. 함수를 두 종류로 구분한다. 1개의 함수에는 1개의 역할만 한다. 함수는 1개의 역할만 수행해야 한다. 이름이 복잡한 함수는 여러가지 역할을 할 가능성이 높다. 초보자는 기능이 많은 함수일수록 좋다고 생각하는 경우가 있다. 하지만 기능이 적은 함수일수록 재사용하기 쉽고 변경에 대한 영향도 적게 받는다. 결과적으로 보수성이 높이진다. 함수를 두종류로 구분한다. 함수는 다음과 같이 두종류로 구분된다. 첫번째: 계산과 알고리즘을 실행하고 실제 작업을 수행하는 함수 두번째: 첫번째 함수들을..
switch 조건문의 감축과 단순화 switch 조건문을 이해하기 쉽게 잡성하는 방법과 불필요한 switch 조건문을 제거하는 기술을 알아보자. case 내부의 함수화 case 내부에는 복잡한 코드를 작성하지 말자. case 내부를 함수화하면 switch 분기에만 집중할 수 있게 된다. default에 assert default에 assert를 사용하면 실수를 방지할 수 있게 된다. 다형성 switch 조건문의 대부분은 다형성을 사용한 분기로 변경할 수 있다. 예를 들어 아래와 같은 switch 조건문이 있다.void update(float delta_time) { switch (state) { case STATE_RUN: run(dalta_time); break; case STATE_JUMP: jump..
for 반복문 감축과 단순화 for 반복문의 기본 원칙은 1개의 작업만 반복이다. for 반복문을 사용한 알고리즘 대부분은 STL 알고리즘 함수로 변환할 수 있다. STL 알고리즘 함수 사용 빈도가 높은 STL 알고리즘 함수를 살펴보자. for_each : 모든 요소를 지정한 함수로 조작 find : 요소 검색 find_if : 조건에 맞족하는 요소 검색 min_element : 최소 요소 리턴 max_element : 최대 요소 리턴 sort : 요소 정렬 count : 지정한 숫자와 일치하는 요소 수 리턴 count_if : 조건을 만족하는 요소 수 리턴 all_of : 모든 요소가 지정한 조건을 만족하면 true 리턴 none_of : 모드 요소가 지정한 조건을 만족하지 않으면 ture 리턴 any..
코드를 복잡하게 만드는 문제의 근원은 if 조건문 또는 for 반복문 등의 제어문이다. 제어문이 없는 코드는 위에서 아래로 쭉 읽으면 되지만, 제어문이 뒤섞여 버린 코드는 처리의 흐름을 추적하기 어렵고 보수하기도 어렵다. if 조건문 감축과 단순화 if 조건문을 하나 추가할 때마다 실행 경로가 하나 증가하게 된다. 따라서 if 조건문을 사용하지 않고 코드를 구성하는 것이 포인트이다. 하한값, 상항값 체크 단순화 하한값과 상한값을 체크하는 if 조건문은 대부분의 프로그램에서 사용하는 코드이다.if (x > 10) { x = 10; } 이럴 때는 조건문을 추가하는 것보다 표준함수나 함수화시켜서 사용하는 것이 좋다. 아래는 C++에서 STL의 min함수를 사용한 방법이다.x = std::min(x, 10); ..
읽기 좋은 코드란? 읽기 좋은 코드는 가독성이 높아서 코드의 변경, 추가, 테스트가 쉽다. 읽기 좋은 코드를 작성하는 방법을 '복잡한 코드를 작게 나누고, 읽기 좋은 이름을 붙여 정리하자'이다. 의미가 명확한 변수 이름 붙이기 변수의 이름은 사용 목적에 맞게 가능한 구체적으로 정해라. 다만 예외적으로 인덱스 전용 지역변수는 i, j, k등의 짧은 이름을 사용하는 것이 좋다. 작은 함수 내부의 지역변수라면 단순한 이름으로도 의도를 전달할 수 있다. 하지만 클래스의 멤버변수 처럼 범위가 넓고, 수명이 긴 변수는 신중하게 이름을 정해야 한다. 의미가 있는 상수값에는 이름 붙이기 일부 상수값은 의미(0:걷기, 1:점프)를 나타내는 경우가 있다. 이런 상수값은 코드 전체의 흐름을 이해하지 못하면 제대로 알 수가 ..