# An overview of design pattern - SOLID, GRASP

๋จผ์ € ๋””์ž์ธ ํŒจํ„ด์„ ๊ณต๋ถ€ํ•˜๊ธฐ ์ „์— Design Principle์ธ SOLID์™€ GRASP์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž

# Design Smells

design smell์ด๋ž€ ๋‚˜์œ ๋””์ž์ธ์„ ๋‚˜ํƒ€๋‚ด๋Š” ์ฆ์ƒ๊ฐ™์€ ๊ฒƒ์ด๋‹ค.

์•„๋ž˜ 4๊ฐ€์ง€ ์ข…๋ฅ˜๊ฐ€ ์žˆ๋‹ค.

  1. Rigidity(๊ฒฝ์ง์„ฑ)
    ์‹œ์Šคํ…œ์ด ๋ณ€๊ฒฝํ•˜๊ธฐ ์–ด๋ ต๋‹ค. ํ•˜๋‚˜์˜ ๋ณ€๊ฒฝ์„ ์œ„ํ•ด์„œ ๋‹ค๋ฅธ ๊ฒƒ๋“ค์„ ๋ณ€๊ฒฝ ํ•ด์•ผํ•  ๋•Œ ๊ฒฝ์ง์„ฑ์ด ๋†’๋‹ค. ๊ฒฝ์ง์„ฑ์ด ๋†’๋‹ค๋ฉด non-criticalํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ๊ด€๋ฆฌ์ž๋Š” ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์ˆ˜์ •์„ ์š”์ฒญํ•˜๊ธฐ๊ฐ€ ๋‘๋ ค์›Œ์ง„๋‹ค.

  2. Fragility(์ทจ์•ฝ์„ฑ)
    ์ทจ์•ฝ์„ฑ์ด ๋†’๋‹ค๋ฉด ์‹œ์Šคํ…œ์€ ์–ด๋–ค ๋ถ€๋ถ„์„ ์ˆ˜์ •ํ•˜์˜€๋Š”๋ฐ ๊ด€๋ จ์ด ์—†๋Š” ๋‹ค๋ฅธ ๋ถ€๋ถ„์— ์˜ํ–ฅ์„ ์ค€๋‹ค. ์ˆ˜์ •์‚ฌํ•ญ์ด ๊ด€๋ จ๋˜์ง€ ์•Š์€ ๋ถ€๋ถ„์—๋„ ์˜ํ–ฅ์„ ๋ผ์น˜๊ธฐ ๋–„๋ฌธ์— ๊ด€๋ฆฌํ•˜๋Š” ๋น„์šฉ์ด ์ปค์ง€๋ฉฐ ์‹œ์Šคํ…œ์˜ credibility ๋˜ํ•œ ์žƒ๋Š”๋‹ค.

  3. Immobility(๋ถ€๋™์„ฑ)
    ๋ถ€๋™์„ฑ์ด ๋†’๋‹ค๋ฉด ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ์‹œ์Šคํ…œ์„ ๋ถ„๋ฆฌํ•ด์„œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์–ด๋ ต๋‹ค. ์ฃผ๋กœ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ด์ „์— ๊ตฌํ˜„๋˜์—ˆ๋˜ ๋ชจ๋“ˆ๊ณผ ๋น„์Šทํ•œ ๊ธฐ๋Šฅ์„ ํ•˜๋Š” ๋ชจ๋“ˆ์„ ๋งŒ๋“ค๋ ค๊ณ  ํ•  ๋•Œ ๋ฌธ์ œ์ ์„ ๋ฐœ๊ฒฌํ•œ๋‹ค.

  4. Viscosity(์ ์ฐฉ์„ฑ)
    ์ ์ฐฉ์„ฑ์€ ๋””์ž์ธ ์ ์ฐฉ์„ฑ๊ณผ ํ™˜๊ฒฝ ์ ์ฐฉ์„ฑ์œผ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค.

    ์‹œ์Šคํ…œ์— ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ํ•ต์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ๋” ์‰ฝ๋‹ค๋ฉด ๋””์ž์ธ ์ ์ฐฉ์„ฑ์ด ๋†’๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ˆ˜์ •์ด ํ•„์š”ํ•  ๋•Œ ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค. ์–ด๋–ค ๊ฒƒ์€ ๋””์ž์ธ์„ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด๊ณ  ์–ด๋–ค ๊ฒƒ์€ ๊ทธ๋ ‡์ง€ ๋ชปํ•  ๊ฒƒ์ด๋‹ค(ํ•ต์„ ์ถ”๊ฐ€).

    ํ™˜๊ฒฝ ์ ์ฐฉ์„ฑ์€ ๊ฐœ๋ฐœํ™˜๊ฒฝ์ด ๋Š๋ฆฌ๊ณ  ํšจ์œจ์ ์ด์ง€ ๋ชปํ•  ๋•Œ ๋‚˜ํƒ€๋‚œ๋‹ค. ์˜ˆ๋ฅผ๋“ค๋ฉด ์ปดํŒŒ์ผ ์‹œ๊ฐ„์ด ๋งค์šฐ ๊ธธ๋‹ค๋ฉด ํฐ ๊ทœ๋ชจ์˜ ์ˆ˜์ •์ด ํ•„์š”ํ•˜๋”๋ผ๋„ ๊ฐœ๋ฐœ์ž๋Š” recompile ์‹œ๊ฐ„์ด ๊ธธ๊ธฐ ๋•Œ๋ฌธ์— ์ž‘์€ ๊ทœ๋ชจ์˜ ์ˆ˜์ •์œผ๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ• ๋ ค๊ณ  ํ•  ๊ฒƒ์ด๋‹ค.

