내 코드가 DRY이거나 읽을 수 있어야합니까?


14

나는 간단한 암호화 연습을 위해 루비 코드를 작성하고 있으며이 딜레마를 자주 겪고있다 (연습은 알고 있어야만하는 솔리테어 암호이다). 간결하고 밀도가 높은 반복문을 제거하거나 오류 가능성을 최소화하는 간결한 문장 대신 함수를 읽을 수 있도록 설명 변수와 단일 단계 명령문으로 논리를 채워야하는지 여부에 대한 질문입니다.

가장 최근의 예 : 내 프로그램은 입력을 받고 엄격한 형식 지침으로 인해 입력을 암호화 또는 해독 해야하는지 쉽게 결정할 수 있습니다. 암호화 키와 메시지가 호환되도록 변환 / 생성되면 암호화 된 메시지에서 키를 빼거나 암호화되지 않은 메시지에 키를 추가하여 원하는 출력 (키를 암호화로 생각) 메시지 + 암호화 = 코드; 코드-암호화 = 메시지). DRY 위치는 암호화 된 메시지를 암호화되지 않은 메시지와 다르게 변환하여 암호화 키를 사용하여 메시지에 적용하는 기능을 구별 할 필요가 없다고 나에게 말합니다. 나는 이것이 함수에 중첩 된 if 문이 필요하지만 논리가 견고하다는 것을 의미한다는 것을 알았습니다. 그러나이 코드는 쉽게 읽을 수 없습니다.

반면에 응용 프로그램이 암호화 또는 암호 해독을 결정할 때 설정되는 플래그를 기반으로 호출되는 두 가지 다른 함수를 작성할 수 있습니다. 이것은 읽기는 쉽지만 암호화 키를 메시지에 적용하는 높은 수준의 기능을 복제하거나 해독합니다.

읽을 수있는 코드 나 간결한 코드를 사용해야합니까? 아니면이 기능을 사용하고 두 원칙을 모두 충족시키는 다른 방법을 놓쳤습니까? 프로젝트의 목적을 고려하고 그 목적을 달성하기 위해 최선의 결정을 내려야하는 규모에 따른 위치인가?

지금까지는 읽을 수있는 코드보다 간결하고 건조한 코드를 강조하는 경향이 있습니다.


2
첫 번째, DRY 두 번째, 읽기 가능한 세 번째. 사용률이 높은 코드는 가독성이 높은 코드를 사용하여 DRY 및 가독성을보다 쉽게 ​​충족시킵니다. 그렇기 때문에 더 이상 복잡하게 만들 수없는 경우 API를 사용하여 어딘가에 복잡하게 만들고 싶습니다. 적어도 그들과 상호 작용하는 코드는이 접근법과 함께 나쁘지 않을 것입니다.
Jimmy Hoffa

4
일부 실제 코드 예제가 도움이 될 수 있습니다. 건조하고 읽을 수있는 코드
jk

2
중복되지 않습니다. 간결한 v. 읽기 및 DRY v. 읽기는 매우 다른 두 비교입니다. 건조하지 않는 것이 간결하지 않은 것보다 훨씬 위험합니다.
djechlin

대량 복제 된 코드가 예측 가능한 패턴에 속하기 때문에 더 읽기 쉽다고 가정하면 함정에 빠지지 마십시오. 중복되는 시스템을 유지 관리 할 때까지 다른 브랜치가 아닌 다른 브랜치에는없는 미묘한 버그를 찾을 때까지 그렇게 생각하기 쉽다고 생각합니다.
KChaloux

"암호화 키를 메시지에 적용하는 고급 기능"이 무슨 뜻인지 이해하지 못합니다. 암호화와 암호 해독이 겹치는 경우 추출 방법 리팩토링을 사용하여 공통 부분을 제거하십시오.
Aaron Kurtzhals

답변:


20

DRY는 종교가 아니라 지침입니다. 무엇보다도 그것을 DRY 지점으로 가져간 사람들은 그것을 너무 멀리 가져 왔습니다.

