블로그

객체 지향 프로그래밍 입문(최범균) 2 - 다형성, 추상화, 조립

  다형성이란, 여러 모형으로 변화하는 것이다. 하나의 객체가 여러 타입을 갖는 것이다. 추상화란, 특정한 성질(interface) 또는 공통 성질(abstract, 일반화)을 뽑아내는 과정이다. 추상화를 통해 객체는 다형적인 모형을 변화 가능하다   <추상화 시점> 추상화는 의존 대상이 변경하는 시점에 추가한다. 실제 변경 및 확장이 일어날 때 공통점을 파악하고 뽑아낸다.   <추상화 예시> 클라우드 파일 관리 기능이 있고, 대상 클라우드의 종류가 n가지일 경우.클라우드 종류에 따라 if문으로 분기하는 로직이 아닌 공통기능인 클라우드 파일 시스템을 추상화한다.클라우드 파일 시스템에서는 파일 목록과 관련된 CRUD 기능을 추상화하고,클라우드 파일에서는 개별 파일의 CRUD 기능을 추상화한다. 특정 클라우드 구현체에서는 추상 클래스를 상속받아서 기능을 재정의한다. 추상화가 진행되면, 구현 클래스의 변경은 있더라도(조립) 서비스 로직은 바뀌지 않는다.   <상속보다는 조립> 상속을 통해서 재사용을 하게 된다면,1. 상위 클래스의 변경이 어렵고2. 기능과 확장이 필요한 만큼 클래스가 증가하고3. 상속을 오용하게 된다.(비슷한 메서드 착오) 상속은 하위타입일 경우에 진행하고, 보통의 경우 객체를 참조하는 방식으로 진행할 것.    

java객체지향최범균강의추상화다형성조립객체참조

객체 지향 프로그래밍 입문(최범균) 3 - 분리, 의존 주입, DIP

<역할과 기능 분리 방법> 1. 패턴 적용 전형적 분리(아키텍처, 디자인패턴) 2. 계산 분리 로직의 기능화 3. 연동 분리 클래스 분리 4. 연속적인 if-else는 추상화 고민할 것   적절한 역할 분리는 테스트도 용이하게 한다.사용자와 직접적으로 관련된 기능은 내부 메서드로, 간접적으로 관련있는 기능은 별도의 클래스로 분리한다.   <의존> 순환 의존은 변경이 연쇄적으로 전파된다. 기능 변경의 파장이 커지면 안 좋기 때문에 의존은 적을수록 좋다. 의존대상의 기능이 많은 경우 클래스로 분리하거나 단일 기능으로 묶을 수 있는지 확인하라. 예를 들어 민원팩토리, 민원리포지토리를 민원등록으로 묶기   <스프링 의존 주입> 추상적 인터페이스를 의존하고, 의존 주입은 보통 생성자 방식으로 외부(스프링)에서 진행한다. 내부에서 new()로 생성하는 것과 반대이다. 1. 의존 대상이 바뀌면 그 대상을 조립하는 부분만 수정하면 됨 2. 대역 객체를 통해 테스트가 가능하다   <DIP 의존 역전 원칙> 고수준 모듈(기대수준), 저수준 모듈(단위적 실제 행위) 고수준 모듈을 의존해야한다. 반대로 고수준 모듈이 저수준 모듈을 의존하는 경우, 저수준 모듈이 변화할 때 고수준 모듈에 영향을 끼침 (목표를 향해 개발하는 것이 아닌, 개발에 따라 목표가 변하는 현상)고수준 모듈을 구현한 추상타입(인터페이스)을 저수준 모듈이 의존하는 방식을 추구해야한다.    

java강의최범균DIPDIinterface분리객체지향

객체 지향 프로그래밍 입문(최범균) 1 - 객체지향, 캡슐화

