클린 소프트웨어 - 애자일 개발

dante Yoon·2021년 12월 29일
0

독서

목록 보기
14/38
post-thumbnail

클린 소프트웨어를 읽으며 챕터 1을 정리한 글입니다.

애자일 실천방법

까다롭고 많은 프로세스는 스케줄 지연, 예산 증가, 낮은 품질이라는 대실패의 산출물들을 예방하기 위해 만들어졌지만 오히려 막고자 했던 것들을 산출하는 모순적인 상황들을 야기시켰다.

2001년 초 이전의 딱딱하고 무거운 프로세스에서 벗어나 변화를 빠르게 수용하여 생산성을 증대하기 위한 원칙을 세우기 위해 사람들은 애자일 연합이라는 모임을 만들었다. 이들이 낸 성명서인 The Manifesto of the Agile Alliance에는

다음과 같은 내용이 담겨있다.

  • 프로세스와 툴보다 개인의 상호작용이 우선이다.
    뛰어난 팀원은 프로젝트를 구원해도 엉터리 프로세스는 뛰어난 팀원을 침몰시킨다.
    프로그래밍 실력이 평범해도 대화가 잘 되는 사람이 팀원으로서 더 적합하다는 입장을 표명한다.

  • 포괄적인 문서보다 동작하는 소프트웨어가 우선이다.
    코드는 의소소통의 이상적인 매체가 아니지만 지나친 문서화는 코드와 동기화시키기 위해 많은 시간이 소모하기 떄문에 독이다. 문서는 최대 12~24페이지를 넘으면 안되며, 명확한 코드와 팀원간의 친밀함이 이를 해결해준다.

  • 계약 협상보다 고객 협력이 우선이다.
    성공적인 프로젝트를 위해서는 계약서나 기술서에 의존하기보다는 클라이언트의 주기적인 피드백에 의존하는 것이 필요하다.

  • 계획을 따르는 것보다 변화에 대한 반응이 우선이다.
    고객의 요구사항은 변하게 될 여지가 많기 때문에 소프트웨어는 변화에 적응할 준비가 되어야 한다. 2주간의 세부적인 계획은 수립할 수 있지만 텀이 긴 3개월의 계획은 개략적으로, 그 이후로는 대강의 계획을 세워야 한다. 짧은 기간의 세부적인 계획은 변경하기가 어렵다.

열두가지 원칙

  1. 간단한 기능으로 자주공개할 수록 최종 품질이 좋다. 애자일 실천방법은 빨리, 자주 공개하여 고객의 피드백을 적용하는 것이다.
  2. 개발 후반부라 할지라도 요구사항 변경을 긍정적으로 여긴다.시장의 요구사항을 충족시키기 위해 어떤 것을 해야 하는지 학습했으므로.
  3. 2주, 2달 간격, 혹은 더 짧은 기간으로 작업물을 공개하라. 문서와 계획 꾸러미는 고객을 만족시키지 않는다.
  4. 고객, 개발자, 이해당사자에는 빈번한 상호작용이 있어야 지속적으로 관리될 수 있다.
  5. 애자일 프로젝트 성공의 가장 중요한 요소는 사람이므로 의용적인 개인을 중심으로 프로젝트를 구성하고 그들에게 자원을 제공하라.
  6. 모든 정보를 문서화하지말고 팀원과 일대일로 대화해라
  7. 개발 중인 소프트웨어가 진척 상황의 일차적 척도다.
  8. 진행 속도는 단거리 질주가 아닌 지속가능한 마라톤의 형태를 띄어야 한다.
  9. 가장 높은 품질의 코드를 유지해야 한다.
  10. 미래의 문제를 예상하는데 지나친 관심을 두지 않고 가장 고품질의 단순한 일을 오늘 행해야 한다.
  11. 하나의 일에 하나의 팀원이 온전한 책임감을 갖는게 아니라 팀 전체가 책임을 공유하고 영향력은 분배되어야 한다.
  12. 조직, 규칙, 대화, 관계등을 계속 조정한다.

익스트림 프로그래밍

ㅇ애자일 개발 프로세스를 구성하는 방법들의 집합이다.

고객은 돈을 주는 사람일 수도 있지만 같은 회사에서 일하는 비즈니스 분석가이나 마케터일 수도 있다. 고객과는 항상 붙어서 함께 일해야 한다. 고객을 대신할 수 있는 사람을 찾아야 한다.

