간결함이 더 이상 미덕이 아닌 시점은 무엇입니까?


102

최근 버그 수정으로 인해 다른 팀 구성원이 작성한 코드를 살펴 보았습니다.이 코드는 C #입니다.

return (decimal)CostIn > 0 && CostOut > 0 ? (((decimal)CostOut - (decimal)CostIn) / (decimal)CostOut) * 100 : 0;

이제는 모든 캐스트에 대한 합당한 이유가 있으므로 여전히 따르기가 매우 어렵습니다. 계산에 사소한 버그가 있었고 문제를 해결하기 위해 그것을 풀어야했습니다.

코드 검토에서이 사람의 코딩 스타일을 알고 있으며 그의 접근 방식은 짧을수록 거의 항상 더 좋습니다. 그리고 물론 거기에는 가치가 있습니다. 우리는 모두 잘 배치 된 몇몇 연산자로 정리할 수있는 불필요하게 복잡한 조건부 논리 체인을 보았습니다. 그러나 그는 하나의 진술로 가득 찬 연산자 체인을 따르는 데있어 나보다 분명히 더 능숙합니다.

물론 이것은 궁극적으로 스타일의 문제입니다. 그러나 코드 간결성을위한 노력이 유용하지 않고 이해의 장벽이되는 시점을 인식하기 위해 어떤 글을 작성하거나 연구 한 적이 있습니까?

캐스트 이유는 Entity Framework입니다. db는 이들을 널 입력 가능 유형으로 저장해야합니다. 소수? C #의 Decimal과 같지 않으며 캐스팅해야합니다.


153
간결함이 가독성을 능가 할 때.
Robert Harvey

27
구체적인 예를 살펴보면 : 캐스트는 (1) 개발자가 컴파일러보다 더 많은 것을 알고 있고 추론 할 수없는 사실을 컴파일러에 알려야하는 장소이거나 (2) 일부 데이터가 "잘못된 "우리가 수행해야 할 작업의 종류에 대한 유형입니다. 둘 다 무언가가 리팩토링 될 수 있다는 강력한 지표입니다. 여기서 가장 좋은 해결책은 캐스트없이 코드를 작성하는 방법을 찾는 것입니다.
Eric Lippert

29
특히, CostIn이 아닌 0과 비교하기 위해 CostIn을 10 진수로 캐스트해야하는 것이 기괴한 것 같습니다. 왜 그런 겁니까? 지구상에서 CostIn의 유형은 10 진수로 캐스팅하여 0과 비교할 수 있다는 것입니까? CostOut이 CostIn과 같은 유형이 아닌 이유는 무엇입니까?
Eric Lippert

12
또한 여기의 논리가 실제로 잘못되었을 수 있습니다. 가정은 CostOut동일하다 Double.Epsilon, 따라서 0보다 크다. 그러나이 (decimal)CostOut경우 0이며, 우리는 0으로 나누기 오류가 있습니다. 첫 번째 단계는 코드를 올바르게 얻는 것입니다. 올바르게 작성하고 테스트 사례를 작성한 다음 우아 하게 만드십시오 . 우아한 코드와 간단한 코드는 공통점이 많지만 간결함은 우아함의 영혼이 아닙니다.
Eric Lippert

5
간결함은 항상 미덕입니다. 그러나 우리의 목적 함수는 간결함과 다른 미덕을 결합합니다. 다른 미덕에 해를 끼치 지 않고 더 짧을 수 있다면 항상 그래야합니다.
Solomonoff의 비밀

답변:


163

현존하는 연구에 대한 질문에 대답하기 위해

그러나 코드 간결성을위한 노력이 유용하지 않고 이해의 장벽이되는 시점을 인식하기 위해 어떤 글을 작성하거나 연구 한 적이 있습니까?

예,이 분야에 대한 연구가있었습니다.

