본문 바로가기

객체, 설계 변경에 취약한 코드결합도(Coupling) : 객체 사이의 의존성 - 결합도가 높을 수록 함께 변경될 확률이 높아진다. - 결합도를 낮춰 변경이 용이한 설계를 만들어야 한다. 자율성을 높이자캡슐화(encapsulation) : 개념적이나 물리적으로 객체 내부의 세부적인 사항을 감추는 것객체를 인터페이스와 구현으로 나누고 인터페이스만을 공개하자 - 객체 사이의 결합도를 낮추고 변경하기 쉬운 코드를 작성하기 위해 따라야 하는 가장 기본적인 설계 원칙 캡슐화와 응집도응집도(cohesion) : 밀접하게 연관된 작업만을 수행하고 연관성 없는 작업은 다른 객체에게 위임하는 것 - 자신의 데이터를 스스로 처리하는 자율적인 객체를 만들면 결합도를 낮추고 응집도를 높일 수 있다. 절차지향과 객체지향절차지향 : 프로세스..
디미터 법칙 소프트웨어 개발 가이드라인 중 하나 최소 지식 원칙 - 한 모듈이 구현을 알아야하는 다른 모듈들을 적게 유지하자 - 결합도가 높으면 모듈을 재사용하기 힘들다 모듈들 사이의 결합도를 줄여 코드 품질을 높이는 것 규칙화 - 어떤 오브젝트(O)의 메서드(m)는 다음과 같은 오브젝트의 메서드만 호출해야 한다- O 자신의 메서드- m의 매개변수로 들어온 객체의 메서드- m 안에서 생성 된 객체- O의 컴포넌트 (A의 인스턴트 변수)- 전역 객체 예제class A { private B b; public setA(B b) { b = b; } public myMethod(OtherObject other) { // ... } /* 디미터의 법칙을 잘 따른 예 */ public okLawOfDemeter(Paramemte..
GRASP 패턴 객체지향 디자인 패턴 - General Responsibility Assignment Software Patterns기본 5가지 패턴들Creator - 객체의 생성은 생성되는 객체의 컨텍스트를 알고 있는 다른 객체가 있다면, 컨텍스트를 알고 있는 객체에 부여하자 - A 객체와 B 객체의 관계가 다음 중 하나라면 A의 생성을 B의 역할로 부여하자- B 객체가 A 객체를 포함하고 있다.- B 객체가 A 객체의 정보를 기록하고 있다.- A 객체가 B 객체의 일부이다.- B 객체가 A 객체를 긴밀하게 사용하고 있다.- B 객체가 A 객체의 생성에 필요한 정보를 가지고 있다. Information Expert - 역할을 수행할 수 있는 정보를 가지고 있는 객체에 역할을 부여하자 - 객체는 데이터와 처리로직이 함께..
TDD, BDD, DDD, RDD TDD (Test) - 테스트를 먼저 작성하고 해당 테스트 케이스를 통과하는 코드를 작성 - 그 후 상황에 맞게 리팩토링 과정을 거침 - 코드 생산성에 문제가 있고, 러닝커브가 크다. BDD (Behavior) - TDD에서 한발 더 나아가 테스트 케이스 자체가 요구사항이 되는 개발 방식 - TDD에서는 유닛 테스트로 작성 된 테스트 케이스에 대한 문서를 작성했지만, BDD는 이것을 결합 테스트와 시나리오 테스트까지 확장하여 각각에 해당하는 문서를 대체했다. DDD (Domain) - 도메인 그 자체와 도메인 로직에 초점을 맞춘다. - 일반적으로 사용하는 데이터 중심의 접근법을 탈피하여 순수한 도메인의 모델과 로직에 집중한다. RDD (Responsibility) - 책임을 찾고 책임을 수행한 적절한 객..
직렬화 자바 직렬화의 대안을 찾으라 - 직렬화 위험을 회피하는 가장 좋은 방법은 아무것도 역직렬화하지 않는 것이다. - 차선책은 신뢰할 수 없는 데이터는 절대 역직렬화하지 않는 것이다. - 새로운 시스템에서 자바 직렬화를 써야 할 이유는 전혀 없다. - 객체 역직렬화 필터링(java.io.ObjectInputFilter)를 사용하자. (블랙리스트 보다는 화이트리스트 방식을 추천한다.) Serializable을 구현할지는 신중히 결정하라 - Serialiazable을 구현하면 릴리스한 뒤에는 수정하기 어렵다. - 버그와 보안 구멍이 생길 위험이 높아진다. - 해당 클래스의 신버전을 릴리스할 때 테스트할 것이 많아진다. - Serializable 구현 여부는 가볍게 결정할 사안이 아니다.- 상속용으로 설계된 클래스..
동시성 공유 중인 가변 데이터는 동기화해 사용하라 - 동기화는 배타적 실행뿐 아니라 스레드 사이의 안정적인 통신에 꼭 필요하다. - Thread.stop은 사용하지 말자. - 가변 데이터는 단일 스레드에서만 쓰도록 하자. - 쓰기와 읽기 모두가 동기화되지 않으면 동작을 보장하지 않는다.- 동기화하지 않으면 한스레드가 수행한 변경을 다른 스레드가 보지 못할 수도 있다.- 공유되는 가변 데이터를 동기화하는데 실패하면 응답 불가 상태에 빠지거나 안전 실패로 이어질 수 있다.(디버깅 난이도가 가장 높은 문제에 속한다.) - 배타적 실행은 필요 없고 스레드끼리의 통신만 필요하다면 volatile 한정자만으로 동기화할 수 있다. 과도한 동기화는 피하라 - 응답 불가와 안전 실패를 피하려면 동기화 메서드나 동기화 블록 안에..
예외 예외는 진짜 예외 상황에만 사용하라 - 예외는 오직 예외 상황에서만 써야 한다. 절대로 일상적인 제어 흐름용으로 쓰여선 안 된다. - 잘 설계된 API라면 클라이언트가 정상적인 제어 흐름에서 예외를 사용할 일이 없게 해야 한다. 복구할 수 있는 상황에는 검사 예외를, 프로그래밍 오류에는 런타임 예외를 사용하라. - 호출하는 쪽에서 복구하리라 여겨지는 상황이라면 검사 예외를 사용하자. - 프로그래밍 오류를 나타낼 때는 런타임 예외를 사용하자. - 구현하는 비검사 throwable은 모두 RuntimeException의 하위 클래스여야 한다. (Error는 상속하지 말아야 할 뿐 아니라, throw 문으로 직접 던지는 일도 없어야 한다.) - 검사 예외도 아니고 런타임 예외도 아닌 throwable은 정의하..
일반적인 프로그래밍 원칙 지역변수의 범위를 최소화하라 - 가장 처음 쓰일 때 선언하자. - 선언과 동시에 초기화해야 한다. - 컬렉션이나 배열 순회for (Element e : c) {...} - 반복자가 필요할 때for (Iterator i = c.iterator(); i.hasNext(); ) {...} - 메서드를 작게 유지하고 한 가지 기능에 집중해라. 전통적인 for문 보다는 for-each문을 사용하라 - for-each문을 사용할 수 없는 상황- 파괴적인 필터링 : 컬렉션을 순회하면서 선택된 원소를 제거해야 하는 경우 (자바 8에서는 Collection의 removeIf 메서드를 사용한다.)- 변형 : 리스트나 배열을 순회하면서 그 원소의 값 일부 혹은 전체를 교체해야 하는 경우- 병렬 반복 : 여러 컬렉션을 병렬로..