์œ„์˜ design smell์€ ๊ณง ๋‚˜์œ ๋””์ž์ธ์„ ์˜๋ฏธํ•œ๋‹ค.(์ŠคํŒŒ๊ฒŒํ‹ฐ ์ฝ”๋“œ)

# Robert C. Martin's Software design principles(SOLID)

Robejt C. Martin์€ 5๊ฐ€์ง€ Software design principles์„ ์ •์˜ํ•˜์˜€๊ณ  ์•ž๊ธ€์ž๋ฅผ ๋”ฐ์„œ SOLID๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

# Single Responsibility Principle(SRP)

A class should have one, and only one, reason to change

ํด๋ž˜์Šค๋Š” ์˜ค์ง ํ•˜๋‚˜์˜ ์ด์œ ๋กœ ์ˆ˜์ •์ด ๋˜์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

# Example

SRP๋ฅผ ์œ„๋ฐ˜ํ•˜๋Š” ์˜ˆ์ œ๋กœ ์•„๋ž˜ ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ์„ ๋ณด์ž

Register ํด๋ž˜์Šค๊ฐ€ Student ํด๋ž˜์Šค์— dependency๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ชจ์Šต์ด๋‹ค. ๋งŒ์•ฝ ์—ฌ๊ธฐ์„œ ์–ด๋–ค ํด๋ž˜์Šค๊ฐ€ Student๋ฅผ ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์ •๋ ฌ์„ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌํ˜„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ Register ํด๋ž˜์Šค๋Š” ์–ด๋– ํ•œ ๋ณ€๊ฒฝ๋„ ์ผ์–ด๋‚˜์•ผํ•˜์ง€ ์•Š์ง€๋งŒ Student ํด๋ž˜์Šค๊ฐ€ ๋ฐ”๋€Œ์–ด์„œ Register ํด๋ž˜์Šค๊ฐ€ ์˜ํ–ฅ์„ ๋ฐ›๋Š”๋‹ค. ์ •๋ ฌ์„ ์œ„ํ•œ ๋ณ€๊ฒฝ์ด ๊ด€๋ จ์—†๋Š” Reigster ํด๋ž˜์Šค์— ์˜ํ–ฅ์„ ๋ผ์ณค๊ธฐ ๋•Œ๋ฌธ์— SRP๋ฅผ ์œ„๋ฐ˜ํ•œ๋‹ค.

์œ„์˜ ๊ทธ๋ฆผ์€ SRP ์œ„๋ฐ˜์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ์ด๋‹ค. ๊ฐ๊ฐ์˜ ์ •๋ ฌ ๋ฐฉ์‹์„ ๊ฐ€์ง„ ํด๋ž˜์Šค๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•˜๊ณ  Client๋Š” ์ƒˆ๋กœ ์ƒ๊ธด ํด๋ž˜์Šค๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

# ๊ด€๋ จ ์ธก์ • ํ•ญ๋ชฉ

SRP๋Š” ๊ฐ™์€ ๋ชฉ์ ์œผ๋กœ responsibility๋ฅผ ๊ฐ€์ง€๋Š” cohesion๊ณผ ๊ด€๋ จ์ด ๊นŠ๋‹ค.

# Open Closed Principle(OCP)

Software entities (classes, modules, functions, etc) should be open for extension but closed for modification

์ž์‹ ์˜ ํ™•์žฅ์—๋Š” ์—ด๋ ค์žˆ๊ณ  ์ฃผ๋ณ€์˜ ๋ณ€ํ™”์—๋Š” ๋‹ซํ˜€ ์žˆ์–ด์•ผ ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