이 내용을 이해하려면 메트릭 을 계산하는 방법을 찾아야 합니다 (다른 답변과 마찬가지로 지혜와 직관을 기준으로 비교를 수행하는 대신) 정량적으로 비교할 수 있습니다. 살펴본 잠재적 인 측정 항목 중 하나는

순환 복잡성 ÷ 소스 코드 라인 ( SLOC )

코드 예제에서이 비율은 매우 높습니다. 모든 것이 한 줄로 압축 되었기 때문입니다.

SATC는 가장 효과적인 평가는 크기와 [Cyclomatic] 복잡성의 조합이라는 것을 발견했습니다. 복잡성과 크기가 큰 모듈은 안정성이 가장 낮은 경향이 있습니다. 크기가 작고 복잡도가 높은 모듈은 코드가 매우 간결하여 변경 또는 수정이 어렵 기 때문에 안정성 위험이 있습니다.

링크

관심이 있다면 몇 가지 참고 자료가 있습니다.

McCabe, T. 및 A. Watson (1994), 소프트웨어 복잡성 (CrossTalk : The Journal of Defense Software Engineering).

Watson, AH, & McCabe, TJ (1996). 구조적 테스트 : Cyclomatic Complexity Metric (NIST Special Publication 500-235)을 사용한 테스트 방법론. McCabe Software 웹 사이트에서 2011 년 5 월 14 일에 확인 함 : http://www.mccabe.com/pdf/mccabe-nist235r.pdf

Rosenberg, L., Hammer, T., Shaw, J. (1998). 소프트웨어 메트릭스 및 신뢰성 (소프트웨어 신뢰성 엔지니어링에 관한 IEEE 국제 심포지엄의 절차). Penn State University 웹 사이트에서 2011 년 5 월 14 일에 확인 함 : http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.104.4041&rep=rep1&type=pdf

내 의견과 해결책

개인적으로, 나는 간결성을 소중히 여기지 않았으며 가독성 만 가지고 있습니다 . 때로는 간결함이 가독성에 도움이되고 때로는 그렇지 않습니다. 더 중요한 것은 WOC (Write-Only Code ) 대신 ROC (Really Obvious Code) 를 작성하는 것입니다.

재미를 위해 여기에 글을 쓰는 방법이 나와 있으며, 팀원들에게 글을 쓰도록 요청하십시오.

if ((costIn <= 0) || (costOut <= 0)) return 0;
decimal changeAmount = costOut - costIn;
decimal changePercent = changeAmount / costOut * 100;
return changePercent;

또한 작업 변수를 도입하면 정수 산술 대신 고정 소수점 산술을 트리거하는 데 따른 부작용이 발생하므로 모든 캐스트 decimal가 필요하지 않습니다.


4
나는 0보다 작은 경우에 대한 guard 절을 정말로 좋아합니다. 논평에 합당 할 수 있습니다. 비용이 어떻게 제로보다 적을 수 있습니까? 어떤 특별한 경우입니까?
user949300

22
+1. 아마도 다음과 같은 것을 추가 할 것입니다if ((costIn < 0) || (costOut < 0)) throw new Exception("costs must not be negative");
Doc Brown

13
@DocBrown : 좋은 제안이지만 테스트를 통해 예외적 인 코드 경로를 사용할 수 있는지 고려할 것입니다. 그렇다면 해당 코드 경로를 연습하는 테스트 사례를 작성하십시오. 그렇지 않다면 모든 것을 Assert로 변경하십시오.
Eric Lippert

12
이것들은 모두 좋은 점이지만이 질문의 범위는 논리가 아닌 코드 스타일이라고 생각합니다. 내 코드 조각은 블랙 박스 관점에서 기능적 동등성에 대한 노력입니다. 예외를 던지는 것은 0을 반환하는 것과 같지 않으므로 솔루션은 기능적으로 동일하지 않습니다.
John Wu