가장 먼저 사용 가능한 코드가 가장 중요합니다. 코드가 유용하지 않고 사용 가능하지 않다면 코드가 유용하지 않으며 처음에는 코드를 작성할 필요가 없습니다.

둘째, 언젠가 누군가 코드를 유지해야 할 것입니다. 코드를 유지 관리 할 수 ​​없으면 이름을 저주하는 동안 "아름답고"조밀하고 간결하며 DRY 디자인이 깨집니다. 이러지 마 나는 그 사람이었고 코드 주석에서 특정 이름을 볼 때마다 소리 지르고 있습니다.

"설명 변수"가없는 조밀 한 코드를 만들고 문서없이 람다를 사용하여 모든 것을 중첩 된 삼항 식에 집어 넣는 것은 영리합니다. 할 수 있다는 것을 아는 것이 좋지만 그렇지 않습니다. 영리한 코드는 디버깅하기가 매우 어렵습니다. 영리한 코드를 작성하지 마십시오 .

소프트웨어에 소비되는 대부분의 시간은 소프트웨어를 처음 작성하는 것이 아니라 소프트웨어 유지 관리에 소비됩니다. 최소한의 이상적인 디자인 변경으로 버그를 빠르고 쉽게 수정하고 필요한 기능을 추가 할 수 있도록 코드를 작성하십시오.


직감적으로, 당신은 내가 간과했던 문제에 부딪쳤다. 나는이 연습을 위해 할 수있는만큼 '영리한'코드를 작성해 왔으며, 내가 할 수 있다는 것을 알기 만하면 좋겠다는 것에 동의하지만 나쁜 행동이라고 여기에 동의합니다. 이제 리팩토링을 많이해야합니다.
lutze

1
@lutze 나는 펄이고 때로는 루비 코더이며 거기에 영리한 코드를 작성하려는 유혹을 확실히 이해할 수 있습니다. 이 답변의 사전 게시 버전에는 hubris 에 대한 Larry Wall의 인용문이 포함되어 있습니다. 언젠가 유지 될 코드로 작업 할 때 이것이 매우 중요한 미덕이라고 생각합니다. 언어의 간결함 때문에 영리하고 조밀 한 코드를 유지하기보다는 더 많은 코드를 작성하는 이점을 얻는 것이 어려울 수 있습니다.

17

DRY를 이해한다는 질문에 근거하지는 않습니다. DRY 코드는 간결하지 않습니다. 종종 반대입니다.

여기,이 예제에 큰 문제가 무엇인지 잘 모르겠습니다. 암호화 기능, 해독 기능, 공통 기능 (믹스 바이트)을위한 도우미 및 입력을 가져 와서 암호화 / 암호 해독을 결정하는 간단한 프런트 엔드를 만드십시오 ... 반복하지 마십시오.

그러나 일반적으로 DRY 및 가독성은 코드 유지 관리 및 확장에 도움이됩니다. 모든 시나리오가 동일하지는 않지만 약간의 반복을 제거하기 위해 큰 가독성을 얻는 것은 좋지 않으며 약간의 가독성을 추가하는 중복도 아닙니다.

누르면, 가독성을 선호합니다. 중복 코드는 여전히 테스트 할 수 있습니다. 읽을 수없는 코드는 잘못된 일을하고 테스트하게합니다.


좋은 점은 실제로 DRY 원칙을 간결한 코드의 목표와 약간 결합한 것입니다.
lutze

12

귀하의 특정 사례에 익숙하지 않지만 일반적인 지침을 제공 할 수 있습니다.

가독성과 DRY의 목적은 유지 보수성 입니다.

유지 관리는 코드를 작성하는 것보다 코드를 유지 관리하는 데 더 많은 시간을 소비하는 대부분의 상황에서 중요합니다. 코드 작성을 특수한 종류의 유지 관리로 생각하는 경우 특히 그렇습니다.

