- 프로시저와 데이터간의 접근이 자유롭다
- 개발 초기단계에서는 편의성이 있지만 시간이 지날수록 프로시저가 어느 데이터에든 접근 할 수있어 캡슐화가 저하되있기 때문에 개발이 어려운 점이 있다.
- 처음에는 어려울 수 있음
- 데이터 프로시저를 알맞게 묶는 것이 어려움
- 하지만 시간이 흘러갈 수록 캡슐화 이점 때문에 큰 장점이 있음
객체의 핵심 -> 기능 제공
-
객체는 제공하는 기능으로 정의
- 내부적으로 가진 필드(데이터로) 정의 하지 않음
- 데이터(맴버 필드)가 중요하지 않음 기능 으로 정의
- 해당 기능이 동작할때 맴버 필드 들이 변경 됨
-
객체와 객체 상호 작용: 메시지를 주고 받는
- 메서드를 출하는 메시지, 리턴하는 메시지, 입렙션 메시지 클래스 간의 상호 작용이 메시지라고 정의
클래스라는 개념의 목적은 데이터를 캡슐화 하고 캡슐화한 데이터를 다루는 코드를 한 곳에서 관리하는 것이다.
- 데이터 + 관련 된 기능 묶기
- 객체가 기능을 어떻게 구현했는지 외부에 감추는 것(정보은닉)
- 구현에 사용된 데이터의 상세 내용을 외부에 감춤
- 정보 은닉 의미 포함
- 최근에는 캡슐화에 정보은닉이라는 개념도 포함시켜 이야기함
- 즉 캡슐화은 정보 은닉이라는 개념도 포함되 있다.
- 외부에 영향 없이 객체 내부 구현 변경 가능
- 기능의 구현을 외부에 감춤
- 기능을 사용한 코드에 영향을 주지 않고 내부 규현을 변경할 수 있는 유연함
// 묻고 있다.
if(acc.getMemberShip() == REGUAR) {...}
if (acc.hasRegularPermission()){...}
- 메서드에서 생성한 객체의 메서드만 호출
- 파라미터로 받은 객체의 메서드만 호출
- 필드로 참조하는 객체의 메서드만 호출
acc.getExpDate().isAfter(now) // 안티
acc.isExpired(now) // 적절
Date date = acc.getExpDate;
data.isAfter(now); // 안티
acc.isValid(now); // 적절
- 캡슐화 : 기능의 구현을 외부에 감춘
- 캡슐화를 통해 기능을 사용하는 코드에 영향을 주지 않고(또는 최소화) 내부 규현을 변경할 수 있는 유연함
- 다형성 : 여러 모습을 갖는 것
- 객체 지향에서는 한 객체가 여러 타입을 갖는 것
- 즉 한 객체가 여러 타입의 기능을 제공
- 타입 상속으로 다형성 구현 (하위 타입은 상위 타입도 됨)
- 데이터나 프로세스 등을 의미가 비슷한 개념이나 의미 있는 표현으로 정의하는 과정
- 두 가지 방식의 추상화
- 특성한 성질, 공통 설징(일반회)
- 간단한 예
- DB의 User 테이블 : 아이디, 이름, 이메일
- Money 클래스 : 통화, 금액
- 프린터 : HP MXXXX, 삼성 SL-M2XXX
- GPU: 지포스, 라데온
- 여러 구현 클래스를 대표하는 상위 타입 도출
- 흔히 인터페이스 타입으로 추상화
- 추상화 타입과 구현 타입 상속으로 연결
- 추상화 -> 추상 타입 증가 -> 복잡도 증가
- 아직 존재하지 않은 기능에 대한 이른 추상화는 주의 : 잘못된 추상화 가능성, 복잡도만 증가
- 실제 변경, 확장이 발생 할때 추상화
- 구현을 한 이유가 무엇 때문인지 생각해야함
- 상위 클래스의 변경시 하위 클래스가 비 정상적으로 동작할 가능성이 높음
- 상위 클래스 입장에서는 어느 하위 클래스가 추가될지 알 수가 없음
- 하위 클래스는 상위 클래스의 동작 방법에 어느정도는 알아야함
- 상위 클래스는 하위 클래스에 대해 캡슐화가 약해지게 됨
- 새로운 조합이 생길때마다 새로은 클래스가 생김
- 새로운 조합이 생길때 어느 클래스를 상속 받아야 할지 어려움
- CompressedStorage 압축 기능 추가 , EncryptedStorage 암호화 기능 이 있을 때 CachedableStorage 캐시 기능을 제공
- CompressedStorage 기능과, EncryptedStorage 기능이 필요할 경우 두 클래스를 상속해서 기능 제공?
- 새로운 조합이 생길때 마다 클래스를 만들어야함
- 상위 클래스의 메소드를 호출할 가능성이 있음
- 상위 클래스의 메소드를 호출하게 되어 생각지 못하게 동작하게됨
- 이는 실수하기 너무 좋은 구조
- 여러 갹체를 묶어서 더 복잡한 기능을 제공
- 보통 필드로 다른 객체를 참조하는 방식으로 조립 또는 객체를 필요 시점에 생성 / 구함
- 조립을 통한 기능 재사용, 단순 재사용의 목적으로 상속을 하는 것은 상속의 오용
- 조립을 통한 확장은 클래스 증가를 억제할 수 있음
- 상속하기 위해 앞서 조립으로 풀 수 없는 지 검토
- 진짜 하위 타입인 경우에만 상속을 사용해야 한다.
변경 대상 확인 -> 대상을 구함, 없으면 오류 응답
암호 변경 ->
대상 암호 변경 -> 암호 일치 여부 확인 -> 불일치 경우 예외, 일치 경우 비밀번호 변경
- 기능은 하위 기능으로 분해
- 기능은 곧 책임
- 분리한 각 기능을 알맞게 분배
- 클래스나 메서드가 커지면 전차 지향의 문제 발생
- 큰 클래스 -> 많은 필드를 많은 메서드가 공유
- 큰 메서드 -> 많은 변수를 많은 코드가 공유
- 여러 기능이 한 클래스 / 메서드에 썩여 있을 가능성
- 많은 필드와 변수를 여러 기능에서 공유할 간으성이 높아짐, 서로 다른 코드가 데이터를 읽고 변경함으로써 점점 코드를 수정하기 어려운 구조가 된다.
- 책임에 따라 알맞게 코드 분리
- 간단한 웹
- 컨트롤러, 서비스, DAO
- 복잡한 도메인
- 엔티티, 베류, 레포지토리, 도메인 서비스
- AOP
- 공통 기능
- GoF
- 팩토리, 빌더, 전략, 템플릿 메서드, 프록시/데코레이터 등
- 기능 구현을 위해 다른 구성 요소를 사용하는 것
- 의존의 예: 객체 생성, 메서드 호출, 데이터 사용
- 의존은 변경이 전파될 가능성을 의미
- 의존하는 대상이 바뀌면 바뀔 가능성이 높아짐
- ex) 호출하는 메서드의 파라미터가 변경
- ex) 호출하는 메서드가 발생할 수 있는 익셉션 타입이 추가
- 순한 의존
- 변경 연쇄 전파 가능성
- 클래스, 패키지, 모듈 등 등 모둔 수준에서 순혼 의존 없도록
- 외부에서 의존 갹체를 주입
- 생성자나 메서드를 이용해서 주입
- DI 장점
- 상위 타입을 사용할 경우 의존 대상이 바뀌면 조립기 설정만 변경하면됨
- DI를 습관처럼 사용하기
- 의존 객체는 주입받도록 코드 작성하는 습관
- 소프트웨어의 가치는 변화
- 적은 비용으로 변화할 수 있는 방법 중 하나 객체 지향
- 객체는 제공하는 기능으로 정의
- ex) 회원 객체, 암호 변경 기능
- 메서드를 이용해서 기능 명세
- 이름, 파라미터, 결과로 구성