블로그

윤대

[인프런 워밍업 0기 Day5] 한 걸음 더! 객체 지향으로 클린코딩!

!! 해당 글은 독자가 인프런 워밍업 0기를 수강하고 있다는 전제 하에 작성되었습니다 !!과제 수행에 있어 스프링부트 3.2.2 버전을 사용하고 있다는 점을 미리 알려드립니다!안녕하세요🙌! 인프런 워밍업 5일차 과제입니다!이번에는 클린코드의 중요성에 대하여 학습하고 클린코드를 작성하는 방법에 대해 배웠습니다!😎저는 이번 과제를 그동안 책으로만 공부했던 객체 지향을 적용하여 해결해보고자 했습니다.이론으로만 공부했기 때문에 많이 서툴 수 있다는 점! 그렇기에, 저의 말이 정답이 아니라는 점을 미리 말씀 드리며!지금부터 객체 지향을 향한 저의 여정을 소개하겠습니다! 🤸‍♂️💡과제 살펴보기아래는 과제로 주어진 지저분한 코드입니다! 바라보기만 해도 머리가 어지러운데요.. 😥public class Main { public static void main(String[] args) throws Exception { System.out.print("숫자를 입력하세요 : "); Scanner scanner = new Scanner(System.in); int a = scanner.nextInt(); int r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0, r6 = 0; for (int i= 0; i < a; i++) { double b = Math.random() * 6; if (b >= 0 && b < 1) { r1++; } else if (b >= 1 && b < 2) { r2++; } else if (b >= 2 && b < 3) { r3++; } else if (b >= 3 && b < 4) { r4++; } else if (b >= 4 && b < 5) { r5++; } else if (b >= 5 && b < 6) { r6++; } } System.out.printf("1은 d%번 나왔습니다.\n", r1); System.out.printf("2는 d%번 나왔습니다.\n", r2); System.out.printf("3은 d%번 나왔습니다.\n", r3); System.out.printf("4는 d%번 나왔습니다.\n", r4); System.out.printf("5는 d%번 나왔습니다.\n", r5); System.out.printf("6은 d%번 나왔습니다.\n", r6); } }위 코드는 결국 다음과 같은 동작을 수행합니다!주어지는 숫자를 하나 받는다.해당 숫자만큼 주사위를 던져, 각 숫자가 몇 번 나왔는지 알려준다.위 코드처럼 로직을 열거하여 프로그래밍 하는 방식을 절차 지향 프로그래밍이라 말하며, 저는 이 코드를 클린코드로 수정해야 합니다!위의 코드는 클린 코딩의 중요성을 위한 극단적인 예시일 뿐, 절차 지향이라 지저분한 것이 아닙니다!지나친 추상화는 오히려 코드의 가독성을 떨어트릴 수 있으니 무조건 '객체 지향이 좋다!'의 글이 아니라는 점 알아주세요!저는 위의 코드를 깔끔하게 바꾸기 위해서 아래와 같이 객체 지향의 형태로 수정하여 과제를 완수했습니다!public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); Dice luckyDice = UnknownDice.decideFaces(6); Note memoPad = new MemoPad(); Dealer dealer = Dealer.playWith(luckyDice, memoPad); System.out.print("숫자를 입력하세요 : "); dealer.rollDiceMultipleTimes(scanner.nextInt()); dealer.tellTheResult(); } }어떤가요? 내부 로직이 어떻게 되는지는 모르겠지만, 메소드명만을 보고도 원래의 코드와 똑같은 동작을 수행할 것이 기대할 수 있습니다!그렇다면, 내부는 어떻게 구현됐을까요? 내부 구현을 함께 살펴보기 전에 객체 지향이 무엇인지 짧게 설명 드리고 가겠습니다! 💡객체 지향 프로그래밍이란?객체 지향은 '프로그램이'라는 거대한 로직을 '객체'라는 작은 역할로 나누고, 그 '객체'들끼리 상호 협력하여 데이터를 처리하는 방식을 말합니다!어젯밤에 저는 오렌지를 하나 먹었는데요! 이 오렌지가 집에 오기 까지의 과정을 '프로그램'이라고 보겠습니다.그리고, 지금부터 오렌지의 여정을 절차 지향적으로 설명해보겠습니다! 😎먼저 오렌지 나무를 볕 좋은 곳을 찾아서 심고, 거름도 포대를 찢어서 뿌리 주변에 뿌려주고, 해충도 유기농을 위해 핀셋으로 잡아주고.. 설명이 끝도 없이 길어집니다!그렇다면 이번엔 오렌지의 여정을 객체 지향적으로 설명해볼까요?오렌지를 농부가 '재배'하고, 운송 회사가 '운송'하고, 마트에서 '판매'되어 저의 집까지 왔습니다!어떤가요? 훨씬 설명이 쉽고 이해하기 좋지 않은가요? 오렌지가 어떻게 재배되었는지, 운송되었는지, 판매되었는지 우리는 구체적으로 알 필요가 없습니다! 궁금하지도 않고요!이렇게 내부 구현을 숨기고, 역할 만을 외부에 공개하여 코드의 가독성을 올리고 협업을 용이하게 하는 것이 객체 지향의 장점입니다!이는 개체 지향의 단편적인 장점입니다! 더 많은 장점이 있지만, 지금은 클린코딩과 관련하여 추상화와 캡슐화로 인한 장점 만을 이야기하고 넘어가겠습니다! 😭😭 💡도메인 선정하기!  자! 이제 다시 과제로 넘어와 보겠습니다~ 위에서 객체 지향에서 중요한 것은 역할과 협력이라고 했습니다!우리는 요구 사항을 잘 읽고 작은 역할을 찾고 그 역할을 수행할 주인공(도메인)을 선정해야 합니다. 😎사용자로부터 숫자를 하나 입력 받는다.해당 숫자만큼 주사위를 던져, 각 숫자가 몇 번 나왔는지 알려준다. -> 핵심 로직!!저는 핵심 로직에서 두 가지 역할을 찾았습니다! 하나는 무작위의 수를 생성하는 것, 다른 하나는 생성된 수를 각각 세는 것입니다.그리고, 발견한 역할을 바탕으로 이를 수행할 두 가지 도메인을 만들었습니다.무작위 수를 생성하는 🎲주사위(Dice)와 이를 기록해주는 📃노트(Note)입니다!그렇다면, 이 둘을 재빠르게 설계해 볼까요?abstract public class Dice { private final int faces; protected Dice(int faces) { this.faces = faces; } protected int getFaces() { return this.faces; } abstract int throwDice(); } public interface Note { void record(Integer number); void printTheResult(); }다양한 경험을 위해, 저는 주사위는 추상 클래스로 노트는 인터페이스로 만들었습니다!Dice의 throwDice()는 주사위를 굴리는 행위를 나타내며 무작위 수를 생성합니다!Note의 record()는 입력되는 수를 기록하고 기록된 수는 printTheResult()를 통해 출력할 예정입니다!이렇게, 추상 클래스와 인터페이스로 만드는 이유는 해당 동작을 수행할 수 있다면 그게 무엇이든 역할을 대체할 수 있게 하기 위함입니다! 숫자를 기록하고 출력할 수 있다면 메모지던, 스케치북이던, 스마트폰이던 상관이 없습니다!이제 이 둘을 구현해보겠습니다!public class UnknownDice extends Dice { private UnknownDice(int faces) { super(faces); } public static UnknownDice decideFaces(int faces) { return new UnknownDice(faces); } @Override public int throwDice() { return (int) (Math.random() * super.getFaces()) + 1; } } import java.util.HashMap; import java.util.Map; public class MemoPad implements Note { private final Map<Integer, Integer> page = new HashMap<>(); @Override public void record(Integer number) { page.put(number, page.getOrDefault(number, 0) + 1); } @Override public void printTheResult() { for(Map.Entry<Integer, Integer> number : page.entrySet()){ System.out.printf("%d은(는) %d번 나왔습니다.\n", number.getKey(), number.getValue()); } } }이렇게, 구현이 끝이 났습니다! 그런데, 이럴 수가! 여전히 문제가 있습니다. 도메인을 구현한 것 만으로는 로직을 수행할 수가 없습니다..! 😥바로, 주사위와 노트를 어떻게 사용할 것인지 맥락(컨텍스트)이 없기 때문입니다! 💡컨텍스트 만들기!주사위는 무작위 수를 생성하고! 노트는 기록을 합니다! 제가 생성한 도메인은 자신의 역할을 잘 수행합니다!그러나 노트는 숫자라면 무엇이든 잘 기록할 수 있습니다! 그게 꼭 주사위의 숫자가 아니어도 상관이 없습니다.그렇기에, 우리는 맥락(컨텍스트)이 필요한 것입니다. 도메인을 연결하여 의미가 있는 역할을 수행하게 하는 것이죠!그렇게 저는 딜러(Dealer)라는 새로운 객체를 만들었습니다! 요청을 받아 주사위를 굴리는 게 게임 같았거든요..!public class Dealer { private final Dice dice; private final Note note; private Dealer(Dice dice, Note note) { this.dice = dice; this.note = note; } public static Dealer playWith(Dice dice, Note note) { return new Dealer(dice, note); } public void rollDiceMultipleTimes(int numberOfRoll) { for (int i=0; i<numberOfRoll; i++) { note.record(dice.throwDice()); } } public void tellTheResult() { note.printTheResult(); } }딜러의 역할은 게임의 진행입니다! 사용자에게 요청 받은 숫자만큼 주사위를 굴려주고! 노트에 결과를 전달하고 기록된 결과를 사용자에게 알려주는 역할을 수행합니다! 😃주사위와 노트는 딜러의 게임 진행이라는 맥락(컨텍스트) 아래에서 자신들의 역할을 수행합니다! 어떤가요? 객체들이 서로 협업 하며 역할을 잘 수행하여 로직을 수행하고 있습니다!또한, 흥미로운 점은 딜러는 주사위와 노트가 자신의 역할만 잘 수행할 수 있다면(인터페이스를 충실히 구현했다면) 얼마든지 다른 주사위나 노트로 바꿀 수 있습니다! 사기를 칠 지도 모르겠군요! 😜 💡정리하며...자, 이제 클린코딩을 수행한 코드를 다시 보겠습니다! 현재의 내부 구현은 모두 알지만, 구현체인 주사위와 노트는 언제든지 바뀔 수 있습니다!그러나, 우리는 주사위와 노트가 자신의 역할만 잘 수행할 수 있다면, 그것이 바뀌어도 상관이 없다는 사실도 알고 있습니다!이것이 객체 지향이 주는 다형성이라는 장점입니다! 글이 너무 길어져서 짧게 설명하는 점 죄송합니다...😭public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); Dice luckyDice = UnknownDice.decideFaces(6); Note memoPad = new MemoPad(); Dealer dealer = Dealer.playWith(luckyDice, memoPad); System.out.print("숫자를 입력하세요 : "); dealer.rollDiceMultipleTimes(scanner.nextInt()); dealer.tellTheResult(); } }객체 지향 정말 매력적이지 않은가요? 책을 통해 이론으로만 배운 객체 지향을 직접 설계부터 구현하며 쓴 저의 긴 기록을 지금까지 읽어주셔서 감사드리며, 객체 지향을 모르시던 분들께 조금이라도 도움이 되었으면 합니다!사실.. SOILD부터 대뜸 외우라고 하면, 어렵습니다 객체 지향..남은 스터디 기간도 다들 즐거운 코딩하시길 바라겠습니다! 🙇‍♂️

