'IT/Java'에 해당되는 글 9건

  1. 프로그래밍 지침 - 작성 2014.02.11

프로그래밍 지침 - 작성프로그래밍 지침 - 작성

Posted at 2014. 2. 11. 09:00 | Posted in IT/Java
홈페이제작업체 NuGuWeb

36. 일반적으로 썬의 코딩 컨벤션을 따르라.
 * 이에 대해서는 http://java.sun.com/docs/codeconv/index.html에서 찾을 수 있다(이 책의 코드도 가능한 이 컨벤션을 따랐다).
이것은 틀림없이 많은 자바 프로그래머 접하게 될 대부분의 코드를 구성하는 데 사용된다.
여러분이 완고하게 계속 사용하는 코딩 스타일을 고집한다면 코드를 읽는 사람을 힘들게 하게 될 것이다.
어떤 코딩 컨벤션을 선택하든 그것이 프로젝트에 일관되게 유지하라. 자바 코드를 자동으로 재구성해주는 무료 툴이 http://jalopy.sourceforge.net에 있다.
무료 스타일 검사기는 http://jcsc.sourceforge.net에서 찾을 수 있다.


37. 어떤 코딩 스타일을 사용하든 여러분의 팀(더 좋게는 여러분의 회사)에서 표준화하는 것이 정말로 중요하다.
 * 이것은 모든 사람이 스타일을 따르지 않는 다른 사람의 코딩 스타일을 고치는 일이 정당하다고 여기게 된다는 점을 의미한다.
코드를 해석하는 데 신경을 덜 쓰고 코드가 의미하는 데 더 초점을 맞추는 것이 표준화의 가치다.

 

38. 표준 대문자 규칙을 따르라.
 * 클래스 이름의 첫 번째 글자는 대문자로 하라. 필드, 메소드, 객체(참조)의 첫 번째 글자는 소문자여야 한다.
모든 식별자는 단어를 연결하고 중간에 있는 단어의 첫 번째 글자는 대문자여야 한다. 예를 들면 다음과 같다.
ThisIsAClassName
thisIsAMethodOrFieldName
정의할 때 상수를 초기화하는 static final 원시 식별자는 모든 글자를 대문자로 하라(그리고 단어를 구분하는데언더스코어를 사용하라).
이렇게 하면 그것이 컴파일할때의 상수라는 걸 알려 준다.
패키지는 특별한 경우이다. 모두 소문자인데 심지어 중간에 있는 단어도 그렇다. 도메인 확장자(com, org, net, edu 등)도 소문자여야 한다. (이것은 자바 1.1.과 자바 2의 차이점이다).

 

39. 자신만의 장식된 private 필드 이름을 만들지 말라.
 * 이것은 대체로 앞에 붙는 언더스코어나 문자 같은 형태이다. 헝가리안 표기법은 가장 나쁜 경우인데, 자료형, 사용 방법위치 등을 알려주는 문자를 붙이는 것으로, 마치 어셈블리 언어로 작성하고 컴파일러가 아무런 도움도 되지 않는경우와 같다.
이 표기법은 혼동되고 읽기 어려우며 강요하거나 유지하기도 불쾌하다. 클래스와 패키지로 네임 스코프를관리하라.
혼란을 막기 위해 이름을 장식해야 한다고 느낀다면, 코드가 혼란스러운 것이니 간단히 해야 한다.

 

40. 범용 클래스를 만들 때 "일반 규칙"을 따르라.
 * equals(), hashCode(), toString(), (Clonable을 구현하거나 직렬화 같이 다른 객체가 복사하도록 하는 경우에는) clone()을 정의하고, Comparable과 Seriaizable을 구현하라.

 

41. 자바빈즈라고 생각되지 않더라고 자바빈즈에서 private 필드를 읽고 변경하는 메소드에는 "get", "set", "is" 네이밍 컨벤션을 사용하라.
 * 이렇게 하면 클래스를 빈으로 사용하기 쉬울 뿐만 아니라, 이런 종류의 메소드 이름에 대한 표준을 따르는 것이어서 읽는 사람이 보다 쉽게 이해할 것이다.

 

42. 만드는 모든 클래스에 jUnit 테스트를 포함하라(www.junit.org와 15장의 예를 보라).
 * 프로젝트에서 사용하기 위해 테스트 코드를 없애지 않아도 되고, 뭔가 변경해도 쉽게 테스트할 수 있다. 이 코드는 클래스를 사용하는 방법에 대한 예가 되기도 한다.

 

