Programming 40

Clean Code - 소프트웨어 창발성(Emergence)

창발성(Emergence) 창발 현상이란 단순한 결합이 의도와 관계 없이 어떠한 결과를 나타나는 현상을 의미한다. 가령, 붉은악마 신드롬은 정부나 월드컵조직위원회가 특정한 계획에 따라 조직한 것이 아니라, 국민들이 인터넷과 방송매체, 주변과의 접촉 등을 통해 자발적으로 상호작용을 일으키며 나타난 현상이다. 아래 켄트 벡이 제시하는 단순한 설계 규칙 네 가지를 따르면 소프트웨어 설계 품질을 크게 높여주는 결과가 발생한다고 믿는다. 모든 테스트를 실행한다. 중복을 없앤다. 프로그래머 의도를 표현한다. 클래스와 메서드 수를 최소로 줄인다. 위 목록은 중요도 순이다. 모든 테스트를 실행하라. 모든 설계는 의도한 대로 돌아가는 시스템을 내놓아야 한다. 문서로는 시스템을 완벽하게 설계했지만, 시스템이 의도한 대로 ..

DDD - 도메인과 유비쿼터스 언어

도메인 용어 코드를 작성할 때 도메인에서 사용하는 용어는 매우 중요하다. 쇼핑몰 프로젝트에서 레거시한 DB 구조를 가지고 있다고 가정하자. Order 테이블에는 status라는 컬럼이 있다. status 컬럼에는 "STEP1", "STEP2", "STEP3"... ,"STEP6" 이라는 정보가 저장된다. 해당 코드를 Enum으로 다음과 같이 작성할 수 있다. public Enum OrderStatus { STEP1, STEP2, STEP3, STEP4, STEP5, STEP6 } 실제 주문 상태는 ‘결제대기중’, ‘상품준비중’, ‘출고완료됨’, ‘배송중’, ‘배송완료’, '주문 취소'인데 기존의 DB에서 전체 상태를 6단계로 본 구조를 그대로 엔터티 속성으로 표현한 것이다. 해당 프로젝트를 맡은 작업자는..

Programming/DDD 2022.05.24

DDD - 엔터티와 밸류

엔터티와 밸류 도출한 도메인 모델은 크게 엔터티(Entity)와 밸류(Value)로 구분할 수 있다. 주문 도메인에서 만든 모델은 다음과 같다. 엔터티도 존재하고 밸류도 존재한다. 엔터티와 밸류를 제대로 구분해야 도메인을 올바르게 설계하고 구현할 수 있기에 이 둘의 차이를 명확하게 이해하는 것은 도메인을 구현하는 데 있어 중요하다. 엔터티 엔터티의 가장 큰 특징은 식별자를 가진다는 것이다. 식별자는 엔티티의 객체마다 고유해서 각 엔티티는 서로 다른 식별자를 갖는다. 주문 도메인에서 각 주문은 주문번호를 갖는데 이 주문번호는 각 주문마다 서로 다르다. 따라서 주문번호가 주문의 식별자가 된다. 주문 도메인 모델에서 주문에 해당하는 클래스가 Order이므로 Order가 엔티티가 되며 주문번호를 속성으로 갖게 ..

Programming/DDD 2022.05.24

DDD - 도메인이란 무엇인가? (+ 도메인 설계 예시)

도메인 개발자 입장에서 온라인 서점은 구현해야 할 소프트웨어의 대상이 된다. 온라인 서점 소프트웨어는 온라인으로 책을 판매하는 데 필요한 상품조회, 구매, 결제, 배송 추적 등의 기능을 제공해야 한다. 이때, '온라인 서점'은 소프트웨어로 해결하고자 하는 문제 영역, 즉 도메인(domain)에 해당한다. 한 도메인은 다시 하위 도메인으로 나눌 수 있다. 예를 들어 다음 그림은 온라인 서점 도메인을 몇 개의 하위 도메인으로 나타낸 것이다. 카탈로그 하위 도메인은 고객에게 구매할 수 있는 상품 목록을 제공하고, 주문 하위 도메인은 고객의 주문을 처리한다. 혜택 하위 도메인은 쿠폰이나 특별 할인과 같은 서비스를 제공한다. 한 하위 도메인은 다른 하위 도메인과 연동하여 완전한 기능을 제공하게 된다. 특정 도메인..

Programming/DDD 2022.05.24

OOP - 객체의 자율성 (+ 의존성, 결합도, 캡슐화, 응집도, 의인화)

