부울 논리의 유지 관리-문이 필요한 경우 중첩이 있습니까?


11

다음 중 유지 관리가 더 좋은 것은 무엇입니까?

if (byteArrayVariable != null)
    if (byteArrayVariable .Length != 0)
         //Do something with byteArrayVariable 

또는

if ((byteArrayVariable != null) && (byteArrayVariable.Length != 0))
  //Do something with byteArrayVariable 

나는 두 번째를 읽고 쓰는 것을 선호하지만, 코드로 읽는 것은 그와 같은 일을하는 것이 유지 관리에 좋지 않다는 것을 기억합니다.

if첫 번째 부분이 거짓이고 모든 언어가 그렇지 않은 경우 언어의 두 번째 부분을 평가하지 않기 위해 언어에 의존하기 때문 입니다. (두 번째 부분은 null로 평가되면 예외가 발생합니다 byteArrayVariable.)

그것이 정말로 걱정해야 할 것인지 모르겠으며 질문에 대한 일반적인 피드백을 원합니다.

감사.


1
첫 번째 형태는 매달려있는 다른 사람의 위험이 있습니다
JBRWilkinson

궁금한 점이 있다면 어떤 언어로 작업하고 있습니까?
STW

@STW-C #을 사용하고 델파이에 레거시 코드가 있습니다.
Vaccano

2
알아 둘만 한. 델파이 익숙하지 않아요하지만 C #에서 당신은 확신 할 수 있습니다 &&||단락 회로 평가를 수행하는 사업자. 한 언어에서 다른 언어로 갈 때 일반적으로 문제가 발생하므로 작은 문제를 포착하는 데 도움이되는 코드 검토를 수행하는 것이 좋습니다.
STW

여기에 많은 답변과 함께 두 번째가 더 읽기 쉽고 첫 번째가 디버깅하기가 훨씬 쉽습니다. 이 경우 디버깅을 쉽게 확인하기 때문에 두 번째를 계속 사용합니다. 그러나 일반적으로 조심하십시오.
Magus

답변:


30

나는 두 번째 형태가 훌륭하다고 생각하며, 당신이하려는 일을보다 명확하게 나타냅니다. 너는 ~라고 말한다...

코드를 읽는 것이 그와 같은 일을하는 것이 유지 관리에 좋지 않다는 것을 기억합니다. 첫 번째 부분이 거짓이고 모든 언어가 그렇지 않은 경우 if의 두 번째 부분을 평가하지 않기 위해 언어에 의존하기 때문입니다.

모든 언어가 그렇게 하는지는 중요하지 않습니다 . 하나의 특정 언어로 작성하고 있으므로 해당 언어가 그렇게하는 경우에만 중요 합니다. 그렇지 않으면 본질적으로 다른 언어가 해당 기능을 지원하지 않을 수 있으므로 특정 언어의 기능을 사용해서는 안된다고 말하는 것입니다.


12
동의했다. 지구상에서 다른 언어로 복사 할 때 코드가 동일하게 실행되는지 걱정해야하는 이유는 무엇입니까?
Tim Goodman

16

나는 아무도 그것을 언급하지 않은 것에 놀랐습니다 (그래서 나는 질문을 잘못 읽지 않기를 바랍니다) .

더 나은 대안은 조기 종료를 사용하는 것입니다 (다른 코드가 실행되지 않아야하는 경우 코드에서 초기에 return 문을 배치). 이것은 코드가 비교적 잘 리팩터링되고 각 방법이 간결한 목적을 가지고 있다고 가정합니다.

이 시점에서 다음과 같은 작업을 수행합니다.

if ((byteArrayVariable == null) || (byteArrayVariable.Length != 0)) {
  return; // nothing to be done, leaving
}

// Conditions met, do something

유효성 검사와 비슷하게 보일 수 있으며 정확히 그 자체입니다. 제공 한 옵션 모두 사전 조건 검사 내에 실제 로직을 숨겼습니다.

코드가 많은 스파게티 (라운드 방법, 논리가 흩어져있는 많은 경우 등) 인 경우 작은 문체 문제보다 먼저 코드를 형태 화하는 큰 문제에 중점을 두어야합니다. 환경과 혼란의 심각성에 따라 도움이되는 몇 가지 훌륭한 도구가 있습니다 (예 : Visual Studio에는 "추출 방법"리팩토링 기능이 있음).