30
"개인적으로, 나는 한 결코 가치없는 간결함 만 가독성이. 때로는 간결 가끔하지 않는, 일기 좋게하는 데 도움이됩니다." 훌륭한 지적입니다. 그냥 +1하십시오. 나는 당신의 코드 솔루션도 좋아합니다.
와일드 카드

49

간결함은 중요한 것들 주위의 혼란을 줄이면 좋지만, 간결 해지면 너무 많은 관련 데이터를 너무 조밀하게 따라 쉽게 따르지 않으면 관련 데이터가 복잡해져 문제가 있습니다.

이 특별한 경우에, 캐스트 decimal는 계속해서 반복된다; 아마도 다음과 같이 다시 작성하는 것이 더 좋습니다.

var decIn = (decimal)CostIn;
var decOut = (decimal)CostOut;
return decIn > 0 && CostOut > 0 ? (decOut - decIn ) / decOut * 100 : 0;
//                  ^ as in the question

갑자기 논리를 포함하는 선이 훨씬 짧고 하나의 수평선에 맞기 때문에 스크롤하지 않고도 모든 것을 볼 수 있으며 그 의미는 훨씬 더 분명합니다.


1
아마 더 멀리 가서 ((decOut - decIn ) / decOut) * 100다른 변수로 리팩토링했을 것 입니다.
FrustratedWithFormsDesigner

9
어셈블러는 훨씬 명확했습니다. 한 줄에 한 작업 만 있습니다. 도!

2
@FrustratedWithFormsDesigner 한 단계 더 나아가서 조건부 검사를 괄호로 묶습니다.
Chris Cirefice

1
@FrustratedWithFormsDesigner : 조건부 이전까지 추출하면 0으로 나누기 검사 ( CostOut > 0)를 무시하므로 조건부를-문 으로 확장해야합니다 if. 이것에 문제가있는 것은 아니지만 현지인을 소개하는 것보다 더 자세한 정보를 제공합니다.
wchargin

1
솔직히 말해서, 캐스트를 없애는 것은 간단한 기본 속도 계산을 인식 할 수 없기 때문에 누군가가 읽기가 어렵다면 공기가 충분히 IMO를 수행 한 것처럼 보입니다.
Walfrat

7

이 주제에 대한 특정 연구를 인용 할 수는 없지만 코드 내 모든 캐스트는 자신을 반복하지 말 것 원칙을 위반하는 것이 좋습니다. 코드가 수행하려고하는 것으로 costInand and costOuttype을 변환 Decimal한 다음 이러한 변환 결과에 대한 온전한 검사를 수행하고 검사가 통과되면 변환 된 값에 대한 추가 작업을 수행합니다. 실제로, 코드는 변환되지 않은 값에 대한 온 전성 검사 중 하나를 수행하여 costOut이 0보다 크지 만 Decimal나타낼 수 있는 가장 작은 0이 아닌 크기의 절반보다 작은 값을 보유 할 가능성을 높 입니다. 코드는 Decimal변환 된 값을 보유하기 위해 유형의 변수를 정의한 다음 그에 따라 작동하면 훨씬 명확 해집니다.

당신이의 비율에 더 관심이있을 것이라고 호기심 보인다 Decimal의 표현 costIncostOut실제 값의 비율보다 더 costIncostOut코드가 일부 다른 목적으로 소수점 표현을 사용하려고하지 않는 한,. 코드가 이러한 표현을 더 많이 사용하려는 경우 코드 전체에 캐스트 시퀀스가 ​​연속되는 것이 아니라 해당 표현을 보유 할 변수를 작성하는 추가 인수가됩니다.


(십진법) 캐스트는 아마도 일부 비즈니스 규칙 요구 사항을 충족시킬 것입니다. 회계사를 다룰 때 때로는 바보 같은 농구대를 뛰어 넘어야합니다. CFO가 요청한 기능을 고려할 때 피할 수없는 "세금 반올림 수정-$ 0.01"라인을 발견했을 때 심장 마비가 일어날 것이라고 생각했습니다. (공급 : 세후 가격. 세전 가격을 계산해야합니다. 답변이 없을 확률은 세율과 같습니다.)
Loren Pechtel