백엔드객체지향클린코딩스프링부트인프런워밍업클럽스터디도메인컨텍스트추상화캡슐화

gotjd9773

[인프런 워밍업 클럽 스터디 2기 백엔드] 2주차 발자국

개요2주차 종료!Readable Code: 읽기 좋은 코드를 작성하는 사고법 을 완강했다.2주차 공부한 내용목요일에 Readable Code 강의를 완강하고, 금요일 부터는 Practical Testing 강의를 수강 시작했다. 배운 것들1. 일급 컬렉션일급 컬렉션이란 걸 처음 알게 되었다.일급 시민과 컬렉션(List, Set, Map)이 합쳐진 개념이다.컬렉션을 가공하는 로직을 캡슐화할 수 있는 장점이 있다.처음 접하는 개념이라 코드로 적용하는 하는 부분에서 어려움을 느꼈다.그렇지만, 잘만 사용하면 엄청 유용한 기법이라는 생각이 든다. 2. supports()이 메서드를 Spring Security 학습하면서 많이 봤었다.그 때는 이게 왜 필요하지 했었는데, 강의를 보면서 궁금증이 해소되었던 것 같다.다형성, 객체지향에 대해서 좀 더 가까워진 느낌? 3. 주석을 어떨 때 써야하는지주석은 웬만하면 사용하지 않는 편이 좋다고 생각했다.하지만, "코드에 히스토리, 개발자의 의도를 전부 녹일 수 없을 때"에는 주석을 써야 한다는 걸 배웠다. 4. 메서드 배치 순서이거 진짜 유용했다.메서드를 어떤 기준으로 배치해야 하는지 고민이 많았었는데,덕분에 기준을 세울 수 있었다. 5. sonarlint정적 코드 분석 도구로, 인텔리제이에서 플러그인 형태로 사용 가능하다.앞으로 Stack 과 Queue 를 쓸 일이 있을 때는 무조건 Deque을 사용할 거다.sonarlint가 Deque을 사용하라고 추천해줬음. 미션이번 주차에는 Day.7 미션이 있었다. Day.7 미션 - 스터디 카페 프로젝트 리팩토링 실습하기강의에서 배운 것을 토대로 실제로 리팩토링하는 실습이었다.추상화 레벨, 일급 컬렉션, DIP, SRP 를 염두에두고 리팩토링 했다.생각보다 쉽지 않았다.스스로 해보고 답지(강의)를 보니 갈 길이 멀어보인다.나의 가장 큰 문제점은 주어진 틀에서만 해결하려고 한다는 점이다.그래서 새로운 객체를 만든다든지, 기존의 if 문들을 다른 구조로 변경하는 것에 두려움을 느끼는 것 같다.문제를 마주할 때 넓게 보는 연습이 필요한 것 같다. 차분히.리팩토링을 더 잘하기 위해서 섹션 8 - 기억하면 좋은 조언들 - 능동적 읽기 강의 내용을 적용하면 좋을 듯 하다. 공백으로 단락 구분하면서 읽기메서드와 객체로 추상화하면서 읽기주석으로 이해한 내용 표기하면서 읽기Day.7 미션을 수행할 때 위의 조언들을 적용했더라면 좀 더 나은 결과물을 얻을 수 있었을 것 같다. 마무리2주 동안 Readable Code 보면서 많이 배웠다.배운 내용들을 체화시키려면 좀 더 노력해야 할 것이다.일단은 3주차부터 테스트 코드 진도를 나가야하니 테스트 코드에 신경을 쓰도록 하고테스트 코드를 빨리 끝낼 수 있다면, Readable Code의 내용을 복습하면 좋겠다. 

