목록개발 (38)
넘치게 채우기

소프트웨어 개체(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.마틴)의 첫 번째 주장: 둘 사이에는 차이가 없다. 보통 ‘아키텍처’는 저수준의 세부사항과는 분리된 고수준의 무언가를 가리킬 때 흔히 사용되는 반면, ‘설계’는 저수준의 구조 또는 결정사항 등을 의미할 때가 많다. 그러나, 아키텍트의 일을 살펴보면, 실제로 이러한 구분은 무의미하다. 새로운 집을 설계하는 아키텍트가 만든 도면에는 무수히 많은 저수준의 세부사항도 확인할 수 있다. 콘센트, 전등, 전등 스위치, 보일러와 온수기, 배출 펌프와 크기 등이 모두 어디에 위치해있는지 알 수 있다. 벽, 지붕, 기초 공사 역시 어떻게 진행되는지도 알 수 있다. 소프트웨어도 마찬가지이다. 저수준의 세부사항..
이 장에서는 깨끗한 클래스를 다룹니다. 클래스 체계 클래스를 정의하는 표준 자바 관리에 따르면, 가장 먼저 변수 목록이 나옵니다. 정적(static) 공개(public) 상수가 있다면 맨 처음에 나옵니다. 그 다음 정적 비공개(private) 변수, 이어서 비공개 인스턴스 변수가 나옵니다. 공개 변수가 필요한 경우는 거의 없습니다. 변수 목록 다음에는 공개 함수가 나옵니다. 비공개 함수는 자신을 호출하는 공개 함수 직후에 넣습니다. 즉, 추상화 단계가 순차적으로 내려갑니다. 그래서 프로그램은 신문 기사처럼 읽히는 것 입니다. 캡슐화 변수와 유틸리티 함수는 가능한 공개하지 않는 편이 낫지만, 반드시 숨겨야 한다는 법칙도 없습니다. 때로는 변수나 유틸리티 함수를 protected로 선언해 테스트 코드에 접근..
1997년만 해도 TDD(Test Driven Development)라는 개념을 아무도 몰랐습니다. 우리 대다수에게 단위 테스트란, 자기의 프로그램이 ‘돌아간다’라는 사실만 확인하는 일회성 코드에 불과했습니다. 지금은 애자일과 TDD 덕분에 단위 테스트를 자동화하는 프로그래머들이 이미 많아졌으며, 점점 늘어나는 추세입니다. TDD 법칙 세 가지 첫째 법칙 : 실패하는 단위 테스트를 작성할 때까지 실제 코드를 작성하지 않는다. 둘째 법칙 : 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다. 셋째 법칙 : 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다. 위 세 가지 규칙을 따르면 개발과 테스트가 대략 30초 주기로 묶입니다. 테스트 코드와 실제 코드가 함께 나올뿐더러..