순환참조는 뭐가 문제일까? 개인 프로젝트는 혼자서 진행하기 때문에 내가 만든 설계가 제대로 된 설계인지 확인해보기 어렵다. 이를 확인하기 위해서 한 가지 기준을 두었는데 패키지간의 의존 방향을 단방향으로 하여 순환되지 않도록 하자는 것이었다. 다이어그램을 그려보고 의존성이 단방향을 나타낼 때는 제대로 된 설계를 했다는 성취감도 들었다. 그러다 문득 이런 생각이 들었다. '그래서 순환참조가 뭐가 문제일까?' 의존 먼저 의존에 대해서 다시 생각해보았다. A객체가 B객체에게 의존한다는 것은 A객체가 B객체를 사용한다는 것이다. 다이어그램으로 화살표를 나타내면 A→B라는 형태로 나타난다. 만약 '변경에 의한 영향' 이라는 기준에서 생각해보면 화살표의 방향은 반대로 나타내야 될 것이다. B가 변경될 때 A에게 영..
요구사항 클라이언트가 서로 다른 2개의 클래스에 의존하고자 할 때, 하나의 추상화된 인터페이스로 의존되어야 한다. 클래스 다이어그램으로 나타내면 위와 같다. DoClass는 do()라는 퍼블릭 메서드를 갖고 있으며, RunClass는 run()이라는 퍼블릭 메서드를 갖고 있다. 메서드 명부터 다른 2개의 클래스를 하나의 추상화된 인터페이스로 의존하고자 한다면 어떻게 해야 할까? 방법 1 : 클래스를 수정한다. (전략 패턴) 간단하게 하는 방법은 클래스들의 코드를 수정하여서 인터페이스를 구현하도록 코드를 수정한다. 각기 다른 메서드 명도 통일시킨다면 클라이언트가 하나의 인터페이스를 통해 달라지는 (혹은 확장되는) 클래스들을 의존할 수 있게 된다. 추가 요구사항 만약 의존하는 클래스들의 코드를 수정할 수 없..
개발은 '데이터'를 할당하는 작업이다. 어떤 개발영역이든 '데이터'를 다루고 할당하는 작업을 한다. 여기서 말하는 '데이터'는 DB에 저장되는 값이 될 수도 있고, 사용자에게 적절하게 반환되어서 보여지는 값이 될 수도 있다. 우리가 만든 코드들은 결국 데이터를 할당하는 작업을 한다. 다시말해 (낯선)코드를 읽고 파악하는 과정은 데이터가 어떤식으로 다루어지고 변경되어지고 할당되어지는지 확인하는 과정이다. 코드를 읽어나가는 사람 입장에서 데이터들이 어떤방식으로 할당되어지는지 예측할 수 없다면 그 코드는 읽기 좋은 코드라고 말할 수 없다. 데이터가 예측되는 메서드를 만들자. DB 값을 변경하기 위한 데이터를 할당하는 작업. 사용자에게 보여주기 위한 데이터를 할당하는 작업. 이 정도 수준의 할당은 아주 낮은 추..
GoogleTechTalks의 "The Clean Code Talks -- Inheritance, Polymorphism, & Testing" 을 참고하여 정리하고 각색하였습니다. https://www.youtube.com/watch?v=4F72VULWFvc if문을 제거합시다. 왜 if문을 제거해야 할까요? (이 포스팅에서는 switch문을 포함한 모든 조건문을 if문이라고 칭하겠습니다.) if 문은 코드의 가독성을 저해시킵니다. if 문은 테스트를 불편하게 만듭니다. if 문은 유지보수하기 어렵게 만듭니다. 모든 if문을 제거할 수는 없습니다. 다만, 대부분의 if문은 다형성을 이용하여서 제거 될 수 있습니다. 다형성을 활용하여 제거 할 수 있는 if문은 2가지 경우가 있습니다. 객체가 다른 상태에 ..
LSP(Liskov Substitution Principle - 리스코프 치환 원칙) 서브타입은 언제나 자신이 기반타입 (base type) (상위 타입) 으로 교체할 수 있어야 한다. S-O-L-I-D로 유명한 다섯가지 객체지향 설계 원칙중에서 LSP는 '상속'에 관한 지침을 이야기 합니다. 오리와 오리장난감 LSP를 설명하는 유명한 예제로 오리와 오리장난감이 있습니다. 오리와 오리장난감이 유사한 점이 있다고 오리장난감이 오리를 상속받게 되면 LSP를 위반하게 된다는 예제입니다. 왜냐하면 오리장난감은 배터리가 있어야 제대로된 동작을 하기 떄문입니다. 만약 오리를 기대하던 클라이언트(사용자)에게 오리 대신 오리장난감을 쥐어준다면, 클라이언트는 자신이 원하는 행동을 기대하기 어렵습니다. 오리장난감은 기반타..
개요아주 간단하지만 아주 끔찍한(?) 클래스를 하나 보겠습니다. class MyClass { void myMethod1() { System.out.println("A"); System.out.println("B1"); System.out.println("C"); } void myMethod2() { System.out.println("A"); System.out.println("B2"); System.out.println("C"); } } public class Main { public static void main(String[] args) { MyClass myClass = new MyClass(); myClass.myMethod1(); myClass.myMethod2(); } } 위의 MyClass..
의존하는 객체가 자주 변하는 경우 Soldier(군인)이라는 클래스와 Gun(총)이라는 클래스가 있고, Soldier클래스는 Gun클래스를 의존하고 있다고 가정해봅시다. 이런 경우를 코드로 간략하게 나타내면 아래와 같습니다. class Soldier{ . . . Gun gun = new Gun(); . . . } 하지만 Soldier입장에서, 사용하는 무기가 Gun이 아닌 다른 경우가 존재 할 수 도 있습니다. 예를 들어, Sword(검)이라던지, Bow(활) 같은 경우입니다. 그럼 매번 의존하는 무기가 변경 될 때 마다 코드를 변경 해주어야 합니다. Soldier의 무기가 Sword로 변경 되어야 하는 경우 class Soldier{ . . . Sword sword = new Sword(); . . ...
응집도? 객체 지향의 이상적인 설계를 위한 많은 원칙들을 한줄로 요약하면, "응집도는 높이고, 결합도는 낮춘다!" 입니다. 설계 부분은 이러한 개념적인 부분이 많아 경험이 수반 되지 않으면 초보개발자들이 완전히 이해하기 어려운 측면이 많이 있습니다. 특히 저는 응집도를 이해하기가 어려웠습니다. 응집도를 높이기 위해 연관된 사항들을 이것 저것 넣게 되면 SRP(단일 책임 원칙)에 크게 위반하게 될 것 같은데, 아이러니 하게도 응집도를 높이는것이 SRP(단일 책임 원칙)을 지키게 되는 지름길이라는 겁니다. 이러한 의문을 풀기위해서 먼저 응집도의 의미부터 정확하게 하기 위해서 찾아보았습니다. 하나의 프로그램을 구성하는 각각의 모듈이 그 고유의 기능을 잘 처리할 수 있는지를 나타내는 정도. - (한국정보통신기술..