백엔드읽기좋은코드클린코드워밍업클럽객체지향추상화

gotjd9773

[인프런 워밍업 클럽 스터디 2기 백엔드] 1주차 발자국

개요인프런 워밍업 스터디 클럽 2기 백엔드(읽기 좋은 코드, 테스트 코드) 9/27 금요일 시작되었다.스터디 주제는 박우빈님의 강의인Readable Code: 읽기 좋은 코드를 작성하는 사고법Practical Testing: 실용적인 테스트 가이드이다.1 ~ 2주차에는 읽기 좋은 코드 강의를 수강하고, 3 ~ 4주차에는 테스트 강의를 수강 하게 되는데,이번 글은 1주차, 읽기 좋은 코드 강의를 수강하고 배운 것들을 정리해 보려고 한다. 1주차 공부한 내용발자국 작성을 위해 표로 정리했다. 생각보다 번거로운 작업이었다. 강의 하나 듣고 로그 기록하고...권장 진도표에 따르면, 섹션 5까지 1주차에 수강 하도록 되어 있는데,이번 주는 섹션 4까지가 한계였다. 생각보다 내용이 많았고, 한 번에 이해되지 않는 내용들은 복습해야 했다. 해결한 것 - 인텔리제이 한글 깨짐 이슈처음부터 난관을 겪었다.인텔리제이 한글 깨짐 이슈...강의에서는 지뢰찾기 게임을 콘솔 프로그램으로 구현이 되어 있고,콘솔에 출력되는 내용이 한글, 지뢰 모양, 네모박스 모양, 깃발 모양 등이 있는데,전부 깨져서 출력되었다.구글링을 통해 해볼 수 있는 것들은 다 해봤던 것 같다.그래도 안 되서 포기하려던 찰나, 유튜브에는 관련 내용이 없는지 살펴보았다.결국, 해결! (유튜브 만세!)Project Structure 에서 SDK와 Language level 을 17 버전으로 동일하게 맞춰주니 한글 깨짐 이슈가 해결되었다.기존에는 SDK는 21 버전이 적용되어 있었다.버전이 제대로 맞지 않으면 한글 깨짐 이슈가 일어나는구나를 깨달았다.  이미 알고 있던 것들1. 이름 짓기 이름을 잘 지어야 한 다는 것은 알고 있었다. 어려워서 그렇지...2. 메서드 추출 이거는 코드짤 때 열심히 활용하고 있다.Ctrl + Alt + M추가적으로 메서드로 추출할 때 주의사항을 설명해주셨는데 도움이 많이 되었다.메서드를 추출할 때마다 항상 주의사항 4가지를 점검해야겠다. 메서드 추출시 주의사항 4가지메서드명은 적절한가?혹시 메서드가 두 가지 일을 하고 있지는 않은가?파라미터는 적절한가?반환타입은 적절한가?왜 이 4가지를 주의 해야 하는지는 강의를 통해 확인하시라. 배운 것들1. 추상화 레벨 "하나의 세계 안에서는 추상화 레벨이 동등해야 한다." - 박우빈추상화 레벨을 동등하게 맞춰야 한다는 개념은 처음 알게 되었다.이해를 돕기 위해 들어주신 서점 비유가 와 닿았다.추상화 레벨을 맞추지 않는 것은 서점 주인이 책들 사이에 표지, 제목도 없는 종이 모음을 책 이랍시고 내놓는 것과 같다.서점에 들어갔는데 종이 모음을 보게 되면 많이 당황스러울 것 같긴 하다. ㅋㅋㅋ나는 이런 서점 주인이 되어서는 안되겠다고 다짐했다. 2. Early returnEarly return 이라는 용어는 처음 접했다.이거를 무의식적으로, 이런 용어가 있다는 것도 모른채 사용해왔던 것 같다.Early return을 사용하면 뇌 메모리의 부하를 줄일 수 있겠구나를 깨달았다. 3. orElse, orElseGet, orElseThrow의 차이자바 8 문법을 배울 때 한 번씩 사용해본 메서드들인데 이번에 제대로 정리할 수 있었다. 4. getter 사용 자제setter를 사용하지 말라는 것은 들어봤지만, getter도 사용 하지 않는 것이 좋다는 것은 처음 들었다.어쩔 수 없을 때는 getter를 써야 겠지만, 클래스를 설계할 때 무지성으로 getter를 선언하는 행동은 지양해야겠다. 미션인프런 워밍업 클럽 스터디는 강의 수강 뿐만 아니라 미션 수행도 해야 한다.이번 1주차에는 Day 2, Day 4 미션이 있었다. Day 2 미션 - 추상과 구체 예시일상 생활에서 추상과 구체에 대한 예시를 찾는 미션이었다.요즘 관심 있는 주제에서 예시를 찾으려고 했다.요즘 관심 있는 주제는 주식, 운동, 스타크래프트인데,운동 분야가 가장 설명하기 쉬워 보였고, 모든 사람이 알만한 스쿼트에 대해서 구체적으로 설명했다. Day 2 미션 답변 - 스쿼트를 구체 레벨에서 표현한다면?발을 어깨너비로 벌리고 무게중심을 발뒤꿈치에 두면서 무릎을 굽힌다.숨을 참고 복압을 유지한 상태로 엉덩이를 뒤로 밀며 허벅지가 지면과 평행해질 때까지 내려간다.하체 근육을 사용해 다시 상체를 들어 올린다.동작이 끝난 후 숨을 내쉰다. Day 4 미션 - 메서드 리팩토링 실습, SOLID 개념을 자신 만의 언어로1. 메서드 리팩터링 실습 public boolean validateOrder(Order order) { if (order.getItems().size() == 0) { log.info("주문 항목이 없습니다."); return false; } else { if (order.getTotalPrice() > 0) { if (!order.hasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } else { return true; } } else if (!(order.getTotalPrice() > 0)) { log.info("올바르지 않은 총 가격입니다."); return false; } } return true; }위의 메서드를 읽기 좋은 코드로 리팩토링 해보는 미션이었다.Early return, 추상화 레벨을 맞춰주기, 공백 라인, 부정어, 이름 짓기에 주의하며 리팩터링을 수행했다.아래 코드가 리팩터링을 거친 코드public boolean validateOrder(Order order) { if (order.getItems().isEmpty()) { log.info("주문 항목이 없습니다."); return false; } if (order.isTotalPriceInvalid()) { log.info("올바르지 않은 총 가격입니다."); return false; } if (order.hasNoCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } return true; }2. SOLID 개념을 자신만의 언어로견고한 객체지향 프로그램을 위해 제시된 개념인 SOLID를 자신만의 언어로 설명하는 미션이었다.글이 너무 길어지니까 이거는 생략하겠다. 아쉬웠던 점읽기 좋은 코드로 리팩터링하기 위해서는 테스트 코드가 꼭 필요하다.원래라면 테스트 코드를 짰을 테지만, 시간이 없었다는 핑계로 테스트 코드는 건너 뛰었다.하지만, 테스트 코드 없는 리팩터링이 오히려 시간을 더 잡아먹을 수 있고, 훨씬 개발자를 불안하게 만드는 것 같다.3주차부터는 테스트 코드를 본격적으로 배우게 될텐데 기대된다. 마무리100점 짜리는 아니었지만, 내 상황에서 최선을 다한 한 주였다.미션을 제 때 낼 수 있어서 기쁘다.2주차도 잘해보자. 