@LorenPechtel : Decimal캐스트가 반올림 하는 정밀도 는 문제의 가치의 크기에 달려 있다는 것을 감안할 때 캐스트가 실제로 동작하는 방식을 요구하는 비즈니스 규칙을 상상하기가 어렵습니다.
supercat

1
좋은 점-십진법의 세부 사항을 잊어 버렸기 때문에 그런 식을 원하는 적이 없었기 때문입니다. 나는 이것이 비즈니스 규칙에 대한화물 컬트 순종이라고 생각합니다. 특히 돈은 부동 소수점이 아니어야합니다.
Loren Pechtel

1
@LorenPechtel : 마지막 요점을 명확히하기 위해 : 고정 소수점 타입은 x + yy가 오버플로하거나 y를 산출 할 수 있도록 보장 할 수 있습니다. Decimal유형은하지 않습니다. 1.0d / 3.0 값은 큰 숫자를 사용할 때 유지 될 수있는 것보다 소수점 오른쪽에 더 많은 숫자를 갖습니다. 따라서 더 큰 수를 더한 다음 빼면 정밀도 손실이 발생합니다. 고정 소수점 유형은 분수 곱셈 또는 나눗셈에서 정밀도를 잃을 수 있지만 덧셈, 뺄셈, 곱셈 또는 나눗셈으로 나누기 (예 : 1.00 / 7은 0.14 나머지 0.2, 1.00 div 0.15는 6 나머지 0.10)가 아닙니다.
supercat

1
@Hulk : 물론입니다. 나는 x + yy x, x + yx y 또는 x + yxy를 사용할 지에 대해 토론하고 있었고 처음 두 가지를 망쳐 놓았습니다. 중요한 것은 고정 소수점 유형은 작업의 많은 시퀀스의 발견되지 않은 반올림 오류의 원인이되지 않을 것이라는 점을 보장 할 수 있다는 것입니다 어떤 크기를. 코드가 총계가 일치하는지 확인하기 위해 여러 가지 방식으로 항목을 추가하는 경우 (예 : 행 소계의 합을 열 소계의 합과 비교) 결과가 정확하게 같게 나오는 것이 "가까운"것으로 나오는 것보다 훨씬 낫습니다.
supercat

5

이 코드를보고 "비용이 어떻게 0 (또는 이하)이 될 수 있습니까?"라고 묻습니다. 그 특별한 경우는 무엇입니까? 코드는

bool BothCostsAreValidProducts = (CostIn > 0) && (CostOut > 0);
if (!BothCostsAreValidProducts)
  return NO_PROFIT;
else {
   // that calculation here...
}

나는 이름을 여기에서 추측하고 있습니다 : 변경 BothCostsAreValidProducts하고 NO_PROFIT적절합니다.


물론 비용은 제로가 될 수 있습니다 (Xmas 선물을 생각하십시오). 그리고 마이너스 금리의 시대에 마이너스 비용은 너무 놀라운 일이 아니며 적어도 코드는 그것을 처리 할 수 ​​있도록 준비해야합니다 (그리고 오류를 던져서)
Hagen von Eitzen

당신은 올바른 길을 가고 있습니다.
danny117

바보입니다. if (CostIn <= 0 || CostOut <= 0)완전히 괜찮습니다.
Miles Rout

가독성이 떨어집니다. 변수 이름은 끔찍합니다 (BothCostsAreValid가 더 좋을 것입니다. 제품에 대해서는 여기에 아무것도 없습니다). 그러나 CostIn을 확인하는 것만으로도 괜찮으므로 가독성에 아무런 영향을 미치지 않습니다. 테스트중인 표현식의 의미가 명확하지 않은 경우 의미있는 이름을 가진 추가 변수를 소개합니다.
gnasher729

