애자일 또는 XP와 같은 혁신적인 방법으로 설계 막 다른 곳에 도달하면 어떻게해야합니까?


11

Martin Fowler의 유명한 블로그 게시물 인 Design Dead는 무엇입니까? 필자가받은 인상적인 인상 중 하나는 애자일 방법론과 극한 프로그래밍에서 프로그래밍뿐만 아니라 디자인도 진화 적이라는 사실을 감안할 때 항상 리팩터링해야하는 포인트가 있다는 것입니다.

프로그래머의 수준이 좋을 때, 설계의 의미를 이해하고 중대한 실수를하지 않으면 코드가 계속 발전 할 수 있습니다. 그러나 정상적인 상황에서이 상황의 기본 현실은 무엇입니까?

정상적인 날에 제품에 대한 상당한 개발이 이루어지고 있으며 요구 사항에 중대한 변화가 발생할 때 기본 설계 측면을 수정할 수 없다는 제약이되지 않습니까? (코드의 주요 부분을 버리지 않고). 설계 및 요구 사항에 대한 추가 개선으로 막 다른 골목에 도달 할 가능성이 낮 습니까?

나는 민첩 하지 않은 관행을 옹호 하지는 않지만 실제 경험과 같이 민첩하거나 반복적이거나 진화적인 개발 방법을 연습하는 사람들로부터 알고 싶습니다.

그런 막 다른 골목에 도달 한 적이 있습니까? 어떻게 피하거나 도망 쳤습니까? 아니면 디자인이 진화함에 따라 깨끗하고 유연하게 유지되도록하는 조치가 있습니까?

답변:


17

나는 당신이 게시 한 기사 링크를 읽었습니다 .Fowler는 몇 가지 좋은 점과 그가 말한 많은 것들을 만들었습니다. 나는 수년간 우리 팀과 옹호 해왔습니다.

IMO, 괜찮은 디자인을한다면 막 다른 상황에 빠지지 않아야합니다. 나는 항상 빌딩 블록 으로 구성된 소프트웨어를 보았다 . 나는 여전히 일부 초기 디자인을 믿지만, 주요 목표는 전체 제품을 디자인하는 것이 아니라 전체 아키텍처 / 방향을 제공하여 팀이 우리 모두가 진행하고있는 공통된 그림을 시각화 할 수 있도록하는 것입니다. 큐브와 삼각형 조각이 많은 경우 조각을 두드리기 전에 성이 어떻게 구성되는지 스케치하는 것이 좋습니다.

OO 랜드에서 왔기 때문에 각 블록은 클래스이며 해당 블록의 표면 영역은 공용 인터페이스입니다 (외부 또는 파생 클래스에서 볼 수있는 것). 훌륭한 SOLID 원칙을 따르는 경우 각 블록을 매우 간단하고 직관적 인 공용 인터페이스를 갖도록해야합니다. 내 비유로 돌아가서, 간단한 모양 만 작성하도록 코드를 작성하려고합니다. 너무 복잡한 클래스 (다수의 함수, 많은 변수)를 만들 때마다 요구 사항이 변경 될 때 재사용하기 어려운 셰이프를 만듭니다.

Fowler는 진화 설계에 대한 가장 큰 위험 / 도전은 설계 결정을 코딩 시간에 맡기고 각 개발자가 그러한 결정을 내리기를 기대한다는 점에서 Fowler에 동의합니다. 적절한 피드백 메커니즘이 없으면 시스템이 고장날 수 있습니다. 새로운 기능이 필요할 때마다 확장해야 할 함수를 찾고, 내부에 어떤 종류의 조건부를 넣은 다음 해당 함수 안에 코드 전체를 추가하는 것이 매우 유혹적입니다. 때로는 이것이 필요한 전부일 수도 있지만, 이것은 데드 엔드 구성 요소로 이끄는 가장 일반적인 관례이기도합니다. 이것은 진화적인 디자인과 관련이 없습니다. 이것이 "디자인 없음"입니다.

