적절한 디자인으로 쉽게 만들 수없는 변화는 무엇입니까?


11

이것은 다소 모호한 질문이지만 적절한 디자인에 대해 읽을 때 만족스럽지 못한 느낌을 받았습니다.

일반적으로 객체 지향 프로그래밍, 추상화, 팩토링 등을 배우면 디자인의 성배-그리고 그들이 항상 개발 기술을 사용한다고 주장하는 이유는 프로그램을 "쉬운 변경하기"만드는 것입니다. , "유지 가능", "유연성"또는 이러한 생산적인 사운드 개념을 표현하는데 사용되는 동의어 중 하나. ivar를 비공개로 표시하고 코드를 여러 개의 작은 자체 포함 된 방법으로 분할하고 인터페이스를 일반 상태로 유지하면 프로그램을 완벽하고 우아하게 수정할 수 있습니다.

비교적 작은 변화의 경우 이것은 나에게 효과적이었습니다. 클래스가 성능 향상을 위해 사용하는 내부 데이터 구조를 변경하는 것은 결코 큰 어려움이 아니며, 텍스트 입력 시스템을 재 설계하거나 게임 플레이 요소의 그래픽을 점검하는 등 API와 상관없이 사용자 인터페이스 끝도 변경되지 않았습니다. .

이러한 모든 변경 사항은 본질적으로 자체 포함 된 것으로 보입니다. 이들 중 어느 것도 관련된 코드 외부에서 수정되는 프로그램 구성 요소의 동작이나 디자인에 대한 변경은 포함하지 않습니다. 큰 기능이나 작은 기능을 사용하여 절차 적으로 또는 OO 스타일로 작성하는지 여부에 관계없이 중간 정도의 디자인만으로도 쉽게 변경할 수 있습니다.

그러나 변경 사항이 크고 털이 커질 때마다 (즉, API 변경) 내 소중한 "패턴"이 구조되지 않습니다. 큰 변화는 여전히 크며 영향을받는 코드는 여전히 영향을받으며 많은 시간이 걸리는 버그가 발생합니다.

제 질문은 이것입니다. 적절한 설계가 얼마나 큰 변화를 촉진 할 수 있다고 주장 하는가? 나에게 알려지지 않았거나 구현에 실패한 추가 디자인 기술이 실제로 끈적 거리는 수정을 간단하게 만들거나 그 약속 (많은 다른 패러다임에 의해 만들어진)에 대한 좋은 아이디어입니까? 소프트웨어 개발의 불변의 진실에서 완전히 분리 되었습니까? 툴 벨트에 추가 할 수있는 "변경 툴"이 있습니까?

특히, 내가 직면하고있는 문제는 포럼으로 이끌었습니다. 나는 해석 된 프로그래밍 언어 (D로 구현되었지만 관련이 없음)를 구현하기 위해 노력하고 있으며 클로저의 주장은 다음과 같아야한다고 결정했습니다. 현재 위치보다는 키워드 기반입니다. 익명 언어 함수를 호출하는 기존의 모든 코드를 수정해야합니다. 운 좋게도 언어 개발 초기 단계 (<2000 줄)이기 때문에 다소 작지만 나중에이 결정을 내렸다면 막대합니다. 그러한 상황에서, 설계에 대한 적절한 예측을 통해이 수정을 더 쉽게 만들 수 있었거나 본질적으로 광범위하게 영향을 미치는 특정 (대부분) 변경이있을 수있는 방법이 있습니까? 이것이 어떤 식 으로든 내 자신의 디자인 기술의 실패인지 궁금합니다.

