OOP 소개 최범균트위터 : @madvirus, 이메일 : madvirus@madvirusnet 강사소개 최범균 트위터 : @madvirus 이메일 : madvirus@madvirusnet 이력 현 ) 에스씨지솔루션즈 전 ) 위메이드엔터테인먼트 전 ) 다음커뮤니케이션 자바 7 프로그래밍, JSP 프로그래밍등저 2 TOC 비용 절차지향 vs 객체지향 객체지향 캡슐화 추상화 유연함 정리 3 1
비용 4 개발비용? 5 비용의구성 최초개발비용 유지보수비용 ( 무수한변화 ) 6 2
유지보수사례 다음카페 아고라게시판 7 비용을줄이려면 유지보수비용줄이려면 코드변경이용이 코드분석이용이 코드변경 / 분석이용이하려면, 코드자체의가독성향상 변경에유연하게대처가능한구조 코드가비즈니스모델을표현 8 답중의하나 Object Oriented 9 3
객체지향 10 절차지향 프로시저 프로시저 데이터 프로시저 프로시저 11 객체지향 객체 객체 객체 객체 객체 객체 객체 12 4
객체 (Object) 객체는제공하는기능으로정의 객체는역할을가짐 객체가어떤데이터를보관하는지로정의하지않음 메시징 객체와객체는기능실행을위해메시지를주고받음 일반적으로메서드호출을통해메시지전달 리모콘객체 TV 객체 채널변경메시지 채널변경기능제공볼륨조절기능제공 13 클래스 객체를표현하기위한수단 자바, C# 과같은언어에서객체를정의하기위한수단으로클래스를사용함 public class TV { public void increasevolume() { public void decreasevolume() { 제공할기능을정의 TV tv = new TV(); tvincreasevolume(); 객체에메시지를전달 14 역할 / 책임 (Responsibility) 그리고관계 각객체들은자신만의역할을가짐 객체간관계형성 서로다른역할을수행하는객체간메시지전달을통해전체기능수행 로그수집객체 흐름제어객체 로그분석객체 DB 연동객체 결과가공객체 15 5
객체설계의기본과정 기능 ( 역할 ) 을제공할객체후보선별 내부에서필요한데이터선별 클래스다이어그램 ( 정적 ) 객체간메시지흐름연결 커뮤니케이션다이어그램 / 시퀀스다이어그램 ( 동적 ) 위과정되풀이 16 캡슐화 17 캡슐화 (Encapsulation) 객체가내부적으로어떻게기능을구현했는지는감춤 캡슐화를통해객체의내부구현이변경되더라도객체를사용하는코드는변경되지않도록함 코드변경에따른비용최소화 객체지향의가장기본 18 6
데이터중심구현 : 절차지향스톱워치 - 최초코드 public class ProceduralStopWatch { public long starttime; // 밀리초 (1/1000 초 ) 단위 public long stoptime; // 1/1000 초단위 public long getelapsedtime() { return stoptime - starttime; ProceduralStopWatch stopwatch = new ProceduralStopWatch(); stopwatchstarttime = SystemcurrentTimeMillis(); // 시작시간 // 측정대상기능실행 stopwatchstoptime = SystemcurrentTimeMillis(); // 종료시간 long elapsedtime = stopwatchgetelapsedtime(); // 시간차이 19 데이터중심의절차지향구현방식 - 기능추가여파 public class ProceduralStopWatch { public long starttime; public long stoptime; public long startnanotime; public long stopnanotime; public long getelapsednanotime() { return stopnanotime - startnanotime; ProceduralStopWatch stopwatch = new ProceduralStopWatch(); stopwatchstartnanotime = SystemnanoTime(); // 시작시간 // 측정대상기능실행 stopwatchstopnanotime = SystemnanoTime(); // 종료시간 long elapsedtime = stopwatchgetelapsednanotime(); // 차이 20 절차지향의한계 - 요구사항변경에따른수정전파 21 7
객체지향방식 - 데이터가아닌기능 / 모델을제공 public class StopWatch { private long starttime; private long stoptime; public void start() { starttime = SystemcurrentTimeMillis(); public void stop() { stoptime = SystemcurrentTimeMillis(); public Time getelapsedtime() { return new Time(stopTime -starttime); 22 객체가제공하는기능을사용 / 모델을사용 StopWatch stopwatch = new StopWatch(); stopwatchstart(); // starttime 필드에값을할당아닌, 기능실행 // 코드 stopwatchstop(); // stoptime 필드에값을할당아닌, 기능실행 Time time = stopwatchgetelapsedtime(); // long 타입이아님 timegetmillitime(); 23 객체지향 - 요구사항변경에따른변화가객체로수렴 public class StopWatch { private long starttime; private long stoptime; public void start() { starttime = SystemnanoTime(); public void stop() { stoptime = SystemnanoTime(); public Time getelapsedtime() { return new Time(stopTime - starttime); public class Time { private long t; public Time(long t) { thist = t; public long getmillitime() { return t / 1000000L; public long getnanotime() { return t; 24 8
절차지향에비해확실히작은변경의여파 StopWatch stopwatch = new StopWatch(); stopwatchstart(); // 코드 stopwatchstop(); Time time = stopwatchgetelapsedtime(); timegetnanotime(); 수정비용의감소 ProceduralStopWatch stopwatch = new ProceduralStopWatch(); stopwatchstartnanotime = SystemnanoTime(); // 시작시간 // 측정대상기능실행 stopwatchstopnanotime = SystemnanoTime(); // 종료시간 long elapsedtime = stopwatchgetelapsednanotime(); // 차이 25 캡슐화 - 구현변경의유연함! 26 기본규칙 : Tell, Don't Ask 27 9
Tell, Don't Ask 데이터달라하지 / 넣지말고, 기능실행해하기 다른말로하면 데이터가흘러다니지않도록 즉, 절차지향이되지않도록 간단한예 if (membergetexpiredate()gettime() < System SystemcurrentTimeMillis) { if (memberisexpired()) { 28 도움되는내용 CQRS(Command Query Responsibility Segregation) Law of Demeter 29 추상화와다형성 30 10
다형성 Polymorphism 이란? 객체가여러역할을수행할수있음 객체지향에서는 ' 상속 Inheritance' 으로구현 타언어의 Duck Typing 등도존재 Motorcycle start() ZetMotorcycle start() ZetEngine zeton() AirPlane ZetMotorcycle zm = new ZetMotorcycle(); zmstart(); zmzeton(); Motorcycle mc = zm; mcstart(); ZetEngine ze = zm; zezeton(); ZetEngine ap = new AirPlane(); apzeton(); 31 상속의두가지 구현상속 상위타입의구현을재사용하는방법 public class ZetEngine { public void zeton() { public class AirPlane extends ZetEngine { public void turnmanualmode() { AirPlane ap = new AirPlane(); apzeton(); 인터페이스상속 다형을갖는방법 public interface ZetEngine { public void zeton(); public interface Motorcycle { public void start(); public class ZetMotorcycle implements ZetEngine, Motorcycle { public void turnmanualmode() { public void start(0 { ZetMotorcycle zm = new ZetMotorcycle(); ZetEngine ze = zm; Motorcycle mc = zm; 32 추상화 Abstraction 데이터 / 프로세스등을의미가비슷한개념 / 표현으로정의하는과정 원격서버파일을 FTP 로다운로드 원격서버파일을 SCP 로복사 DB 서버로그테이블을조회 추상화 로그수집 33 11
타입추상화 공통된데이터나프로세스를제공하는객체들을하나의 ( 인터페이스 ) 타입으로추상화하는것 class FtpLogCollector { private String ftpserver; public FtpLogSet collect() { class FtpLogSet { Iterator iterator() { class DBLogCollector { private String jdbcurl; public DBRowLogSet collect() { class DBrowLogSet { Iterator iterator() { interface LogCollector { LogSet collect(); interface LogSet { Iterator iterator(); 구현없이기능만정의 34 추상타입과구현과의연결 : 상속 class FtpLogCollector implements LogCollector { private String ftpserver; public LogSet collect() { return new FtpLogSet( ); class FtpLogSet implements LogSet { Iterator iterator() class { DBLogCollector implements LogCollector { private String jdbcurl; public LogSet collect() { return new DBRowLogSet( ); class DBrowLogSet implements LogSet { Iterator iterator() { 35 추상화와다형성 LogCollector collector = new FtpLogCollector(ftpServer); LogSet logset = collectorcollect(); Iterator iter = logsetiterator(); 구현클래스가아닌추상화타입을이용한코드작성가능 LogCollector collector = LogCollectorFactorycreate(); LogSet logset = collectorcollect(); Iterator iter = logsetiterator(); 36 12
추상화와뇌 로그수집 로그분석 설계 결과저장 상세구현 디렉토리에서파일을읽어와메모리에저장하고, 한줄한줄을정규표현식으로파싱하고그결과를 DB 에일단저장한다음에 37 추상화 / 다형성과유연함 38 구현클래스를직접사용한다면, FtpLogCollector collector = new FtpLogcollector(); FtpLogSet logset = collectorcollect(); Iterator iter = logsetiterator(); 파일로바꿔주세요 FileLogCollector collector = new FileLogcollector(); FileLogSet logset = collectorcollect(); Iterator iter = logsetiterator(); 바꿔주세요 XXXLogCollector collector = new XXXLogcollector(); XXXLogSet logset = collectorcollect(); Iterator iter = logsetiterator(); 39 13
추상화타입에대고프로그래밍하기 ( 가능한 ) 구현클래스가아닌인터페이스사용 LogCollector collector = ; LogSet logset = collectorcollect(); Iterator iter = logsetiterator(); LogCollector collector = 요기 ; LogSet logset = collectorcollect(); Iterator iter = logsetiterator(); LogCollector collector = 요기 ; LogSet logset = collectorcollect(); Iterator iter = logsetiterator(); 바꿔주세요 바꿔주세요 40 추상화 / 다형성의혜택 : 구현교체의유연함 LogCollector collector = LogCollectorFactorycreate(); LogSet logset = collectorcollect(); Iterator iter = logsetiterator(); 바꿔주세요 LogCollector collector = LogCollectorFactorycreate(); LogSet logset = collectorcollect(); Iterator iter = logsetiterator(); 바꿔주세요 LogCollector collector = LogCollectorFactorycreate(); LogSet logset = collectorcollect(); Iterator iter = logsetiterator(); 41 중요한 / 필요한역량 : 인터페이스 ( 추상타입 ) 뽑아내기! 인터페이스후보 public 메서드 public 메서드는기능을제공할가능성이높고, 기능은공통된프로세스일가능성이높음 여러클래스에서중복되는구현 공통의프로세스일가능성높음 인터페이스는항상? 미래를너무대비할필요는없다 모든클래스에대해상위인터페이스를만들필요없음 단, 객체간호출이많다면인터페이스분리좋음 42 14
기본규칙 :Composition over inheritance 43 ( 잘못된 ) 구현상속의문제 public class LuggageCompartment extends ArrayList<Luggage> { private int restspce; public void add(luggage piece) { thisrestspace -= piecegetsize(); superadd(piece); public void cancontain(luggage piece) { return thisrestspace > piecesize(); LuggageCompoartment lc = new LuggageCompartment(); lcadd(new Luggage(10)); // 앗!! restspace 가계산되지않는다! lcremove(someluggage); lcextract(anyluggage); lccancontain(aluggage); // 잘못된결과 public void extract(luggage piece) { thisrestspace += piecegetsize(); superremove(piece); 44 상속은 IS-A 에대한것 수화물창고!= 배열기반목록 동일역할인경우에만구현상속통한재사용 예, ArrayList is a AbstractList 구현상속의고민거리 구현상속은상위클래스의변경이모든하위클래스에영향을줌 45 15
조립을통한구현재사용 구현재사용은상속보단조립 (composition) public class LuggageCompartment { private List<Luggage> luggages = new ArrayList<Luggage>(); private int restspce; public void add(luggage piece) { restspace -= piecegetsize(); luggagesadd(piece); public void cancontain(luggage piece) { return thisrestspace > piecesize(); public void extract(luggage piece) { restspace += piecegetsize(); luggageremove(piece); 46 조립과유연함 조립과다형성이만나유연함을증가시킴 public class Calculator { private PriceStrategy strategy; public Calculator(PriceStrategy strategy) { thisstrategy = strategy; public void calculate( ) { thisstrategyapply(price); public interface PriceStrategy { void apply(money price); public class RegularCustomerStrategy implements PriceStrategy { public class FirstCustomerStrategy implements PriceStrategy { PriceStrategy strategy = new RegularCustomerStrategy(); Calculator cal = new Calculator(strategy); calcalculate(); PriceStrategy strategy = new FirstCustomerStrategy(); Calculator cal = new Calculator(strategy); calcalculate(); Calculator 변경없이새로운가격정책적용이가능 47 정리 48 16
모두아우르는大원칙! High Cohesion ( 높은응집 ) 관련된것들은최대한한곳에모은다 변화가한곳에집중되기때문에, 변화에따른영향최소화 Low Coupling ( 낮은결합도 ) 상호간얽혀있는부분을최소화 한코드의변화로인해다른코드의변화가발생하는것을최소화 49 정리 비용 : 최초개발 <<<< 유지보수 유지보수비용을줄이기위한방법 코드가독성향상, 변경에유연한구조, 객체지향 서로다른기능을제공하는객체간의메시징 자바나 C# 과같은언어는클래스와메서드로객체 / 메시징구현 캡슐화, 추상타입을통한변화에따른영향최소화 이는개발비용의감소로이어짐 기본규칙 Tell, Don't Ask Program To Interface Composition over Inheritance 50 개발자로서성장하기위해해야할것 표현방법익히기 UML 객체지향익히기 설계원칙 패턴 (GoF 패턴 ): 공통된상황을추상화하는방법 TDD 기능중심의설계를할수있도록유도! 좋은코드만들기 Clean Code Implementation Pattern 51 17
질문 52 18