사용자스토리

계획을 세우기 위해서는 요구사항을 알아야 하지만 추정을 위해 구체적인 세부사항을 알필요는 없다. 고객과 대화를 하며 몇 개의 단어를 적고 이 연상기호를 이용해 구현일정을 수립한다.

짧은 반복

2주마다 고객의 요구를 처리하는 소프트웨어를 만들고 이를 시연한다. 이런 반복을 통해 고객에게 하나의 2주마다 충족해야 할 스토리의 내용의 범위를 가늠하게 해준다.
반복이 시작되면, 스토리 정의나 우선순위가 바뀌지 않는다는 점을 고객이 동의해야 한다.
6번의 반복일정 끝에 메이저 공개를 하며 이런 방식으로 개발을 하게되면 고객이 요청한 사용자 스토리의 묶음으로 하나의 메이저 공개가 구성된다.

인수테스트

QA, 테스트 스크립트를 이용해 요구사항 구현을 점검한다.

짝 프로그래밍

한 사람이 입력에 지치면 다른 사람이 키보드를 잡는다. 결과물은 두 멤버가 함께 설계하고 작성한 것이며 공적의 반 이상을 한사람에게 몰아주지 않는다.
짝은 매일 변경되어야 한다. 이런 페어프로그래밍은 팀 내부에서 지식이 더 빨리 확산되게 한다.

로리 윌리엄스와 노섹의 연구에 따르면, 페어프로그래밍은 효율성을 떨어뜨리지 않고 결함 발생률을 줄여준다.

테스트 주도 개발

모든 코드는 실패하는 단위 테스트를 통과하기 위해 작성된다.
테스트 케이스를 먼저 작성하고 코드를 작성한다. 두 간격은 1분 정도로 매우 빠르며 두 기능은 함께 진화하며 테스트케이스가 약간 더 앞선다.

공동 소유권

한 팀원이 단일 모듈에 개인적으로 책임을 지지 않는다. 모든 팀원은 미들웨어 작업에 참여하고 GUI에 참여하고 데이터베이스에 참여한다. 페어 프로그래밍은 모든 부분에 있어서 이뤄져야 한다.

지속적인 통합

하루에도 여러번 동일 모듈에 대해 다른 작업이 일어날 수 있다.
따라서 하루에도 여러번 처음부터 끝까지 전체 시스템을 빌드해야 한다.

지속 가능한 속도

마지막 릴리즈 주를 제외하고는 초과 근무를 하지 않는다.

열린 작업 공간

작업 공간은 낮은 웅성거림으로 가득 차 있다. 누군가에게 문제가 생겼을 때 들을 수 있어야 한다.

미시간 대학교의 연구에 따르면 이런 환경 속에서 일하는 것이 두 배 정도의 생산성을 향상할 수 있다고 한다.

계획 세우기 게임

계획 세우기 게임은 업무와 개발의 책임 분리를 하는 것이다.
여기서 업무 관련 인력은 고객이고 개발 관련 인력은 개발자이다.

개발자는 기능 요소를 구현하는데 비용산정을 해야할 책임이 있는데, 개발자는 최근의 반복이나 릴리즈 때 산출했던 양을 기준으로 고객에게 비용 내용을 전달한다. 짧은 계획의 반복과 빈번한 릴리즈를 통해 고객과 개발자는 서로의 리듬에 익숙해진다.

단순한 설계

현재 반복에서 작업하기로 한 계획을 스토리라고 한다. 이 스토리 공략에만 초점을 맞추고 다음 스토리에 대해서는 걱정하지 않는다. 하지만 다음 반복으로 넘어갈 때 다음 스토리에서 가장 적합한 설계가 되도록 한다.

어떻게든 동작하는 가장 단순한 것을 생각한다.

필요하지 않을 것이라는 가정에서 시작한다.

데이터베이스나 멀티스레딩이 추후 프로젝트에 필요할 수는 있지만 확실히 필요해지기 전에는 이렇나 기반구조를 추가하고 싶은 유혹을 냉정하게 거절해야 한다.

코드를 중복해서 쓰지 않는다.

코드 중복을 허용하지 않으며 둘 이상의 알고리즘이 매우 비슷하지만 미묘한 부분에서 다른 경우가 있다. 완전히 같으면 함수나 부모 클래스를 만들어 제거하고, 비슷하지만 미묘한 부분은 탬플릿 메소드 패턴을 사용한다. 중복성을 제거하는 방법은 추상화이다.