예시. 티켓 판매 어플리케이션 시나리오: 소극장에서 이벤트를 통해 초대장을 분배하고 초대장이 있는 사람은 초대장을 티켓으로 교환한 후에 입장하고, 초대장이 없는 사람은 입장권을 구매한 뒤 입장한다. 구현한 클래스 다이어그램은 다음과 같다. 먼저 이벤트 당첨자에게 발송되는 초대장을 구현하는 것으로 시작하자. 초대장(Invitation)은 공연을 관람할 수 있는 초대일자(when)을 인스턴스 변수로 포함하는 간단한 클래스다. public class Invitation { private LocalDateTime when; } 공연을 관람하기 원하는 모든 사람은 티켓을 소지하고 있어야만 한다. Ticket 클래스를 추가하자. public class Ticket { private Long fee; public L..

Programming/OOP 2022.05.19

OOP - 객체지향이란 무엇인가?

객체지향 많은 분들이 객체지향 프로그래밍은 현실 세계의 모방, 추상화를 통해 프로그래밍에 반영하는 것이라고 말한다. 이러한 설명은 실용적인 관점에서 객체지향을 설명하기에 적합하지 않다. 가령 우리는 상속의 예시를 들 때 인간, 도형 등의 예시를 들고 추상화를 배울 때 동물, 타이어, 자동차 등의 예시를 들곤 한다. 이를 실제 소프트웨어에 접목할 수 있는가? 객체지향의 목표는 실세계를 모방하는 것이 아니다. 새로운 세계를 창조하는 것이다. 객체지향에서 가장 널리 퍼져있는 오해는 클래스가 객체지향 프로그래밍의 중심이라는 것이다. 객체지향은 객체를 지향하는 것이지 클래스를 지향하는 것이 아니다. 역할, 책임, 협력 객체지향이라는 말에서 어떤 단어가 먼저 떠오르는가? 많은 사람들은 클래스와 상속을 떠올린다. 하..

Programming/OOP 2022.05.16

Clean Code - 깨끗한 시스템이란 무엇인가?! (+ 관심사 분리)

깨끗한 시스템 시스템을 도시에 비유해보자. 도시의 온갖 세세한 사항을 혼자서 관리할 수 있을까? 그럴 순 없다. 그럼에도 도시는 잘 돌아간다. 수도관리 팀, 전력관리 팀, 교통관리 팀, 치안관리 팀 등 각 분야를 관리하는 팀이 있기 때문이다. 누군가는 각 팀의 역할을 자세히는 몰라도 대략적으로 파악하고 전체 그림을 설계하기도 한다. 누군가는 자신의 팀의 역할과 관련 팀과의 이해 관계 정도 까지만 집중한다. 이러한 부분이 프로그래밍에서는 적절한 추상화와 모듈화이다. 팀이 제작하는 시스템도 객체들을 적절하게 관심사를 분리해서 추상화를 이뤄내게 된다. 시스템 수준에서도 깨끗함을 유지하는 방법에 대해서 알아보자. 시스템 제작과 사용을 분리하라 제작(Construction)과 사용(Use)는 많이 다르다. 소프트..

Clean Code - 깨끗한 클래스란 무엇인가?! (클래스 고찰)

깨끗한 클래스 해당 포스팅은 클래스에 대해 다룬다. 깨끗한 클래스란 무엇인가에 대해 알아보자. 클래스 체계 깨끗한 클래스를 정의할 때 따르는 표준 자바 관례가 있다. 클래스의 내부 요소를 정의할 때 가장 먼저 변수 목록을 정의한다. 변수 중에서는 가장 먼저 static public 상수를 정의하고 다음으로 static private 변수를 정의한다. 그 다음 private 인스턴스 변수를 정의한다. 변수 목록 다음에 public 메소드를 정의하고 그 다음 private 메소드를 정의한다. 클래스가 내부에서 추상화 단계가 순차적으로 내려가는 관례를 지키면서 신문 기사처럼 읽히는 효과를 가진다. 캡슐화 변수와 유틸리티 함수는 가능한 공개하지 않는 것이 좋지만 반드시 숨겨야 한다는 법칙도 없다. 내가 속한 팀..

Clean Code - 깨끗한 테스트 코드 유지하기

개요. 애자일과 TDD 덕택에 단위 테스트를 자동화하는 개발자들이 이미 많아졌고 점점 더 늘어나는 추세다. 하지만 많은 개발자들이 테스트 코드 작성을 급하게 서두르면서 제대로 된 테스트 케이스 작성을 놓치고 있다. 제대로 된 좋은 테스트 케이스를 작성하는 것에 대해 알아보자 TDD 법칙 세 가지 지금은 TDD가 실제 코드를 짜기 전에 단위 테스트부터 작성하라고 요구한다. 아래는 TDD가 추구하는 세 가지 원칙이다. 실패하는 단위 테스트 를 작성할 때까지 실제 코드를 작성하지 않는다. 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다. 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다. 위 세가지 규칙을 지키면 개발과 테스트가 대략 30초 주기로 묶인다. 추가적으로 테스..

Clean Code - 외부 코드 사용하기 (+ 경계 클래스, 어댑터 패턴)

개요. 시스템에 들어가는 모든 소프트웨어를 직접 개발하는 경우는 드물다. 패키지를 사거나 라이브러리 등 오픈 소스를 사용하기도 한다. 이 때 우리는 외부 코드를 우리코드에 어떻게 해야 더 깔끔하고 안전하게 통합할 수 있는 지 고민해야 한다. 고민은 외부 코드와 우리 코드의 경계를 파악하는 것부터 시작한다. 경계(Boundaries) 전체 소프트웨어 개발에 사용하게 되는 외부 코드를 내 코드에서 호출하는 부분을 경계(boundaries)라고 한다. 경계 없이 단순하게 외부 코드를 사용하려는 곳에서 직접 호출할 수 있지만 그렇게 했을 때 아래와 같은 문제가 생긴다. 인터페이스 제공자가 지원한 인터페이스를 그대로 사용해야 한다. 인터페이스 제공자는 최대한 범용적이게 개발하는 것을 선호한다. 인터페이스 사용자는..