5

간결함 은 그 자체가 미덕 이라기보다는 목적을 의미한다는 것을 잊었을 때 미덕이되는 것을 멈 춥니 다 . 우리는 간결함과 관련이 있기 때문에 간결함을 좋아하고, 간단한 코드는 이해하기 쉽고 수정하기 쉽고 버그가 적기 때문에 단순함을 좋아합니다. 결국 우리는 코드가 이러한 목표를 달성하기를 원합니다.

  1. 최소한의 작업으로 비즈니스 요구 사항 충족

  2. 버그를 피하십시오

  3. 앞으로도 계속해서 1과 2를 충족시키는 변경을 할 수 있습니다.

이것이 목표입니다. 모든 설계 원칙 또는 방법 (KISS, YAGNI, TDD, SOLID, 증명, 유형 시스템, 동적 메타 프로그래밍 등)은 이러한 목표를 달성하는 데 도움이되는 정도로 미덕입니다.

해당 라인이 최종 목표를 놓친 것 같습니다. 짧지 만 간단하지 않습니다. 실제로 동일한 캐스팅 작업을 여러 번 반복하여 불필요한 중복성을 포함합니다. 코드를 반복하면 복잡성과 버그 가능성이 높아집니다. 캐스팅과 실제 계산을 혼합하면 코드를 따르기가 어렵습니다.

라인에는 가드 (특수 케이싱 0), 유형 캐스팅 및 계산의 세 가지 문제가 있습니다. 개별적으로 고려할 때 각 문제는 매우 간단하지만 모두 같은 표현으로 혼합되어 따르기 어렵습니다.

그것이 CostOut처음 사용되었을 때 캐스트되지 않는 이유 는 분명 하지 않습니다 CostIn. 좋은 이유가있을 수 있지만 의도는 명확하지 않습니다 (적어도 컨텍스트가없는 것은 아님). 관리자는 숨겨진 가정이있을 수 있기 때문에이 코드를 변경하는 것에주의해야합니다. 그리고 이것은 유지 보수성에 대한 혐오입니다.

CostIn0과 비교하기 전에 캐스팅되기 때문에 부동 소수점 값이라고 가정합니다. (int 인 경우 캐스팅 할 이유가 없습니다). 그러나 CostOut부동 소수점 인 경우 부동 소수점 값은 작지만 0이 아닌 10 진수로 캐스팅 할 때 0이되기 때문에 코드가 모호한 0으로 나누기 버그를 숨길 수 있습니다 (적어도 가능할 것이라고 생각합니다).

따라서 문제는 간결하거나 부족한 것이 아니며, 유지 관리하기 어려운 코드로 이어지는 문제의 논리와 혼란이 반복됩니다.

캐스트 된 값을 보유하는 변수를 도입하면 아마도 수의 코드 수로 계산되는 코드의 크기가 증가하지만 복잡성을 줄이고 우려를 분리하며 명확성을 향상시켜 이해하고 유지하기 쉬운 코드의 목표에 더 가깝게 만듭니다.


1
중요한 점 : CostIn을 두 번이 아닌 한 번 캐스팅하면 읽을 수 없습니다. 독자는 이것이 명백한 수정이 필요한 미묘한 버그인지 또는 의도적으로 수행되었는지 여부를 알 수 없기 때문입니다. 분명히 작가가 문장의 의미를 확실하게 말할 수 없다면 읽을 수 없습니다. 두 개의 캐스트가 있거나 CostIn을 처음 사용할 때 캐스트가 필요하지 않은 이유를 설명하는 주석이 있어야합니다.
gnasher729

3

간결함은 미덕이 아닙니다. 가독성은 미덕입니다.

