Programming Language/Python

@abstractmethod๋ฅผ ํ†ตํ•œ SOLID ์›์น™ ์ ์šฉํ•˜๊ธฐ

soheeeeP 2022. 2. 27. 17:06

 

๐Ÿš€ ๊ฐœ์š”

db์—๋Š” ์—ฌ๋Ÿฌ ์ข…๋ฅ˜์˜ table์ด ์กด์žฌํ•œ๋‹ค. 
์„œ๋น„์Šค์˜ business layer์—์„œ๋Š” ํ•„์š”์— ๋”ฐ๋ผ ๊ฐ table์— ์ ‘๊ทผํ•˜์—ฌ query๋ฅผ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•  ๊ฒƒ์ด๋‹ค.

ORM๊ฐ™์€ ํ”„๋ ˆ์ž„์›Œํฌ ํˆด์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  raw query๋ฅผ ์ „๋ถ€ ์„ ์–ธํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, ์ด query๋“ค์„ ์–ด๋–ป๊ฒŒ ์ž‘์„ฑํ•˜๋Š”๊ฒŒ ์ข‹์„๊นŒ?
์ „๋ถ€ ํ•˜๋‚˜์˜ class์— method๋กœ์„œ ์„ ์–ธํ•˜๊ธฐ? create, update๋“ฑ ์šฉ๋„์— ๋”ฐ๋ผ ๋ถ„๋ฆฌํ•˜๊ธฐ?

entity, interface, repository, ๊ฐ๊ฐ layer๋ฅผ ์ถ”์ƒํ™”ํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉฐ ๋‚ด๊ฐ€ ๊ทธ๋ฆฌ๊ณ ์ž ํ–ˆ๋˜ ํŒŒ์ด์„  architecture๊ฐ€ ์–ด๋–ค ๋ชจ์Šต์ด์—ˆ๋Š”์ง€ ๊ธฐ๋กํ•ด๋ณด๋ ค ํ•œ๋‹ค.

 

๐Ÿ“ SOLID ์›์น™: ๊ฐ์ฒด์ง€ํ–ฅ์„ค๊ณ„ 5์›์น™

๋กœ๋ฒ„ํŠธ ๋งˆํ‹ด์ด 2000๋…„๋Œ€ ์ดˆ๋ฐ˜์— ๋ช…๋ช…ํ•œ ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐ ์„ค๊ณ„์— ๋Œ€ํ•œ 5์›์น™์ด๋‹ค. ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ๊ณผ ํ™•์žฅ์„ฑ์„ ์œ„ํ•œ ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ์›์น™์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค. 

SRP ๋‹จ์ผ ์ฑ…์ž„ ์›์น™ (Single Responsibility Principle) ํ•œ ํด๋ž˜์Šค๋Š” ํ•˜๋‚˜์˜ ์ฑ…์ž„๋งŒ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค
OCP ๊ฐœ๋ฐฉ-ํ์‡„ ์›์น™ (Open-Closed Principle) ์†Œํ”„ํŠธ์›จ์–ด ์š”์†Œ๋Š” ํ™•์žฅ์—๋Š” ์—ด๋ ค ์žˆ์œผ๋‚˜ ๋ณ€๊ฒฝ์—๋Š” ๋‹ซํ˜€ ์žˆ์–ด์•ผ ํ•œ๋‹ค
LSP ๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™ (Liskov Substitution Principle) ํ”„๋กœ๊ทธ๋žจ์˜ ๊ฐ์ฒด๋Š” ํ”„๋กœ๊ทธ๋žจ์˜ ์ •ํ™•์„ฑ์„ ๊นจ๋œจ๋ฆฌ์ง€ ์•Š์œผ๋ฉด์„œ ํ•˜์œ„ ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค
ISP ์ธํ„ฐํŽ˜์ด์Šค ๋ถ„๋ฆฌ ์›์น™ (Interface Segregation Principle) ํด๋ž˜์Šค๋Š” ์ž์‹ ์ด ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๋ฉ”์†Œ๋“œ์— ์˜์กดํ•˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค
DIP ์˜์กด๊ด€๊ณ„ ์—ญ์ „ ์›์น™ (Dependency Inversion Principle) ๊ตฌ์ฒดํ™”๊ฐ€ ์•„๋‹Œ ์ถ”์ƒํ™”์— ์˜์กดํ•ด์•ผ ํ•œ๋‹ค

 

 

๐Ÿ“ ์ธํ„ฐํŽ˜์ด์Šค ๋ถ„๋ฆฌ ์›์น™(ISP)๋ž€?