한 걸음 물러서서 잠시 기다려야하는 한,이 클래스에는 이미 15 개의 멤버 변수가 있습니다.이 중 6 개를 추출하여 자체 포함 된 클래스에 넣으면 소프트웨어가 매우 가벼워집니다. 가볍고 유연하며 재사용 가능한 빌딩 블록. PM이 와서 제품 요구 사항의 절반을 변경하는 경우 블록을 가져 와서 선반에 다시 놓고 새로운 성을 쌓아야 할 수도 있습니다 (성 구축시와 같이 모두 사용하지 못할 수도 있음) 실린더). 그러나 그 시점에서 그것은 사업을하는 것의 일부일뿐입니다. 요구 사항이 변경되었으며 코드를 유연하고 모듈 식으로 유지함으로써 새로운 비즈니스 방향에 맞게 제품을 변경할 수 있어야합니다.

디자인에 대한이 혁신적인 접근 방식은 모든 수준의 엔지니어 기술로 작동합니다. 개인적으로 저는 매우 오랫동안 소프트웨어를 개발했으며 팀이 민첩한 방법론으로 전환하기 전에 거의 모든 QA를 사용하여 개발자 PC의 몇 가지 주요 구성 요소를 거의 고객에게 직접 배송했습니다. 동시에 이러한 구성 요소는 항상 유연하고 유지 관리가 가능합니다.

나는 소프트웨어를 디자인하는 데 상대적으로 괜찮다고 생각하려고합니다. 동시에 100 페이지 디자인 문서를 작성하여 코더에게 제공하고 작동 할 것으로 예상하면 종이 봉지로 디자인 할 수 없었을 것입니다. 작업을 시작할 때 때로는 UML과 같은 (매우 단순화 된 전체 언어가 아닌) 다이어그램을 거의 스케치하지 않았지만 코딩을 시작할 때 필요에 따라 리팩터링하고 최종 코드는 내가 원래 그린 것과 전혀 같지 않습니다. 모든 세부 사항에 대해 한두 달을 생각하더라도 다른 사람이 내 다이어그램을 가져 와서 코딩 할 때 디자인을 수정하지 않고 견고한 소프트웨어를 만들 수는 없습니다.

스펙트럼의 다른 쪽 끝에서, 현재 우리 팀 (현재 민첩하고 완벽하게 지원하고 있음)에는 지난 15 년 동안 C 만 수행 한 임베디드 랜드에서 우리와 합류 한 두 사람이 있습니다. 나는 초기 계획과 수업 계획에 분명히 도움을 주었지만, 정기적 인 코드 검토와 브레인 스토밍 세션을 통해 SOLID의 적용과 설계 원칙에 대해 논의했습니다. 그들은 내가 약간 울부 짖는 스파게티 코드를 만들었지 만, 나에게서 약간의 조금 찔림으로 이미 생산 된 것을 리팩토링하기 시작했으며 재미있는 부분은 그들 중 하나가 며칠 후에 나에게 돌아와서 싫어한다는 것입니다. 말하자면 코드를 옮기고 나면 훨씬 더 읽기 쉽고 이해할 수 있습니다. 막 다른 골목을 피했다. 포인트 I ' OO를 완전히 처음 접하는 사람이라도 경험이 많은 멘토가있는 한 "진화 적 디자인"은 "디자인 없음"과 같지 않다는 점을 상기시키기 위해 다소 괜찮은 코드를 생성 할 수 있습니다. 심지어 그의 "더 복잡한"클래스들 중 일부는 각 클래스가 그다지 책임을 갖지 않기 때문에 무섭지 않습니다 (즉, 코드가 많지 않기 때문에). 그것을 이해하고 동일한 공용 인터페이스를 가진 대체 클래스를 작성하십시오 (지금까지는 우리가 작성한 것에서이 우연의 필요성을 보지 못했으며 일주일에 두 번 코드 검토를 수행했습니다).