좋은 코드란, 낮은 비용으로 변화할 수 있는 코드이다 이것은 1. 캡슐화 2. 추상화(다형성 지향)로 이루어낼 수 있다.   절차지향적 코드는 진행될수록 여러 조건문으로 복잡해질 수 있다. 객체지향적 코드는 객체가 제공하는 기능(메서드)이 중심이 되어 설계하는 것이다.  - 호출, 리턴, 익셉션 등의 메세지의 교환 - 데이터 클래스(VO, DTO)는 객체가 아니다. 객체의 기능이 없이 값에만 접근하기 때문이다.   캡슐화는 데이터와 관련된 기능을 묶는 것이다. 데이터의 상세 내용을 외부에 감추고, 외부와 무관하게 객체 내부의 구현 변경이 가능하다. 객체의 기능을 비즈니스 로직이 아닌 객체 내부의 메서드로 구현하면, 기능에 변화가 요구될 때 해당하는 내부 기능을 변경하면 캡슐화를 사용한 곳에 별도의 수정이 필요하지 않다.   캡슐화의 규칙 1. 데이터를 요구하는 것이 아닌 데이터의 처리를 요구할 것if(member.getAge() > 19) Xif(member.isAdult()) O 2. 메서드에서 생성한 객체의 메서드만 호출할 것파라미터로 받은 객체의 메서드만 호출할 것필드로 참조하는 객체의 메서드만 호출할 것 >> 연속적인 메서드 호출이 아닌 객체에 있는 하나의 메서드로 처리member.isAdult() + member.isVIP() + member.addCoupon()으로 하나씩 처리하는 것보다member.receiveBenefits()로 위 세 개 기능 묶기     객체는 속성과 기능으로 구성되어있다. 객체의 여러 기능을 참조하고 묶어서 새로운 기능에 사용하는 것은 객체 지향적인 방식이다.        

java객체지향최범균강의캡슐화DDD

<도서정리> 테스트 주도 개발 시작하기 - 최범균

TDD 단계: 레드 - 그린 - 리팩토링 테스트 선 작성 후 테스트를 통과시킬 만큼의 코드를 작성한다.(기능을 구현한다)마지막으로 리팩토링을 통해 코드를 다듬는다.테스트를 통해 개발의 범위가 정해진다. 테스트가 진행될수록 검증하는 범위가 넓어지면서 기능 구현이 점점 완성되어간다. TDD는 개발 과정에서 코드를 지속적으로 정리하므로 코드품질을 높이고 유지보수 비용을 낮춘다.코드 수정 후 테스트가 진행되므로 향후 올바르지 않은 코드가 배포되는 것을 방지할 수 있다.   테스트 코드 작성 순서 쉬운 경우(넓은 범위)에서 어려운 경우로 진행 예외적인 경우에서 정상인 경우로 진행 한 번에 많은 코드를 만들면, 그 사이 발생한 버그를 잡기 위해 많은 비용이 들어간다. 정해진 값 리턴 값 비교를 통해 정해진 값 리턴 다양한 경우 추가하면서 구현을 일반화 테스트를 먼저 작성하고 return 상수로 테스트 통과시킨 후에 비즈니스 로직 하나씩 추가하면서 테스트 매번 실행   대역 MockitomemoryRepository implements 리포지토리 인터페이스 - Map 사용하기@TempDir   기능명세 테스트할 기능을 생성하면서 클래스, 메서드, 파라미터 구성결과 검증하면서 리턴값 구성-> 테스트하면서 설계까지 진행됨클래스, 메서드, 변수명은 주석보다 코드 이해에 효과적이게 구성하기필요한만큼만 설계하기예외적인 상황, 복잡한 상황은 최대한 많이 기획자와 상의하고 대비하는 것이 효율적이고 완성도 높은 개발을 이끌어냄   리팩토링 기능 개발을 다 끝낸 후에 리팩토링하기또는 커밋 후에 리팩토링하기리팩토링은 클래스 분리, 메서드 추출, or문, count 로직 등 이용...파라미터 개수가 3개 이상이면 객체화하기 꿀팁 Assert 메서드를 테스트 클래스에 별도 생성해서 응용도 가능하다.로직을 중복 호출하지 않고, Assert 메서드에 로직을 넣어버려서 검증만 진행하도록 할 수도 있다. 중간에 예외처리를 하면, 조건문 중복 등 코드가 복잡해지기 때문에초반에 예외처리를 하는 것이 시스템 운영 중에 NPE를 만나지 않는 방법이다. before setUp으로 데이터를 미리 생성해놓는 것은 중복이 제거되는 듯이 보이지만,각 테스트마다 필요한 데이터가 항상 일정하지 않을 수 있음으로 각 테스트에서 데이터 생성하는 것을 추천한다. 검증 시 굳이 변수나 필드명으로 검증하는 것보다 기댓값을 실제값으로 넣는 것도 좋다.테스트에서는 직관적으로 확인할 수 있는 것이 좋기 때문이다. given으로 파라미터를 넘길 때는 값보다 타입으로 넘겨주자.(범용성) update와 같은 내부구현 검증이 필수적일 때는 내부구현 검증이 필요하다.하지만 웬만하면 실행결과 검증 중심으로 진행할 것.테스트 실패의 경우를 줄이기 위해서 검증해야할 부분을 명확히 하기 위해서이다.

TDDtest최범균junit도서

채널톡 아이콘