리펙토링

기능을 추가하면 코드는 버그를 양산하게 될 가능성이 많고 부패하기 쉽다. 리펙토링을 이용해 이런 현상을 반전시킬 수 있다. 행위에 영향을 주지 않고 시스템의 구조를 개선하는 방식이다. 작은 변환들이 끝나면 단위 테스트를 실시한다.
프로그래머는 1시간 혹은 30분마다 리팩토링을 한다.

메타포

프로그램을 구성하는 각 기능과 코드조각을 퍼즐을 완성하기 위한 각 조각이라고 말한다면, 퍼즐조각을 하나로 묶는 것은 전체 그림에 해당하는 전체 프로그램이다. 이처럼 전체 시스템을 하나로 묶는 큰 그림, 시스템의 비전을 메타포라고 한다.

계획 세우기

애자일 소프트웨어 방법론 중 계획 세우는 방법에는 스크럼, 크리스털등 여러 방법이 있으며 계획 세우기는 XP의 애자일 소프트웨어 개발 방법이다.

초기 탐색

개발자와 고객은 스토리의 기간을 산정하기 위해 논의한다. 기간에는 포인트라는 단위로 그 사이즈가 정해지며 8포인트의 스토리는 4포인트의 스토리보다 두 배의 시간이 필요하다는 사실을 알 수 있다.

스파이크, 분할, 속도

매우 크거나 매우 작은 스토리는 포인트가 정확하게 매겨지기 어려우므로 적절한 덩어리로 분리되거나 합쳐져야 한다.

사용자는 계좌에 안전하게 돈을 넣고, 꺼내고, 이체할 수 있어야 한다.라는 스토리는

  • 사용자는 로그인할 수 있다.
  • 사용자는 로그아웃 할 수 있다.
  • 사용자는 자신의 계좌에 돈을 입금할 수 있다.
  • 사용자는 자신의 계좌에서 돈을 인출할 수 있다.
  • 사용자는 자신의 계좌에서 다른 계정으로 돈을 이체할 수 있다.

4포인트 스토리 두개를 하나로 합친다고 8포인트로 되는 것은 아니다.
반대로 5포인트 스토리가 여러 개로 분할되어 전체 포인트의 합이 10포인트로 되는 것도 자연스러운 결과이다.

포인트에 속도라는 요소를 곱함으로 스토리가 완료되기까지의 기간을 추정할 수 있다. 한두개의 스토리를 합쳐 프로토 타입을 만드는 것을 스파이크라고 한다.

릴리즈 계획 세우기

첫번째 릴리즈 날짜는 보통 2~4달 후 정도가 되며 고객이 첫 릴리즈에 실어질 스토리와 대략적인 구현 순서를 선택한다. 이러한 계획은 처음에는 다소 결과물과 거리가 있을 수 있으나 추후 점점 정확해진다.

반복 계획 세우기

고객이 한 반복에서 구현되야할 스토리를 선택하고 개발자는 합리적인 순서에 따라 스토리를 구현한다. 순차적으로 진행하든 동시에 진행하는 것은 개발자의 몫이다.

변경이 될 수 있는 스토리는 현재 반복에 포함되지 않은 스토리로 제한되어야 한다.

테스크 계획 세우기

개발자는 스토리를 분할해 개발 태스크로 만든다. 테스크는 4~16시간 동안 구현될 수 있는 기능이다.
데이터베이스 담당자라고 데이트베이스 관련 테스크만 담당할 수 있는게 아니라 GUI 태스크에도 적용될 수 있다.

반환점

반복이 반쯤 진행됐을 때, 팀이 미팅을 갖고 스토리의 반이 완료되어 있지 않는다면 팀은 태스크와 책임을 재분배하여 모든 스토리가 확실히 완료되도록 해야 한다.
이때 문제가 있으면 고객에게 보고하며 고객이 어떤 테스크나 스토리를 제외할지 결정한다.

반복

2주마다 반복하며 현재 동작하는 부분을 고객에게 시연하며 개발자는 피드백을 받는다.


테스트

테스트 주도 개발