마지막으로, 나는 또한 디자인 문서 (적어도 현재 팀의 비즈니스 조건에 대한)를 굳게 믿고 있지만 디자인 문서의 주요 목표는 조직 메모리입니다 . 따라서 실제 문서는 코드가 생성되고 작성된 후에 작성됩니다. 리팩토링. 코딩하기 전에 일반적으로 냅킨 / mspaint / visio의 클래스를 스케치하는 빠른 (때로는 그리 빠르지 않은) 디자인 단계가 있으며,이 단계에서는 청사진이 아니라 따라야 할 경로를 만들고 코딩을 시작할 때 항상 사람들에게 상기시킵니다. 이해가되지 않는 것은 바꾸어야합니다. 이러한 알림에도 불구하고, 새로운 사람들은 심지어 부 자연스럽게 느껴도 코드를 원래 디자인에 맞추려고 시도하는 경향이 있습니다. 이것은 일반적으로 코드 검토에서 나타납니다.

Dang, 나는 많이 썼다. 미안합니다.


1
+1 모든 단어에 가치가 있습니다. 나는 당신이 묘사 한대로 이러한 상황을 겪고 마감일이 충족되면 디자인의 상식이라고 생각하는 것에서 더 많은 것을 정리 (리 팩터 읽기)하도록 요청하십시오. 그러나 종종 사람들은 같은 질문이 반복되는 것을 발견합니다. 왜 다시 같은 일을합니까? 시장 출시 기간이 단축되고 디자인이 발전 할 수 있도록 허용하는 경우 리팩토링은 기존의 죄에 대한 보상이 아니라 실제로 합법적 인 일입니다.
Dipan Mehta

예, 많이 썼지 만 좋은 일이었습니다. 그것을 읽는 것을 정말로 즐겼다 ​​:).
Radu Murzea

11

"디자인 막 다른 곳"현상은 민첩한 방법과 직교한다고 말할 수 있습니다. 내 말은 폭포를 할 수 있고 (나쁜) 디자인에 많은 시간을 할애한다는 것입니다. 그런 다음 막 다른 길에 자신을 찾기 위해 많은 시간을 투자하십시오.

어쨌든 민첩한 방법 을 사용하면 설계를 잘못 선택했음을 일찍 발견 수 있습니다. 그 이유는 백 로그에 고객 가치가 가장 높은 항목이 먼저 있어야하고 유용한 증분 소프트웨어를 제공하는 데 집중해야하기 때문입니다. 디자인이 높은 가치와 유용성을 제공 할 수 있다면 이미 뭔가 좋은 것입니다 :-) 반면에, 폭포가 많은 상황 에서이 디자인이 제공 할 수없는 것을 수년 동안 알지 못하는 나쁜 디자인이있을 수 있습니다 모든 가치와 유용성-좋은 디자인이라는 착각 만 있으면됩니다. 그들이 말하는 것처럼, 증거는 푸딩에 있습니다.

단점은 민첩한 방법에서도 반복에서 반복까지 결정을 내리는 시스템 설계에 대한 실행 가능한 비전을 갖는 것이 중요하다는 것입니다. Ken Schwabber는 당신이 끔찍한 개발자 팀을 가지고 있다면 반복적으로 나쁜 소프트웨어를 일관되게 반복 할 것이라고 말합니다. 당신이 배우거나 상상할 수있는 일에 제한이 있기 때문에 당신이 구현 시작 (전에 애자 단순히 수단은 시간 선행을 많이 소비하지 않는 또한 요구 사항 변경). 그러나 선행 작업 (예 : 연구)을 수행해야하는 상황이 있으며 그렇게해야합니다.

막 다른 길을 어떻게 피합니까?

나는 미래의 요구 사항을 예상함으로써 주로 말할 것입니다. 이것은 유사한 프로젝트 / 제품에 대한 경험과 친숙 함을 통해 얻을 수있는 것입니다. 이러한 기대는 부분적으로 현재 시스템에 대해 많은 "만약"질문을하기 때문에 좋은 설계를하는 데 도움이됩니다. 나에게 이것은 중요한 구성 요소입니다. OO와 같은 기술은 현재하고있는 일을 이미 알고있을 때 도움을줍니다.

막 다른 골목이 있다면 어떻게해야합니까?