43. 가끔 기간 클래스의 protected 멤버에 접근하기 위해서 상속하는 경우가 있다.
 * 이것은 다중 기반 타입을 요구할 수 있다. 상향 캐스팅 하지 않다고 된다면 먼저 protected에 접근하는 새로운 클래스를 도출하라.
그러고 나서 그 클래스를 필요한 클래스의 멤버 객체로 집어 넣으라, 상속하는 것보다 낫다.

 

44. 능률을 위해 final 메소드를 사용하지 말라.
 * 프로그램을 실행할 때만 final을 사용하라, 하지만 그렇게 빠르지 않고, 프로파일러가 메소드가 시동할 때 병목 현상이 생긴다고 일려 준다.

 

45. 두 클래스가(컨테이너와 반복자 같이) 기능상 서로 연관이 있다면, 하나를 다른 하나의 내부 클래스로 만들어 보라.
 * 이것은 클래스간의 연관성을 강조할 뿐만 아니라 클래스에 내포함으로 써 패키지 안에서 클래스 이름을 재사용하게 한다.
 자바 컨테이너 라이브러리는 이를 위해 각 컨테이너 클래스에 내부 Iterator 클래스를 정의하므로, 컨테이너에 공통 인터페이스가 제공된다.
내부 클래스를 사용하고자 하는 다른 이유는 private 구현의 일부이기 때문이다.
이 점에서 내부 클래스는 클래스 연관에 비해 구현을 감추기 쉬우며 언급한 네임스페이스 오염 문제도 방지한다.

 

46. 서로 강하게 연결된 클래스를 발견하는 족족 내부 클래스를 이용하여 코딩과 유지보수를 향상시킬 수 있는지 고려하라.
 * 내부 클래스를 사용한다고 클래스 연결이 풀어지는 건 아니지만, 연결성을 확실하게 하므로 보다 편해진다.

 

47. 성급한 최적화의 희생양이 되지 말라.
 * 그건 미친 짓이다. 특히 처음으로 시스템을 구성할 때는 네이티브 메소드를 작성하는 일(또는 피하는 일), final 메소드를 만드는 일, 효율적으로 코드를 조정하는 일 등을 걱정하지 말라. 목표는 설계를 입증하는 것이어야 한다.
설계가 어떤 효율성을 요구하더라도 먼저 작동하게 하고 그 다음에 빠르게 하라.

 

48. 객체의 가시성과 수명을 가능한 작게 하기 위해 스코프를 가능한 작게 유지하라.
 * 이렇게 하면 객체가 잘못된 부분에 쓰이거나 찾기 힘든 버그가 숨을 수 있는 기회가 줄어든다.
예를 들어 컨테이너와 그것을 반복하는 코드가 있다고 하자. 만약 새로운 컨테이너를 사용하는데 그 코드를 복사했다면, 예전 컨테이너의 크기를 새로운 컨테이너의 상한선으로 잘못 사용할 수 있다. 하지만 예전 컨테이너가 스코프 밖에 있다면 컴파일할 때 에러를 잡게 된다.

 

49. 표준 자바 라이브러리에 있는 컨테이너를 사용하라.
 * 그들을 사용하는 데 익숙해지면 생산성이 크게 향상될 것이다. 순서에는 ArrayList, 집합에는 HashSet, 연관되 배열에는 HashMap, 스택(스택 인터페이스를 제공하는 어댑터를 만들어야 하지만 Stack보다 낫다)과 Queue(이 책에서처럼 어댑터가 필요하다)에는 LinkedList가 좋다. 처음 세 가지를 사용할 때는 각가 List, Set, Map으로 상향 캐스트 하는데, 그렇게하면 필요할 때 다른 구현으로 쉽게 바꿀 수 있다.

 

50. 프로그램이 단단하려면 각 컴포넌트가 단단해야 한다.
 * 클래스를 만들 때마다 자바가 제공하는 모든 도구(접근 제어, 예외, 타입 검사, 동기화 등)를 사용하라.
이렇게 하면 시스템을 구축할 때 안전하게 다음 단계의 추상화로 넘어갈 수 있다.

 

51. 런타임 에러보다 컴파일 에러가 낫다.
 * 가능하면 에러가 발생하는 순간에 가장 가까운때 처리하려고 하라.
