기능과 구조 모든 소프트웨어의 설계에는 기능과 구조의 두 가지 측면이 있다. 기능은 소프트웨어가 무엇을 처리할 수 있는지이고, 구조는 소프트웨어의 형태가 어떻게 구성되어있는가이다. 당연히 소프트웨어를 만드는 목적을 달성하기 위해서는 기능적인 측면을 완성하는 것이 필요하지만, 같은 기능을 가지는 소프트웨어끼리 비교하면 좋은 구조를 가지는 소프트웨어가 좋을 것이다. 그렇다면 '좋은 구조'란 무엇일까? 이에 대한 답은 여러가지가 있겠지만, 성공적인 소프트웨어들의 공통적인 특징은 기존의 기능을 변경하고 새로운 기능을 추가하는 것이 쉬워야 한다는 것이다. 대부분의 경우 한 번 만든 소프트웨어를 계속 사용하는 것이 아니라 요구사항이 변경되고 지속적인 업데이트를 통해 개선되어간다. 예를 들어, 크롬 브라우저의 버전을..
독서
객체의 책임 수행 객체지향 설계를 통해 각 객체에 책임을 할당하는 것까지 살펴보았다. 이제는 객체에 할당된 책임을 수행하기 위해 필요한 것을 살펴볼 차례다. 앞서 객체의 책임을 '객체가 수행해야 할 행동'이라고 정의하였고, 이러한 행동은 다른 객체로부터 요청 메시지를 받아서 수행된다고 했다. 메시지와 메소드 객체는 요청 메시지를 받아서 책임을 수행하는데, 이 때 객체 내부에 모든 정보가 있다면 자체적으로 해결할 수 있지만 그렇지 않은 경우도 존재한다. 이러한 경우, 다른 객체에 요청할 수도 있지만, 메시지와 함께 필요한 정보를 받을 수도 있다. 이렇게 추가적으로 필요한 정보를 인자(argument)라고 하며, 메시지는 메시지 이름과 인자들의 결합으로 구성된다. 예를 들어, 계좌이체를 하는 경우, 내 계좌..

