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,Dogclass - 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 superclasshasfly()method Penguin extends Birdshould overridefly()and penguin should be able to fly ➡️ bad LSPParrot extends Birdshould overridefly(). If parrot eats instead of flying ➡️ bad LSP- thus, create
Bird superclassandFlyable interfacewithfly() Penguin extends BirdonlyParrot extends Bird implements Flyable
☑️ Interface Segregation principle
- instead of having one large interface with many unrelated methods, break it into smaller more specific interfaces
Carclass can haveDrive interfaceandFix interface- can have
driver client classandengineer client class - even when
Fix interfaceis modified,driver client classdoes not have to be altered
☑️ Dependency Inversion principle
- depend on
abstractorinterface, not on a certain class
👎🏻 Bad example of solid
OrderServiceImplis client codeOrderServiceImplneedsDiscountPolicy- so, created
DiscountPolicy interface - then, created
FixDiscountPolicy implements DiscountPolicy - however, decided to change business logic from Fix ➡️ Rate
- now,
OrderServiceImplneedsRateDiscountPolicy 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은 책임이 너무 많음! 👎🏻
SRPOrderServiceImplshould 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());
}
}
- 👍🏻
OrderServiceImplhas SRP - 👍🏻
OrderServiceImpldoes 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.

