2015년 11월 25일 수요일

[번역]10가지 유용하지만, 편집증 적인 Java 프로그래맹 기술들

Top 10 useful, yet paranoid Java programming techniques

시간날 때 추후 번역

https://jaxenter.com/top-10-useful-yet-paranoid-java-programming-techniques-119498.html

1. 문자 값을 앞에 넣어라

다음과 같은 equals()  비교문의 왼쪽에 문자 값을 넣으면 가끔씩 발생하는 NullPointerException 을 방지하는데 것도 결코 나쁘지 않은 생각이다 :
// Bad
if (variable.equals("literal")) { ... }

// Good
if ("literal".equals(variable)) { ... }
이건 생각할 필요도 없다.  좋은 버전에서 더 좋은걸 사용 하기 위해 표현을 바꾼다고 해도 달라지는 건 없다.
그냥 다르게도 표현 할 수 있다는 걸 알았잖아? 다른 의견...

2. 초기의 JDK API들을 믿지 말라
Java 초기에는, 프로그램을 한다는 건  큰 고통이었다. API들은 여전히 부실했고 이 같은 코드 조각들이 난무했다:
String[] files = file.list();

// Watch out
if (files != null) {
    for (int i = 0; i < files.length; i++) {
        ...
    }
}
편집증 같아보이나? 하지만, Javadoc을 읽어보라:
이 추상(abstract)경로명이 디렉토리를 나타내지 않는다면, 이 메소드는 null을 반환한다. 그렇지 않다면 디렉토리 안의 각각의 파일이나 디렉토리를 의미하는, 하나의 문자들의 배열이 반환된다.
맞다. 그냥 좀 더 확인을 위해서 하나더 추가를 한다면:
if (file.isDirectory()) {
    String[] files = file.list();

    // Watch out
    if (files != null) {
        for (int i = 0; i < files.length; i++) {
            ...
        }
    }
}
안됐군! 우리가 아는 Java 코딩시 미묘한 모범 사례(10 Subtle Best Practices when Coding Java)의 5,6 번을 위반했다. 그래서 null 에대한 확인을 추가해야 했다!

3. “-1”을 믿지 마라
난 이건 편집증 적이라 생각한다. Javadoc의 String.indexOf()는 다음과 같이 분명하게 말한다...
이 오브젝트(반환되는)의 나열된 문자에서 처음으로 나오는 문자의 위치를 나타내거나,
문자가 나오지 않는다면 -1을 반환한다.
그래서, -1 이 괜찮다고 할 수 있나? 아니다.  이걸 생각해 보라:
// Bad
if (string.indexOf(character) != -1) { ... }

// Good
if (string.indexOf(character) >= 0) { ... }
Who knows. Perhaps they’ll need ANOTHER encoding at some point in time to say, the otherString would have been contained if checked case-insensitively… Perhaps a good case for returning -2? Who knows.
모를일이지만. 만약 같은위치에서 다른 인코딩이 필요한, 말하자면,  대소문자를 구별해야 줘야하는게 포함된 otherString 이 있다고 하면... 아마 -2를 반환하는게 좋은 예시일까? 모를일이다.
(의미를 잘 모르겠음.)
결국,  NULL이 되는 10억달라짜리 실수에 대한 10억개의 토론을 하는거다. 근본적인 형식인 int에 대해서  null 대신 - 을 사용하는게 맞는지,-1에 대한 토론을 해야 시작해야 하나?

4. 돌발적인 할당을 피하라

그래. 최고로 많이 일어난다(난 아니다. 7번을 보라).
(이게 JavaScript라고 가정하고, 그냥 언어로서 편집증 적이 되어 보자)
// Ooops
if (variable = 5) { ... }

// Better (because causes an error)
if (5 = variable) { ... }

// Intent (remember. Paranoid JavaScript: ===)
if (5 === variable) { ... }
반복. 구문에 문자가 있다면, 왼쪽에 두자.  =표시가 하나더 붙었다고 느껴도, 여기선 실수라고 생각안한다.

5. null과 길이를 확인하라

Whenever you have a collection, array, etc., make sure it’s present AND not empty.
// Bad
if (array.length > 0) { ... }

// Good
if (array != null && array.length > 0) { ... }
You never know where those arrays come from. Perhaps from early JDK API?

6. 모든 메소드들은 final이다