가장 가까이 있으면서 처리하는 데 충분한 정보를 제공하는 핸들러에서 모든 예외를 잡으로. 현재 예외 수준에서 할 수 있는 일을 하라.
문제를 해결하지 못하면 다시 예외를 던지라.

 

52. 긴 메소드 정의를 주의하라.
 * 메소드는 간경한 기능적인 단위로써 클래스 인터페이스 각 부분을 설명하고 구현해야 한다.
길고 복잡한 메소드는 유지하기 어렵고 비용도 많이 들며, 그 자체만으로도 너무 많은 일을 한 것이다. 그런 메소르를 발견하면 여러 개의 메소드로 분리해야 한다. 새로운 클래스를 만드는 것도 고려할 수 있다. 작은 메소드는 클래스에서 계속 재사용될 것이다(메소드가 커야 하는 경우가 있는데, 이 때도 단지 한 가지만 해야 한다).

 

53. "가능한 private"으로 유지하라.
 * 한 번 라이브러리(메소드, 클래스, 필드)의 관점을 공개하면 다시는 되돌릴 수 없다.
그렇게 하려면 누군가의 코드를 망치고 그들에게 재작성하고 재설계하도록 강요하게 될 것이다.
꼭 필요한 것만 공개하면 아무런 문제 없이 변경할 수 있고, 설계가 변경되는 경우가 많기 때문에 그렇게 자유로울 수 있다는 사실이 중요하다.
이 경우 구현을 변경해도 유도 클래스에 미치는 영향은 극히 적다.
멀티쓰레딩을 처리할 때 private이 특히 중요한데 private 필드만이 비 synchronized로부터 보호받을 수 있다.
패키지 접근이 가능한 클래스도 private 필드를 갖는데, public으로 만들기보다는 패키지 접근을 위한 메소드를 제공하는 게 좋다.

 

54. 주석을 많이 사용하고 프로그램 문서를 만들기 위해 javadoc 주석 문서 문법을 사용하라.
 * 그러나 주석이 코드에 진정한 의미를 부여해야 한다. 코드가 명확하게 표현한 것을 되풀이하는 주석은 불쾌하다.
자바 클래스와 메소드 이름에 대한 전통적이고 장황한 설명이 몇몇 주석을 필요없게 만든다는 사실을 알아두라.

 

55. "매직 넘버"를 사용하지 말라.
 * 그것은 코드에 박혀 있는 숫자이다. 변경하려고 할 때, "100"이 "배열 크기"를 의미하는지 "다른 어떤 것 전체"를 의미하는지 모른다는 것은 악몽이다.
대신 설명이 잘 된 이름으로 상수를 만들고 프로그램에서 상수 식별자를 사용하라. 이렇게 하면 이해하기 쉽고 유지하기도 쉽다.

 

56. 생성자를 만들 때 예외를 고려하라.
 * 가장 좋은 경우는 생성자에서 예외를 던질 만한 일을 안 하는 것이다. 그 다음으로 좋은 경우는 클래스가 조립되고 단단한 클래스에서만 상속받아서 예외가 발생했을 때 청소할 필요가 없는 것이다. 대신 finally 절에서 조립된 클래스를 청소해 주어야 한다. 생성자가 확실히 실패했다면, 예외를 던져서, 객체가 제대로 생성되었다고 생각한 채 호출자가 무턱대고 나아가지 않도록 하는 것이 가장 적절하다.

 

57. 생성자에서는 상황에 맞게 객체를 설정하는 데 필요한 것만 하라.
 * 특히(final 메소드를 제외한) 다른 메소드를 호출하지 않도록 하는데, 다른 누군가에 의해서 오버라이드되어 생성하는 동안 예기치 못한 결과가 발생할 수 있기 때문이다(자세한 사항은 7장 참조). 생성자가 작고 간단할수록 예외를 던지거나 문제가 발생하는 일이 줄어든다.

 

58. 클라이언트 프로그래머가 객체를 사용한 다음에 클래스를 청소해야 한다면, 청소 코드를 잘 정의된 메소드 하나에 넣으라.
 * 그에 맞추어 dispose()라는 이름을 추천한다. dispose()가 호출되었는지 알려주는 boolean 플래그를 클래스에 추가해서 finalize()가 "종료 상태"를 검사할 수 있도록 한다(4장 참조).

 

59. finalize()는 디버깅하기 위해 객체의 "종료 상태"를 검증할 때만 책임이 있다(4장 참조).
 * 특별한 경우 가비지 컬렉터에 의해 해제되지 않은 메모리를 해제해야 한다.