# Example

void incAll(Employee[] emps) {
    for (int i=0; i<emps.size(); i++) {
        if(emps[i].empType == FACULTY)
            incFacultySalary((FACULTY)emps[i])
        else if(emps[i].empType == STAFF)
            incStaffSalary((STAFF)emps[i])
        else if(emps[i].empType == SECRETARY)
            incSecretarySalary((SECRETARY)emps[i])
    }
}

์œ„์˜ ์˜ˆ์ œ๋Š” ์•„๋ž˜ ๋ฌธ์ œ์ ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

Rigid - ์ƒˆ๋กœ์šด employee type์ด ๊ณ„์† ์š”๊ตฌ๋œ๋‹ค.

Fragile - ๋งŽ์€ if/lese ๊ตฌ๋ฌธ๊ณผ ์ฝ”๋“œ๋ฅผ ์ฐพ๊ธฐ ์–ด๋ ต๋‹ค

์ด์ „์— ์„ค๋ช…ํ•œ ๋ฌธ์ œ์ ์„ ํ•ด๊ฒฐํ•œ ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ์ด๋‹ค.

incAll() ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด์„œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

# Liskov Substitution Principle(LSP)

subtypes must be substitutable for their base types

base ํด๋ž˜์Šค์—์„œ ํŒŒ์ƒ๋œ ํด๋ž˜์Šค๋Š” base ํด๋ž˜์Šค๋ฅผ ๋Œ€์ฒดํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์•ผํ•œ๋‹ค.

# Example

์•„๋ž˜๋Š” Java ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ Date ํด๋ž˜์Šค์ด๋‹ค.

java.util.Date date = new java.util.Date();
int dateValue = date.getDate(); // Okay

date = new java.sql.Time(10,10,10);
dataValue = date.getDate(); // throws IllegalArgumentException

# Inheritance Vs. Composition

์œ„์˜ ์˜ˆ์ œ์—‡ ๋งŒ์•ฝ List์˜ Implemenation์„ ์žฌ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด inheritance๋ณด๋‹ค object composition์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•œ๋‹ค.

์œ„์—์„œ Queue ํด๋ž˜์Šค๊ฐ€ List ํด๋ž˜์Šค๋ฅผ inheritance ํ•œ๋‹ค๋ฉด LSP๋ฅผ ์œ„๋ฐ˜ํ•˜๊ฒŒ ๋œ๋‹ค.

# Interface Segregation Principle(ISP)

Clients should not be forced to depend on methods they do not use

์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๋ฉ”์†Œ๋“œ์— ์˜์กดํ•˜๋ฉด ์•ˆ๋œ๋‹ค.

Roast Application์€ getName(), getSSN() ๋ฉ”์†Œ๋“œ๋งŒ์„ ์‚ฌ์šฉํ•˜๊ณ  Account Application์€ getInvoice(), postPayment() ๋ฉ”์†Œ๋“œ๋งŒ์„ ์‚ฌ์šฉํ•œ๋‹ค.

์œ„ ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ ์ฒ˜๋Ÿผ ํด๋ž˜์Šค์— ๋งž๋Š” interface๋ฅผ ๋งŒ๋“ค์–ด์„œ ์ œ๊ณตํ•˜๋ฉด ISP ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

# Dependency Inversion Principle(DIP)

high-level modules should not depend on low-level modules. Both should depend on abstractions

์ž์‹ (high level module)๋ณด๋‹ค ๋ณ€ํ•˜๊ธฐ ์‰ฌ์šด ๋ชจ๋“ˆ(low level modeul)์— ์˜์กดํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค.

# Inversion?

Program ํด๋ž˜์Šค๋Š” Module ํด๋ž˜์Šค์— dependency๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ Module ํด๋ž˜์Šค๋Š” Function ํด๋ž˜์Šค์— ์˜์กดํ•˜๊ณ  ์žˆ๋‹ค.

Module ํด๋ž˜์Šค๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค ํด๋ž˜์Šค๋กœ ๋ณ€๊ฒฝ์„ ํ•œ ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ์ด๋‹ค. ์ด์ „ ๊ทธ๋ฆผ๊ณผ ๋‹ค๋ฅด๊ฒŒ depenedency๊ฐ€ inversion ๋œ ๋ชจ์Šต์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

DIP๋Š” dependency๋ฅผ inversion ํ•˜๋Š” ๊ฒƒ ๋ฟ ์•„๋‹ˆ๋ผ ownership ๋˜ํ•œ inversion ํ•œ๋‹ค.

์ตœ์ข… ์ˆ˜์ • : 12/17/2022, 7:23:59 AM