짐 언급으로 여전히에 대한 논쟁의 여지가있어 어떻게 조기 종료를 구성 할 수 있습니다. 위에있는 것의 대안은 다음과 같습니다.

if (byteArrayVariable == null) 
  return; // nothing to be done, leaving

if (byteArrayVariable.Length != 0)
  return;

// Conditions met, do something

1
나는 좋은 논리를 감싸는 대신에 답에 동의하지만 같은 사람들은 || &&.
MIA

14

조건 이 아닌 모든 상황 을 잡으려고 시간을 낭비하지 마십시오 . 데이터 나 조건을 실격시킬 수있는 경우 가능한 빨리 처리하십시오.

if (byteArrayVariable == null) Exit;
if (byteArrayVariable.Length == 0) Exit;
// do something

이를 통해 새로운 조건에 훨씬 쉽게 코드를 적용 할 수 있습니다

if (byteArrayVariable == null) Exit;
if (byteArrayVariable.Length == 0) Exit;
if (NewCondition == false) Exit;
if (NewerCondition == true) Exit;
// do something

2
+1 ,, ,, .. 이처럼 간단한 논리는 코드를 어렵게 만들지 않아야합니다. 당신의 (아스 커) 직감이 당신에게 이것을 말해야합니다.
Job

11

ifs부울 비교를 제대로 지원하는 대부분의 언어 에서 중첩 이 나쁜 접근 방식 인 이유에 대한 완벽한 예입니다 . 중첩은 ifs의도가 명확하지 않은 상황을 만듭니다. 두 번째 if가 첫 번째를 즉시 따라야합니까? 아니면 아직 다른 작업을 넣지 않았기 때문입니까?

if ((byteArrayVariable != null) && (byteArrayVariable.Length != 0))
  //Do something with byteArrayVariable 

이 경우, 이들은 거의 함께 있어야 합니다. 이들은 예외를 초래하는 작업을 수행하지 않도록 보호 역할을합니다. nested를 사용하면 ifs두 부분이 두 부분으로 구성된 가드인지 또는 다른 분기 논리를 나타내는 지에 따라 사용자를 따르는 사람에게 해석됩니다. 그것들을 단일로 결합함으로써 if나는 그것을 진술하고 있습니다. 안되어서는 안되는 내부 작업을 몰래하는 것이 훨씬 어렵습니다.

나는 항상 "모든 언어에서 작동하지는 않는다"는 어리석은 주장에 대한 나의 의사 소통에 대해 분명한 의사 소통을 선호 할 것이다. throw모든 언어에서 작동하지 않는 것은 무엇 입니까?

그러나 STW가 답변에서 말한대로 만족 하지 않으면 반전하고 훨씬 더 쉽게 읽을 수 있습니다.


두 개 이상의 조건이 null을 반환하는 자체 함수를 보증 할 수 있습니다.
직업

3

이 경우 두 절이 직접 관련되므로 두 번째 형식이 바람직합니다.

그것들이 관련이 없다면 (예를 들어 다른 조건에 대한 일련의 가드 절), 나는 첫 번째 형식을 선호합니다 (또는 복합 조건이 실제로 나타내는 것을 나타내는 이름을 가진 메소드를 리팩터링합니다).


1

Delphi에서 작업하는 경우 첫 번째 방법은 일반적으로 더 안전합니다. (예를 들어, 중첩 if를 사용하면 얻을 것이 많지 않습니다.)

델파이에서는 컴파일러 스위치를 통해 불리언 표현식이 "단락"인지 평가할 수 있습니다. 방법 # 1 (중첩 된 ifs)을 사용하면 첫 번째 절이 true로 평가되는 경우에만 (그리고 엄격하게 뒤에 ) 두 번째 절이 실행되도록 할 수 있습니다 .


1
23 년 동안의 델파이 개발 에서 "Complete boolean eval"옵션을 바꾸지 않았습니다 . 다른 곳에서 코드를 배송하는 경우 {$ BOOLEVAL OFF} 또는 {$ B-}를 기기에 넣었습니다.
Gerry