A "데드 엔드"는 다른 기술 블록 다르지 않습니다 소설 아무것도의 개발 기간 동안했다. 가장 먼저 알아야 할 사실은 당신이 완전히 역 추적하게하는 진정한 "데드 엔드"가 없다는 것입니다. 최소한 지금까지 배우는 것은 노력을 낭비하지 않도록 앞으로 나아갈 수있게하는 것입니다. 막 다른 길을 쳤을 때 문제가 있습니다. 문제는 새로운 (또는 오래된) 요구 사항을 충족시키기 위해 변경해야 할 사항과이 변경을 최적화하는 방법입니다. 이제이 문제를 해결하기 만하면됩니다. 비행기 설계와 같이 소프트웨어가 아니라 소프트웨어라는 점에 감사하십시오. 변경이 훨씬 쉽기 때문입니다. 문제를 식별하고 수정하십시오 == 리 팩터 == 소프트웨어 엔지니어링. 때로는 많은 일이 관련되어 있습니다 ...

Scrum을 사용하는 경우이 변경은 자연스럽게 사용자 스토리에서 가져와야합니다 (사용자는이 변경에서 무엇을 얻습니까?). 프로세스는 현재 디자인 (oops)에 의해 쉽게 수용 될 수없는 하나의 스토리에서 시작하며이 스토리를 분해하는 방법에 대해 제품 소유자와 논의 할 것입니다. 이 변경을 통해 민첩한 원칙을 계속 적용합니다.

내 마음에 오는 OS 세계에서 유명한 몇 가지 큰 요구 사항이 변경되었습니다.

어느 쪽을 보더라도 이것들은 많은 작업입니다. 오리지널 디자인은 이런 일이 발생할 가능성을 거의 고려하지 않았습니다 (즉, 이식성이 큰 요구 사항이 아니 었습니다). 디자인이 OO인지 아닌지는 아마도 큰 요소가 아닐 것입니다. 좋은 디자인에서는 플랫폼 별 부분이 다소 격리되어 작업이 쉬워집니다.


실제로 Windows NT의 초기 버전은 "하드웨어 추출 계층"을 구현하고 DEC Apha 및 x86을 지원했습니다. 아무도 DEC 알파 기반 머신을 구입 한 적이 없어 조용히 떨어졌습니다. 이 "기계 독립성"은 현재 릴리스에서 여전히 흔적 형식으로 존재하므로 ARM 포트가 그렇게 어렵지 않을 수 있습니다.
제임스 앤더슨

3

프로젝트를 영구적으로 리팩터링하고 UML 클래스 다이어그램도 사용합니다. 패키지로 하나 이상의 클래스 다이어그램을 만듭니다. 각 다이어그램은 패키지의 루트에 저장됩니다. 각 UML 분류기에는 관련 Java ID에 맵핑되는 고유 ID가 있습니다. 다이어그램을 열면 최신 코드 리팩토링 변경 사항으로 자동 업데이트됩니다. 클래스 다이어그램을 그래픽 레벨에서 직접 변경할 수도 있으며 모든 프로젝트가 즉시 리팩터링됩니다. 그것은 잘 작동하지만 결코 인간을 대체하지는 않습니다. 내 UML 클래스 다이어그램은 또한 내 코드의 그래픽 뷰일뿐입니다. 리팩토링을 수행하자마자 모델 정보도 손실되기 때문에 EMF 이클립스와 같이 코드와 모델을 혼합하지 않는 것이 매우 중요합니다. 나는 쓸모가 없기 때문에 모델 중심 개발 코드 생성기를 사용하지 않습니다. 나는

내 프로젝트 구조의 모든 세부 사항을 나타내는 100 개 이상의 클래스 다이어그램과 모든 곳에서 메모로 가득 찬 것이 정말 도움이된다고 말했습니다. 일반적으로 개발자는 다른 다이어그램을 배우거나 사용할 시간이 없기 때문에 프로젝트에 대한 클래스 다이어그램 만 작성합니다. 자동으로 업데이트되기 때문에 클래스 다이어그램도 좋습니다. 패키지를 뒤집고 메모를 추가하면 코드 다음에 클래스 다이어그램을 만들 수 있습니다. 빠르고 정확하며 100 % 반복적입니다.

