ToC
모빌리티서비스
터틀봇 실습 준비로 리눅스 세팅 및 ip 세팅.
라즈베리파이 이미지 다운로드가 아주 오래걸리니 가이드를 미리 확인해보고 몰아서 다운받아놓은 후 진행할 것
알고리즘
동적 프로그래밍
피보나치 수열
재귀로 구현하는 피보나치 수열은 Θ(2^n/2)
의 시간복잡도를 갖는다. 이는 한 번 계산했던 값을 매번 다시 계산하기 때문이므로 한 번 계산한 값을 따로 기억하게 하면 Θ(n)
으로 줄일 수 있다.
최단경로
예를 들어 δ(s, v)
는 s에서 v로 가는 최단경로라고 하자. 그리고 이 경로상에는 u, t 등의 정점이 포함된다. 그러므로 다음과 같이 식을 다시 쓸 수 있다. w(x1, x2)
는 x1에서 x2로 연결된 단일 간선의 가중치를 나타낸다.
δ(s, v) = δ(s, t) + w(t, v) = δ(s, u) + w(u, t) + w(t, v)
위와 같은 식으로 모든 정점에서 다른 모든 정점까지의 최단경로를 알 수 있고, 이걸 기억해두면 된다. ?
소프트웨어분석및설계
- 파생 클래스: 상속 관계에서 상속을 받은 하위 클래스를 말함. 부모-자식 중 자식
- 추상 클래스: 생성자가 없고 객체를 생성할 수 없음. 하위 클래스의 아웃라인, 템플릿.
이진관계 예: 자신의 배우자를 p로 지정(setSpouse(*p)
)
- p가 현 배우자가 아닌지
- 현 배우자가 없는지
- p를 현 배우자로 지정
- p의 배우자를 자신으로 지정
- return
- 배우자가 있음
- 기존 배우자 데려옴
- 자신의 배우자 지움
- 기존 배우자의 배우자(자신) 지움
- 현 배우자가 없는지
- 배우자를 p로 지정
- 만약 현 배우자(p)가 존재한다면
- 현 배우자의 배우자를 자신으로 지정
- return
- 상태 다이어그램: 시스템의 변화를 모델링, 시간이 흐름에 따라 변화하는 객체의 값을 상태라 이름.
- 상태 다이어그램의 구현:
enum
으로 상태를 구분함. 상태 entry와 exit를 위한 helper 함수 추가, 이벤트 핸들러 추가. - Helper 함수:
onEntry()
함수는 특정 상태에 진입했을 때 객체가 수행할 액션의 순서를 정의함. - 상태 entry와 exit 관련 함수, helper는 시스템 본인에 의해 수행되므로 protected로 정의된다.
- 이벤트: 사용자 또는 외부 엔티티에 의해 발생하므로 public 함수로 정의됨
- 이벤트 핸들러: 발생한 이벤트와 현재 상태에 맞게 올바른 상태 전이를 발생시킴.
- 중첩 상태는 시험 범위에서 제외
- 상태 다이어그램의 구현:
- 컴포넌트 다이어그램
- Color Slide Bar 예제: 슬라이더 * 3, 패널 * 4, 라벨 * 3, 리스너 * 1로 구성된 컬러피커.
- 물리적인 실제 대상을 상정하고 구조를 만들기 때문에 설계 단계에서 하는 일이다.
- 반복을 통한 정제
- 전화기 다이얼 예제
- 눈으로 보이는 버튼을 누른다고 그 정보가 바로 스크린으로 가는 것이 아니다. 겉보기엔 그렇게 되는 것 같지만 논리적으로는 다이얼러를 거쳐서 전달된다. 물리 ≠ 논리
- 다이얼러가 중간에 끼어서 클래스 간의 소통을 관리하면 사용자가 어떤 버튼을 누르는지도 구분해서 전달하기 좋다.
- 처음부터 모든 것을 만들지 말고 핵심부터 하나씩 추가하라.
소프트웨어디자인패턴
- Flyweight 패턴
- 고유 객체와 공유 객체, 생산자. 많은 메모리를 요구하지만 공통적으로 사용되는 데이터를 공유 객체가 갖고, 생산자가 고유 객체와 공유 객체를 이용하여 하나의 완성된 오브젝트를 생산.
- 다른 것보다 훨씬 많은 메모리를 요구하지만, 많은 객체가 공유하는 데이터로 인해 메모리 사용량 증가 문제를 해결 -> 공유 데이터를 하나의 공유 객체로 이동하여 필요할 때마다 가져와서 씀.
- 참고: 인기도가 낮고 자주 쓰이지 않는다. 정말정말 이게 없으면 안 될 정도가 되어야 사용하는 패턴
- RAM 사용을 줄이는 것이 목적. 인스턴스를 공유해서 불필요핸
new
를 사용하지 않게 함 - 텍스트 에디터 예제
- 각 문자의 폰트, 사이즈, 색상 등을 공유 데이터로 사용.
- 주의: 공유 데이터를 변경하면 해당 데이터를 공유한 모든 곳에 영향을 주기 때문에 꼭 공유해야만 하는 것이 무엇인지 잘 정하는 게 중요함.
- 시퀀스 다이어그램 그릴 때 주의: 비슷한 작업을 여러 번 할 때, 각각의 작업에 대해 모두 그리기. 하나만 그리고 까먹으면 안 된다.
- intrinsic(본질적인): 상태에 의존하지 않고, 공유되어야 하는 정보 + extrinsic(부대적인): 상태에 따라 바뀌고 공유할 수 없는 정보
- 공유 객체로 관리되고 있는 인스턴스는 가비지 콜렉션이 안 된다 -> 메모리가 부족해졌을 때 멋대로 사라질 일이 없다.
- 메모리 이외의 리소스 개선
- 시간:
new
를 적게 사용하므로 프로그램의 속도 높일 수 있음.
- 시간:
- Command 패턴
- 객체의 행위를 클래스로 만들어 캡슐화. 객체 간의 의존성을 제거하고 시스템에 확장성과 유연성 부여.
- 관심사 분리의 원칙 기반 프로그래밍
- 버튼 클래스 예제
- OK, 취소, 수락, 프린트 등 다양한 버튼을 만들어야 한다. 이들을 모두 버튼 클래스의 자식으로 만들면 부모 클래스의 의존성이 증가하고, 여러 위치에서 호출되는 일부 작업이 존재할 수 있고, 중복된 코드가 사용됨.
- 레스토랑 주문 예시: 손님은 밥이 맛있기만 하면 되지 요리를 어떻게 하는지는 관심 없다. 주문을 주방에 전달하고 그에 상응하는 동작을 응답받는 것이 이 패턴의 예시에 해당함.
- mp3 플레이어 예제: 버튼 하나로 많은 작업을 처리해야 한다. 요소가 추가될 때마다 의존도가 높아져 구현이 번거롭기 때문에 수행해야 하는 행위를 캡슐화한다.
- 버튼에 각 커맨드를
setter
로 지정하고, 버튼을 누르면 지정된 커맨드가 실행된다. - 각 행위에 대해 클래스가 만들어져야 버튼에 지정할 수 있다.
- 버튼에 각 커맨드를
- mp3 플레이어 예제의 UML을 그리는 게 과제다. 기말고사에서 물어볼 것이기 때문이다. 비슷하지만 한 번도 본 적이 없는 코드를 줄 테니 그것을 보고 관계를 파악하여 그리면 된다. 말만 하면 연습 안 할 것 같아서 과제로 낸다.
- 커맨드, 구체커맨드, 인보커, 리시버. 커맨드는 구현되어야 할 인터페이스, 구체커맨드는 실제 커맨드, 인보커는 기능을 요청하는 호출자(버튼), 리시버는 요청받은 동작을 수행하는 실행자(mp3 플레이어).
- 시퀀스 다이어그램은 호출 스택을 따라 그리면 된다.
- invoker와 리시버, 커맨드가 따로 캡슐화되어서 결합도가 낮아진다는 장점이 있지만 커맨드의 개수만큼 클래스를 만들어야 하는 단점이 있다.
- 되돌릴 수 있는 작업을 구현하려고 할 때 사용하지만, 기록을 따로 구현해야 하고, 앱의 상태가 비공개라면 상태를 저장하는 게 쉽지 않고, 백업이 메모리를 잡아먹을 수 있다.