이 기사에는 내 주변 동료의 Java 코드에서 볼 수 있는 몇 가지 일반적인 오류가 나열되어 있습니다. 분명히 정적 코드 분석(우리 팀은 qulice를 사용함)으로 모든 문제를 찾을 수는 없으므로 여기에 나열합니다.
뭔가 빠진 것이 있다고 생각되면 알려주시면 기꺼이 추가해 드리겠습니다.
아래 나열된 이러한 오류는 모두 기본적으로 객체 지향 프로그래밍, 특히 Java의 OOP와 관련이 있습니다.
수업명
이 짧은 기사 "객체란 무엇인가"를 읽어보세요. 클래스는 "검증기", "컨트롤러" 및 "관리자"가 아닌 실제 생활의 추상 엔터티여야 합니다. 클래스 이름이 "er"로 끝나면 잘못된 디자인입니다.
물론 도구 클래스도 Apache의 StringUtils, FileUtils 및 IOUtils와 같은 안티패턴입니다. 위의 모든 것은 잘못된 디자인의 예입니다. 추가 자료: OOP의 도구 클래스에 대한 대안.
물론 클래스와 인터페이스를 구별하기 위해 접두사나 접미사를 사용하지 마세요. 예를 들어 IRecord, IfaceEmployee 또는 RecordInterface와 같은 이름은 잘못되었습니다. 일반적으로 인터페이스 이름은 실제 엔터티의 이름이어야 하며, 클래스 이름은 구현 세부 사항을 설명해야 합니다. 구현에 특별한 것이 없다면 이를 Default, Simple 또는 이와 유사한 이름으로 부를 수 있습니다. 예를 들어:
다음과 같이 코드 코드를 복사합니다.
SimpleUser 클래스는 사용자 {}를 구현합니다.
클래스 DefaultRecord는 Record {}를 구현합니다.
Suffixed 클래스는 Name {}을 구현합니다.
Validated 클래스는 Content {}를 구현합니다.
메소드 이름
메소드는 값을 반환하거나 void를 반환할 수 있습니다. 메서드가 값을 반환하는 경우 해당 이름은 반환되는 내용을 설명해야 합니다. 예를 들어 get 접두어를 사용하지 마세요.
다음과 같이 코드 코드를 복사합니다.
boolean isValid(문자열 이름);
문자열 내용();
int ageOf(파일파일);
void를 반환하는 경우 이름으로 무엇을 하는지 설명해야 합니다. 예를 들어:
다음과 같이 코드 코드를 복사합니다.
void save(파일파일);
무효처리(업무)
void 추가(파일 파일, 문자열 라인);
방금 언급한 규칙에는 단 하나의 예외가 있습니다. JUnit의 테스트 방법은 포함되지 않습니다. 이에 대해서는 아래에서 논의하겠습니다.
테스트 방법의 이름
JUnit 테스트 케이스에서는 메소드 이름은 공백 없이 영문으로 작성해야 합니다. 다음 예를 보면 더 명확해질 것입니다.
다음과 같이 코드 코드를 복사합니다.
/**
* HttpRequest는 해당 콘텐츠를 유니코드로 반환할 수 있습니다.
* @throws 예외 테스트가 실패할 경우
*/
public void returnItsContentInUnicode()에서 예외가 발생합니다.
}
JavaDoc의 첫 번째 문장은 테스트하려는 클래스 이름으로 시작하고 그 뒤에 can이 와야 합니다. 그러므로 첫 번째 문장은 "누군가는 뭔가를 할 수 있다"와 같아야 합니다.
메소드 이름도 동일하며 테마만 제외됩니다. 메서드 이름 중간에 제목을 추가하면 위의 예와 같이 "HttpRequest가 해당 콘텐츠를 유니코드로 반환합니다."라는 완전한 문장을 얻게 됩니다.
시험법명은 캔으로 시작하지 않는다는 점에 유의하시기 바랍니다. JavaDoc의 주석만 can으로 시작됩니다. 또한 메소드 이름은 동사로 시작하면 안 됩니다.
실제로는 Exception을 발생시키는 테스트 메서드를 선언하는 것이 가장 좋습니다.
변수 이름
timeOfDay, firstItem 또는 httpRequest와 같은 변수 이름을 결합하지 마십시오. 이는 클래스 변수와 메서드 내의 변수에 해당됩니다. 변수 이름은 표시 범위 내에서 모호함을 피할 수 있을 만큼 길어야 하지만 가능하면 너무 길면 안 됩니다. 이름은 단수 또는 복수 형태의 명사이거나 적절한 약어이어야 합니다. 예를 들어:
다음과 같이 코드 코드를 복사합니다.
<String> 이름 나열;
void sendThroughProxy(파일 파일, 프로토콜 프로토콜);
개인 파일 콘텐츠;
공개 HttpRequest 요청;
경우에 따라 생성자가 새로 초기화된 객체에 입력 매개 변수를 저장하는 경우 매개 변수 이름과 클래스 특성 이름이 충돌할 수 있습니다. 이 경우 모음을 제거하고 약어를 사용하는 것이 좋습니다.
예:
다음과 같이 코드 코드를 복사합니다.
공개 수업 메시지 {
개인 문자열 수신자;
공개 메시지(문자열 rcpt) {
this.recipient = rcpt;
}
}
클래스 이름을 보면 변수에 어떤 이름을 붙여야 하는지 알 수 있는 경우가 많습니다. 다음과 같이 신뢰할 수 있는 소문자 형식을 사용하세요.
다음과 같이 코드 코드를 복사합니다.
파일 파일;
사용자 사용자;
지점 지점;
그러나 정수 숫자나 문자열 문자열과 같은 기본 유형에서는 이 작업을 수행해서는 안 됩니다.
성격이 다른 여러 변수가 있는 경우 형용사 사용을 고려하세요. 예를 들어:
다음과 같이 코드 코드를 복사합니다.
문자열 접촉(문자열 왼쪽, 문자열 오른쪽);
건설자
예외를 무시하고 데이터를 개체 변수에 저장하는 데 사용되는 생성자는 하나만 있어야 합니다. 다른 생성자는 다른 매개변수를 사용하여 이 생성자를 호출합니다. 예를 들어:
다음과 같이 코드 코드를 복사합니다.
공개 클래스 서버 {
개인 문자열 주소;
공용 서버(문자열 uri) {
this.address = uri;
}
공용 서버(URI uri) {
this(uri.toString());
}
}
일회성 변수
일회용 변수는 어떻게 해서든지 피해야 합니다. 여기서 "일회성"이란 한 번만 사용되는 변수를 의미합니다. 예를 들면 다음과 같습니다.
다음과 같이 코드 코드를 복사합니다.
문자열 이름 = "data.txt";
새 파일(이름)을 반환합니다.
위의 변수는 한 번만 사용되므로 이 코드는 다음과 같이 재구성될 수 있습니다.
다음과 같이 코드 코드를 복사합니다.
새로운 파일을 반환("data.txt");
때로는 드문 경우(주로 더 보기 좋은 서식 지정을 위해) 일회용 변수가 사용될 수 있습니다. 그러나 이는 가능한 한 피해야 합니다.
이상
말할 필요도 없이, 예외를 스스로 삼켜서는 안 되며, 가능한 한 많이 넘겨야 합니다. 개인 메소드는 항상 확인된 예외를 발생시켜야 합니다.
흐름 제어에 예외를 사용하지 마세요. 예를 들어 다음 코드는 잘못되었습니다.
다음과 같이 코드 코드를 복사합니다.
정수 크기;
노력하다 {
크기 = this.fileSize();
} catch (IOException ex) {
크기 = 0;
}
그렇다면 IOException이 "디스크가 가득 찼습니다"라는 메시지를 표시하면 어떻게 해야 합니까? 아직도 파일 크기가 0이라고 생각하고 계속 처리하시겠습니까?
톱니 모양
들여쓰기와 관련하여 여는 괄호는 줄의 끝에서 끝나거나 같은 줄에서 닫히는 것이 주요 규칙입니다(닫는 괄호의 경우 그 반대임). 예를 들어, 다음은 첫 번째 여는 괄호가 같은 줄에서 닫히지 않고 그 뒤에 다른 문자가 있기 때문에 올바르지 않습니다. 두 번째 괄호도 앞에 문자가 있지만 해당 여는 괄호가 같은 줄에 있지 않기 때문에 문제가 있습니다.
다음과 같이 코드 코드를 복사합니다.
최종 파일 파일 = 새 파일(디렉토리,
"파일.txt");
올바른 들여쓰기는 다음과 같아야 합니다.
다음과 같이 코드 코드를 복사합니다.
StringUtils.join(
배열.asList(
"첫 번째 줄",
"두 번째 줄",
StringUtils.join(
Arrays.asList("a", "b")
)
),
"분리 기호"
);
들여쓰기에 대한 두 번째 중요한 규칙은 한 줄에 가능한 한 많은 문자를 동시에 작성해야 한다는 것입니다. 최대 제한은 80자입니다. 위의 예는 이 점을 만족하지 않으며 축소될 수도 있습니다.
다음과 같이 코드 코드를 복사합니다.
StringUtils.join(
배열.asList(
"첫 번째 줄", "두 번째 줄",
StringUtils.join(Arrays.asList("a", "b"))
),
"분리 기호"
);
중복 상수
클래스의 메소드 내에서 정보를 공유하려면 클래스 상수를 사용해야 합니다. 정보는 클래스에 고유해야 합니다. 문자열이나 숫자 리터럴의 대체물로 상수를 사용하지 마십시오. 이는 매우 나쁜 습관이며 코드를 오염시킬 것입니다. OOP의 모든 객체와 마찬가지로 상수는 실제 세계에서 고유한 의미를 가져야 합니다. 실제 생활에서 이러한 상수가 무엇을 의미하는지 살펴보겠습니다.
다음과 같이 코드 코드를 복사합니다.
클래스 문서 {
private static final String D_LETTER = "D" // 나쁜 습관
private static final String EXTENSION = ".doc" // 좋은 습관
}
또 다른 일반적인 실수는 테스트 메서드에서 중복된 문자열이나 숫자 리터럴을 피하기 위해 단위 테스트에서 상수를 사용하는 것입니다. 이렇게 하지 마세요! 각 테스트 메서드에는 고유한 입력 값이 있어야 합니다.
새로운 테스트 방법마다 새로운 텍스트나 값을 사용하세요. 그들은 서로 독립적입니다. 그렇다면 왜 그들은 여전히 동일한 입력 상수를 공유합니까?
테스트 데이터 결합
다음은 테스트 방법에서 데이터 결합의 예입니다.
다음과 같이 코드 코드를 복사합니다.
사용자 user = new User("제프");
// 여기에 다른 코드가 있을 수도 있습니다.
MatcherAssert.assertThat(user.name(), Matchers.equalTo("Jeff"));
마지막 줄에서 "Jeff"는 첫 번째 줄의 동일한 문자열 리터럴에 연결됩니다. 몇 달 후에 누군가가 세 번째 줄의 값을 변경하려는 경우 "Jeff"가 동일한 방법으로 사용되는 위치를 찾는 데 시간을 소비해야 합니다.
이를 방지하려면 변수를 도입하는 것이 좋습니다.