백엔드읽기좋은코드클린코드워밍업클럽객체지향추상화

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

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

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

<도서정리> 객체지향의 사실과 오해

객체지향이란. 흔히 객체지향을 세상을 객체들의 모임으로 보고, 객체들이 상호작용하는 것을 소프트웨어 세계에 모방하는 방식으로 소개한다. 하지만, 객체지향은 실세계를 모방하는 것이 아닌 새로운 세계를 창조하는 것이다. 현실 속에서 수동적인 존재가 소프트웨어 객체로서는 능동적인 객체가 된다. 사물의 의인화가 이루어지며, 얼마든지 필요한 능력을 가질 수 있다. 객체 상태와 행동의 명명 또한 창조의 영역이다.   객체란. 객체들 간에는 특정한 목표를 위해 협력하며, 객체는 협력 속에서 맡은 역할에 책임을 진다. 협력은 연쇄적인 요청과 응답으로 구성되어있다. 객체 특징재활용성 - 여러 객체가 동일한 역할을 수행할 수 있다.활용성 - 역할을 대체가능성을 의미한다.다형성 - 책임을 수행하는 방법은 자율적으로 선택할 수 있으며, 다양한 방식으로 요청 수행이 가능하다.한 객체가 동시에 여러 가지 역할을 수행할 수 있다. 다양한 곳에 참여한다.(참조되어 사용된다)   협력. 시너지; 전체는 부분의 합보다 크다. 성공적인 협력을 위해서는 적절한 단위적인 책임을 부여하는 것이 중요하다.  객체는 충분히 협력적이어야한다. 다른 객체에게 적극적으로 도움을 요청할 정도로 열린 마음을 지녀야 하며, 모든 것을 스스로 해결하려는 전지전능한 객체는 복잡함에 의해 자멸한다. 객체는 자율성을 가진다.   객체의 자율성. 캡슐화 - 객체의 자율성은 객체의 내부와 외부를 명확하게 구분하는 것으로부터 나온다. 객체의 사적인 부분은 객체 스스로 관리하고, 외부에서 일체 간섭할 수 없도록 차단해야한다. 객체의 외부에서는 접근이 허락된 수단을 통해서만 객체와 의사소통해야한다. 무엇을 수행하는지는 알 수 있지만 어떻게 수행하는지에 대해서는 알 수 없다. 객체는 상태와 행동을 지닌다.  객체는 자신의 상태를 직접관리하고 상태를 기반으로 스스로 판단하고 행동하는 자율적인 존재이다. 객체의 행동이 상태를 결정한다. 객체의 행동은 객체가 협력에 참여하는 방법이며, 객체의 적합성은 객체의 행동으로부터 결정된다. 책임주도설계 - 객체가 어떤 책임을 갖는가가 설계를 주도한다. interface를 통해 제공가능한 정보와 서비스를 알려주는 동시에 캡슐화를 수행할 수 있다 인터페이스가 변경되지 않는다면, 내부 방식을 변경하더라도 그것이 영향을 끼치지 않는다. 동일한 인터페이스에 의존한다면, 어떠한 구현체와도 상호작용을 할 수 있다.   객체와 추상화. 추상화를 통해 현실세계의 복잡성을 극복할 수 있으며, 그를 통해 사물의 본질에 접근할 수 있다. 추상화 과정 - 유사성, 공통점을 통해 분류한다. 객체의 추상화는 분류(classification)를 통해 이루어진다. 객체지향은 객체를 지향하는 것이지 클래스를 지향하는 것이 아니다 일반화/특수화 서브타입은 슈퍼타입(본질)을 대체할 수 있어야한다. 슈퍼타입의 행동은 서브타입에 자동으로 상속된다. 타입 타입은 추상화이다. 타입은 동적인 상태 변경을 단순화하는 정적 객체 특징에 집중한다. 클래스는 타입을 구현하는 도구이다. 추상화를 통해 다양한 객체들이 조립되어 역할을 수행할 수 있다면 협력이 유연해지며 객체들의 재사용성이 높아진다.   메세징 메세징(요청)은 객체에게 접근할 수 있는 유일한 방법이다. 어떻게 할지는 객체 스스로가 결정하며, 메세지로는 무엇을 할지만을 요청한다. 요청을 받은 후 객체는 적절한 메서드를 선택하여(다형성) 요청을 수행할 것이다.  객체지향은 객체들이 주고받는 메세지들로 구성된다. 클래스는 객체들의 속성과 행위를 담는 틀일 뿐이며, 객체의 속성과 행위가 중심이 되어야한다. 또한 객체지향은 객체를 넘어서 객체들 간의 커뮤니케이션에 초점을 맞출 때 이루어진다. 메세징을 이용한 객체지향 객체가 책임을 완수하기 위해, 다른 객체의 도움이 필요하다고 판단되면도움 요청 메세지를 결정한다. 메세지를 결정한 후 메세지를 수행하기에 적합한 객체를 선택한다. -> 메세지가 수신자의 책임을 결정한다.   

도서객체지향협력역할책임추상화다형성캡슐화

채널톡 아이콘