티스토리 뷰

golang

SOLID in GO - Single Responsibility Principle

주먹불끈 2021. 3. 31. 16:12

Photo by Austin Distel on Unsplash

 

SOLID 여러 마주쳤지만 제대로 이해했다고는 못하겠다. 이번에는 실제 Go 코드를 통해 이해해 보려 한다. SOLID 따르는 Go 코드는 어떤 모양이어야 할까Dave Cheney 발표내용을 기반으로 하여  알아보았다.

 

- Dave Cheney posting: https://dave.cheney.net/2016/08/20/solid-go-design

- Dave Cheney YouTube: https://youtu.be/zzAdEt3xZ1M

 

SOLID 무엇인지 위키부터 찾아보자. https://www.wikiwand.com/en/SOLID

 

In object-oriented computer programming, SOLID is a mnemonic acronym for five design principles intended to make software designs more understandable, flexible, and maintainable

OOP에서 이해하기 쉽고, 유지와 변경이 쉬운 소프트웨어 디자인이 되도록 하는 다섯가지 디자인 원칙의 첫문자를 것이다.

코드리뷰의 기준

 

경험있는 개발자라면, 코드를 보면 엉망인지 짜여져 있는지 느낌이 것이다.

근데 이건 주관적이다.(subjective!) 좀더 객관적인(objective) 기준을 가져야 한다.

 

나쁜 코드란 무엇일까?

Dave Cheny 정리를 가져와보자.

 

Rigid. Is the code rigid? Does it have a straight jacket of overbearing types and parameters, that making modification difficult?

- 너무 고정되어 있어서 변경하기 힘들다.

 

Fragile. Is the code fragile? Does the slightest change ripple through the code base causing untold havoc?

- 위태롭게 구현해서, 조금만 고쳐도 시스템 전체가 영향을 받는다.

 

Immobile. Is the code hard to refactor? Is it one keystroke away from an import loop?

- 의존성이 얽혀있어서 리팩터링이 어렵다.

 

Complex. Is there code for the sake of having code, are things over-engineered?

- 과하게 구현되었다.

 

Verbose. Is it just exhausting to use the code? When you look at it, can you even tell what this code is trying to do?

- 장황하고 번잡스럽다.

 

누가 코드를 보고 이렇게 부정적인 지적을 해주면 기분이 좋지 않을 것이다.

좋은 디자인은 이래야 한다는 긍정적이면서도 객관적인 리뷰를 해주면 좋겠다.

 

그게 바로 SOLID 이다!

 

- Single Responsibility Principle

- Open/Closed Principle

- Liskov Substitution Principle

- Interface Segregation Principle

- Dependency Inversion Principle

 

지금부터 하나씩 들여다보자

 

Single Responsibility Principle

 

"A class should have one, and only one, reason to change." - Robert C Martin

“Do one thing and do it well” - McIlroy (Unix philosophy)

 

가지 기능만 하게, 그걸 제대로 하게 구현하자는 거다. 그러면 기능을 수정할 필요가 있을 때에만 수정하면 된다.

이러한 작고 날카로운 기능의 도구들을 조합해서 애초에 만든 사람도 상상 못한 기능을 수행할 수도 있다.

 

Coupling & Cohesion - 결합과 응집?

coupling 하나 변경하면, 다른것도 변경해야 한다는 것이다. 좋은 아니다. 

cohesion 떨어져 있지만 관련이 있다는 것이다. 서로 끌린다고 할까? 관련이 있으면 가까이 붙어 있는게 좋다.

 

Go code example

아래 링크에 정리가 되어 있다.

참고 링크: https://medium.com/@felipedutratine/solid-single-responsibility-principle-in-golang-dc4a6be9bb3a

 

class struct 바꿔서 이야기하면 struct 오직 하나의 responsibility만을 가져야 한다는 것이다.

이를 체크해보려면 아래 가지를 챙겨보면 된다.

 

1. 구조체의 메서드가 구조체와 관련이 있는 행위인가?

 

- 아래 예제로 보면 book title 알아내는 구조체와 관련이 있는 행위이지만

- book 저장하는건 관련이 있는 행위라고 보기 어렵다. 이런 경우 별도의 구조체와 메서드로 분리시켜야 하는 것이다.

- 하나의 구조체에 하나의 기능. Single structure single responsibility

 

2. 구조체가 다른 구조체와 단단하게 결합(tightly coupled) 되어있나?

 

- 느슨하게 결합(loosely-coupled)되어 있어야 한다. 결합도가 낮을 수록 좋다

- BookToFile 이나 BookToDB 구조체의 Save() 메서드를 변경한다 하여도 Book 구조체나 구조체의 GetTitle() 메서드는 변경할 필요가 없다

 

3. 메서드를 다르게 적용할 있나?

 

- 만약 Book 구조체의 메서드로 Save() 구현했다면 어떨까?

- 아마도 어디에 저장할지를 인자로 받거나, SaveToFile, SaveToDB와 같이 여러 개의 메서드를 따로 구현해야 했을 것이다.

- 하지만 SRP 입각해서 각각의 다른 구조체의 역할로, 아래와 같이 구현하면 문제가 해결된다.

 

코드 링크: https://play.golang.org/p/Js1PwFo1X6j

 

 

Go code example 2

 

반복 학습 삼아서 다른 예제를 살펴보자. 미묘하게 다르다.

참고 YouTube 링크: https://youtu.be/AKdvlr-RzEA

 

1. Circle 구조체의 메서드인 area() 너무(?) 많은 일을 한다. 면적 계산도 하고, 출력도 해준다.

 

2. Square 구조체의 구현을 들여다보자.

 

- name() area()라는 메서드를 가지고 있다. 둘다 Square 밀접한 관계가 있음을 있다.

- Shape 인터페이스를 만족하려면 name(), area() 메서드를 구현한 녀석이어야 한다.

- Outputter 라는 구조체가 있는데 이건 Shape라는 인터페이스를 만족하는 인스턴스를 인자로 받는다. 바로 Square 구조체가 이를 만족한다.

- Outputter Text(), JSON() 이라는 메서드가 있다. Outputter, 출력하는 녀석이라는 이름에 걸맞게 Text 또는 JSON 형태로 출력을 해준다.

 

코드 링크: https://play.golang.org/p/WDcBlmOH3W1

 

 

 

다음 포스팅에서는 Open/Closed Priciple 알아보자

 

 

 

반응형
반응형
잡학툰 뱃지
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함