나도 마찬가지야 나는 또한 항상 범위 검사를 사용하지만 다른 사람들은 사용하지 않습니다. 그리고 그것은 당신이 becuase 아마도 성능 관점에서 제외하고 차이가 부울 표현식에서 사용하는 기능에 부작용을 사용. 그래도 누군가가 할 것이라고 확신합니다!
Frank Shearar

@Gerry : 동의합니다. 완전한 평가를 원할 수있는 유일한 이유는 부작용이며 조건부 부작용은 나쁜 생각입니다!
Loren Pechtel

내 의견을 다시 읽으십시오 23 년은 13이어야합니다! 나는 Tardis가 없다
Gerry

1

두 번째 스타일은 첫 번째 테스트가 개체가 생성 된 경우에도 두 번째 테스트를 수행하고 오류를 발생시키기 때문에 VBA에서 역효과를 일으킬 수 있습니다. 나는 항상 첫 번째 방법을 사용하기 위해 객체 검증을 다룰 때 VBA에서 습관에 빠져 있습니다.


2
VBA는 끔찍한 언어이기 때문입니다.
Falmarri

@ 팔 마리, 그것에 관한 끔찍한 것들 (그리고 좋은 것들)이 있습니다. 내가 진실을 가지고 있다면 많은 것을 고칠 것입니다.

2
단락 부울 평가의 부족은 무엇보다 레거시입니다. 그들이 왜 시작하지 않았는지 모르겠다. OrElse와 AndAlso의 VB.NET "수정"은 다소 성가 시지만, 이전 버전과의 호환성을 유지하지 않고 처리 할 수있는 유일한 옵션 일 것입니다.
JohnFx

1

두 번째 양식은 특히 각 절 주위에 {} 블록을 사용하는 경우 더 읽기 쉽습니다. 첫 번째 양식은 중첩 된 {} 블록과 여러 레벨의 들여 쓰기로 이어지기 때문에 읽기가 어려울 수 있습니다 (들여 쓰기 공간을 계산해야 함) 각 블록이 끝나는 위치를 파악하십시오.


0

나는 그것들을 읽을 수 있고 언어를 바꾸려면 코드 유지 관리에 대해 걱정해야한다는 주장을 받아들이지 않습니다.

일부 언어에서는 두 번째 옵션이 더 잘 수행되므로 분명한 선택이 될 것입니다.


0

난 너와 함께있어; 나는 두 번째 방법입니다. 나에게는 논리적으로 더 명확합니다. 인생에서 "일부 언어"로 실행되는 프로그램을 작성해 본 적이 없기 때문에 첫 번째 언어가 거짓으로 평가 되더라도 일부 언어가 두 번째 부분을 실행할 것이라는 우려는 저에게 어리석은 것처럼 보입니다. 내 코드는 항상 특정 언어로 존재하는 것으로 보입니다.이 언어는 해당 구성을 처리 할 수 ​​있거나 처리 할 수 ​​없습니다. (그리고 특정 언어가 그것을 처리 할 수 ​​있는지 확실하지 않다면, 그것은 내가 실제로 배워야 할 것이 아닙니다.)

내 마음에, 그것을하는 첫 번째 방법의 위험은 if의도하지 않은 중첩 된 블록 외부에 실수로 코드를 삽입하는 데 취약 하다는 것입니다. 물론 큰 문제는 아니지만 내 코드가 언어에 구애받지 않는지에 대해 걱정하는 것보다 합리적입니다.


0

더 읽기 쉽기 때문에 두 번째 옵션을 선호합니다.

구현하는 논리가 더 복잡한 경우 (문자열이 null이 아니고 비어 있지 않은지 확인하는 것이 단지 예일 경우) 유용한 리팩토링을 수행 할 수 있습니다. 부울 함수 추출. 나는 "Code Complete"발언에 @mipadi를 사용하고있다. 부울 피연산자가 평가되는 곳은 그들에게 논쟁의 여지가 있습니다.


0
if ((byteArrayVariable != null)
 && (byteArrayVariable.Length != 0)) {
    //Do something with byteArrayVariable 

하지만 기본적으로 두 번째 옵션입니다.

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