1. 애플리케이션 설계란?
- 구성 요소간 유기적 관계를 표현
- 요구사항 해결을 위한 계획 및 과정
- 텍스트, 그림, 다이어그램 등으로 표현
- 애플리케이션은 일단 구현되고 나면 변경하는데 큰 비용이 듦
- 잘 설계된 어플리케이션은 유지 보수비를 줄여줌.
- 성능, 보안, 안정성 등 측면에서 많은 이점이 있음
- 앱의 경우 미래에 나오는 플랫폼 호환성, 정책 등으로 끊임없는 변화에 대한 대응이 필요함
2. 애플리케이션의 설계 원칙
- 로버트 C. 마틴의 객체지향 프로그래밍 및 설계에 대한 SOLID 원칙
1. 단일 책임 원칙(Single Responsibility Principle)
- 모든 클래스는 하나의 책임만 가져야하며, 클래스는 그 책임을 완전히 캡슐화해야 함.
- 어떤 클래스나 모듈 또는 매서드가 단 하나의 기능만을 가져야 한다는 뜻.
- 이것이 클래스를 더욱 튼튼하게 만든다.
2. 개방-폐쇄 원칙(Open Closed Principle)
- 소프트웨어가 확장에 대해서는 열려있고, 수정에 대해서는 닫혀있어야 한다.
- 시스템 구조를 옳바르게 구성하여 변경 사항이 발생하더라도 다른 코드나 모듈에 영향이 없도록 함.
- 이를 통해 새기능 추가 및 유지보수에 용이하게 된다.
3. 리스코프 치환 원칙(Liskov Subsitution Principle)
- 클래스 S가 클래스 T의 자식 클래스라면 별다른 변경 없이 부모 클래스 T를 자식 클래스 S로 치환할 수 있어야 함
- 다운 캐스팅된 인스턴스가 논리적으로 역할에 있어서 문제가 되면 아니됨.
- 아래 사항을 강제한다.
- 하위 클래스에서 메서드 파라미터의 반공변성
- 하위 클래스에서 반환형의 공변성
- 하위 클래스에서 메서드는 상위 클래스 메서드에서 던져진 예외 사항을 제외하고 새로운 예외 사항을 던지면 안됨.
- 하위 클래스에서 선행 조건은 강화될 수 없음
- 하위 클래스에서 후행 조건은 약화될 수 없음
- 하위형에서 상위형 불변 조건은 반드시 유지되어야 함
open class A{}
open class B: A() {}
open class C: B() {}
- 위 같은 클래스가 있을 때
fun main() { val list:List<B> = listOf<B>() val list2:List<B> = listOf<C>() // 공변성 val list3:List<B> = listOf<A>() // 반공변성 (error!) // 불변성은 list2, list3 둘다 허용하지 않는 것. }
4. 인터페이스 분리 원칙(Interface Segregation Principle)
- 어떠한 클래스가 자신이 이용하지 않는 메서드에 의존하지 않아야 한다는 원칙
- 큰 덩어리 인터페이스를 작은 단위로 분리
- 작은 단위 인터페이스를 역할 인터페이스 라고 부른다.
- 시스템의 내부 의존성을 약화시켜 리팩토링, 수정, 재배포를 용이하게 할 수 있다.
abstract class Bird{
abstract fun fly()
abstract fun cry()
}
class Eagle : Bird(){
override fun fly() {
}
override fun cry() {
}
}
- 새는 울고, 난다.
- 독수리도 울고, 난다.
- 그런데 펭귄은?
- 날지 못한다.. 이는 ISP 원칙에 위배될 수 있다.
abstract class Bird{
abstract fun cry()
}
interface Flyable{
fun fly()
}
class Eagle : Bird(), Flyable{
override fun fly() {
}
override fun cry() {
}
}
class Penguin : Bird(){
override fun cry() {
}
}
- 날기, 울기 기능을 나눠 구현
5. 의존 역전 원칙(Dependency Inversion Principle)
- 모듈들을 분리하는 특정 형식을 지칭
- 상위 계층이 하위 계층에 의존하는 전통적인 의존 관계를 역전 시킨다.
- 상위 계층이 하위 계층의 구현으로 부터 독립되게 함.
- 상위 모듈은 하위 모듈에 의존해서는 안됨. 상위 모듈 하위 모듈 모두 추상화에 의존해야함
- 추상화는 세부 사항에 의존해서는 안됨. 세부 사항이 추상화에 의존해야함 (상위와 하위 객체 모두 동일한 추상화에 의존해야함)
안드로이드 기기 -> 전용 충전기
- 기기 마다 충전기가 다를 수 있고 A 기기 충전기로 B 기기를 충전하지 못하는 상황 발생 가능.
- 즉, 전용 충전기에 강한 의존성을 갖는다.
안드로이드 기기 → C-Type 충전기 ← (S 제조사 충전기, L 제조사 충전기, X 제조사 충전기)
- USB-C 규격을 가지는 충전기와 모두 호환 (interface)
- 특정 충전기가 아니라 type-C라는 인터페이스에 의존하게 된다. (의존성 역전: 제조사가 인터페이스에 의존하게됨)
해당 글은 '아키텍처를 알아야 앱 개발이 보인다' 를 공부하며 요약 정리한 글 입니다.
'Android > 클린 아키텍처' 카테고리의 다른 글
[Clean Architecture] 06-Dagger2 란? (+ Adnroid 적용 샘플) (0) | 2021.07.20 |
---|---|
[Clean Architecture] 05-의존성 주입(DI)과 그 필요성 (0) | 2021.07.19 |
[Clean Architecture] 04-안드로이드 앱 설계 패턴 (MVC, MVP, MVVM) (0) | 2021.07.19 |
[Clean Architecture] 03-안드로이드 권장 애플리케이션 설계 원칙 (2) | 2021.07.17 |
[Clean Architecture] 02-안드로이드 클린 아키텍처 (1) | 2021.07.16 |