분명히, 나는 OOP 나 일반적으로 사용되는 다른 패턴들에 대해 전혀 회의적이지 않다. 그러나 저에게는 그들의 미덕이 코드 기반을 유지 관리하는 것이 아니라 원본으로 작성되었습니다. 상속을 통해 반복적 인 패턴을 잘 추출 할 수 있으며, 다형성을 통해 기계 이해 효과 ( switch문의 분기)가 아닌 사람이 이해하는 함수 (어떤 클래스)로 코드를 분리 할 수 있으며 작고 독립적 인 함수를 사용하면 매우 즐거운 "하단"스타일로 작성하십시오. 그러나 나는 유연성에 대한 그들의 주장에 회의적입니다.


귀하의 언어 변화가 파서 이외의 다른 것에 어떻게 영향을 미치는지 알 수 없습니다. 이것을 명확히 할 수 있습니까?
scarfridge

A의 스몰 토크와 같은 언어, 그것이 치료의 간단한 문제 일 것이기 때문에 만, 파서를 수정해야 할 것입니다 것은 사실 foo metarg1: bar metarg2: bazfoo.metarg1_metarg2_(bar, baz). 그러나 내 언어는 더 큰 변경을하고 있습니다. 즉, 목록 기반 매개 변수를 사전 기반 매개 변수로 변경하면 런타임에 영향을 미치지 만 파서에는 영향을 미치지 않습니다 . 실제로 내 언어의 특정 속성으로 인해 지금 들어 가지 않습니다. 정렬되지 않은 키워드와 위치 인수 사이에 명확한 매핑이 없으므로 런타임이 주요 문제입니다.
존재-전체

답변:


13

마이그레이션 경로를 디자인해야 할 정도로 변경이 큰 경우가 있습니다. 시작점과 끝 점이 잘 설계되어 있어도 차가운 칠면조를 전환 할 수없는 경우가 많습니다. 그렇지 않으면 많은 훌륭한 디자이너가 좋은 마이그레이션 경로를 설계하지 못합니다.

그렇기 때문에 모든 프로그래머가 연중 무휴 프로덕션 환경에 적합한 쓰기 소프트웨어를 사용해야한다고 생각합니다. 분당 연봉 순서대로 잃어버린 손실에 대해 강력한 마이그레이션 코드 작성을 배우도록 동기가 부여됩니다.

사람들이 자연스럽게 큰 변화를 위해하는 일은 오래된 방식을 버리고 새로운 방식으로 넣은 다음 코드가 마침내 컴파일 될 때까지 bazillion 컴파일 오류를 수정하는 데 며칠을 보내고 테스트를 시작할 수 있습니다. 이틀 동안 코드를 테스트 할 수 없었기 때문에 갑자기 얽힌 버그를 엄청나게 정리했습니다.

위치 인수에서 키워드로 변경하는 것과 같은 대규모 디자인 변경의 경우 위치 지원을 제거하지 않고 키워드 인수에 대한 지원을 먼저 추가하는 것이 좋습니다 . 그런 다음 키워드 인수를 사용하도록 호출 코드를 체계적으로 변경합니다. 변경되지 않은 호출 코드가 여전히 작동하기 때문에 테스트를 진행할 수 있다는 점을 제외하고는 이전에 수행 한 방식과 비슷합니다. 테스트마다 변경 사항이 더 작기 때문에 버그를 미리 수정하기가 더 쉽습니다. 그런 다음 모든 호출 코드가 변경되면 위치 지원을 제거하는 것이 쉽지 않습니다.

그렇기 때문에 공개적으로 게시 된 API는 차가운 칠면조를 제거하는 대신 이전 방법을 더 이상 사용하지 않습니다. 코드 호출을위한 완벽한 마이그레이션 경로를 제공합니다. 잠시 동안 둘 다를 지원하는 것이 더 많은 작업처럼 느껴질 수 있지만 테스트 시간을 보충하십시오.

따라서 처음에 말한 것처럼 질문에 대답하기 위해 적절한 디자인으로 쉽게 만들 수없는 너무 큰 변경 사항은 거의 없습니다. 변경 사항이 너무 큰 것 같으면 코드를 마이그레이션하기위한 임시 중간 단계를 디자인하면됩니다.


