프레임워크(Framework)/Spring
SOLID?
cha_eyoon
2024. 7. 16. 06:14
✅ SOLID
분리를 잘한다 ⇒ 객체 지향적
예시 코드를 만들어보자.
- SRP (Single Responsibility Principle) 단일책임 원칙
- 한 클래스는 하나의 책임만 가져야 한다.
- 이 클래스를 수정해야 하는 이유는 하나의 직군(역할) 때문이어야 한다.
- 수정을 가하는 대상이 하나의 역할을 해야한다.
- A ⇒ B ⇒ C 연쇄적으로 수정하는 일이 없도록..
- 액터: 클래스에 수정을 가하는 역할자
class XSrp {
class Employee {
String name;
String positon;
Employee(String name, String position) {
this.name = name;
this.positon = position;
}
// * 초과 근무 시간을 계산하는 메서드 (두 팀에서 공유하여 사용)
void calculateExtraHour() {
// ...
}
// * 급여를 계산하는 메서드 (회계팀에서 사용)
void calculatePay() {
// ...
this.calculateExtraHour();
// ...
}
// * 근무시간을 계산하는 메서드 (인사팀에서 사용)
void reportHours() {
// ...
this.calculateExtraHour();
// ...
}
}
class CorrectSrp {
class Employee {
private String name;
private int salary;
private int workHours;
Employee(String name, int salary, int workHours) {
this.name = name;
this.salary = salary;
this.workHours = workHours;
}
void calculateExtraHour() {
new Calculator().calculateExtraHour();
}
void reportHours() {
new Reportor.~()
}
}
class Calculator {
private int workHours;
private int standardHour;
private int salary;
Calculator(int workHours, int standardHour, int salary) {
this.workHours = workHours;
this.standardHour = standardHour;
this.salary = salary;
}
private int calculateExtraHour() {
int extraHours = workHours - standardHour;
return extraHours > 0 ? extraHours : 0;
}
void calculatePay() {
int extraPay = this.calculateExtraHour() * 20000;
int totalPay = this.salary + extraPay;
System.out.println("Total Pay: " + totalPay);
}
}
Class Reporter(){
// 따로 분리
}
- OCP (Open/Closed Principle) 개방-폐쇄 원칙
- 소프트웨어 요소는 확장에는 열려있으나 변경에는 닫혀있어야 한다.
- 코드의 추가로 기존의 코드가 영향을 받으면 안 된다.
- LSP (Liskov Substitution Principle) 리스코프 치환 원칙
- 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으며 하위타입의 인스턴스로 바꿀 수 있어야 한다.
- 부모 클래스의 객체를 자식 클래스의 객체로 치환하더라도 프로그램의 정상적인 동작 유지
- 자식 클래스는 부모 클래스의 모든 기능을 대체할 수 있어야 하며, 부모 클래스의 메서드와 동작을 일관되게 유지 ⇒ 올바른 상속을 위해, 자식 객체의 확장이 부모 객체의 방향을 따른다.
- 인터페이스(공통규약) 만들고 그 이상의 것을 만든다? 말이 안됨
IPerson = sleep, work
Student implements IPerson = sleep, work("공부를한다');
Adult implements IPerson = sleep, work("돈을 번");
IPerson stu= new Student();
IPerson adu = new Student();
stu.work();
adu.work();
- ISP (Interface Segregation Principle) 인터페이스 분리 원칙
- 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.
interface Playable {
void play();
}
interface StringInstrument extends Playable {
void tuneStrings();
}
interface WindInstrument extends Playable {
void adjustBreath();
}
class Guitar implements StringInstrument {
@Override
public void play() {
System.out.println("나 기타쳐~~~");
}
@Override
public void tuneStrings() {
System.out.println("기타 튜닝중이야~~~~");
}
@Override
public void adjustBreath() {
System.out.println("기타연주는 호흡조절이 필요 없는데, 어쩔 수 없이 구현한다.......");
}
}
// 플루트 클래스
class Flute implements WindInstrument {
@Override
public void play() {
System.out.println("나 플룻부는 중~~~~");
}
@Override
public void adjustBreath() {
System.out.println("관악기는 호흡조절이 생명이다~~~~");
}
@Override
public void tuneStrings() {
System.out.println("플룻은 줄이 없는데, 어쩔 수 없이 구현한다...");
}
}
- DIP (Dependency Inversion Principle) 의존관계 역전 원칙
- 프로그래머는 “추상화에 의존해야지, 구체화에 의존하면 안된다” - 의존성 주입은 이 원칙을 따르는 방법 중 하나다.
- Phone이 추상화한 것 , 그리고 그걸 구체화 한게 Galaxy, Iphone
interface Phone {}
class Galaxy implements Phone {}
class IPhone implements Phone {}
class User {
Phone phone; // 합성
void setPhone(Phone phone) {
this.phone = phone;
}
void turnOnGalaxy() {}
void turnOnIPhone() {}
}
public class Main {
public static void main(String[] args) {
User user = User();
// 1. 갤럭시 폰을 켰을 때
Phone phone = new Galaxy();
user.setPhone(phone);
user.turnOnGalaxy();
// 2. 아이폰을 켰을 때
Phone phone = new IPhone();
user.setPhone(phone);
user.turnOnIPhone();
}
}
팀원들마다 개념을 이해한 방향이 달라서 각자 제시한 정의와 예시코드가 다 달랐다.
내가 생각했을 때 SOLID 원칙을 모두 준수하면서 코드를 작성하는 것은 어렵지만 개발자로 원칙을 지향하며 코드를 작성하도록 노력해야하는 것은 분명하다!!!