목록개발/Clean Architecture (28)
넘치게 채우기
소프트웨어 개체(aritifact)는 확장에는 열려 있어야 하고, 변경에는 닫혀 있어야 한다. 다시 말해, 소프트웨어 개체의 행위는 확장할 수 있어야 하지만, 이때 개체를 변경해서는 안 된다. 소프트웨어 아키텍처를 공부하는 가장 근본적인 이유가 바로 이 때문이다. 만약 요구사항을 살짝 확장하는 데 소프트웨어를 엄청하게 수정해야 한다면, 그 소프트웨어 시스템을 설계한 아키텍트는 엄청난 실패에 맞닥뜨린 것이다. 소프트웨어 설계를 공부하기 시작한 지 얼마 안 된 사람들 대다수는 OCP를 클래스와 모듈을 설계할 때 도움되는 원칙이라고 알고 있다. 하지만 아키텍처 컴포넌트 수준에서 OCP를 고려할 때 훨씬 중요한 의미를 가진다. 사고 실험 재무제표를 웹 페이지로 보여주는 시스템이 있다고 생각해보자. 웹 페이지에 ..
SRP는 아래와 같이 기술되어 왔다. “단일 모듈은 변경의 이유가 하나, 오직 하나뿐이어야 한다.” 소프트웨어 시스템은 사용자와 이해관계자를 만족시키기 위해 변경된다. 이 원칙은 아래와 같이 바꿔 말할 수도 있다. “하나의 모듈은 하나의, 오직 하나의 사용자 또는 이해관계자에 대해서만 책임져야 한다.” 안타깝게도, ‘사용자’와 ‘이해관계자’라는 단어를 여기에 쓰는 건 올바르지 않다. 시스템이 동일한 방식으로 변경되길 원하는 사용자나 이해관계자가 두 명 이상일 수도 있기 때문이다. 여기에서는 이런 의미보다는 집단, 즉 해당 변경을 요청하는 한 명 이상의 사람들을 가리킨다. 이러한 집단을 액터(actor)라고 부르겠다. 이제 SRP의 최종 버전은 다음과 같다. “하나의 모듈은 하나의, 오직 하나의 액터에 대..
여러 가지 의미로, 함수형 프로그래밍이라는 개념은 프로그래밍 그 자체보다 앞섰다. 이 패러다임에서 핵심이 되는 기반은 람다(lambda)계산법으로, 알론조 처지(Alonzo Church)가 1930년대에 발명했다. 정수를 제곱하기 25까지의 정수의 제곱을 출력하는 간단한 문제를 다뤄보자. 자바 언어라면 아래처럼 작성할 수 있다. public class Squint { public static void main(String args[]) { for(int i = 0; i < 25; i++) { System.out.println(i*i); } } 리스프에서 파생한 클로저(Clojure)는 함수형 언어로, 클로저를 이용하면 같은 프로그램을 다음과 같이 구현한다. (println (take 25(map (fn ..
객체 지향 프로그래밍. OOP(Object-Oriented-Programming)에서 이 OO의 본질을 설명하기 위해서 세 가지 주문에 기대곤 한다. 캡슐화(encapsulation) 상속(inheritance) 다형성(polymorphism) OO언어는 최소한 이 세가지를 충족해야한다고 한다. 캡슐화? OO를 정의하는 요소 중 하나로 캡슐화를 언급하는 이유는 데이터와 함수를 쉽고 효과적으로 캡슐화하는 방법을 OO언어가 제공하기 때문이다. 그리고 이를 통해 데이터와 함수가 응집력 있게 구성된 집단을 서로 구분 짓는 선을 그을 수 있다. 구분선 바깥에서 데이터는 은닉되고, 일부 함수만이 외부에 노출된다. 이 개념들이 실제 OO 언어에서는 private 멤버 데이터와 public 멤버 함수로 표현된다. 이러..
증명 데이크스트라가 초기에 인식한 문제: 프로그래밍은 어렵고, 프로그래머는 프로그래밍을 잘하지 못한다라는 사실. 모든 프로그램은 설령 단순할지 몰라도 인간의 두뇌로 감당하기에는 너무 많은 세부사항을 담고 있었다. 데이크스트라는 증명(proof)라는 수학적인 원리를 적용하여 이 문제를 해결하고자 했다. 수학자가 유클리드 계층구조를 사용하는 방식을 프로그래머도 사용할 수 있다고 믿었다. 데이크스트라는 이 연구를 진행하면서 goto 문장이 모듈을 더 작은 단위로 분해하는 과정에 방해가 도는 경우가 있다는 사실을 발견했고, 반면, goto문장을 사용하더라도 문제가 되지 않는 경우를 찾았다. if/then/else와 do/while과 같은 분기와 반복이라는 단순한 제어 구조에 해당한다는 사실을 발견했다. 그는 이..
이 장에서는 세 가지 패러다임인 구조적 프로그래밍(structured programming) 객체지향 프로그래밍(object-oriented programming) 함수형 프로그래밍(functional programming) 에 대해 설명한다. 구조적 프로그래밍 최초로 적용된 패러다임은 구조적 프로그래밍으로, 1968년 에츠허르 비버 데이크스트라(Edsger Wybve Dijkstra)가 발견했다. 데이크스트라는 무분별한 점프(goto문장)는 프로그램 구조에 해롭다는 사실을 제시했다. 데이크스트라는 이러한 점프들을 if/then/else 와 do/while/until과 같이 더 익숙한 구조로 대체했다. 구조적 프로그래밍은 다음과 같이 요약할 수 있다: “구조적 프로그래밍은 제어흐름의 직접적인 전환에 대해..
모든 소프트웨어 시스템은 이해관계자에게 서로 다른 두 가지 가치를 제공하는데, 행위(behavior)와 구조(structure)가 있다. 소프트웨어 개발자는 두 가치를 모두 반드시 높게 유지해야 하는 책임을 가진다. 불행하게도 개발자는 한 가지 가치에만 집중하고 나머지 가치는 배제하곤 한다. 행위 소프트웨어의 첫 번째 가치는 바로 행위. 프로그래머는 이해관계자가 기능 명세서나 요구사항 문서를 구체화할 수 있도록 돕는다. 그리고 이해관계자의 기계가 이러한 요구사항을 만족할 수 있도록 돕는다. 기계가 이러한 요구사항을 위반하면, 프로그래머는 디버거를 켜고 문제를 고친다. 많은 프로그래머들은 이러한 활동이 자신이 해야 할 일의 전부라고 생각한다. 이들은 요구사항을 기계에 구현하고 버그를 수정하는 일이 자신의 ..
설계(design)와 아키텍처(architecture) 사이에는 오랫동안 많은 혼란이 있었다. 밥아저씨(로버트 C.마틴)의 첫 번째 주장: 둘 사이에는 차이가 없다. 보통 ‘아키텍처’는 저수준의 세부사항과는 분리된 고수준의 무언가를 가리킬 때 흔히 사용되는 반면, ‘설계’는 저수준의 구조 또는 결정사항 등을 의미할 때가 많다. 그러나, 아키텍트의 일을 살펴보면, 실제로 이러한 구분은 무의미하다. 새로운 집을 설계하는 아키텍트가 만든 도면에는 무수히 많은 저수준의 세부사항도 확인할 수 있다. 콘센트, 전등, 전등 스위치, 보일러와 온수기, 배출 펌프와 크기 등이 모두 어디에 위치해있는지 알 수 있다. 벽, 지붕, 기초 공사 역시 어떻게 진행되는지도 알 수 있다. 소프트웨어도 마찬가지이다. 저수준의 세부사항..