1. - 화면 출력 (View 조작)
- 입력 (User Action)
- Logic 들이 커지고 복잡해짐에 따라 의존성은 더 강해지고, 유지보수는 더 어려워짐
(비즈니스 로직)
(프리젠테이션 로직)
2. - MVC 패턴
- Controller : 사용자의 입력(Action)을 받고 처리하는 부분
- Controller가 n개의 View를 알고 있고 선택 하기 때문에 Controller 소스가 비대 해질 수 있다.
- Model 과 View 사이의 의존성이 높아 유지보수가 어렵다.
3. - MVP 패턴
- Presenter : View에서 요청한 정보로 Model을 가공하여 View에 전달 해 주는 역할을 한다.
- Presenter를 통해야 하기 때문에 View와 Model 사이에서 의존성이 없다.
- 하지만 View, Presenter는 서로를 알고 있다. (서로를 Interface로 정의 하여 알고 있다)
- (참조변수로 갖고 있다고 생각하면 됨)(1:1 관계)
- 따라서 View와 Presenter 사이의 의존성이 강하다.
- Presenter : UserAction 이벤트 로직(화면 입력/ 하지만 View에서 호출됨)
- View : 화면 출력
4. - MVVM 패턴
- ViewModel : View를 표현 해주기 위한 Model 이다.
- ViewModel은 View의 상태와 View에 대한 Action을 구현 합니다.
- View는 ViewModel을 알고 있지만 ViewModel은 View를 모른다.
- 따라서 1:n 가능 하다.
5. - 하지만
- 안드로이드에서는 애니메이션, 액티비티 전환, Context를 필요로 하는 로직 등
- 데이터 바인딩으로 구현하기 어려운 항목이 있습니다.
- 이 경우 뷰(xml) 와 뷰모델이 곧바로 통신 하지 않고
- 뷰컨트롤러(Activity, Fragment)(일종의 뷰)를 통하게 하여 해결 할 수 있습니다.
- 단점은 데이터 바인딩을 처리는 부분이 블랙박스화 되어 가독성이 낮고 디버깅 하기 어렵습니다.
- Observer 패턴
- LiveData.setValue()- (양방향 데이터 바인딩)
- Callback 패턴
10. Dao
- Room 예제에서는
- AsyncTask로 CRUD 수행
- AsyncTask의 Worker 스레드가 많아져 스레드 관리 힘듬
- onPostExecute(Main 스레드)로는 View 를 참조 할 수 없음
- AsyncTask().execute().get()는 blocking 걸림
- AsyncTask의 보일러 플레이트 코드가 많아져 가독성도 떨어짐
- ==> AppExecutor 로 스레드 분리/관리
홍채 수동 분석 인터페이스
홍채 자동 분석 인터페이스
…….
또는
홍채 분석 인터페이스
안저 분석 인터페이스
Local, Remote 분기 로직
- 데이터 read/write
- Map-Reduce 로직(데이터 가공)
- 스레드 분리 로직(AppExecutor)
Retrofit
유스케이스 인터페이스(오퍼레이션 집합)
(비즈니스 로직)
…….
또는
UserCreatorUseCase
ManagerCreatorUseCase
12. - DB에서 데이터를 읽어
와서(Worker 스레드), UI(Main
스레드)를 변경 해줘야 하는데
- 어떻게 스레드를 분리 시키죠?
- DB에서 데이터를 읽어오는
작업은 Worker 스레드
- UI를 변경 해주는 작업은 Main
스레드
13. - TodoDatabase,
- TasksRepository,
- TasksLocalDataSource,
- TaskRemoteDataSource는 누가 생성 해주나요?
- 어떠한 특정 로직에 의해서 생성 될 필요 없는 객체들 이다.
- 어플리케이션이 돌아가만 가게 되면 항상 필요한 객체들 이다.
- 그렇다면 어플리케이션이 시작 되는 순간 생성을 다 해주면 되지 않을까?
- 그리고 추후에(또는 테스트시에) 생성 시점에서 필요한 객체로만 변경(다형성)
- 해주면 되지 않을까?
14. Main 영역 Application 영역
- 어플리케이션이 동작
하도록 각 객체들을
연결해 주는 Main 영역
- 객체 생성 로직(생성)
- 고수준 정책 및 저수준
구현을 포함한
어플리케이션 영역
- 런타임 로직(사용)
- 객체 생성 로직을 분리 하므로써 필요에 따라 환경에 따라 객체를
- 교체 하여 생성 하기 쉬움
- 또한 변화가 자주 발생하는 객체를 새로운 객체로 확장 하기 좋음
- Application 영역에서 객체 생성 로직이 없어 가독성이 좋음
- 객체 교체가 편해 테스트 시 쉽게 페이크 객체(Mock) 으로도 교체
하여 테스트 가능
- 생성과 사용을 분리 하는 방법
- 팩토리 패턴
- (객체가 생성되는 시점을
- 어플리케이션이 결정 할 때)
- 서비스 로케이터
- (생성은 메인 영역, 주입은
어플리케이션 영역)
- DI(Dependency Injection)
- (생성, 주입 모두 메인 영역
- (어플리케이션 입장에서 외부
영역))
15. - 객체가 생성 되는 시점을 뷰(어플리케이션
영역이 알고 결정 함(액티비티 –onCreate))
- 따라서 팩토리 패턴이 사용
- (네이밍에 디자인 패턴 이름 이나 설계 패턴
이름을 넣어서 개발자가 의도를 파악 할 수
있게 함)
16. - ToDoDatabase
- TasksRepository
- TasksLocalDataSource
- TasksRemoteDataSource 모두
- ViewModelFactory에 싱글턴 패턴(Lazy Initalization)으로 객체가 최초, 한번 생성 될
때 생성 됨
- 따라서 ViewModelFactory는 팩토리 패턴, 다른 객체들은 DI 라고 봐도 무방함.
- 이런 DI를 사용 하기 쉽도록 만들어 놓은 프레임워크 : Dagger(자바), Koin(코틀린)
- 스프링 프레임워크는 XML로 쉽게 DI를 하도록 만들어 놓은 유명한 DI 프레임 워크다.
- XML 로 DI 구현시 컴파일, 재배포 안해도 된다, 대신 오타가 발생 할수 있다.
17. - 데이터 암호화, 복호화는 언제 해줘야 할까?
- 디버깅 상황에서 UserId가 궁금해서 확이 해 봤다.
- 하지만 UserId는 내가 알아볼 수 없는 암호화 된
값으로 보인다.
- 그래서 UserId를 복호화 시켜야 겠다.
- 우선 UserId를 암호화, 복호화 시키기 위해서
- Encryption 객체에 인스턴스가 필요 하다.
- 또한 암호화, 복호화 메서드도 항상 UserId를 따라
다니며 호출 시켜줘야 한다.
- UserId와 암,복호화 객체는 의존성을 갖게 된다.
- 하지만 이런 UserId는 한,두 군데가 아니다.
- 갑자기 제품에 정책이 바뀌었다!
- UserId를 암호화 하지 말고 UserName을 암호화
해달라는 요구 사항 이다.
18.
19. - 데이터 암호화, 복호화는 언제 해줘야 할까요?
Dao Entity
setUserId
getUserId
OR- 핵심 로직(UI 로직, 비즈니스 로직
등)에는 암,복호화 로직이 없어 핵심
로직을 더럽히지 않는다.
AOP를 효과적으로 구현 할 수 있는 방법
- 프록시 패턴 (스프링 프레임워크에 경우 내부에서 프록시 패턴 으로 AOP를 지원)
- 데코레이터 패턴
- AspectJ (A.java -> (관심사 로직 추가) -> A.class)
횡단 관심사 분리(Cross Cutting Concern)
20. 유틸리티 클래스는?
• 개발에 필요한 유틸성 클래스는 메서드는 static으로 사용하고
• 인스턴스화를 막기위해서 abstract class 로 만들거나
• 생성자를 private으로 만들어 인스턴스화를 막는다.
• abstract class는 상속해서 인스턴스화 하라는 뜻으로 오해를 살수 있기 때문에 private
생성자가 더 좋은 방법 이라고 함.
21. 리팩토링 어떻게 해야 할까요?
(의미 있는 이름)
• 소스 코드는 카멜표기법 / 리소스는 스네이크 표기법
• 클래스, 변수는 명사 / 함수는 동사
• 클래스명과 함수명은 추상화 수준에 맞는 이름
• 설계 의도를 밝혀라 (디자인 패턴, 설계 패턴 이름에 반영)
• 매직넘버는 명명된 상수로 교체 한다.
22. 리팩토링 어떻게 해야 할까요?
(함수)
• 함수는 한가지 일만 해야 한다.
• 함수 호출 순서는 밑으로 내려 갈 수록 저차원 함수
• (위에서 아래로 코드가 읽히도록)
• 함수 인자는 적을 수록 좋다.
• (필요 한 경우 인자를 사용하지 않고 멤버변수로 승격)
• 플래그 인자는 되도록 피한다.
• (플래그 인자가 있다는 얘기는 일단 함수가 한가지 이상의 일을 한다.)
• 출력 인자는 되도록 피한다.
• 명령과 조회를 분리 한다.