폐쇄 . 이 질문은 더
중점 이 필요합니다. 현재 답변을 받고 있지 않습니다.
댓글
답변
플래그를 사용하는 코드를 유지할 때 내가 본 문제는 상태 수가 빠르게 증가하고 거의 항상 처리되지 않은 상태가 있다는 것입니다. 제 경험의 한 가지 예 : 저는이 세 개의 플래그가있는 코드를 작업하고있었습니다.
bool capturing, processing, sending;
이 세 가지는 8 개의 상태를 생성했습니다 (실제로 다른 두 개의 플래그가있었습니다. 게다가). 가능한 모든 값 조합이 코드에 포함되지는 않았으며 사용자는 버그를 발견했습니다.
if(capturing && sending){ // we must be processing as well ... }
if 문에 가정이있는 경우가있었습니다. 위의 내용은 거짓입니다.
플래그는 시간이 지남에 따라 복잡 해지는 경향이 있으며 클래스의 실제 상태를 숨 깁니다. 그렇기 때문에 피해야합니다.
댓글
. '에 대해 추가하고 싶지만 일부 상황에서는 플래그가 필요합니다 ' (일부는 ' 필요한 악 ')
@TrevorBoydSmith 제 경험으로는 그렇지 않습니다. 사용하는 평균 두뇌 파워보다 약간 더 필요합니다. 플래그
예시에서는 부울 3 개가 아니라 상태를 나타내는 단일 열거 형이어야합니다.
I 지금 직면하고 있습니다. 가능한 모든 상태를 포함하는 것 외에도 두 애플리케이션이 동일한 플래그를 공유 할 수 있습니다 (예 : 고객 데이터 업로드). 이 경우 업 로더 한 명만 플래그를 사용하고 플래그를 설정하면 나중에 문제를 찾을 수 있습니다.
답변
여기에 플래그가 유용한 경우의 예가 있습니다.
암호화 보안 의사 난수 생성기를 사용하여 암호를 생성하는 코드가 있습니다. 메서드 호출자는 여부를 선택합니다. 비밀번호에는 대문자, 소문자, 숫자, 기본 기호, 확장 기호, 그리스 기호, 키릴 문자 및 유니 코드가 포함되어서는 안됩니다.
플래그를 사용하면이 메서드를 쉽게 호출 할 수 있습니다.
var password = this.PasswordGenerator.Generate( CharacterSet.Digits | CharacterSet.LowercaseLetters | CharacterSet.UppercaseLetters);
그리고 다음과 같이 단순화 할 수도 있습니다.
var password = this.PasswordGenerator.Generate(CharacterSet.LettersAndDigits);
플래그가 없으면 메소드 서명은 무엇입니까?
public byte[] Generate( bool uppercaseLetters, bool lowercaseLetters, bool digits, bool basicSymbols, bool extendedSymbols, bool greekLetters, bool cyrillicLetters, bool unicode);
다음과 같이 호출 :
// Very readable, isn"t it? // Tell me just by looking at this code what symbols do I want to be included? var password = this.PasswordGenerator.Generate( true, true, true, false, false, false, false, false);
주석에서 언급했듯이 또 다른 접근 방식은 컬렉션을 사용하는 것입니다.
var password = this.PasswordGenerator.Generate( new [] { CharacterSet.Digits, CharacterSet.LowercaseLetters, CharacterSet.UppercaseLetters, });
true
및 false
이지만 여전히 두 가지 단점이 있습니다.
주요 단점은 CharacterSet.LettersAndDigits
Generate()
메소드에서 다음과 같이 작성합니다.
if (set.Contains(CharacterSet.LowercaseLetters) || set.Contains(CharacterSet.Letters) || set.Contains(CharacterSet.LettersAndDigits) || set.Contains(CharacterSet.Default) || set.Contains(CharacterSet.All)) { // The password should contain lowercase letters. }
다음과 같이 다시 작성 될 수 있습니다.
var lowercaseGroups = new [] { CharacterSet.LowercaseLetters, CharacterSet.Letters, CharacterSet.LettersAndDigits, CharacterSet.Default, CharacterSet.All, }; if (lowercaseGroups.Any(s => set.Contains(s))) { // The password should contain lowercase letters. }
플래그를 사용하여 현재 가지고있는 것과 비교하세요.
if (set & CharacterSet.LowercaseLetters == CharacterSet.LowercaseLetters) { // The password should contain lowercase letters. }
에스 econd, 매우 사소한 단점은 다음과 같이 호출 할 경우 메서드가 어떻게 작동할지 명확하지 않다는 것입니다.
var password = this.PasswordGenerator.Generate( new [] { CharacterSet.Digits, CharacterSet.LettersAndDigits, // So digits are requested two times. });
코멘트
답변
거대한 함수 블록은 냄새입니다. , 플래그가 아닙니다. 5 행에 플래그를 설정 한 경우 354 행에만 플래그를 확인하는 것은 좋지 않습니다. 8 행에 플래그를 설정하고 10 행에 플래그를 확인하면 괜찮습니다. 또한 코드 블록 당 하나 또는 두 개의 플래그는 괜찮습니다. 함수에있는 300 개의 플래그는 잘못되었습니다.
답변
일반적으로 플래그 플래그의 가능한 모든 값에 대해 하나의 전략 구현을 사용하여 전략 패턴의 일부 풍미로 완전히 대체 될 수 있습니다. 이렇게하면 새로운 동작을 훨씬 쉽게 추가 할 수 있습니다.
성능이 중요한 상황에서는 간접 비용이 할 수 있으며 명확한 플래그로 분해 할 수 있습니다. 실제로 그렇게해야했던 한 가지 사례를 기억하는 데 어려움이 있습니다.
답변
아니요, 플래그는 나쁘지 않거나 어떤 대가를 치르더라도 리팩토링해야하는 악한 것이 아닙니다.
Java의 Pattern.compile (String regex, int flags) 호출. 이것은 전통적인 비트 마스크이며 작동합니다. 자바의 상수 를 살펴보고 2 n 무리가있는 곳마다 플래그가 있음을 알 수 있습니다.
이상적인 리팩토링 된 세계에서는 대신 상수가 열거 형의 값인 EnumSet 을 사용하고 설명서에 다음과 같이 표시됩니다.
이 클래스의 공간 및 시간 성능은 기존 int 기반 “비트 플래그”에 대한 고품질의 형식 안전 대안으로 사용할 수있을만큼 충분히 우수해야합니다.
완벽한 세상에서 Pattern.compile 호출은 Pattern.compile(String regex, EnumSet<PatternFlagEnum> flags)
가됩니다.
모두 즉, 여전히 플래그입니다.Pattern.compile("foo", Pattern.CASE_INSENSTIVE | Pattern.MULTILINE)
로 작업하는 것이 Pattern.compile("foo", new PatternFlags().caseInsenstive().multiline())
또는 플래그가 실제로 무엇인지를 시도하는 다른 스타일을 갖는 것보다 훨씬 쉽습니다. 좋습니다.
플래그는 시스템 수준에서 작업 할 때 자주 나타납니다. 운영 체제 수준에서 무언가와 인터페이스 할 때, 프로세스의 반환 값, 파일의 권한, 소켓을 열기위한 플래그 등 어딘가에 플래그가있을 가능성이 있습니다. 인지 된 코드 냄새에 대해 마녀 사냥에서 이러한 인스턴스를 리팩토링하려고 시도하면 플래그를 수락하고 이해 한 경우보다 코드가 더 나빠질 수 있습니다.
이 문제는 사람들이 플래그를 잘못 사용하여 플래그를 함께 던질 때 발생합니다. 모든 종류의 관련없는 플래그의 frankenflag 세트를 만들거나 플래그가 아닌 곳에서 사용하려고합니다.
답변
메서드 시그니처 내의 플래그에 대해 이야기하고 있다고 가정합니다.
단일 플래그를 사용하는 것은 충분하지 않습니다.
동료가 본 순간에는 아무런 의미가 없습니다. 그들은 “메소드가 무엇을하는지 확인하기 위해 메소드의 소스 코드를 살펴 봐야 할 것입니다. 당신의 메소드가 무엇인지 잊었을 때 당신은 아마도 몇 달 후 같은 위치에있을 것입니다.
플래그를 메소드에 전달하는 것은 일반적으로 메소드가 여러 작업을 담당 함을 의미합니다. 메소드 내에서 다음 행에 대한 간단한 검사를 수행 할 수 있습니다.
if (flag) DoFlagSet(); else DoFlagNotSet();
“불량한 문제 분리이며 일반적으로 해결 방법을 찾을 수 있습니다.
일반적으로 두 가지 방법이 있습니다.
public void DoFlagSet() { } public void DoFlagNotSet() { }
해결중인 문제에 적용 할 수있는 메소드 이름을 사용하면 더 의미가 있습니다.
여러 플래그를 전달하는 것은 두 배나 나쁩니다. 실제로 여러 플래그를 전달해야하는 경우 클래스 내에서 캡슐화하는 것보다 좋습니다. 그래도 메서드가 여러 작업을 수행 할 가능성이 있으므로 동일한 문제에 직면하게됩니다.
답변
플래그 및 대부분의 온도 변수는 강한 냄새입니다. 대부분 리팩토링되고 쿼리 메서드로 대체 될 수 있습니다.
수정 :
상태를 표현할 때 플래그 및 임시 변수는 쿼리 메서드로 리팩터링되어야합니다. 상태 값 (부울, 정수 및 기타 기본)은 구현 세부 정보의 일부로 거의 항상 숨겨져 야합니다.
제어, 라우팅 및 일반 프로그램 흐름에 사용되는 플래그는 다음을 나타낼 수도 있습니다. 제어 구조의 섹션을 별도의 전략이나 팩토리로 리팩토링 할 수있는 기회, 또는 쿼리 메서드를 계속 사용하는 상황에 따라 적절할 수 있습니다.
Answer
플래그에 대해 이야기 할 때 플래그가 프로그램 실행 시간에 걸쳐 수정 될 것이며 상태에 따라 프로그램의 동작에 영향을 미칠 것이라는 점을 알아야합니다. 이 두 가지를 깔끔하게 제어 할 수있는 한 훌륭하게 작동합니다.
플래그는 적절한 범위에서 정의한 경우 훌륭하게 작동 할 수 있습니다.
- 적절하게는 범위에 수정할 필요가 없거나 수정할 필요가없는 코드가 포함되어서는 안됩니다. 또는 적어도 코드는 안전합니다 (예 : 외부에서 직접 호출 할 수 없음)
- 외부에서 플래그를 처리해야하고 플래그가 많은 경우 유일한 방법으로 플래그 처리기를 코딩 할 수 있습니다. 플래그를 안전하게 수정합니다. 이 플래그 핸들러는 자체적으로 플래그와 메소드를 캡슐화하여 수정할 수 있습니다. 그런 다음 싱글 톤으로 만들어 플래그에 액세스해야하는 클래스간에 공유 할 수 있습니다.
- 마지막으로 플래그가 너무 많으면 유지 관리를 위해 :
- 그렇게해야한다고 말할 필요가 없습니다. 합리적인 이름 지정
- 유효한 값이 무엇인지 문서화해야합니다 (열거 형일 수 있음)
- 각각을 수정하는 코드가 문서화되어야하며 결과가 발생하는 조건도 함께 문서화되어야합니다. 플래그에 특정 값을 할당합니다.
- 어떤 코드가 그것들을 소비하고 어떤 행동이 특정 값에 대해 결과를 가져올 지
플래그가 엄청나게 많으면 플래그 이후에 좋은 디자인 작업이 선행되어야하며 프로그램 동작에서 키 역할을 시작해야합니다. 모델링을 위해 상태 다이어그램으로 이동할 수 있습니다. 이러한 다이어그램은 처리하는 동안 문서화 및 시각적 지침으로도 작동합니다.
이러한 요소가 제자리에있는 한 엉망으로 이어지지는 않을 것이라고 생각합니다.
답변
질문에서 QA가 함수 매개 변수의 비트가 아니라 플래그 (전역) 변수를 의미한다고 가정했습니다.
상황이 있습니다. 다른 가능성이 많지 않은 경우. 예를 들어 운영 체제가 없으면 인터럽트를 평가해야합니다.인터럽트가 매우 자주 발생하고 ISR에서 긴 평가를 수행 할 시간이없는 경우 ISR에서 일부 전역 플래그 만 설정하는 것이 허용 될뿐만 아니라 때로는 모범 사례까지도 허용됩니다 (가능한 한 적은 시간을 소비해야합니다). ISR에서), 메인 루프에서 해당 플래그를 평가합니다.
답변
무엇이든 는 프로그래밍에서 절대적인 악입니다.
플래그가 순서대로있을 수있는 또 다른 상황이 있습니다. 아직 여기에 언급되지 않았습니다 …
이 자바 스크립트 스 니펫에서 클로저 사용을 고려하세요.
exports.isPostDraft = function ( post, draftTag ) { var isDraft = false; if (post.tags) post.tags.forEach(function(tag){ if (tag === draftTag) isDraft = true; }); return isDraft; }
전달되는 내부 함수 “Array.forEach”에 단순히 “참을 반환”할 수는 없습니다.
따라서 플래그를 사용하여 상태를 외부에 유지해야합니다.