์ธํ„ฐํŽ˜์ด์Šค ๋ถ„๋ฆฌ ์›์น™(ISP, Interface Segregation Principle)์ด๋ž€,
ํ•˜๋‚˜์˜ ํด๋ž˜์Šค(์ธํ„ฐํŽ˜์ด์Šค)๋Š” ๊ทธ '์ฑ…์ž„'์— ์ ํ•ฉํ•œ ๋ฉ”์†Œ๋“œ๋งŒ์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ์›์น™์ด๋‹ค.


์˜ˆ๋ฅผ ๋“ค์–ด๋ณด์ž. ์ด ํด๋ž˜์Šค์—๋Š” config์™€ user. ๋‘ ๊ฐœ์˜ ์„œ๋กœ ๋‹ค๋ฅธ table์— ์ ‘๊ทผํ•˜๋Š” method๋“ค์ด ์„ ์–ธ๋˜์–ด ์žˆ๋‹ค.

QueryMethodInterface

์ด ๊ฒฝ์šฐ, ์šฐ์„ ์ ์œผ๋กœ ํ•„์š”ํ•œ config์— ๋Œ€ํ•œ query method ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, config์™€ ๋ฌด๊ด€ํ•œ user์— ๋Œ€ํ•œ method๊นŒ์ง€ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.
์ฆ‰, ์ž์‹ ์ด ์ด์šฉํ•˜์ง€ ์•Š๋Š” method์— ์˜์กดํ•˜๋Š” ๋ชจ์Šต์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

๋ฌผ๋ก  ๊ตฌํ˜„ํ•˜์ง€ ์•Š๊ณ , ์œ„ ์˜ˆ์ œ์ฒ˜๋Ÿผ pass๋กœ ๋Œ๋ ค๋ฒ„๋ ค๋„ ์—๋Ÿฌ๋ฅผ ๋ฑ‰์ง„ ์•Š์ง€๋งŒ.. ISP๋ฅผ ์ค€์ˆ˜ํ–ˆ๋‹ค๊ณ  ๋ณผ ์ˆ˜๋Š” ์—†๋‹ค.

๋‘ ๊ฐœ์˜ ํด๋ž˜์Šค๋กœ ์ฑ…์ž„์„ ๋ถ„๋ฆฌํ•ด์ฃผ์—ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ด์ œ table์— ๋Œ€ํ•œ ๋…๋ฆฝ์ ์ธ query class๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.


์—ฌ๊ธฐ์„œ ์šฐ๋ฆฌ๊ฐ€ ์žŠ์ง€ ๋ง์•„์•ผ ํ•  ํฌ์ธํŠธ๋Š”,
ISP๋ž€ ํ•˜๋‚˜์˜ interface์— ํ•˜๋‚˜์˜ '๊ธฐ๋Šฅ(method)'๋งŒ ์กด์žฌํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ํ•˜๋‚˜์˜ '์ผ(TASK)'๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๋ชจ๋“  '๊ธฐ๋Šฅ(method)'๊ฐ€ ํฌํ•จ๋˜๋„๋ก ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

 

๐Ÿ“ abc.ABCMeta๋ฅผ ํ†ตํ•ด ์ถ”์ƒ ํด๋ž˜์Šค ์„ ์–ธํ•˜๊ธฐ

๊ทธ๋ ‡๋‹ค๋ฉด ์ด์ œ์œ„์—์„œ ์„ ์–ธํ•œ ํด๋ž˜์Šค๋ฅผ ์ถ”์ƒํ™”์‹œ์ผœ์„œ interface๋กœ์„œ ๋™์ž‘ํ•˜๋„๋ก ๋งŒ๋“ค์–ด๋ณด์ž.
interface๋กœ์„œ ๋™์ž‘ํ•  ์ถ”์ƒ ํด๋ž˜์Šค์— entity์— ์ข…์†์ ์ธ query method๋“ค์„ ์ถ”์ƒ ๋ฉ”์†Œ๋“œ๋กœ ์„ ์–ธํ•ด์ค„ ๊ฒƒ์ด๋‹ค.

ABCMeta๋Š” ํŒŒ์ด์„ ์—์„œ ์ง€์›ํ•˜๋Š” ์ถ”์ƒ metaclass์ด๋‹ค.
์ƒ์„ฑํ•  ์ถ”์ƒ ํด๋ž˜์Šค์— metaclass=abc.ABCMeta๋ฅผ ์ง€์ •ํ•˜๊ณ , 
@abstractmethod ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ๋ถ™์—ฌ์„œ ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๐Ÿ“ ์ถ”์ƒ ํด๋ž˜์Šค(interface)๋ฅผ ์ƒ์†ํ•˜๋Š” ๊ตฌํ˜„ ํด๋ž˜์Šค ์ž‘์„ฑํ•˜๊ธฐ

