소프트웨어 파괴의 미학 - 불확실성에 대항하는 방법
(kciter.so)- 소프트웨어는 많은 것이 불확실하다.
- 불확실한 이유는 무엇일까?
- 가장 큰 이유는 비즈니스의 복잡성이 존재하기 때문
- 복잡성으로 인해 상황은 계속해서 변하며 이로 인해 개발자의 예측은 높은 확률로 틀린다.
- 공들인 탑이 무너져 그대로 기술부채로 변한다.
- 작은 이유는 지식과 경험의 부족 때문
- 지식과 경험이 없다면 개발자 스스로 만들어낸 기술부채를 만들 수 있음
- 비즈니스의 복잡성은 개발자가 통제할 수 없는 외부 요인, 반면 지식과 경험은 개발자가 통제할 수 있는 내부 요인
- 개발자에게는 세 가지 길이 있음
- 복잡성에 대항하는 것은 무의미하다고 생각하는 염세주의적 길
- ’어차피 변경될테니 그냥 하자’, ‘기술은 무의미해’와 같은 말을하게 됨
- 편하고 안락한 길이기에 자신도 모르게 이 길을 선택 할 수 있음
- 복잡성을 외면하고 이상적인 가상만을 생각하는 길
- 자신이 이상적이라 생각하는 한 가지 기술로 모든 것을 해결할 수 있다고 믿음
- 경직되고 획일화된 사고를 가지게 됨
- 개발자는 쉽게 빠질 수 있는 길이지만 빠져나오기 힘듬
- 복잡성을 받아들이고 맞서 싸우는 길
- 완벽할 수 없다는 것을 받아들여도 계속 더 나은 길을 찾으려 하는 것
- 어렵고 견뎌야하는 길
- 소프트웨어 개발은 계속해서 복잡성과 싸워왔음
- 아키텍처, 방법론, 애자일 등…
- 다음은 무엇이 등장할까?
- 복잡성에 대항하는 것은 무의미하다고 생각하는 염세주의적 길
- 파괴 지향 개발
- 현실을 보면 어차피 지워진다라는 염세주의적 생각에 빠지기 쉽다.
- 우리가 열심히 작성한 코드가 실패작이라 느끼며 스스로 지우는 것은 매우 고통스럽기 때문
- 차라리 거꾸로 생각하여 차라리 잘 지울 수 있게 만드는 것은 어떨까?
- 파괴는 좋은 것인가?
- 파괴가 없다면 새로운 것은 탄생할 수 없음
- 소프트웨어에서 볼 수 있는 파괴는 크게 두 가지 - 피벗과 리팩터링
- 피벗은 조직과 제품이 더 나은 길을 선택할 수 있게 해줌
- 리팩터링은 소프트웨어의 생명은 더 연장하기 위해서 꼭 필요한 일
- 그래서 파괴 지향 개발이란?
- 언젠가 코드가 파괴될 것이라는 사실을 받아들이고, 그것을 지향하여 개발하는 방법론
- 세 가지 대원칙을 지향
- 불확실성이 있다면 가능한 만큼 불확실성을 줄인다.
- 여러 방법을 선택할 수 있다면 파괴하기 쉬운 쪽을 선택한다.
- 필요한 것만을 유지한다. 따라서 필요 없는 것은 전부 지운다.
- 분석 -> 경계 분리 -> 코드 구현 -> 복잡성 제거
- 내부 요인에 따른 불확실성을 줄이고 어쩔 수 없는 외부 요인으로 인한 파괴에 대비하는 것이 핵심
- 경계 분리
- 불확실성은 변화율이며 이를 기반으로 분리하는 것이 가능
- 개발자는 외부 요인에 대비하며 최대한 내부 요인으로 인한 변화율을 줄여야 함
- 각 요인의 변화율은 조직마다 다를 수 있기 때문에 고정적인 수치로 표현하는 것은 불가능 -> 휴리스틱한 방법으로 측정
- ex) 스토리 포인트 측정
- 무엇을 기준으로 분리할지 추상화 레벨을 결정해야함
- 파괴 가능성
- 구현을 할 때는 대원칙에 따라 파괴하기 쉬운 쪽을 선택
- 독립성, 인지가능성, 통제가능성을 고려하여 파괴 가능성을 판단할 수 있음
- 독립성은 결합도와 응집도의 정도, 단일 책임 원칙을 어느정도로 지켰는지로 판단
- 인지가능성은 개발자가 코드를 보고 이해할 수 있는 정도
- 통제가능성은 개발자가 통제할 수 있는 영역인지를 판단
- 복잡성 제거
- 불필요한 것이 있는지 확인하고 제거해야 한다. 즉, 최종적으로 코드베이스엔 필요한 것만을 남겨야 함
- 마감일 등에 대한 문제로 인해 작업하는 것이 어렵다면 기록만 해두고 작업해도 문제는 없음
- 내부 요인은 통제 가능하기 때문
- 파괴에 대비하여 최대한 단순성을 유지하는 것이 핵심
- 코드 파괴의 기술
- 코드를 잘 지우는 여러 원칙과 방법이 있음
- 단계 쪼개기 (리팩터링 패턴)
- 참조 투명성 지키기
- 단일 책임 원칙 지키기
- 인터페이스 분리 원칙 지키기
- 스트랭글러 무화과 패턴
- 메서드 전문화
- 중복 코드 작성
- 변화율 기록
지식과 경험이 부족해서 코드 부채를 만든다는 말은 별로 공감이 안가네요
-> 요구사항 구현에 주어진 시간이 모자랄 수도 있고, 협업하는 경우 타인과 조화를 위해 약간의 기술부채를 감내하는 경우도 있고 상황은 다양하다고 생각합니다.
지식과 경험을 개발자가 통제할 수 있는 내부 요인으로 보는 것도 잘 모르겠어요
-> 비즈니스는 복잡해서 어떤 상황이 닥쳐올지 예측할 수 없는데 모든 경우의 수를 그때그때 공부할 수도 없죠. 그 상황에 닥쳐서 공부를 하더라도 다음번엔 전혀 새로운 문제가 발생해 지식이 쓸모없어질 수도 있고요.
안녕하세요. 의견 주셔서 감사합니다.
저는 극단을 들여다보았을 때 비로소 본질을 볼 수 있다고 생각합니다. 그런 측면에서 봤을 때 ‘지식과 경험’을 완벽하게 알고 있었다면 시간 내에 부채가 아닌 코드를 만들어낼 수 있다고 생각했습니다.
시간이 부족하다는 것은 두 가지로 나뉠 수 있습니다. 첫 번째는 말 그대로 구현에 필요한 시간이 부족한 경우입니다. 이 경우는 지식과 경험과 별개로 코드를 작성하는 물리적인 시간이 부족해집니다. 따라서 애초에 목표 달성이 불가능한 조건입니다. 두 번째는 무엇이 좋은지 알아볼 시간이 부족한 경우입니다. 이런 경우는 구현에 대한 방법을 알아보거나 더 나은 좋은 것을 찾는 시간이 부족하기 때문에 지금 알고 있는 지식으로만 코드를 작성하여 일을 끝냅니다. 이렇게 일을 완수하면 ‘어딘가 잘못됐다는 것’은 알지만 정확히 어떻게 고쳐야 하는지는 모릅니다. 만약 정확한 지식이 있었고 그에 대한 경험으로 자신감을 얻었다면 이런 문제가 생기지 않을 겁니다.
위에 작성한 시간 부족은 제 의견을 뒷받침해 준다고 생각합니다. 물론 현실적으론 굉장히 어려운 문제입니다. 저는 그저 이상적인 말을 했을 뿐이죠. 완벽하게 지식과 경험을 갖춘 상태는 드물고 말씀하신 것처럼 조직을 위해 일부러 감내하는 경우도 분명 있습니다. 억울함이 있을 수 있지만 저는 이 문제를 ‘극단적으로 본다면’ 지식과 경험이 부족했기에 생긴 문제라고 생각했습니다.
두 번째로 말씀 주신 내부 요인은 간단합니다. ‘비즈니스는 복잡해서 어떤 상황이 닥쳐올지 예측할 수 없는데 …’ 이 부분은 제가 작성한 글에서 ‘비즈니스의 복잡성’에 대한 이야기입니다. 즉, 외부 요인으로 인한 문제입니다. 외부 요인이기 때문에 개발자가 통제할 수 없고 두려움을 느끼는 것입니다. 이 또한 극단적으로 바라봐 비즈니스의 복잡성이 없다고 가정한다면 개발자가 작성한 코드만이 남을 뿐입니다. 그렇다면 내부적으로 통제할 수 있는 ‘지식과 경험’의 문제만이 남습니다.
물론 제가 작성한 글 또한 저의 의견일 뿐입니다. 충분히 반례가 있을 수 있습니다. 의견 교환은 더 나은 길로 갈 수 있는 기회라고 생각합니다. 앞으로도 많은 의견 부탁드립니다. 감사합니다.
글 잘 읽었습니다. 조직의 스테이지에 따라 무엇이 이른 최적화고 오버엔지니어링이냐도 달라지는 듯 해요. 어차피 다시 짜야할 코드기도 하면서 다시 짤 순간이 올지 안올지도 모르는 코드라는게 어려운 지점이네요. 저는 xxx 서비스, 기능이 없어진다 했을 때 yyy 코드, 데이터는 어디에 있는게 적절한가? 라는 질문으로 판단할 때도 있는데 다른 분들의 방법도 궁금하네요.
코드 말고도 데이터나 스키마도 없어지거나 변경될 수 있는지 생각하는 편입니다
- DB 스키마, 프로토콜(REST API 같은), 기능 세 가지 분류 중 코드가 어디에 해당하는지 생각합니다. 스키마와 프로토콜은 필연적으로 회사 내부의 코드나 외부에 전파되기 때문에 나중에 바꾸려면 혼자 며칠만에 해결할 수 없고 협업이 필요하게 됩니다. 따라서 설계 단계에서 시간을 좀 더 씁니다
- 코드가 다루는 데이터의 라이프사이클과 휘발성을 생각합니다. winterjung님께서 고민하시는 서비스가 없어질때의 상황도 포함이 될 것 같네요. OLTP에서 얘기하는 원장, 거래, 이력 테이블 분류도 이런 고민을 시작해보는 방법이 될 수 있을 것 같습니다