모델 생성 코드 인 모델 중심 개발과 일반적으로 코드에서 업데이트 된 UML 클래스 다이어그램과 함께 UML을 그래픽 프리젠 테이션으로 사용하는 모델 중심 개발을 혼동하지 마십시오. 반복이 여러 개인 경우 UML 동기화 코드 만 실제 값을 갖습니다.

너무 길어서 죄송하지만 프로젝트의 그래픽 보기로 만 사용되는 경우 UML 클래스 다이어그램에 두 번째 기회를 주어야한다고 생각합니다. 이는 UML이 전체 프로젝트를 다루고 전체 프로젝트를 나타내는 대형 클래스 다이어그램으로 구성된 단일 모델을 가지고 있음을 의미합니다. 수백 개의 뷰를 가진 프로젝트 내에서 수백 개의 작은 뷰와 각 뷰에 대한 모델을 갖는 것은 어리석은 일입니다. :-)


1
우편 번호 UML의 아이디어를 보여주기 위해 +1! 흥미롭게도 코드 후에 다이어그램 문서로 돌아 가지 않습니다 !
Dipan Mehta

예, 이것은 UML과 관련된 모델 중심 개발의 문제입니다. 문서를 생성 한 다음 프로젝트 수정시 사용하지 마십시오. 모델과 코드 병합을 통해 UML을 사용하고 필요한만큼 변경할 수 있습니다.
UML_GURU

3

잘못된 디자인, 방향 변경 등으로 인해 내 코드 및 다른 코드의 막 다른 곳에 도달했습니다. 또한 많은 사람들 이이 문제에 부딪 치는 것을 보았습니다. 큰 실수는 (적어도 나에게는 실수처럼 보입니다) 작업 코드를 버리고 모든 것을 처음부터 다시 구현하려는 즉각적인 욕구입니다.

나는 잘 작동하는 것처럼 동일한 방식으로 각 사례에 접근했습니다.

  • 현재 디자인이 작동하지 않는 이유를 식별
  • 새로운 디자인 전환 계획을 제시
  • 더 이상 사용되지 않는 코드에 태그를 지정하십시오.
  • 즉각적인 요구를 충족시키기 위해 새로운 디자인에 필요한 것만 구현
  • 새로운 코드가 쓸모없는 코드를 제거

소송 비용:

  • 코드베이스에서 동시에 2 개의 구현으로 인해 더 복잡한
  • 적절한 사용 사례 및 테스트를 가정하여 전체 재 설계 / 재 구현을 수행하는 것보다 기능 / 버그 수 정당 총 비용

혜택:

  • 여전히 오래된 작업 디자인 / 코드를 가지고 있기 때문에 위험이 훨씬 적습니다.
  • 완전한 재 설계가 필요없는 1 대 n-1 기능의 시장 출시 기간 단축
  • 전체 재 설계를 완료하기 전에 제품 / 코드가 죽는 경우 개발 시간 차이를 저장하게됩니다
  • 반복적 접근과 그 안의 모든 이점

2

약 1 ~ 2 개월 전에 현재 프로젝트는 SCRUM 개발 스타일을 사용하여 일부 잘못된 디자인 결정 (한 곳에서 많은 디자인 부족)으로 인해 약간 멈췄습니다.

우리의 솔루션 (그리고 내가 SCRUM의 표준 솔루션이라고 생각하는 것)은 전체 스프린트 (약 2 주)를 리팩토링 이외의 것에 헌신하는 것이 었습니다. 이 기간 동안 새로운 기능이 추가되지 않았지만 현재 코드베이스에 대해 생각할 수 있었고 현재 수행하고있는 작업에 훨씬 적합한 시스템을 설계 할 수있었습니다.

우리는 이제 그 장애물을지나 새로운 기능을 다시 추가하고 있습니다.