불행하게도, DRY는 종종 오해를받습니다. 이것은 부분적으로 너무 단순 해 보이지만 많은 간단한 것들처럼 복잡 할 수 있습니다.

DRY의 의도는 모든 기능 단위가 한 곳에만 존재한다는 것입니다. 원칙을 준수하면 해당 기능을 변경하거나 확인해야하는 코드 관리자가 코드를 한 번에 처리 할 수 ​​있습니다. DRY를 따르지 않으면 기능의 일부 복사본이 제대로 유지 관리되지 않을 위험이 있습니다.

DRY의 가장 명백한 위반은 전체 코드 블록이 코드 기반에서 그대로 반복되는 복사-붙여 넣기 코딩입니다. 이것은 놀랍게도 내 경험에서 일반적이며 가독성을 높이는 방법은 없습니다. 따라서 일반적인 방법을 도입하기 위해 코드를 리팩토링하면 DRY 적합성 및 가독성이 항상 증가합니다.

두 번째로 가장 명백한 위반은 "복사-붙여 넣기 및 약간 변경"입니다. 다시 말하지만, 매개 변수가있는 comon 방법을 도입하기 위해 리팩토링하거나 함수를 단계로 나누고 공통성을 추상화하면 거의 항상 가독성이 향상됩니다.

그런 다음 기능이 중복되지만 코드가 다른 미묘한 위반이 있습니다. 이것은 항상 파악하기 쉽지는 않지만 공통 코드를 단일 메소드 / 클래스 / 함수로 가져 오기 위해 리팩토링하고 리팩토링하면 코드가 이전보다 일반적으로 더 읽기 쉽습니다.

마지막으로 디자인이 반복되는 경우가 있습니다. 예를 들어 코드 기반에서 상태 패턴을 여러 번 사용한 경우이 반복을 제거하기 위해 리팩토링을 고려하고 있습니다. 이 경우주의하여 진행하십시오. 더 많은 추상화 수준을 도입하여 가독성을 떨어 뜨릴 수 있습니다. 동시에, 당신은 실제로 기능의 중복을 다루는 것이 아니라 추상화의 중복을 다루고 있습니다. 때로는 가치가 있지만 때로는 그렇지 않습니다. 당신의지도 원칙은 "이들 중 어느 것이 더 유지 보수가 용이한지"물어 보는 것입니다.

이러한 판단을 할 때마다 사람들이 코드를 유지하는 데 소요되는 시간을 고려하려고합니다. 코드가 핵심 비즈니스 기능이라면 유지 관리가 더 필요할 것입니다. 이 경우 코드 기반과 관련된 추상화에 익숙한 사람들이 코드를 유지 관리 할 수있게 만드는 것을 목표로합니다. 반복을 줄이기 위해 추상화를 조금 더 도입하는 것이 더 행복합니다. 반대로, 거의 사용되지 않고 자주 유지 관리되지 않는 스크립트는 너무 많은 추상화를 포함하는 경우 관리자에게 이해하기 쉽지 않을 수 있습니다. 이 경우 반복 측면에서 실수를 저지 릅니다.

또한 팀의 다른 구성원의 경험 수준도 고려합니다. 경험이 부족한 개발자의 "팬시"추상화는 피하지만보다 성숙한 그룹과 함께 불완전한 인식 된 디자인 패턴을 활용하십시오.

결과적으로 질문에 대한 답변은 코드를 가장 유지 관리하기 쉽게 만드는 것입니다. 시나리오에서 의미하는 바는 결정에 달려 있습니다.


내 문제 중 하나를 정확하게 해결했다고 생각합니다. 복제하지 않으려는 기능에 대한 예는 추상화의 중복 가능성이 높습니다.
lutze

+1. 현재 복사 및 붙여 넣기를 악용하는 시스템을 엄청나게 다루고 있습니다. 복사 / 붙여 넣기 코드에서 단일 메소드를 제외하면 오늘 내 클래스 중 하나에서 400 줄 이상이 제거되었습니다. 불행히도, 나는 900 라인 방식으로 그것을 발견했다 ...
KChaloux

