SOLID, DI
✅ What is a good OOP
distinguish role and implementation
- ✔️
role
: interface, abstraction - what something should do
ex)
OrderService
,MemberRepository
- ✔️
implementation
: class that implements interface - how to do
ex)
OrderServiceImpl
,JpaMemberRepository
- ➡️
DIP
,ISP
를 지킨다 - 👍🏻 향후 구체 클래스가 바뀌더라도 쉽게 바꿔끼워 대처할 수 있다
✅ SOLID
- SRP
- OCP
- LSP
- ISP
- DIP
☑️ Single Responsible principle
- one class should have one responsibility
- when extended, modification should be minimized
- ex)
MVC
: model, view, controller code is distinguished - ex)
controller
,service
,repository
☑️ Open Closed principle
- open for extension, closed for modification
- do not modify client code, modify concrete class only
- should be able to add
Fish
, without changingAnimal
,Dog
class - use polymorphism, interface
☑️ Liskov Substitution principle
- correctly use inheritence without breaking the program
Objects of a superclass should be replaceable with objects of its subclass
- If
Bird superclass
hasfly()
method Penguin extends Bird
should overridefly()
and penguin should be able to fly ➡️ bad LSPParrot extends Bird
should overridefly()
. If parrot eats instead of flying ➡️ bad LSP- thus, create
Bird superclass
andFlyable interface
withfly()
Penguin extends Bird
onlyParrot extends Bird implements Flyable
☑️ Interface Segregation principle
- instead of having one large interface with many unrelated methods, break it into smaller more specific interfaces
Car
class can haveDrive interface
andFix interface
- can have
driver client class
andengineer client class
- even when
Fix interface
is modified,driver client class
does not have to be altered
☑️ Dependency Inversion principle
- depend on
abstract
orinterface
, not on a certain class
👎🏻 Bad example of solid
OrderServiceImpl
is client codeOrderServiceImpl
needsDiscountPolicy
- so, created
DiscountPolicy interface
- then, created
FixDiscountPolicy implements DiscountPolicy
- however, decided to change business logic from Fix ➡️ Rate
- now,
OrderServiceImpl
needsRateDiscountPolicy
1️⃣ 👎🏻 have to change
OrderServiceImpl
- 1️⃣ 👎🏻 OCP: need to modify client code
- 2️⃣ 👎🏻 DIP: relying on a concrete class, instead of interface or abstract
1
2
3
4
5
public class OrderServiceImpl implements OrderService {
// private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
private final DiscountPolicy discountPolicy = new RateDiscountPolicy(); // 👎🏻 OCP, DIP 못 지킴
}
OrderServiceImpl
은 주문하는 business logic만 가지고 있어야 하는데DiscountPolicy
도 받아와야 하는 책임도 있음- 3️⃣ 👎🏻
OrderServiceImpl
은 책임이 너무 많음! 👎🏻
SRP
OrderServiceImpl
should only depend on interfaceDiscountPolicy
- however, in this case, depends both on interface and on concrete class
FixDiscountPolicy
👍🏻 Implement SOLID
implement
AppConfig
- 이제
OrderServiceImpl
은 생성자를 통해DiscountPolicy
를 주입받는다 - ⭐️ Dependency Injection
- 3️⃣
OrderServiceImpl
는 fix인지 rate인지 전혀 모른다! 나는 이제 비즈니스 로직에만 집중하면 된다. ➡️ SRP - 2️⃣ only rely on abstract
interface DiscountPolicy
➡️ DIP - 1️⃣ fix에서 rate으로 변경되더라도 client code인
OrderServiceImpl
는 바뀌지 않는다 ➡️ OCP
1
2
3
4
5
6
7
8
9
public class OrderServiceImpl implements OrderService {
private final DiscountPolicy discountPolicy; //DIP, Dependency Injection
public OrderServiceImpl(DiscountPolicy discountPolicy) {
this.discountPolicy = discountPolicy;
}
//SRP
//only business logic
- 그리고 별도의 클래스
AppConfig
를 만들어 의존관계를 관리한다. - 이제 Fix ➡️ Rate으로 바꿔도
OrderServiceImpl
은 바뀌는게 없음 AppConfig
만 바꿔주면 됨
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class AppConfig {
public OrderService orderService(){
return new OrderServiceImpl(new FixDiscountPolicy());
}
}
//여기서 Rate으로 바꾸면?
//AppConfig만 바꾸면 됨, OCP
public class AppConfig {
public OrderService orderService(){
return new OrderServiceImpl(new RateDiscountPolicy());
}
}
- 👍🏻
OrderServiceImpl
has SRP - 👍🏻
OrderServiceImpl
does not rely on a concrete class, relies on interface ➡️ DIP 👍🏻 application maintains OCP, only has to modify
AppConfig
, and not modify client code- now, config and business logic is totally seperate
✅
✅
✅
✅
✅
✅
This post is licensed under CC BY 4.0 by the author.