간결함은 미덕을 달성하는 도구 일 수도 있고, 예와 같이 정확히 반대의 것을 달성하는 도구 일 수도 있습니다. 이런 식 으로든, 그것은 그 자체의 가치도 거의 갖지 않습니다. 코드가 "가능한 한 짧아야"한다는 규칙은 "가능한 한 외설적"으로 대체 될 수 있습니다. 더 큰 목적을 달성하지 않으면 모두 의미가없고 잠재적으로 피해를줍니다.

또한 게시 한 코드는 간결한 규칙을 따르지 않습니다. 상수는 M 접미사 선언했다 끔찍한 대부분의 (decimal)컴파일러가 남아 촉진하는 것처럼 캐스트는 피할 수 intdecimal. 나는 당신이 묘사하는 사람이 단지 간결성을 변명으로 사용하고 있다고 생각합니다. 고의적으로는 아니지만 여전히 가능성이 높습니다.


2

수년간의 경험에서, 나는 최고의 간결함이 시간의 것임을 믿게되었습니다 . 시간은 다른 모든 것을 지배합니다. 여기에는 성능 시간 (프로그램이 작업을 수행하는 데 걸리는 시간)과 유지 관리 시간 (기능을 추가하거나 버그를 수정하는 데 걸리는 시간)이 모두 포함됩니다. (이 두 가지의 균형을 맞추는 방법은 문제의 코드가 얼마나 자주 수행되고 있는지에 따라 달라집니다. 조기 최적화는 여전히 모든 악의 근원 이라는 것을 기억하십시오 .) 코드의 간결함은 두 가지의 간결성을 향상시키기위한 것입니다. 더 짧은 코드는 일반적으로 더 빨리 실행되며 일반적으로 이해하고 유지하기가 더 쉽습니다. 둘 중 하나도 수행하지 않으면 순 부정적인 것입니다.

여기에 표시된 경우 텍스트의 간결함이 가독성을 희생하여 줄 수의 간결함으로 잘못 해석되어 유지 관리 시간이 늘어날 수 있다고 생각합니다. (캐스팅 수행 방법에 따라 수행 시간이 더 오래 걸릴 수 있지만 위의 행을 수백만 번 실행하지 않으면 걱정할 필요가 없습니다.)이 경우 반복적 십진법 캐스팅은 읽기가 어렵습니다. 가장 중요한 계산이 무엇인지 확인하십시오. 나는 다음과 같이 썼을 것이다.

decimal dIn = (decimal)CostIn;
decimal dOut = (decimal)CostOut;
return dIn > 0 && CostOut > 0 ? ((dOut - dIn) / dOut) * 100 : 0;

(편집 : 이것은 다른 답변과 동일한 코드이므로 끝났습니다.)

나는 삼항 연산자의 팬 ? :이므로 그것을 그대로 두겠습니다.


5
특히 반환 값에 단일 값 또는 변수 이외의 표현식이있는 경우 용어를 읽기가 어렵습니다.
Almo

그것이 부정적인 투표를 주도하고 있는지 궁금합니다. 내가 쓴 것을 제외하고는 현재 10 표로 메이슨 휠러와 많은 동의를하고있다. 그는 또한 삼항을 떠났다. 왜 많은 사람들이 문제를 겪고 있는지 모르겠습니다. ? :위의 예가 충분히 간결하다고 생각합니다. if-then-else와 비교하십시오.
Paul Brinkley

1
확실하지 않습니다. 난 당신을 downvote하지 않았다. 의 양쪽에 무엇이 있는지 명확하지 않기 때문에 삼항을 좋아하지 않습니다 :. if-else영어처럼 읽습니다. 의미를 놓칠 수 없습니다.
Almo

FWIW 나는 Mason Wheeler와 매우 유사한 답변이지만 그의 첫 번째 결과를 얻었 기 때문에 당신이 downvotes를 얻고 있다고 생각합니다.
Bob Tway