객체지향 설계 기법 지금까지는 객체의 특징을 주로 살펴보았다. 객체는 역할, 책임, 협력이라는 특징을 가지며, 상태와 행동, 식별자로 구성되어있다. 모든 객체는 다른 객체들과의 상호작용을 통해 유용한 일을 할 수가 있다. 따라서 이제는 객체들이 모인 시스템을 설계하는 방법에 대해 알아보도록 한다. 객체지향 설계 기법에는 여러가지가 있지만 여기서는 책임-주도 설계, 디자인 패턴, 테스트-주도 개발에 대해 살펴보자. 책임-주도 설계(Responsibility-Driven Design) 책임-주도 설계는 시스템의 책임을 분할하여 적합한 객체에게 책임을 할당하는 방식으로 전체 시스템을 설계하는 방법이다. 전체 시스템이 수행해야 하는 책임은 수많은 작은 책임으로 분할될 수 있고, 이렇게 나누어진 책임은 적절한 객..
객체지향과 추상화 이전 글에서 객체에 대해 자세히 살펴보았다. 객체는 고정된 속성을 가지는데, 이러한 속성은 어디서 온 것일까? 예를 들어, 온라인 쇼핑몰의 판매자는 주민등록번호와 집 주소, 가족관계 등의 정보가 있을 것이다. 그런데 객체지향의 세계에서는 이러한 정보들이 사라지고, 사업자 번호와 계좌번호 등의 꼭 필요한 정보만 가지게 된다. 이렇게 실제 세계에서의 물체나 개념 등을 객체지향의 세계로 가져오는 것을 추상화라고 한다. 이번 글에서는 추상화를 하는 방법에 대해 자세히 살펴보도록 하자. 단순화 추상화를 위해서는 단순화가 필요하다. 위의 예시처럼 객체지향의 세계에서 해결하려는 문제와 관련된 것만 남기고 관련이 없는 특징들은 숨기는 것이다. 이렇게 단순화를 하기 위해서는 큰 범위에서 공통점을 찾아야..
객체의 구성요소 지난 글에서는 객체지향의 의미와 객체의 성질에 대해 살펴보았다. 객체는 각자 역할과 책임을 가지고 있는 능동적인 존재이며, 서로 메시지를 통해 상호작용하며 협력한다고 했다. 그렇다면 이제는 객체가 구체적으로 어떻게 구성되어 있는지 살펴볼 차례이다. 상태 먼저, 각 객체는 내부적으로 상태를 저장한다. 객체가 다른 객체로부터 요청을 받으면 상태에 따라 처리가 달라진다. 예를 들어, 3만원짜리 상품을 주문할 때 계좌의 잔고가 충분하다면 성공적으로 주문이 되겠지만, 잔고가 2만원밖에 없다면 주문이 완료되지 못할 것이다. 이렇게 객체가 상태를 저장하고 있으면 과거에 어떤 일이 있었는지 하나하나 기록해 둘 필요가 없다. 과거에 컴퓨터를 샀든, 책을 샀든, 갈비찜을 샀든 중요한 것은 현재의 상태, 즉..
객체지향 프로그래밍 프로그래밍을 공부하다보면 객체지향이라는 말을 한 번은 들어봤을 것이다. 그러나 막상 '객체지향이 뭔데?'라고 물어보면 간단히 설명하기는 어렵다. 정확히 무엇인지는 몰라도, 이미 본능적으로 객체를 만들어서 잘 사용하고 있기 때문일 것이다. 위키백과는 객체지향 프로그래밍은 다음과 같이 설명하고있다. 객체 지향 프로그래밍(Object-Oriented Programming, OOP)은 컴퓨터 프로그래밍의 패러다임 중 하나이다. 객체 지향 프로그래밍은 컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러 개의 독립된 단위, 즉 "객체"들의 모임으로 파악하고자 하는 것이다. 각각의 객체는 메시지를 주고받고, 데이터를 처리할 수 있다. 쉽게 말해, 알고리즘 문제를 푸는 것처럼 명령어를 나..
동시성 문제 하드웨어 발전이 두드러지던 시기에는 더 나은 성능을 얻기 위해 단순히 하드웨어를 교체하기만 하면 됐다. 그러나 더 이상 CPU 클록을 높여도 성능 향상을 기대하기 어려운 시대가 되었고, 하드웨어 개발자들은 멀티코어라는 새로운 방법을 찾았다. 덕분에 소프트웨어 개발자들은 예전처럼 하드웨어만 바꾸는 것이 아니라, 소프트웨어 개발에도 멀티코어를 활용하기 위한 동시성 프로그래밍이 필요해졌다. 그러나 동시성 프로그래밍은 기존의 순차적인 프로그래밍보다 훨씬 복잡하고 어렵다. 아래와 같은 예제를 보자. public class Counter { private int i; public Counter(int i) { this.i = i; } public int increment() { return i = i..
리소스 반환 Java를 사용할 때는 GC 덕분에 객체를 직접 삭제하지 않아도 된다. 그러나 객체 내에서 리소스를 가지고 있는 경우, 이것을 반환하지 않고 GC가 일어나면 리소스가 낭비된다. 예를 들어, File을 읽기 위해 InputStream을 열거나, DB 연결을 위해 Connection을 여는 경우, 사용이 끝나면 close를 호출해줘야한다. 그렇지 않으면 file descriptor나 DB Connection 같은 한정된 리소스를 낭비하게 된다. 그러나 close 호출을 빼먹는다고 컴파일 에러가 나거나 exception이 발생하지도 않는다. 따라서 오랜 시간이 지나 문제가 발생하게되고, 이것을 디버깅하기 위해서는 오랜 시간이 걸린다. Java 개발자들은 이러한 실수를 줄이기 위해 여러 방법을 시도..