You can tell me all you want about your open/closed principles, that’s all bollocks. I don’t trust you (to correctly extend my classes) and I don’t trust myself (to not accidentally extend my classes). Which is why everything that is not explicitly intended for subtyping (i.e. only interfaces) is strictly final. See also item #9 of our 10 Subtle Best Practices when Coding Java list.
// Bad
public void boom() { ... }

// Good. Don't touch.
public final void dontTouch() { ... }
Yes. It’s final. If that doesn’t work for you, patch it, or instrument it, or rewrite the byte code. Or send a feature request. I’m sure that your intent of overriding the above isn’t a good idea anyway.

7. 모든 변수들과 파라메터들은 final이다

As I said. I don’t trust myself (to not accidentally overwrite my values). Having said so, I don’t trust myself at all. Because…
… which is why all variables and parameters are made final, too.
// Bad
void input(String importantMessage) {
    String answer = "...";

    answer = importantMessage = "LOL accident";
}

// Good
final void input(final String importantMessage) {
    final String answer = "...";
}
OK, I admit. This one, I don’t apply very often, really, although I should. I wish Java got it right like Scala, where people just type val all over the place, without even thinking about mutability – except when they need it explicitly (rarely!), via var.

8. 오버로드시에는 제너릭을 믿지 마라

Yes. It can happen. You believe you wrote that super nice API which totally rocks and is totally intuitive, and along comes some user who just raw-casts everything up to Object until the darn compiler stops bitching, and suddenly they’ll link the wrong method, thinking it’s your fault (it always is).
Consider this:
// Bad
<T> void bad(T value) {
    bad(Collections.singletonList(value));
}

<T> void bad(List<T> values) {
    ...
}

// Good
final <T> void good(final T value) {
    if (value instanceof List)
        good((List<?>) value);
    else
        good(Collections.singletonList(value));
}

final <T> void good(final List<T> values) {
    ...
}
Because, you know… Your users, they’re like:
// This library sucks
@SuppressWarnings("all")
Object t = (Object) (List) Arrays.asList("abc");
bad(t);
Trust me. I’ve seen everything. Including things like:
7h6fah71



It’s good to be paranoid.

9. switch문의 default에는 항상 throw를 사용하라

Switch… One of those funny statements where I don’t know whether to petrify with awe or to just cry. Anyway, we’re stuck with switch, so we may as well get it right when we have to. i.e.
// Bad
switch (value) {
    case 1: foo(); break;
    case 2: bar(); break;
}

// Good
switch (value) {
    case 1: foo(); break;
    case 2: bar(); break;
    default:
        throw new ThreadDeath("That'll teach them");
}
Because that moment where value == 3 is introduced into the software, it’ll come for sure! And don’t sayenum, because it’ll happen to enums as well!

10. Switch에 중괄호(curly braces)를 사용하라

In fact, switch is the most wicked statement anyone has every allowed to get into a language while they were either drunk or lost a bet. Consider the following example:
// Bad, doesn't compile
switch (value) {
    case 1: int j = 1; break;
    case 2: int j = 2; break;
}

// Good
switch (value) {
    case 1: {
        final int j = 1;
        break;
    }
    case 2: {
        final int j = 2;
        break;
    }

    // Remember:
    default:
        throw new ThreadDeath("That'll teach them");
}
Within the switch statement, there is only one scope defined among all the case statements. In fact, thesecase statements aren’t even really statements, they’re like labels and the switch is a goto call. In fact, you could even compare case statements with the astonishing FORTRAN 77 ENTRY statement, a device whose mystery is only exceeded by its power.
This means that the variable final int j is defined for all the different cases, regardless if we issue a break or not. Not very intuitive. Which is why it’s always a good idea to create a new, nested scope per case statement via a simple block. (but don’t forget the break within the block!)

Conclusion

Paranoid programming may seem weird at times, as code often turns out to be a bit more verbose than really needed. You might think, “oh this is never gonna happen”, but as I said. After 20 years or so programming, you just don’t want to fix those stupid little unnecessary bugs anymore that exist only because the language is so old and flawed. Because you know…

댓글 없음:

댓글 쓰기

BE Band (비밴드) - 2024년 03월 02일 잠실새내 락앤롤욱스 공연

나의 10~20대를 보낸 잠실에서의 공연.. 오랜만에 가보니.. 여기가.. 마눌님과 자주 가던 영화관이었는데... 여긴 뭐가 있었는데... 란 추억도 떠올리며 기분좋게 감.​ 공연장은 좀 협소한 편이었고, 인천의 쥐똥나무 보다는 약간 크고... 인천 ...