1
삼항 연산자의 죽음 !! (또한 Allman을 제외한 탭, 공백 및 공백 및 괄호 및 들여 쓰기 모델로 사망 (실제로 Donald (tm)는 이것이 20 일에 제정 된 최초의 세 가지 법률이 될 것이라고 트윗했습니다)
Mawg

2

위의 거의 모든 답변과 마찬가지로 가독성은 항상 기본 목표가되어야합니다. 그러나 나는 또한 형식화가 변수와 줄 바꾸기를 통해 이것을 달성하는보다 효과적인 방법이라고 생각합니다.

return ((decimal)CostIn > 0 && CostOut > 0) ?
       100 * ( (decimal)CostOut - (decimal)CostIn ) / (decimal)CostOut:
       0;

대부분의 경우 순환 복잡성 인수에 강력하게 동의하지만 함수가 작고 단순하여 좋은 테스트 사례로 더 잘 해결할 수 있습니다. 호기심 때문에 왜 십진수로 캐스트해야합니까?


4
캐스트 이유는 Entity Framework입니다. db는 이들을 널 입력 가능 유형으로 저장해야합니다. 더블? C #의 Double과 같지 않으며 캐스팅해야합니다.
밥 트웨이

2
@MattThrower 그렇죠 decimal? double! = decimal큰 차이가 있습니다.
pinkfloydx33

1
@ pinkfloydx33 네! 두뇌 만 반으로 만 전화로 입력 :)
Bob Tway

학생들에게 SQL 데이터 유형이 프로그래밍 언어에서 사용되는 유형과 이상하게 다르다는 것을 설명해야합니다. 나는 그들에게 설명 할 수 없었습니다 . "모릅니다!" "작은 엔디안!"

3
나는 이것을 읽을 수 없다고 생각한다.
Almo

1

필자는 여기에서 가독성과 관련한 큰 문제가 서식이 완전히없는 것 같습니다.

나는 이것을 다음과 같이 쓸 것이다.

return (decimal)CostIn > 0 && CostOut > 0 
            ? (((decimal)CostOut - (decimal)CostIn) / (decimal)CostOut) * 100 
            : 0;

의 여부를 유형에 따라 CostInCostOut부동 소수점 형 또는 정수형입니다, 캐스트의 일부는 불필요 할 수있다. 달리 float하고 double, 정수 값은 암시 적으로 추진된다 decimal.


나는 이것이 설명없이 하향 투표 된 것을 보았지만 유감스럽게도 배낭 코드의 대답 에서 그의 발언 중 일부를 뺀 것과 동일한 것 같습니다 . 그래서 그것이 정당하다고 생각합니다.
PJTraill

@PJTraill 나는 그것을 놓쳤을 것입니다. 그것은 거의 동일합니다. 그러나 새로운 줄에 연산자를 사용하는 것을 강력하게 선호하므로 버전을 세우게됩니다.
Felix Dombek

다른 답변에 대한 의견에서 언급 한 것처럼 운영자에 대해 동의합니다. 선호하는대로 수행 한 것을 발견하지 못했습니다.
PJTraill

0

코드는 서둘러 작성할 수 있지만 위의 코드는 훨씬 나은 변수 이름으로 작성해야합니다.

그리고 코드를 올바르게 읽으면 총 마진 계산을 시도합니다.

var totalSales = CostOut;
var totalCost = CostIn;
var profit = (decimal)(CostOut - CostIn);
var grossMargin = 0m; //profit expressed as percentage of totalSales

if(profit > 0)
{
    grossMargin = profit/totalSales*100
}

3
0으로 나누면 0이 반환됩니다.
danny117

1
그것이 간결성을 위해 최대화 된 다른 사람의 코드를 리팩터링하는 것이 까다로운 이유와 그 이유 / 어떻게 작동하는지 설명하는 추가 의견을 갖는 것이 좋은 이유
Rudolf Olah

0

CostIn * CostOut은 정수라고 가정합니다.이를
쓰는 방법입니다
.M (돈)은 10 진수입니다

return CostIn > 0 && CostOut > 0 ? 100M * (CostOut - CostIn) / CostOut : 0M;