새 사례와 기존 사례를 지원하기 위해 +1하므로 단계적으로 퇴출 할 수 있습니다.
Erik Reppen

9

Big Ball of Mud 에세이 를 읽는 것이 좋습니다 .

기본적으로 개발을 진행함에 따라 디자인이 저하되는 경향이 있으며 복잡성을 억제하기 위해 노력해야합니다. 복잡성 자체는 해결하려는 문제에 내재되어 있기 때문에 제거 할 수없고 포함 할 수 없습니다.

이는 민첩한 개발의 주요 원칙으로 이어집니다. 가장 관련성이 높은 두 가지는 "필요하지 않을 것"인데 아직 구현하지 않을 기능에 대해 디자인을 준비하지 말라고 지시하는 것입니다. 어쨌든 디자인을 제대로 얻지 못하고 "무자비하게 리팩터링"할 수 있기 때문입니다. 프로젝트 전반에 걸쳐 코드의 무결성을 유지하는 데

정답은 디자인이 실제보다 강하다는 것을 보여주기 위해 특별히 고안된 예제를 넘어서서 어떤 변화도 촉진 할 수 없다는 것입니다.

참고로 객체 지향 프로그래밍에 대해 회의적 이어야 합니다. 많은 상황에서 유용한 도구이지만 한계에 대해 알고 있어야합니다. 특히 상속을 잘못 사용하면 믿을 수 없을 정도로 복잡한 코드가 생길 수 있습니다. 물론 다른 디자인 기법에 대해서도 회의적이어야합니다. 각각은 용도가 있고 약점이 있습니다. 은 총알이 없습니다.


1
+1 : 새로운 선행 디자인이 거의 성공하지 못했습니다. 성공적인 디자인은 입증 된 디자인을 요약하거나 반복적으로 수정 한 것입니다.
kevin cline

1
하나는 당신이 해야 우리가 찾는 우리의 분석 기술을 적용 할 경우에만 목적 비판을 통해 모든 프로그래밍 개념의 회의적 적합한 솔루션을 단지보다는 솔루션 .
Jimmy Hoffa

4

일반적으로 "코드 조각"(함수, 메소드, 객체 등)과 "코드 조각 간 인터페이스"(API, 함수 선언 등 모든 동작 포함)가 있습니다.

다른 코드 조각이 의존하는 인터페이스를 변경하지 않고 코드 조각을 변경할 수 있으면 변경이 더 쉬워집니다 (OOP를 사용하는지 여부는 중요하지 않음).

다른 코드 조각이 의존하는 인터페이스를 변경하지 않고 코드 조각을 변경할 수 없으면 변경이 더 어려워집니다 (OOP를 사용하는지 여부는 중요하지 않음).

OOP의 주요 이점은 공용 "인터페이스"가 명확하게 표시되어 있고 (예 : 객체의 공용 메소드) 다른 코드는 내부 인터페이스 (예 : 객체의 전용 메소드)를 사용할 수 없다는 것입니다. 공용 인터페이스는 분명하게 표시되어 있기 때문에 사람들은 공용 인터페이스를보다 신중하게 디자인하는 경향이 있습니다 (더 어려운 변경을 피하는 데 도움이 됨). 다른 인터페이스에서는 내부 인터페이스를 사용할 수 없으므로 인터페이스에 따라 다른 코드에 대해 걱정하지 않고 변경할 수 있습니다.


OOP의 또 다른 장점은 데이터를 처리하는 논리로 데이터를 캡슐화하면 공용 인터페이스가 더 작아진다는 것입니다.
Michael Borgwardt

2

큰 요구 사항 / 범위 변경의 번거 로움에서 벗어날 수있는 디자인 방법이 없습니다. 나중에 생각할 수있는 모든 가능한 변화를 상상하고 설명하는 것은 불가능합니다.