테스트 설계의 효과는 다음과 같다.

  • 모든 단일 함수가 그 동작을 검증하는 테스트를 갖게 된다.

  • 프로그래머는 편리하게 호출할 수 있다는 인터페이스의 관점에서 소프트웨어를 설계할 수 있게 된다.

  • 반드시 테스트 가능한 프로그램을 설계하도록 강제한다. 이 말은 테스트 가능해지기 위한 모듈들은 주위 환경에서 분리되도록 만들어지는 것을 강제할 수 있다는 뜻이다.

  • 문서화의 한 형태로 기능할 수 있다.

    계획된 프로그래밍 (intentional programming)

    게임 캐릭터를 움직이는 함수를 작성한다고 했을때 이 함수가 실행된 이후 객체의 상태를 파악하는 테스트 코드를 먼저 작성하는 경우를 예로 들 수 있다.
    의도를 쉽게 이해할 수 있는 테스트를 먼저 제시하고 테스트를 통과하기만 하면 의도에 맞는 기능을 작성했다고 볼 수 있는 것이다.
    요점은 테스트를 먼저 작성하는 것이 아주 이른 시기에 주요한 설계의 이슈를 명백히 할 수 있는 것이다.

    테스트 분리

    코드를 작성하기 전에 UML 다이어그램을 그려 객체간의 관계를 추상화할 수 있는데, 이 객체가 데이터베이스를 사용한다면 데이터베이스가 완벽하게 기능을 갖추어야 하는 등 하나의 객체를 테스트하기 위해 보장되어야 할 선결조건들이 많다.

의사 객체 (Mock Object)패턴을 이용해 테스트를 원하는 객체와 관계를 맺는 모든 요소 사이에 인터페이스를 추가하고 이 인터페이스를 구현하는 테스트를 생성한다.

P.38 그림 4-2 테스트를 위해 의사 객체를 사용하는 분리된 Payroll

CheckWriter, Employee, Employee Database 인터페이스 각각에 적절한 의사 객체를 생성하고 PayrollTest 객체가 이들과 소통해 Payroll 객체에 넘겨준다.

옳은 데이터를 사용했을 시 옳은 함수를 호출했는지 여부를 검사할 수 있다. 이 말은 곧 Payroll 클래스가 분리된 것처럼 동작하는지 여부를 검사한다.

운좋게 얻은 분리

코드보다 테스트를 먼저 작성하면 설계가 개선된다. 데이터베이스와 수표 기록기를 교체할 수 있도록 설계되었다는 점에서 확장성에서 이득을 보게 되었다.

인수 테스트

단위 테스트가 작은 구성요소가 독립적으로 동작하는지 여부를 검증한다면, 인수테스트는 시스템이 전체로서 제대로 동작하는지에 대해 검증한다.

테스트는 크게 두가지의 종류가 있다.

  • 화이트박스 테스트 - 테스트 하는 모듈 내부 구조를 알고 그것에 의존하는 테스트 (단위 테스트)

  • 블랙박스 테스트 - 테스트하는 모듈의 내부 구조를 모르고, 그것에 의존하지 않는 테스트 (인수 테스트)

    인수테스트는 시스템의 내부 매커니즘을 모르는 사람들이 작성한다. QA 엔지니어, 고객들이 여기에 속한다.

    테스트 가능한 시스템을 만드려면 상위 아키텍처 수준에서 주변 환경으로 부터 분리시켜야 한다. 이러한 압박 때문에 프로젝트의 초기 반복에는 인수 테스트를 수동으로 하려는 충동이 생기지만 이는 현명한 선택이 아니다.
    단위 테스트가 작은 단위에서 뛰어난 설계 의사결정을 할 수 있게 만드는 것과 마찬가지로, 인수 테스트는 큰 단위에서 뛰어난 아키텍처 의사결정을 할 수 있게 해준다.

리팩토링

외부 행위를 바꾸지 않으면서 내부 구조를 개선하는 방법으로, 소프트웨어 시스템을 변경하는 프로세스 - 마틴 파울러

리팩토링은 세가지의 소프트웨어 모듈의 기능을 정상으로 돌리기 위해 사용된다.
1. 기능 동작
2. 변경에 용이함
3. 읽기 쉬움

향상된 가독성은 몇 나노초 단위의 가치가 있다고 생각한다.
성능의 손해는 무시할 수 있다고 가정하고 틀렸다는 것이 증명될 때까지 기다리는 것이 좋을 수 있다.

profile
성장을 향한 작은 몸부림의 흔적들

0개의 댓글