이것은 또 다른 마찰입니다. 첫 번째 버전을 넘긴 후에는 새로운 기능이없는 기능을 고객에게 말해야합니다. 고객에게이 정보를 얼마나 자주 그리고 자주 (있는 경우) 알릴 수 있습니까? 또는 어떻게 설명 할 수 있습니까?
Dipan Mehta

두 가지 기본 옵션이 있습니다. 먼저 간단한 진실을 말하십시오-비록 당신이 일하는 것이 엉망이긴하지만 앞으로 나아 가기 위해 정리해야하거나 두 번째로 진행중인 개발을 지원하기 위해 인프라를 구축한다고 말합니다 어느 정도 사실이지만 조금 더 긍정적으로 회전합니다). 기능을 제공하기 위해 현재 상환해야하는 기술 부채가 발생했다고 말함으로써이 두 가지를 마무리 할 수 ​​있습니다.
Murph

@Dipan Mehta : 고객이 2 층짜리 집을 원한다고 가정 해 봅시다. 당신은 그것을 디자인하고 제공합니다. 그런 다음 4 층을 추가로 원합니다. 저는 현재 건물을보다 견고하게 만들어서 4 개의 층을 추가로 확보하기 위해이 시간을 보내야한다고 말합니다. 따라서 원래 계획에 2 층만 포함 된 경우 고객에게 이것이 문제가되지 않을 것이라고 생각합니다. 처음부터 6 층을 계획했다면 고객에게 알리는 것이 문제 일 수 있습니다.
Giorgio

@DipanMehta 우리는 또한 고객이이 프로젝트에 대해 반드시 알 필요가 없다는 점에서 약간 운이 좋습니다. 이 제품은 현재 사용중인 제품으로 업그레이드되며, 연말 쯤에 막연한 완료 날짜가 있습니다. () 디자인 결정의 대부분을 처리하는 관리자가) 자체이다, 그들은 심지어 리팩토링에 대한 지연에 대해 알 필요가 없습니다 그래서
Izkata

2

설계 변경 비용을 제한하는 핵심은 코드를 가능한 한 건조하게 유지하는 것입니다. 이것은 대부분의 응용 프로그램 코드를 매우 높은 수준으로 이끌며, 대부분의 코드는 의도를 직접 표현하고 메커니즘은 거의 지정하지 않습니다. 이렇게하면 디자인 결정이 코드에서 가능한 가장 작은 표현을 갖게되고 디자인 변경은 가능한 최소 비용을 갖습니다.


2

디자인 막 다른 길을 피하는 열쇠는 디자인을 변경해야 할 때 가능한 빨리 인식하고 변경하는 것입니다. 가장 큰 문제는 디자인을 지속적으로 발전 시키는 것이 아니라 큰 문제가 될 때까지 디자인을 발전시키는 것을 거부함으로써 발생합니다.

예를 들어, Netflix에는 다른 가족 구성원이 동일한 요금제로 청구 할 수 있지만 별도의 대기열이있는 프로필 기능이 있습니다. 몇 년 전만해도 사용자 중 10 %만이이 기능을 사용했기 때문에이 기능을 취소해야한다고 발표했지만 구현이 해킹되어 많은 양의 유지 관리 작업이 필요했습니다. 소란이 난 후, 그들은 고객을 유지하기 위해 총알을 물고 값 비싼 재 설계를했습니다.

처음에 그 기능을 추가했을 때 차선의 디자인을 인식 한 엔지니어가 있었을 것입니다. 그들이 당시에 그것을 바꾸었다면, 그다지 큰 거래는 아니었을 것입니다.


1

프레드 브룩스가 "첫 번째를 버릴 계획"과 같은 말을하지 않았습니까? 막연한 느낌을 가지지 말고 막 다른 디자인도 모든 디자인을 미리 시도하는 프로젝트에 나타납니다. 재 설계는 처음부터 불가능한 디자인 (최근 20 %가 "마귀가 세부 사항에있다")이거나 고객의 초점이 바뀌었기 때문에 모든 유형의 개발에서 발생합니다. 알람 벨이 실제로 필요하지 않으므로 너무 걱정하지 마십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.