좋은 디자인 도움이되는 부분은 모든 부품의 결합 방식과 제안 된 변경의 영향을 이해하는 데 도움이됩니다.
또한 우수한 디자인은 제안 된 변경 사항의 대부분에 영향을받는 부품을 제한 할 수 있습니다.

요컨대, 좋은 디자인으로 모든 변경을 쉽게 할 수 있지만 좋은 디자인으로 큰 변경을 작은 것으로 바꿀 수는 없습니다. (반면에 나쁘거나 전혀없는 디자인은 작은 변화를 큰 것으로 바꿀 수 있습니다.)


1

디자인은 무 공지 시트에서 개발 작업 프로젝트를 신뢰할 수있는 최종 제품 (적어도 하나의 디자인)으로 가져 가기위한 것이므로 프로젝트의 가장 큰 변화는 의심의 여지가 있습니다. 처리하기에는 너무 큰 변화.

무엇이든 그것은 반대입니다. 어떤 변화는 너무 작아서 "디자인"이나 공상적인 사고로 귀찮게 할 수 없습니다. 예를 들어 간단한 버그 수정.

디자인 패턴은 수많은 작은 동일한 유형의 객체를 만드는 것과 같이 일반적인 상황에 대해 명확하게 생각하고 좋은 디자인 솔루션을 찾는 데 도움이됩니다. 패턴 목록이 완료되지 않았습니다. 당신과 우리 모두는 일반적이지 않고 비둘기 구멍에 맞지 않는 디자인 문제를 겪을 것입니다. 하나의 공식적인 패턴에 따라 소프트웨어 개발 프로세스에서 모든 작은 움직임을 시도하는 것은 지나치게 종교적인 방법이며, 유지하기 어려운 혼란을 초래합니다.

소프트웨어의 모든 작업은 당연히 버그가 발생합니다. 축구 선수는 부상을 당합니다. 음악가들은 악기에 따라 굳은 살이나 입술 연축을받습니다. (기타를 연주 할 때 입술 경련이 생기면 잘못하고있는 것입니다.) 소프트웨어 개발자는 버그를받습니다. 우리는 스폰 속도를 줄이는 방법을 찾고 있지만 절대 0이되지는 않습니다.


3
시작 위치도 음수 일 수 있습니다. 레거시의 힘을 과소 평가하지 마십시오 :)
Maglob

제로에서 프로젝트를 설계하는 것은 쉬운 부분입니다. 그러나 드문 일이지만 처음부터 새 프로젝트를 시작하더라도 처음 며칠 동안 아무것도 만들지 않아도됩니다. 최초의 초기 설계 결정보다 잘못된 것으로 판명되고 거기서부터 내리막 길이 시작됩니다. 0에서 디자인은 실제로는 전혀 관련이 없습니다.
Jan Hudec

1

변경 사항을 스위핑하는 비용은 종종 코드 기반의 크기에 비례합니다. 따라서 코드베이스의 크기를 줄이는 것이 항상 적절한 디자인의 목표 중 하나 여야합니다.

예를 들어, 적절한 설계로 이미 작업이 쉬워졌습니다. 20000 또는 200000 줄의 코드 기반 대신 2000 줄의 코드 기반을 변경해야합니다.

적절한 디자인은 변경 사항을 줄여 주지만 제거하지는 않습니다.

언어 분석 도구의 적절한 지원이있는 경우 스위핑 변경을 자동으로 쉽게 수행 할 수 있습니다. 담요 리팩토링 변경은 언어 규칙을 적절히 준수하면서 검색 및 교체 스타일로 전체 코드베이스에 적용될 수 있습니다. 프로그래머는 모든 검색 히트에 대해 예 / 아니오 판단 만하면됩니다.


자동화 제안에 +1. 필자는 클로저를 호출하는 많은 라이브러리 함수에 실제로 이것을 사용할 것이라고 생각합니다. 블록을 취하는 함수를 감지하고 인수 이름에 추가 기호 매개 변수를 갖도록 수정하여 값을 전달하는 것은 간단합니다.
존재-전체
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.