36. 칠판
형사들은 다른 형사의 존재를 알 필요가 없다. 형사들은 칠판을 보며 새로운 정보를 얻고, 자기가 발견한 것을 칠판에 덧붙인다.
느슨한 결합의 정수
일반적으로 의존성을 줄이기 위해 interface 를 사용하여 DI 를 한다.
결국 caller 는 callee 의 존재를 알아야하고, 칠판 아키텍처에서는 그 연결조차 끊어버린다.
이는
이벤트 기반 아키텍처 ( Event Driven Architecture )와 맞닿아있음.여러 서비스 간에는 서로를 모른다.
차량 서비스는 회원 서비스를 모른다.
누가 해당 데이터를 쓸지고민하는 게 아니라, 데이터 그 자체를 그냥 발행하는 것인 거임
데이터의 도착 순서는 이제 상관없다. 어떤 사실이 칠판에 올라가면 적절한 규칙이 발동되도록 하면 된다.
순차적인 프로그래밍에서 탈피해야한다고 말하는 것 같다.
SAGA pattern (코레오그래피 방식)이 그 예시가 될 수 있을 것 같다.
이는 중앙 제어자(오케스트레이터) 가 없는 방식이고
서비스 A 이벤트 발행 → 서비스 B 가 해당 이벤트 구독후 다음 작업 실행하는 방식인데
순서를 제어하는 것이 아니라, 상태(Context) 에 반응하는 것을 말한다.A 동작 → B 동작이 아니라
B 는 칠판에 A 가 완료된 사실이 적히면 동작한다.. 라는 관점으로 변경되는 것임.
이런 접근 방식을 사용하면 많은 동작이 간접적으로 일어나므로 분석이 더 힘들다… 고유한
추적 아이디 trace id를 만들어서 붙이는 것이다.
일단 칠판 아키텍처의 경우 서비스간에 서로를 인지하지 않고 개발되기에, 서비스간에 이벤트가 발행되는 경우 흐름을 추적하기가 어렵다
그래서
분석 추적이라는 기술을 하용하는데Spring Cloud Sleuth나Zipkin이라는 도구가 왜 필요한지 말해준다.Spring CLoud Sleuth → 로그에 Trace ID 와 Span ID 를 자동으로 삽입해줌.
Span ID 는 각 서비스 단위로 부여되는 ID
Trace ID 는 하나의 요청이 시작되어 끝날 때까지 유지되는 고유 ID
뭐 암튼, 추적 아이디로 비동기 아키텍처의 단점을 대처할 수 있다고는 한다
다만!
디버깅이 어려워지는 건 어쩔수없다. 실제 응답을 전부 로깅할 순 없기에 머릿속으로 예측해야하는 상황이 발생하긴 할 것이다..
결
이벤트 기반 아키텍처 구성
복잡한 비즈니스 로직을 if - else 보다는, 상태 변화에 반응하는 리스너들의 집합으로 한 번 짜보기
Trace ID..
40. 리팩토링
소프트웨어 개발은 건축보다 정원 가꾸기에 더 가깝다… 정원의 건강 상태를 지속적으로 관찰하며, 필요하면 토양, 식물, 정원 배치를 조정한다.
소프트웨어 아키텍처는
건축이 아니다설계도를 아무리 완벽하게 그리고, 그대로 건물을 올리려도 끝이 아닌게
잘 짜인 것 같은 로직도 결국에 시간이 지나면 잡초가 무성해진다 ( 기술 부채 )
완벽주의는 개발자에게는 독이다.꾸준함이 더 중요하다고 한다.우리는
정원사다꾸준히 매일 조금씩 가꾸는 정원사가 되어야 하는 것이다.
애자일과 지속적 통합의 철학과 매우 가깝다고 볼 수 있다.
밖으로 드러나는 동작은 그대로 유지한 채 내부 구조를 변경함으로서.. 이 활동은 체계적이다. 아무렇게나 하는 것이 아니다.
안전장치 == 테스트 코드
테스트 코드가 없는 상황에서 코드 수정은 리팩토링이 아니라 도박임
리팩토링 실력을 늘리려면,
테스트 코드를 작성하는 능력을 길러야 한다.
리팩토링은 여러분이 무언가를 알게 되었을 때 한다. 작년이나 어제, 심지어 10분 전과 비교해서 더 많이 알게 되었다면, 리팩토링을 한다
과거에 내가 짠 코드를 보면서
내가 왜 이렇게 짰지?라며 부끄러워 한 적이 모두 있을 것이다.그 부끄러움은
성장의 증거이다.
코드가 구려 보이는 이유는
지금의 내가 비즈니스 도메인을 더 깊이 이해했거나, 프레임워크의 동작 원리를 더 잘 알게 되었기 때문이다.
No Longer valid knowledge지식은 시간에 따라 변하고
그 변환에 따라 현행화되어야 한다.
지행합일
아는 것과 행하는 것은 본래 하나여야 한다.
머리로 이해한 구조가 코드에도 그대로 흐르게 하는 것이 중요하다.
리팩토링과 기능 추가를 동시에 하지마라
켄트 벡 : 두 개의 모자 이론
기능 추가의 모자를 썼을 때는 기능 구현에만 집중하고
리팩토링의 모자를 쓴 경우, 오로지 구조 개선에만 집중핼라.
기능 구현과 리팩토링이 하나의 커밋에 섞이는 순간, 코드 리뷰어는 고통받고 롤백이 힘들어진다.
결
테스트 코드가 없는 레거시를 건드려야 한다면, 아주 작은 단위의 테스트라도 먼저 만들고 시작하기
리팩토링과 기능 추가 커밋을 철저히 분리하기
44. 이름 짓기
우리는 코드에서 하는 역할에 따라 이름을 지어야 한다고 믿는다… 내가 왜 이것을 만드는 거지? 라고 생각해야 한다는 뜻이다.
기능 구현에 급급하다보면 쓰레기같은 변수명이 등장할때도 있다.
이름 짓기가
설계 검증에서의 첫 단계임을 기억해야 한다.적절한 이름이 잘 떠오르지 않으면, 해당 클래스나 메서드가 역할이 모호하지 않은가 고민해야한다.
변수명은 user다. 언제나 user니까. 하지만 왜 그래야 할까? customer 나 buyer 는 어떤가?
모든 도메인에서
User라는 단어 하나로 퉁치려는 경향이 있음.쇼핑몰의 경우 사는 사람은
Buyer이고, 배송 받는 경우에는Recipient이다.DDD 상의 개념으로 기획자나 현업 담당자가 쓰는 용어를 코드에 그대로 투영해야 한다.
user.buy() 보다 buyer.placeOrder() 같은 도메인에 녹아있는 코드가 완성되는 것이다.
글자의 색깔을 크게 말해보자… 여러분의 뇌는 단어를 꼭 지켜야 하는 것으로 인식한다. 그렇다면 이에 걸맞게 우리가 사용하는 이름을 잘 지어야 한다.
그냥 코드가 읽히는 대로 잘 동작해야 한다고 말하는 것이다.
스트루트 효과를 책에서는 예시로 드는데
글자 색과 단어의 의미가 다를 때 사람의 인지 속도가 느려지는 현상을 말한다.
만약에 코드에서
getAccount가 내부적으로 DB 조회가 아니라계정 생성을 수행한다면, 내부 로직을 별도로 확인하지않고 치명적인 버그로 이어질 수도 있음.
Fib.of(0)... Fib.nth(20)... 이름을 지을 때는 여러분의 표현하고 싶은 것을 더 명확하게 다듬기 위해 끊임없이 노력해야 한다.
그냥 메서드이름과 파라미터가 합쳐졌을 때 하나의 영어 문장처럼 자연스럽게 읽히도록 설계하는 것이 가독성의 핵심임
48. 애자일의 핵심
물리적인 세계에서든 소프트웨어 개발에서든 애자일, 즉 기민함이라는 것은 변화에 대응하느 것, 일을 시작한 이후 맞부딪히는 미지의 것에 대응하는 것이 전부이기 때문이다.
개발자의 덕목은
완벽한 예측이 아니라,빠른 피드백 수집이다.거창한 아키텍처를 세우느라 2주를 쓰는 것 보다, 핵심 기능만 들어가는 프로토타입을 2일 만에 만들어 클라이언트에게 던지는 것이
미지의 영역을 줄이는 기민한 방법임
좋은 설계는 나쁜 설계보다 바꾸기 쉬운 결과물을 만든다… 바꾸기 쉽다면 모든 층위에서 아무런 주저 없이 문제를 바로잡을 수 있을 것이다. 이것이 애자일이다.
코드가 엉망이면 애자일은 불가능하다.
애자일의 핵심은
변화에 대한 대응이다.코드가 스파게티처럼 얽혀있는 경우 변화 자체가 공포가 된다.
수정 하나에 버그가 10개씩 터지면, 팀이 보수적으로 변화하게 될 수 밖에 없다.
SOLID 원칙을 지키고, 테스트 코드를 짜고, 리팩토링을 하는 행위자체는 팀내에서기동성을 획득하기 위한 생존 활동임.기술 부채가 많으면
애자일할 수 없는 것임.
52. 사용자를 기쁘게하라
여러분의 사용자가 진짜로 원하는 것은 코드가 아니다… 진정한 여러분의 직함은
문제 해결사이다.
요구사항 너머의 진짜 문제를 볼 수 있어야 한다.
개발자는 기획자의 요구사항을 법전처럼 여기는 경향이 있는데
엑셀 다운로드 기능이 필요하다면 왜 필요한지 물어봐야한다.
실제로는 월별 통계를 보고 싶었던 것이고
월별 통계만 보는 것이면 대시보드 페이지 하나 만들어서 제공하는게 시스템 부하도 줄고, 사용자도 더 황홀하게 만들 수 있다
기술적인 우월감보다는 비즈니스 가치를 바라봐야한다.
사용자를 기쁘게 하는 것은
우아한 코드가 아니라,나의 문제를 해결해 준 투박한 기능 하나이다.