interface๋ฅผ ์ƒ์†ํ•˜๋Š” repository๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ ,

๋‹จ, ์ถ”์ƒ ํด๋ž˜์Šค์— ์„ ์–ธ๋œ method๋Š” ๋ฐ˜๋“œ์‹œ ์ „๋ถ€ ๊ตฌํ˜„๋˜์–ด์•ผ ํ•œ๋‹ค.

โœ๏ธ  ์†Œ์Šค์ฝ”๋“œ


ํ”„๋กœ๊ทธ๋žจ์˜ main์—์„œ ์ด repository ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  service layer์—์„œ๋Š” ์ด ์ƒ์„ฑ๋œ ๊ฐ์ฒด๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์‚ฌ์šฉํ•œ๋‹ค.
์ฆ‰ ํ”„๋กœ๊ทธ๋žจ์—์„œ, ํ•ด๋‹น entity์— ๋Œ€ํ•ด ์กด์žฌํ•˜๋Š” '์œ ์ผํ•œ' repository๋กœ์„œ ๋™์ž‘ํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๊ตฌํ˜„ ํด๋ž˜์Šค ๊ฐ์ฒด๋ฅผ db์™€ ์—ฐ๊ฒฐํ•œ ์˜ˆ์‹œ

์˜ˆ๋ฅผ ๋“ค์–ด๋ณด์ž.
๋‚ด๊ฐ€ config table์— ์ ‘๊ทผํ•˜์—ฌ, ๊ฐ’์„ ์ˆ˜์ •ํ•˜๋Š” update method๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด?
๋ฐ˜๋“œ์‹œ database.config_repository.__method__๋ฅผ ํ†ตํ•ด์„œ๋งŒ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.
์‹ค์ œ๋กœ ์ด update์— ๊ด€๋ จ๋œ __method__์—์„œ ์–ด๋–ค ๋™์ž‘๋“ค์ด ์ˆ˜ํ–‰๋˜๋Š”์ง€๋Š” ์ € method๋ช…์œผ๋กœ ์ถ”์ƒํ™”๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— service layer๋‹จ์—์„œ ๋ณผ ์ˆ˜ ์—†๋‹ค. 

์•„๋ž˜ ์†Œ์Šค์ฝ”๋“œ ์˜ˆ์‹œ์ฒ˜๋Ÿผ ์ ‘๊ทผํ•˜์—ฌ ์‚ฌ์šฉํ•˜์˜€๋‹ค.

 

์•„ํ‚คํ…์ณ์— ๊ด€์‹ฌ์ด ๋งŽ์•„์„œ ์ฑ…์ด๋‚˜ ์ž๋ฃŒ๋ฅผ ์ฐพ์•„๋ณด๊ณ , ํ˜ผ์ž ์—ด์‹ฌํžˆ ๊ณ ๋ฏผํ•˜๋ฉฐ ์ฝ”๋“œ๋ฅผ ๊ตฌ์ƒํ–ˆ๊ณ  ๋‚˜๋ฆ„์˜ ๊ธฐ์ค€์„ ๊ฐ€์ง€๊ณ  ์„ค๊ณ„ํ–ˆ๋‹ค.
ํ˜ผ์ž A๋ถ€ํ„ฐ Z๊นŒ์ง€ ๊ฒฐ๊ณผ๋ฌผ์„ ๋งŒ๋“ค์–ด๋ณธ๊ฒŒ ์ฒ˜์Œ์ด๋ผ..๐Ÿคฏ 
์ฝ”๋“œ์˜ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ์ฆ๊ฐ€์‹œํ‚ค๊ณ  ์ ‘๊ทผ์„ฑ์„ ์šฉ์ดํ•˜๊ฒŒ ํ•˜์ž ๋ผ๋Š” ์ƒ๊ฐ์—์„œ ์‹œ์ž‘๋œ ์•„ํ‚คํ…์ณ ์„ค๊ณ„๊ฐ€ ์˜คํžˆ๋ ค ๋‹จ์ˆœํ•œ ์ฝ”๋“œ๋ฅผ ๋” ๋ณต์žกํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์€ ์•„๋‹๊นŒ ๊ณ ๋ฏผํ•˜๊ธฐ๋„ ํ–ˆ๋‹ค. 

๊ณ„์† ์Šค์Šค๋กœ์—๊ฒŒ ๋˜์กŒ๋˜ ์งˆ๋ฌธ์ด๋‹ค.

"What do we get for this? And what does it cost us?

 

๐Ÿ” Reference