1
둘 다 부정적인 생각이
아니길

2
0으로 나눈 값이 여전히 있습니까?
danny117

@ danny117 간결함이 틀린 답을 얻었을 때 그것은 멀었다.
paparazzo 2012 년

질문을 업데이트하고 활성화하고 싶지 않습니다. 100M과 0M은 소수점을 강제합니다. (CostOut-CostIn)은 정수 수학으로 수행되고 그 차이는 10 진수로 캐스팅됩니다.
paparazzo

0

사람들이 이해하도록 코드가 작성되었습니다. 이 경우의 간결함은 많이 사지 않으며 관리자의 부담을 증가시킵니다. 이 간결성을 위해 코드를보다 자체 문서화 (더 나은 변수 이름)로 만들거나 이런 방식으로 작동 하는지 설명하는 주석을 추가하여 확장해야합니다 .

오늘날 문제를 해결하기 위해 코드를 작성할 때 요구 사항이 변경되면 해당 코드가 내일 문제가 될 수 있습니다. 유지 보수는 항상 고려해야하며 코드의 이해도를 향상시키는 것이 필수적입니다.


1
소프트웨어 엔지니어링 관행과 원칙이 적용되는 곳입니다. 비 기능 요구 사항
hanzolo

0

간결함은 더 이상 미덕이 아닙니다

  • 사전에 0을 점검하지 않고 Division이 있습니다.
  • 널 검사는 없습니다.
  • 정리가 없습니다.
  • TRY CATCH는 오류를 처리 할 수있는 먹이 사슬을 던집니다.
  • 비동기 작업의 완료 순서에 대한 가정
  • 향후 일정 변경 대신 지연을 사용하는 작업
  • 바늘 IO가 사용됩니다
  • 낙관적 업데이트를 사용하지 않음

답변이 충분하지 않은 경우.

1
좋아, 이것은 대답이 아닌 의견이어야합니다. 그러나 그는 새로운 사람이므로 적어도 설명하십시오. 그냥 downvote & 도망하지 마십시오! 탑승 환영합니다, 대니 나는 downvote를 취소했지만 다음에 주석을 달았습니다 :-)
Mawg

2
Ok 나는 어려운 방법과 간단한 코드를 작성하는 쉬운 방법을 배운 더 복잡한 것들을 포함하도록 답변을 확장했습니다.
danny117

@Mawg를 환영 해 주셔서 감사합니다. null 확인은 간단한 코드에서 가장 많이 발생하는 문제입니다.
danny117

방금 Android를 통해 편집했으며 편집에 대한 설명을 요구하지 않았습니다. 나는 낙관적 갱신 (변경 감지하고 경고) 추가
danny117을

0

이것이 유효성 검사 단위 테스트를 통과했다면 새로운 사양이 추가되거나 새로운 테스트 또는 향상된 구현이 필요하고 코드의 간결성을 풀어야 할 때, 즉 문제가 발생합니다.

분명히 코드의 버그는 Q / A에 또 다른 문제가 있음을 보여 주므로 발견되지 않은 버그가 있다는 사실은 우려의 원인입니다.

코드의 "가독성"과 같은 비 기능적 요구 사항을 처리 할 때는 개발 관리자가이를 정의하고 수석 개발자가 관리해야하며 적절한 구현을 보장하기 위해 개발자가이를 존중해야합니다.

"가독성"과 "유지 보수 용이성"을 보장하기 위해 표준화 된 코드 구현 (표준 및 규칙)을 유지하십시오. 그러나 이러한 품질 속성이 정의되고 적용되지 않으면 위의 예와 같은 코드가 생깁니다.

이런 종류의 코드를보고 싶지 않다면 팀이 구현 표준 및 규칙에 동의하도록하고 코드를 작성하고 규칙을 준수하는지 확인하기 위해 임의 코드 검토 또는 스팟 검사를 수행하십시오.

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