λ¨μΌ μ± μ μμΉ(Single Responsibility Principle, SRP)
SRPλ SOLID μμΉ μ€ μ²« λ²μ§Έ μμΉμΌλ‘, ν κ°μ λͺ¨λμ μ€μ§ ν κ°μ μ‘ν°μλ§ μ± μμ κ°μ ΈμΌ νλ€λ μμΉμ΄λ€.
A module should be responsible to one, and only one, actor.
(Actor : λͺ¨λμ λ³κ²½μ μꡬνλ νλ μ΄μμ μ΄ν΄κ΄κ³μλ μ¬μ©μ κ·Έλ£Ή)
SRPμμ μ± μμ μλ―Έ
μΌλ°μ μΈ κ°μ²΄μ§ν₯ μ€κ³μμμ μ± μ(μν , μ± μ, νλ ₯μμμ μ± μ)
- κ°μ²΄κ° μνν΄μΌ νλ νλ(behavior)μ μλ―Έ
- κ°μ²΄κ° "무μμ μκ³ "(knowing) "무μμ νλμ§"(doing)λ₯Ό λνλ
- νλ ₯ κ΄κ³ μμμ κ°μ²΄κ° μνν΄μΌ νλ μν μ μλ―Έ
- μ£Όλ‘ λ©μλλ κΈ°λ₯ λ¨μμ μ± μμ μλ―Έ
SRPμμμ μ± μ
- λ³κ²½μ μ΄μ (reason for change)λ₯Ό μλ―Έ
- νΉμ μ‘ν°(μ΄ν΄κ΄κ³μ)μ μꡬμ¬νμ μλ―Έ
- νλμ λͺ¨λμ΄ λ³κ²½λμ΄μΌ νλ μ΄μ λ μ€μ§ νλμ¬μΌ ν¨
- λ ν° λ¨μμ μ± μμ λ€λ£Έ
λ²μ | μ μ© μμ€ | λͺ©μ | κ²°κ³Ό | |
μΌλ°μ μ± μ | κ°μ²΄μ νλκ³Ό μνμ μ΄μ | λ©μλλ κΈ°λ₯ λ¨μμ λ―Έμμ μ± μ | κ°μ²΄μ μν κ³Ό νλ ₯ κ΄κ³ μ μ | μ μ μλ κ°μ²΄μ νλ |
SRPμμμ μ± μ | λ³κ²½μ μμΈκ³Ό μ΄ν΄κ΄κ³μμ μ΄μ | ν΄λμ€λ λͺ¨λ λ¨μμ κ±°μμ μ± μ | λ³κ²½μ μν₯ λ²μ μ μ΄μ κ΄λ¦¬ | λ 립μ μΌλ‘ λ³κ²½ κ°λ₯ν λͺ¨λ |
SRPμμ μ€μν μ
- "μ± μ"μ "λ³κ²½μ μ΄μ "λ₯Ό μλ―Ένλ€.
- νλμ ν΄λμ€λ νλμ μ‘ν°(μ΄ν΄κ΄κ³μ)μ λν΄μλ§ μ± μμ μ ΈμΌ νλ€.
- μλ‘ λ€λ₯Έ μ΄μ λ‘ λ³κ²½λλ κ²λ€μ λΆλ¦¬λμ΄μΌ νλ€.
λ³κ²½ν μ΄μ λ₯Ό 무μμΌλ‘ μ μνλκ°?
- λ²κ·Έ μμ μ΄λ 리ν©ν λ§μ κ΄ν κ²μ΄ μλ(νλ‘κ·Έλλ¨Έμ μ± μ)
- νλ‘κ·Έλ¨μ μ± μκ³Ό λꡬμκ² μλ΅νλμ§μ μ΄μ
μμ μ½λ 1
μ‘°μ§ κ΅¬μ‘°
- μ΅μμμ CEO
- CEOμκ² λ³΄κ³ νλ Cλ 벨 μμ(Employee)
- CFO (μ¬λ¬΄ λ΄λΉ)
- CTO (κΈ°μ λ΄λΉ)
- COO (μ΄μ λ΄λΉ)
μλλ¦¬μ€ 1) κΈμ¬ κ³μ° κ·μΉμ μλͺ» λͺ μΈνμ¬ λͺ¨λ μ§μλ€μ΄ λ λ°°μ κΈμ¬λ₯Ό λ°μ
calculatePay λ©μλκ° μΉλͺ μ μΌλ‘ μλͺ» λͺ μΈλ κ²μ΄λ―λ‘ μ΄ μ± μμ CFOκ° μ ΈμΌνλ€.
μλλ¦¬μ€ 2) μ μ₯νλ κ³Όμ μ κΈ°μ λ°μ΄ν°κ° μμ
save λ©μλμ μΉλͺ μ μΈ μλͺ»λ λͺ μΈκ° μλ κΈ°μ μ μΈ λ¬Έμ λ‘ μ΄ μ± μμ CTOκ° μ ΈμΌ νλ€.
μλλ¦¬μ€ 3) μ§μλ€μ 근무 νν© λ° λ³΄μμ μΆμ νλ 리ν¬νΈμ μ€λ₯κ° μλ κ²½μ°
reportHours λ©μλμ μλͺ»λ λͺ μΈκ° μ‘΄μ¬νλ μ΄μμμ μ± μμΌλ‘ μ΄ μ± μμ COOκ° μ ΈμΌ νλ€.
// SRP μλ°
public class Employee {
public Money calculatePay(); // CFO μ‘°μ§μ μ±
μ (κΈμ¬ κ³μ° λ‘μ§)
public void save(); // CTO μ‘°μ§μ μ±
μ (λ°μ΄ν° μ μ₯ κΈ°μ )
public String reportHours(); // COO μ‘°μ§μ μ±
μ (μ΄μ/κ°μ¬ λ³΄κ³ )
}
μ μ½λλ νλμ ν΄λμ€ λ΄μ μλ‘ λ€λ₯Έ μ‘°μ§μ μ± μλ€μ΄ μμ¬ μλ€.
calculatePay λ©μλ λ΄μ μκ³ λ¦¬μ¦μ λ³κ²½μ΄ μ΄λ£¨μ΄μ§ λ, κ·Έ λ³κ²½ μμ²μ CFOκ° μ΄λλ μ‘°μ§μμ λ°μν κ²μ΄λ€.
λ§μ°¬κ°μ§λ‘ reportHours λ©μλμ λν λ³κ²½μ COOμ μ‘°μ§μμ μμ²ν κ²μ΄κ³ , save λ©μλμ λν λ³κ²½μ CTOμ μ‘°μ§μμ μμ²ν κ²μ΄λ€.
νμ¬ ν΄λΉ ν΄λμ€μλ μλ‘ λ€λ₯Έ μ‘ν°(CFO, CTO, COO μ‘°μ§)μ μλ΅νλ 3κ°μ λ©μλκ° μλ€. (SRP μλ°)
μμ μ½λμ²λΌ ν ν΄λμ€ λ΄μ 3κ°μ λ€λ₯Έ κ·Έλ£Ήμ λΉμ§λμ€ κΈ°λ₯μ΄ μκ² λ κ²½μ°, CTOκ° μμ²ν λ³κ²½μ΄ μλμΉ μκ² COOκ° μ± μμ μ ΈμΌ λλ μν©μ΄ λ°μν μ μλ€. (calculatePay λ©μλμ λ³κ²½μ΄ μλμΉ μκ² reportHours λ©μλλ₯Ό λ§κ°λ¨λ¦° μν©)
λ°λΌμ, μννΈμ¨μ΄ λͺ¨λμ μμ±ν λ, λ³κ²½μ΄ μμ²λ λ κ·Έ λ³κ²½μ λ¨μΌνκ³ μ’κ² μ μλ λΉμ¦λμ€ κΈ°λ₯μ λννλ λ°μ νκ² κ²°ν©λ κ·Έλ£ΉμΌλ‘λΆν°λ§ λ°μν μ μλλ‘ νλ κ²μ΄ μ΄μμ μ΄λ€. μ¦, λͺ¨λλ€μ μ‘°μ§ μ 체μ 볡μ‘μ±μΌλ‘λΆν° 격리μν€κ³ , κ° λͺ¨λμ΄ νλμ λΉμ¦λμ€ κΈ°λ₯μ νμμλ§ μ± μμ μ§λλ‘ μμ€ν μ μ€κ³ν΄μΌ νλ€.
SRPλ₯Ό μ€μνλ €λ©΄ λ€μ μ½λμ κ°μ΄ λΆλ¦¬λμ΄μΌ νλ€. (ν ν΄λμ€κ° ν μν°μ λν μ± μ(λ³κ²½μ μ΄μ )λ§ κ°μ§λλ‘)
// SRP μ€μ
// CFO μ‘°μ§μ μ±
μ
public class EmployeePayCalculator {
public Money calculatePay(); // CFO μ‘°μ§μ μ±
μ (κΈμ¬ κ³μ° λ‘μ§)
}
// CTO μ‘°μ§μ μ±
μ
public class EmployeeRepository {
public void save(); // CTO μ‘°μ§μ μ±
μ (λ°μ΄ν° μ μ₯ κΈ°μ )
}
// COO μ‘°μ§μ μ±
μ
public class EmployeeTimeReporter {
public String reportHours(); // COO μ‘°μ§μ μ±
μ (μ΄μ/κ°μ¬ λ³΄κ³ )
}
μμ²λΌ κ° ν΄λμ€κ° νλμ λ³κ²½μ μ΄μ (μ± μ)λ§ κ°μ§λλ‘ μ€κ³νλ©΄ λ€μκ³Ό κ°μ μ΄μ μ΄ μλ€.
- κ° ν΄λμ€λ νλμ μ‘°μ§μμλ§ λ³κ²½ μμ²μ΄ λ°μ
- ν κΈ°λ₯μ λ³κ²½μ΄ λ€λ₯Έ κΈ°λ₯μ μν₯μ μ£Όμ§ μμ(μ± μ νΌν© νΌν¨)
- κ° μ‘°μ§μ μꡬμ¬ν λ³κ²½μ λ 립μ μΌλ‘ λ°μ κ°λ₯
λ°λΌμ SRP μ€μνλ©΄ "κΈμ¬ κ³μ° λ‘μ§μ μμ νλλ° κ·Όλ¬΄μκ° λ³΄κ³ μμ κ²°ν¨μ΄ λ°μνλ" μν©μ μλ°©ν μ μλ€.
μμ μ½λ 2
리ν¬νΈ λͺ¨λ μ¬λ‘
- λ³κ²½ μ΄μ 1: 리ν¬νΈ λ΄μ© λ³κ²½
- λ³κ²½ μ΄μ 2: 리ν¬νΈ νμ λ³κ²½
- μλ‘ λ€λ₯Έ μ΄μ λ‘ λ³κ²½λλ―λ‘ λ³λ λͺ¨λλ‘ λΆλ¦¬ν΄μΌ ν¨
// SRP μλ°
class Report {
private String content;
private String format;
public Report(String content, String format) {
this.content = content;
this.format = format;
}
// 리ν¬νΈ λ°μ΄ν° μμ± μ±
μ
public void generateReport() {
// λ°μ΄ν°λ² μ΄μ€μμ λ°μ΄ν°λ₯Ό κ°μ Έμ€λ λ‘μ§
System.out.println("리ν¬νΈ λ΄μ© μμ± μ€...");
this.content = "리ν¬νΈ λ°μ΄ν°...";
}
// 리ν¬νΈ ν¬λ§·ν
μ±
μ
public void formatReport() {
// ν¬λ§·ν
λ‘μ§
System.out.println("리ν¬νΈ ν¬λ§·ν
μ€...");
}
// 리ν¬νΈ μΆλ ₯ μ±
μ
public void printReport() {
// μΆλ ₯ λ‘μ§
System.out.println("리ν¬νΈ μΆλ ₯ μ€...");
}
}
SRP μλ°
- Report ν΄λμ€κ° μ¬λ¬ μ±
μμ κ°μ§κ³ μλ€.
- 리ν¬νΈ λ°μ΄ν° μμ±(generateReport())
- 리ν¬νΈ ν¬λ§·ν (formatReport())
- 리ν¬νΈ μΆλ ₯(printReport())
- λ°μκ°λ₯ν λ¬Έμ
- λ°μ΄ν° μμ± λ°©μμ΄ λ³κ²½λλ©΄ ν΄λμ€ μ 체(Report ν΄λμ€)μ μν₯
- ν¬λ§·ν μꡬμ¬ν λ³κ²½ μ (Report ν΄λμ€) μμ νμ
- μΆλ ₯ λ°©μ λ³κ²½ μμλ (Report ν΄λμ€) μμ νμ
// SRP μ€μ
// 1. 리ν¬νΈ λ°μ΄ν° μμ± μ±
μ
class ReportGenerator {
private String content;
public String generateReport() {
// λ°μ΄ν°λ² μ΄μ€μμ λ°μ΄ν°λ₯Ό κ°μ Έμ€λ λ‘μ§
System.out.println("리ν¬νΈ λ΄μ© μμ± μ€...");
return "리ν¬νΈ λ°μ΄ν°...";
}
}
// 2. 리ν¬νΈ ν¬λ§·ν
μ±
μ
class ReportFormatter {
public String formatReport(String content, String format) {
// ν¬λ§·ν
λ‘μ§
System.out.println("리ν¬νΈ ν¬λ§·ν
μ€...");
return "ν¬λ§·ν
λ " + content;
}
}
// 3. 리ν¬νΈ μΆλ ₯ μ±
μ
class ReportPrinter {
public void printReport(String formattedReport) {
// μΆλ ₯ λ‘μ§
System.out.println("리ν¬νΈ μΆλ ₯: " + formattedReport);
}
}
SRP μ€μ
- κ° μ±
μμ΄ λ³λμ ν΄λμ€λ‘ λΆλ¦¬λμ΄ μλ€.
- ReportGenerator: λ°μ΄ν° μμ±λ§ λ΄λΉ
- ReportFormatter: ν¬λ§·ν λ§ λ΄λΉ
- ReportPrinter: μΆλ ₯λ§ λ΄λΉ
- μ₯μ
- ν λΆλΆμ λ³κ²½μ΄ λ€λ₯Έ λΆλΆμ μν₯μ λ―ΈμΉ μν κ°μ
- ex : 리ν¬νΈ μ»΄νμΌ νλ‘μΈμ€ λ³κ²½μ΄ μΆλ ₯ μ½λμ μν₯μ μ£Όμ§ μμ
- λ³κ²½μ΄ νμν λ κ΄λ ¨ ν΄λμ€λ§ μμ (μ μ§λ³΄μμ± ν₯μ)
- κ° μ»΄ν¬λνΈλ₯Ό λ 립μ μΌλ‘ μμ κ°λ₯
- λ²κ·Έ λ°μ μ μμΈ νμ μ¬μ
- ν
μ€νΈ μ©μ΄μ±
- κ° μ± μμ λ 립μ μΌλ‘ ν μ€νΈ κ°λ₯
- Mock κ°μ²΄ μ¬μ© μ©μ΄
- ν λΆλΆμ λ³κ²½μ΄ λ€λ₯Έ λΆλΆμ μν₯μ λ―ΈμΉ μν κ°μ
λ¨μΌ μ± μ μμΉ λ€λ₯Έ νν λ°©μ
Gather together the things that change for the same reasons. Separate those things that change for different reasons. (Robert C. Martin, 2014)
κ°μ μ΄μ λ‘ λ³κ²½λλ κ²λ€μ ν¨κ» λͺ¨μΌκ³ (μμ§λ↑), λ€λ₯Έ μ΄μ λ‘ λ³κ²½λλ κ²λ€μ λΆλ¦¬νμ.(κ²°ν©λ↓).
SRPλ μ¬λμ κ΄ν κ²
λ§μ§λ§μΌλ‘, λ³κ²½μ μ΄μ λ μ¬λμ΄λΌλ κ²μ μκ°νμ. λ³κ²½μ μμ²νλ κ²μ μ¬λλ€μ΄λ€.
μ°λ¦¬λ μλ‘ λ€λ₯Έ μ΄μ λ‘ μ¬λλ€μ΄ κ΄μ¬μ κ°μ§λ μ½λλ₯Ό νΌν©μ νΌν΄μΌ νλ€.
- λ³κ²½μ ν μ¬λ/κ·Έλ£Ήμμλ§ λ°μν΄μΌ ν¨
- κ° λͺ¨λμ νλμ λΉμ¦λμ€ κΈ°λ₯μλ§ μλ΅ν΄μΌ ν¨
- μ‘°μ§μ 볡μ‘μ±μΌλ‘λΆν° 격리λμ΄μΌ ν¨
μ°Έκ³ μλ£ :
https://en.wikipedia.org/wiki/Single-responsibility_principle
Single-responsibility principle - Wikipedia
From Wikipedia, the free encyclopedia Computer programming principle The single-responsibility principle (SRP) is a computer programming principle that states that "A module should be responsible to one, and only one, actor."[1] The term actor refers to a
en.wikipedia.org
https://blog.cleancoder.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html
Clean Coder Blog
The Single Responsibility Principle 08 May 2014 In 1972 David L. Parnas published a classic paper entitled On the Criteria To Be Used in Decomposing Systems into Modules. It appeared in the December issue of the Communications of the ACM, Volume 15, Number
blog.cleancoder.com