1
이 명 코드 구조는 현재 같은 일을하지만, 하나의 변화는 일반적으로하는 경우는 없습니다 / 복사, 다른 변경을 의미하는 더 나은 인수 분해 일반적인 기능보다 수 붙여 넣습니다. 코드가 문자마다 동일한 두 문자를 사용하는 경우 서로 다른 목적으로 동일한 작업을 수행하고 필요한 목적에 따라 방법 선택을 일관되게 기반으로 한 다음 나중에 해당 목적 중 하나를 위해 약간의 작업을 수행 해야하는 경우 적절한 변경 방법은 영향을받는 행동에만 영향을 미칩니다. 하나의 일반적인 방법을 사용하면 변경이 훨씬 어려워 질 수 있습니다.
supercat

7

함수를 DRY로 만들려고 할 때 함수가 더 복잡해지고 길어 지므로 (가독성이 떨어짐) 잘못된 동작입니다. 두 번째 함수에서 동일한 코드 조각을 반복하지 않는 유일한 방법이라고 생각하기 때문에 하나의 함수에 너무 많은 기능을 배치하려고합니다.

코드를 DRY로 만드는 것은 거의 항상 공통 기능을 더 작은 기능으로 리팩토링한다는 의미입니다. 각 함수는 원래 함수보다 단순하고 읽기 쉬워야합니다. 원래 기능의 모든 것을 동일한 추상화 레벨로 유지하려면 다른 곳에서는 사용하지 않는 추가 부품을 리팩터링해야합니다. 그런 다음 원래 함수는 "높은 수준의 함수"가되어 더 작은 함수를 호출하며 더 작고 단순 해집니다.

결과적으로이 작업을 수행하면 코드에서 추상화 수준이 달라지며 대부분의 사람들은 그러한 종류의 코드를 읽을 수 없다고 생각합니다. 내 경험에 따르면 이것은 잘못된 것입니다. 여기서 중요한 점은 작은 기능에 좋은 이름을 부여하고 잘 알려진 데이터 형식과 추상화를 도입하여 다른 사람이 쉽게 파악할 수 있다는 것입니다. 그런 식으로 "건조"와 "가독성"은 아주 거의 충돌하지 않아야합니다.


2

여기서 문제의 원인이 정확히 무엇인지 확실하지 않지만 내 경험은 DRY와 가독성이 충돌 할 때 무언가를 리팩토링 할 시간이라고 말합니다.


0

요일 중 DRY 대신 읽을 수있는 (= 유지 관리 가능)을 선택합니다. 실제로 DRY 개념을 가진 사람은 일반적으로 (대부분) 읽을 수있는 코드를 생성합니다.


2
설명이 없으면 다른 사람이 반대 의견을 게시 할 경우이 답변이 쓸모 없게 될 수 있습니다. 예를 들어, 누군가 "요일을 읽을 수있는 대신 DRY (= 유지 관리 가능)를 선택합니다"와 같은 클레임을 게시하는 경우이 답변이 독자가 두 가지 반대 의견을 선택하는 데 어떻게 도움이됩니까? 더 나은 형태로 편집 하는 것을 고려하십시오
gnat

0

내 경력에서 매우 매우 매우 적은 횟수만으로 DRY에 대한 가독성이 좋은 합법적 인 사례를 발견했습니다. 먼저 읽을 수있게 만드십시오. 이름을 잘 지정하십시오. 필요한 경우 복사하여 붙여 넣습니다.

이제 뒤로 물러서서 그림을 보려고 물러나있는 아티스트처럼 자신이 만든 전체 성을 살펴보십시오. 이제 반복을 올바르게 식별 할 수 있습니다.

반복되는 코드는 자체 메서드로 리팩토링하거나 자체 클래스로 가져와야합니다.

반복 코드는 최후의 수단이어야합니다. 읽기 가능 및 건조가 먼저 반복되는 코드의 범위를 제한하면 읽을 수 없습니다.

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