
Single Responsibility Principle
클래스나 모듈은 하나의 책임만 가져야하며, 오직 하나의 이유로만 변경되야 한다.
복잡성을 줄이기 위한 핵심 원칙으로, 클래스가 여러가지 일을 할 때 발생할 수 있는 변경의 부담을 줄임
한 가지 목적에 집중된 클래스는 이해하기 쉽고, 변경이 필요할 때 변경의 영향을 최소화할 수 있음
안드로이드 앱의 구성요소들이 점점 무거워지면, 화면 전환 시 느려지는 문제, 메모리 누수, 뷰 상태 저장 문제 등이 발생할 수 있음
단일 책임 원칙 적용 전


Open/Closed Principle
확장에 개방적이고, 수정에는 폐쇄적이어야 한다.
즉, 새로운 기능을 추가할 때는, 기존 코드 변경없이, 코드를 확장하는 방식으로 코드를 작성해야 한다.
이 원칙은 유연성과 확장성을 보장하며, 변경이나 새로운 요구사항이 생길 때 기존 코드를 손상시키지 않고 기능을 추가할 수 있다.
개방/폐쇄 원칙 적용 전

위 코드는 새로운 뷰홀더가 생길때마다, onBindViewHolder() 안의 코드를 수정해야 한다.
개방/폐쇄 원칙 적용 후

새로운 뷰홀더를 추가하게 될 경우에도, 기존 코드를 수정할 필요 없이, 확장하기만 하면 된다.
클린 아키텍처에서의 개방/폐쇄 원칙
유스케이스 설계 시 매우 중요 : 유스케이스나 기능의 변경 없이도 새로운 요구사항에 대응할 수 있도록 함
새로운 기능을 추가할 때 기존의 코드를 수정하지 않고, 기존 코드를 확장하는 방식으로 기능을 추가할 수 있어야 한다
새로운 데이터소스(로컬 캐시, 원격API)를 추가할 때, 기존의 코드에 영향을 주지않고 Repository 인터페이스를 확장하거나 새로운 데이터 소스를 추가
Liskov Substitution Principle
바바라 리스코프 교수님이 처음으로 주장한 원칙이라 이렇게 부름
서브클래스는 언제나 자신의 기반 클래스를 대체할 수 있어야한다
즉, 상위 클래스의 객체가 사용되는 모든 곳에서 하위 클래스의 객체도 문제없이 동작해야 한다.
서브클래스는 상위 클래스가 제공하는 모든 기능을 동일하게 수행하거나 더 구체적으로 확장해야 하며, 상위 클래스의 동작을 변경하거나 제한해서는 안 된다.
이 원칙은 객체지향 시스템의 다형성을 보장하여, 유연하고 재사용 가능한 코드를 설계하는 데 필수적이다.
리스코프 치환 원칙 적용 전

텍스트 뷰홀더는 이미지를 사용하지 않는데 이미지를 받을 수 밖에 없어 문제 발생.
리스코프 치환 원칙 적용 후

클린 아키텍처에서의 리스코프 치환 원칙
클린 아키텍처의 계층 간에 인터페이스를 통해 통신을 하는데 리스코프 치환이 안정적인 인터페이스를 보장한다.
인터페이스와 추상 클래스는 모든 구현체에 일관된 동작을 보장해야 한다.
예를 들어, Repository 인터페이스를 구현하는 여러 데이터소스(Remote, Local)는 동일한 방식으로 동작해야 하며, 데이터 소스가 변경되더라도 도메인 레이어나 프레젠테이션 레이어는 동질하게 작동해야 한다.
Interface Segregation Principle
인터페이스에 안쓰는 메서드가 있고 그것을 구현하는 행위를 하면 안된다.
자신이 사용하지 않는 메서드에 의존하지 않아야 한다
즉, 인터페이스는 구체적인 기능별로 최대한 작게 분리되어, 특정 클라이언트가 불필요한 메서드를 강제로 구현하지 않도록 해야 한다
이 원칙은 클라이언트 코드의 결합도를 낮추고, 시스템의 유연성을 증가시키며 변경시 영향 범위를 최소화하는 데 도움을 준다.
인터페이스 분리 원칙 적용 전

인터페이스 분리 원칙 적용 후

클린 아키텍처에서의 인터페이스 분리 원칙
인터페이스 분리 원칙은 모듈(레이어) 간의 결합도를 낮추고, 변경의 영향을 최소화한다.
각 layer는 자신이 필요한 기능만을 제공하는 인터페이스에 의존하므로, 변경의 범위가 줄어들고 유지보수가 쉬워진다.
Dependency Inversion Principle
고수준(domain) 모듈은 저수준(Presentation) 모듈에 의존해서는 안되며, 둘 다 추상화에 의존해야 한다. 안쪽에 있는 layer가 바깥 layer를 의존하면 안된다. (밖에서 안쪽을 향해야 한다.)
유연성을 확보하고, 상위 계층이 하위 계층의 변경에 영향을 받지 않도록 한다.
의존 역전 원칙 적용 전

UserRepository()에서 localDataSource와 remoteDataSource를 변수로 사용하기에
하위인 Local과 Remote에서 변경이 발생하면 상위인 userRepository()에 영향을 끼칠수 밖에 없는 구조다.
의존 역전 원칙 적용 후

UserDataSource를 추상화 한 후, Local과 Remote에서 각각 impl을 한다.
UserRepository에서는 local과 remote변수를 사용하는데 각각 UserDataSource 인터페이스이기 때문에 그것이 무엇인지 알 수 없다. 따라서 의존성이 사라진다.
클린 아키텍처에서의 의존 역전 원칙
의존 역전 원칙은 계층간의 의존성을 역전시켜, 상위 계층이 하위 계층의 구현에 의존하지 않도록 한다.
이를 통해 테스트 용이성이 높아지고, 구현체 교체가 용이해짐
Repository나 DataSource와 같은 데이터 관련 클래스들을 인터페이스로 추상화하고, DI(Dagger, Hilt)를 통해 의존성을 주입