가비지 컬렉터는 특정 객체를 위해 호출되지 않기 때문에 필요한 청소 작업을 수행하는 데 finalize()를 사용할 수 없다.
그래서 여러분만의 dispose()메소드를 만들어야 한다. 클래스의 finalize() 메소드에서는 객체가 청소되었는지 확인하고 그렇지 않다면 RuntimeException으로 부터 도출된 클래스를 던져서 프로그래밍 에러를 알린다.
그런 계획에 의지하기 전에 시스템에서 finalize()가 확실히 작동하는지 확인하라(확인하려면 System.gc()를 호출해야 할 것이다)

 

60. 객체가 특정한 스코프에서 가비지 컬렉션이 아닌 다른 방법으로 청소되어야 한다면 다음 관습을 따르라.
 * 객체를 초기화하고, 성공하면 곧장 try 블록으로 들어가서 finally 절에서 청소한다.

 

61. 상속하면서 finalize()를 오버라이드한다면, 잊지 말고 super.finalize()를 호출하라(Object가 직계 슈퍼 클래스인 경우에는 상관 없다).
 * 오버라이드한 finalize()에서 super.finalize()를 호출하는 일은 첫 번째보다는 마지막이 좋은데, 필요할 때에 기반 클래스 컴포넌트가 유요한지 확인하기 위해서이다.>

 

62. 크기가 고정된 객체 컨테이너를 만들면 배열로 옮기라.
 * 메소드로부터 반환받는 경우 특히 그렇다. 이렇게 하면 배열이 제공하는 컴파일할 때의 타입 검사를 활용하고, 배열을 받는 쪽도 배열 안의 객체를 사용하기 위해 캐스트 연산을 하지 않는다. 컨테이너 라이브러리의 기반 클래스인 java.util.Collection이 이러한 일을 할 수 있는 두개의 toArray() 메소드를 가지고 있다는 데 주목하라.

 

63. 추상 클래스에서 인터페이스를 선택하라.
 * 기반 클래스가 될 것이 있다면, 먼저 인터페이스가 될 것을 골라내고, 변경되는 메소드 정의나 멤버 변수가 있을 때만 추상 클래스로 한다.
인터페이스는 클라이언트가 하려고 하는 것에 관심을 두는 반면, 클래스는 세부적인 구현에 초점을 맞춘다(또는 구현하도록 한다).

 

64. 큰 좌절을 경험하고 싶지 않다면, 패키지되지 않은 클래스는 클래스 패스에 각각의 이름을 써라.
 * 그렇지 않으면 컴파일러가 같은 이름을 가진 다른 클래스를 먼저 찾아서 말도 안 되는 에러 메시지를 보일 수 있다.
클래스 패스에 문제가 있다고 생각되면, 클래스 패스가 시작되는 지점에서부터 같은 이름을 가진 .class 파일을 찾도록 하라.
이상적으로는 모든 클래스를 패키지 안에 넣으라.

 

65. 우연한 과부하를 주의하라.
 * 기반 클래스의 메소드를 오버라이드할 때 철자를 제대로 맞추지 못하면, 기존 메소드를 오버라이드하는 게 아니라 새로운 메소드를 추가하게 된다.
하지만 이것은 지극히 정상이어서 컴파일할 때나 런타임에 어떤 에러 메시지도 볼 수 없다. 단지 코드가 제대로 동작하지 않을 뿐이다.

 

66. 성급한 최적화를 주의하라.
 * 먼저 동작하게 하고 그 다음에 빠르게 하라. 다만 꼭 해야 하거나 여러분의 코드 특정 부분에서 성능이 저하된다고 입증되었을 경우에만 그렇다.
 병목 지점을 발견하기 위해 프로파일러를 사용하면 시간을 절약할 수 있다.
성능 조정을 하게 되면 코드의 이해성과 유지보수성이 떨어질 가능성이 있다.

 

67. 코드란 작성되기보다 읽혀지는 것이라는 사실을 명심하라.
 * 깨끗한 설계는 프로그램을 이해하기 쉽게 해주지만 주석, 상세 설명, 테스트, 예제는 값을 매길 수 없을 정도이다.
그것은 여러분과 여러분의 후임 개발자 모두에게 도움이 된다. 아무것도 없다면 JDK 문서로부터 유용한 정보를 찾아 보려는 노력도 허사가 될 것이다.

//