81
오픈에스엔에스 AA조영석

Sonarqube 20160509

  • Upload
    -

  • View
    423

  • Download
    4

Embed Size (px)

Citation preview

Page 1: Sonarqube 20160509

오픈에스엔에스AA팀조영석

Page 2: Sonarqube 20160509

소프트웨어 품질

소프트웨어 구현

SonarQube 기능 및 특징

SonarQube 사용방법

소스 품질을 위한 코딩

Q&A

Page 3: Sonarqube 20160509

기능적 요구사항(Functional Requirements)- 수행될 기능과 관련되어 입력과 출력 및 그들 사이의 처리과정- 목표로 하는 제품의 구현을 위해 소프트웨어가 가져야 하는 기능적 속성

비기능적 요구사항(Non-Functional Requirements)◦ 제품의 품질 기준 등을 만족시키기 위해 소프트웨어가 가져야 하는 성능, 사용의 용의성, 안전성과 같은 행위적 특성

◦ 시스템의 기능에 관련되지 않는 사항을 나타냄

기능 비기능

Page 4: Sonarqube 20160509

효율적인 SW 개발 관리

가치있는 SW

계 획

명확한 목표수립

수 행

효율적인 개발활동

검 증

지속적인 모니터링 및 통재

“계획 기반의

지속적 검증”

“시각적 검증을

위한 시스템 활용”

Page 5: Sonarqube 20160509

Subversion

Eclipse

Jenkins

Ant, Script

NSIQ Conllector

PMD, CPPCheck

Emm

a, gcov

Junit, CPPUnit

Impasse

Redmine

SonarQube

요구사항 테스트 구현 형상관리

Page 6: Sonarqube 20160509

1. 소스코드를 바이너리 파일로 컴파일 한다.2. 바이너리 파일을 배포 형태로 패키징한다.3. 단위테스트(커버리지 포함) 수행한다.4. 정적분석을 수행한다.5. 분석 결과를 리포팅한다.6. 패키징한 파일을 테스트 서버에 배포한다.

Page 7: Sonarqube 20160509

SW 구현은 SW 공학의가장 기본적인활동으로 코드작성, 디버깅, SW통합, 개발자 테스팅 활동들로 이루어진다.

SW 구현할 때 고려해야 할 4가지 주요원칙

- 코딩의 복잡성을 최소화

- 향후에 일어날 변화를 고려

- 소프트웨어 구현은 검증이 가능해야 한다는 것

- 표준을 활용하는 것

코딩 규칙이나 표준을 수립하여모든 개발자가 프로젝트에서 조화롭게작업할

수 있도록 해야 한다. 이렇게 해서 좋아진 소스 코드의가독성은 개발자가 SW 시스템을 이해하는데영향을 미치게 되고, 가독성이향상되면 이해가 용이해지고

유지보수가 수월해지며일반적으로 코드의 품질도좋아진다.

Page 8: Sonarqube 20160509

품질 관리 도구의 주요기능 잠재적 오류 소스 코드 검출 개발 표준 준수 쉬운 룰 생성 및 편집 자동 룰 업데이트

정적 분석 도구를 통해 검색 되는 내용 공유된 코딩 스타일 위반 잠재적 버그의 코딩 설계상의 문제가 되는 코드 중복되고 보안에 위반되는 코드 등등……

Page 9: Sonarqube 20160509

정적 분석 도구로 소스코드에대한 전반적인 품질을 확보할 수 있도록 정보를 제공하는통합 플랫폼

Server / Client 구조 C/C++/Java 등 15개 이상의 다양한 프로그램언어 지원

플러그인설치로 다양한 도구와 유연한 통합 웹 기반 애플리케이션으로다양한 결과를 서버에서 통합 관리 용이

Page 10: Sonarqube 20160509

프로젝트 소스 품질을 관리할 수 있도록 여러가지 모니터링 툴을 제공하는 오픈소스 플랫폼

보통 SonarQube는 단독으로 사용되기 보다는 Jenkins 같은 CI 서버와 연동이 되어서 사용이 되어지고 있으며Java를 포함한 20가지가 넘는 프로그램밍 언어로 제작된프로젝트의 모니터링을 제공

Page 11: Sonarqube 20160509

Java 기반의 정적분석 툴로써, 다양한 항목에 대해 분석및 결과를 볼 수 있는 품질관리 대시보드 툴

- 소스코드관리 하는 오픈소스기반의 무료툴

- 자바검증도구(PMD, findbugs, Checkstyle)가 PlugIn형태로 들어가 있음

- 중복코드(Squid, CPD) 체크- 코드 커버리지(Cobertura, jaCoCo)

Page 12: Sonarqube 20160509

JDK 환경에서 동작, 웹서버 및 DBMS 필요

다양한 OS를 지원 : Windows, Linux, Mac OS X, Unix DBMS 필요

=> Derby(기본 제공), MSSQL, MySQL, Oracle 웹서버(WAS : Web Application Server) 필요

=> Jetty6, Apache Tomcat 자바 기반 프로그램 : JDK 1.5 이상 필요

Page 13: Sonarqube 20160509

- Sonar 자체는 분석결과를 보여주는 툴. 실제분석은 Sonar 내의Plug-in을 통하여 분석

- 기본적으로 제공되는 분석 툴1) PMD : 소스코드의 표준준수 분석2) FindBugs : 자바바이트코드를 분석하여 정적분석3) CheckStyle : 코드 스타일체크4) Cobertura : 테스트 커버리지체크5) Surefire : 유닛테스트

- Sonar에서 분석결과를 보기 위해 분석을 위한 Client의 종류1) Sonar runner : 권장되는 기본 클라이언트2) Maven : Maven 기반으로 작성된 프로젝트에 적합3) Ant Task : Ant 작성된 프로젝트에 적합

Page 14: Sonarqube 20160509

- Sonar는 Checkstyle, PMD, FindBugs, Coberbura 등의분석툴 들을 이용하여 소스의 정적분석을 실시하고, 이를 웹브라우저를 통하여 전체적인 분석결과를 보여주는툴

SonarQube

Analysers Eclipse

DatabaseServer

Page 15: Sonarqube 20160509

- Sonar가 제공하는 분석결과는 다음과 같음- 코드 중복 체크- 코드의 표준- 코드 coverage- 코드 복잡도- 주석- 디자인 과 아키텍쳐

- 기본적으로는 Java 언어를 분석할 수 있지만, 추가 플러그인을 통하여 다른 대부분의 언어에 대해서도 검사 가능

Page 16: Sonarqube 20160509

JAVA, C/C++등의 다수 프로그램 언어 지원 플러그인 설치로 다양한 도구와 유연한 통합 여러가지 분석 툴을 통합하여 여러 항목들을 한번에 검사 가능(Checkstyle, PMD, FindBugs, CPPCheck, Cobertura 등)

웹기반 애플리케이션으로 다양한 분석 결과들을 확인 가능(버그&잠재버그체크, 코딩 표준 위반 체크, 중복 코드 체크, 단위 테스트 커버리지 체크, 소스 복잡도 체크, 주석 처리량 체크)

분석을 위한 여러 클라이언트를 제공(Sonar runner, Maven, Ant T ask)

Page 17: Sonarqube 20160509

정적 코드 분석 도구 선정부터적용까지 모든 프로세스에 개발자 참여

코드에 알맞은 도구 선택 새롭게 작성하는코드에 집중하기. 이미 작성된코드에 너무 신경쓰지말 것

결함 찾는데 혈안 되지 말고 개발 생산성에집중 정적코드분석 및 결과에 대한 이슈 관리를자동화

Page 18: Sonarqube 20160509
Page 19: Sonarqube 20160509
Page 20: Sonarqube 20160509
Page 21: Sonarqube 20160509
Page 22: Sonarqube 20160509
Page 23: Sonarqube 20160509
Page 24: Sonarqube 20160509
Page 25: Sonarqube 20160509
Page 26: Sonarqube 20160509
Page 27: Sonarqube 20160509

https://nemo.sonarqube.org/ 코딩 규칙(Rules)◦ Lanauage : Java◦ Tag : Security, performance

Page 28: Sonarqube 20160509

"@Deprecated" code should not be used이 Annotation은가급적사용을 자제해달라는의미로사용된다. 예를들어어떤method 앞에 @Deprecated가 붙으면, 이 메소드를사용하거나오버라이드할 경우, 컴파일할 때 경고가 뜬다.

더 나은, 개선된메소드가있음을 나타내고자할 때에주로 사용한다. 개발자가어떤 메소드를썼는데, 이 메소드가 deprecated annotation 처리되어있다면, 이 메소드는다음 버젼에서사라지거나더 개선된메소드로대체될것이기 때문에, 이용을자제해야한다. (요약 하자면, 더 나은기능을 제공하고있으니, 차선책을찾아보라는의미로 쓰인다)/*** @deprecated As of release 1.3, replaced by {@link #Fee}*/@Deprecated

class Fum { ... }

public class Bar extends Fum { // Noncompliant; Fum is deprecated

public void myMethod() {Foo foo = new Foo(); // okay; the class isn't deprecatedfoo.doTheThing(); // Noncompliant

}}

Page 29: Sonarqube 20160509

"ConcurrentLinkedQueue.size()" should not be usedConcurrentLinkedQueue.size() 를 사용을자제 해라.해당 명령문은 Queue의크기가클 경우 작업시간이오래 걸릴 수가있다.또는 Queue가실행중에 변경되는경우 또한결과가 정확하지않을수가 있다.

단지, 크기만을위해서체크해야할 경우 isEmpty() 메소드와함께 사용해야합니다.

ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue();//...log.info("Queue contains " + queue.size() + " elements");

Page 30: Sonarqube 20160509

"Exception" should not be caught when not required by called methods예외처리를위해 try~catch 구문이사용될때, catch 문에서잡는 예외는예외사항별로세부대응을하도록코딩한다. 광역 대응이꼭 필요한 경우에는앞에서적용 가능한세부 대응을먼저 사용 한 후 맨 마지막에대응하도록한다.try {// do something that might throw an UnsupportedDataTypeException or

UnsupportedEncodingException} catch (Exception e) { // Noncompliant// log exception ...

}try {// do something

} catch (UnsupportedEncodingException|UnsupportedDataTypeException|RuntimeException e) {// log exception ...

}

Page 31: Sonarqube 20160509

"HttpServletRequest.getRequestedSessionId()" should not be used- getRequestedSessionId 메소드는?: 클라이언트로부터 지정된세션ID를 반환한다. 이는 요청에대한 현재 유효한세션 ID와 동일하지않을 수 있다. 클라이언트가세션 ID를 지정하지않은 경우,이 메소드는null를돌려주게됩니다.

세션ID가 어떠한 HTTP의 요청에 의해변경이 될 수 있기때문에 사용하지않는다.if(isActiveSession(request.getRequestedSessionId()) ){...

}

Page 32: Sonarqube 20160509

"java.lang.Error" should not be extendedJava.lang.Error 클래스와그 서브클래스 들은시스템의뭔가 비정상적인상황이발생했을 경우사용된다.그래서주로 자바 VM에서발생시키는것이고 어플리케이션코드에서잡으려고하면 안된다.

OutofMemoryError나 ThreadDeath 같은에러는 catch 블럭으로잡아도대응 방법이없다.

따라서시스템 레벨에서특별한작업을하는 게 아니라면어플리케이션에서는이런에러에 대한처리는 신경쓰지 않아도된다.public class MyException extends Error { /* ... */ } // Noncompliant

public class MyException extends Exception { /* ... */ } // Compliant

Page 33: Sonarqube 20160509

"main" should not "throw" anythingmain 메소드에서는 throw 를 사용하지 않는다.Exception이 발생할 경우 던질 곳이 없다.public static void main(String args[]) throws Exception { // Noncompliant

public static void main(String args[]) {

Page 34: Sonarqube 20160509

"NullPointerException" should not be caughtNullPointerException 이 발생할 수 있는부분을 try catch로 구현하려는것보다발생할 수 있는 부분에미리 null 체크를하여 발생하지않도록한다.public int lengthPlus(String str) {int len = 2;try {

len += str.length();}catch (NullPointerException e) {log.info("argument was null");

}return len;

}

public int lengthPlus(String str) {int len = 2;

if (str != null) {len += str.length();

}else {log.info("argument was null");

}return len;

}

Page 35: Sonarqube 20160509

"Object.finalize()" should remain protected (versus public) when overridingObject.finalize()를 오버라이드할때 protected 상태를유지 해야한다.

finalize는 Garbage Collector에 의해호출 됩니다.따라서어디에서나호출할수 있는 public을 사용하는것은잘못된 방법입니다.

보통 finalize() 메소드를 override 하여사용하고, System.gc() 메소드를통해 가비지컬렉션이발생되도록하여정의된 finalize() 메소드를수행시킨다.public class MyClass {

@Overridepublic void finalize() { // Noncompliant

/* ... */}

}

Page 36: Sonarqube 20160509

"public static" fields should be constantpublic static 필드는변하지않아야 합니다.final을선언하지않고 public 과 static 필드를선언할이유가 없다.

static 으로 변수를선언하게되면은한 클래스의모든 인스턴스에서해당 static 변수를공유할수 있다.public class Greeter {public static Foo foo = new Foo();...

}public class Greeter {public static final Foo FOO = new Foo();...

}

Page 37: Sonarqube 20160509

"runFinalizersOnExit" should not be called"runFinalizersOnExit"는 호출할 수 없다.

System.gc() 와 System.runFinalization() 메소드들을 사용하지 말자.그 메소드들은 파이널라이저가 실행될 가능성을 높여주긴 하지만, 실행됨을 보장하지는 않는다.파이널라이즈를 보장하는 유일한 메소드들은 System.runFinalizersOnExit() 와Runtime.runFinalizersOnExit() 인데 이 메소드들은 치명적 결함이 있어 현재는 사용 금지되었다.public static void main(String [] args) {...System.runFinalizersOnExit(true); // Noncompliant...

}

protected void finalize(){doSomething();

}public static void main(String [] args) {Runtime.addShutdownHook(new Runnable() {

public void run(){doSomething();

}});//...

Page 38: Sonarqube 20160509

"static final" arrays should be "private"static final 배열엔 private를 사용해라

public static final 배열 필드를두거나, 배열 필드를반환하는접근자를정의 하면안된다. 그런 멤버를두면 클라이언트가배열 내용을변경할 수 있게되므로, 보안에문제가 생긴다. 이 문제를고치는첫번째는 public으로 선언되었던배열은 private으로바꾸고 변경이불가능한 public 리스트를하나 만드는것이다.public class Estate {// Noncompliant; array contents can be modifiedpublic static final String [] HEIRS = new String [] {

"Betty", "Suzy" };}

public class Malicious {public void changeWill() {Estate.HEIRS[0] = "Biff";if (Estate.HEIRS.length > 1) {for (int i = 1; i < Estate.HEIRS.length; i++) {Estate.HEIRS[i] = "";

}}

}

public class Estate {private static final String [] HEIRS = new String [] {

"Betty", "Suzy" };

public String [] getHeirs() {// return copy of HEIRS

}}

Page 39: Sonarqube 20160509

클래스와 멤버의 접근 권한은 최소화 하라- 각 클래스와 멤버는 가능한 접근 불가능하도록 만들어라

: 정보은닉 또는 캡슐화는 시스템을 구성하는 모듈 사이의 의존성을 낮춰서 개발 속도 및 유지보수에 효율적이다.

- 객체필드(instance field)는절대로 public으로선언하면 안된다.: 변경 가능 public 필드를 가진 클레스는 다중 스레드에 안전하지 않다. 변경 불가능 객체를 참조하는 final 필드라 해도 public으로선언하면 클래스 내부 데이터 표현 형태를 유연하게 바꿀 수없게 된다

- static으로 선언된 필드에도 똑같이 적용되지만 한가지 예외가 있다. 어떤상수들이 클래스로 추상화된 결과물의 핵심적 부분을 구성한다고 판단되는경우, 해당 상수들을 public static final 필드들로 선언하여 공개할 수 있다. (public static final 필드가 참조하는 객체는 변경 불가능 객체로 만들어라.)

- 길이가 0 아닌 배열은 언제나 변경 가능하므로, public static final 배열 필드를 두거나, 배열 필드를 반환하는 접근자를 정의하면 안 된다. 그런 멤버를 두면 클라이언트가 배열 내용을 변경할 수 있게 되므로, 보안에 문제가생긴다.

Page 40: Sonarqube 20160509

//보안 문제를 초래할 수 있는 코드public static final Thing[] VALUES { ... };

이 문제를 고치는 방법 중 첫 번째는 public으로 선언되었던 배열은 private으로 바꾸고, 변경이 불가능한 public 리스트를 하나 만드는 것이다.

private static final Thing[] PRIVATE_VALUES = { ... };public static final List<Thing> VALUES = Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUE));

두 번째 방법은 배열은 private으로 선언하고, 해당 배열을 복사해서 반환하는public 메서드를 하나 추가하는 것이다.

private static final Thing[] PRIVATE_VALUES = { ... };public static final Thing[] values(){ return PRIVATE_VALUES.clone(); }

Page 41: Sonarqube 20160509

"wait(...)" should be used instead of "Thread.sleep(...)" when a lock is held실행 대기 할 경우 Thread.sleep(…) 대신에 wait(…)를 사용하여라.

Thread.sleep()은 대상 Thread가 sleep 상태가 되는 것인데 lock을 획득한 상태로 sleep 합니다Object에 대해 wait()을수행하게 되면 해당 Object lock을 소유하고 있다면 lock을 반환하고 wait() 후 깨어나게 됩니다.즉, wait()하게 되면 lock을획득한 상태에서 lock를 반환하고 wait()하게됩니다.그러면 lock 대기중인 다음 Thread가 lock을 획득하게 됩니다.public void doSomething(){synchronized(monitor) {

while(notReady()){Thread.sleep(200);

}process();

}...

}

public void doSomething(){synchronized(monitor) {

while(notReady()){monitor.wait(200);

}process();

}...

}

Page 42: Sonarqube 20160509

Checked Exception should not be thrownChecked Exception 은 발생하지않아야한다.

검증된예외는 컴파일러나 jvm에 의해말그대로 ‘걸러낸/확인된’ 자동화된예외처리방법이고자바에서는예외처리하도록강제하기위해예외처리하지 않으면 에러라간주하고진행되지않는다.public void myMethod1() throws CheckedException {...throw new CheckedException(message); // Noncompliant...throw new IllegalArgumentException(message); // Compliant; IllegalArgumentException is unchecked

}

public void myMethod2() throws CheckedException { // Compliant; propagation allowedmyMethod1();

}

Page 43: Sonarqube 20160509

Classes should not be compared by name클래스는이름으로비교해서는안된다.

클래스의이름은패키지 내에서고유하지만패키지가다를경우 고유하지않습니다. 따라서 해당클래스의이름을 기준으로비교는위험 합니다.악의적인사용자가비교 할 클래스의이름과같은 객체를전송하여액세스 할 경우위험할 수 있습니다.package computer;class Pear extends Laptop { ... }

package food;class Pear extends Fruit { ... }

class Store {

public boolean hasSellByDate(Object item) {if

("Pear".equals(item.getClass().getSimpleName())) { // Noncompliant

return true; // Results in throwing away week-old computers

}}

}

class Store {

public boolean hasSellByDate(Object item) {if (item instanceof food.Pear) {return true;

}}

}

Page 44: Sonarqube 20160509

Cookies should be "secure"쿠키는 secure로 사용해야한다.

setSecure는쿠키의 보안설정으로 true로 설정할경우 HTTPS나 SSL과같은 secure protocol 에서만사용 할 수 있다.Cookie c = new Cookie(SECRET, secret); // Noncompliant; cookie is not secureresponse.addCookie(c);Cookie c = new Cookie(SECRET, secret);c.setSecure(true);response.addCookie(c);

Page 45: Sonarqube 20160509

Credentials should not be hard-coded자격증명은하드코딩하지말아라

하드코딩할 경우 컴파일된응용프로그램에서문자열을추출하기쉽기 때문이다.자격증명은암호화된외부구성 파일이나데이터베이스에저장해야합니다.Connection conn = null;try {conn =

DriverManager.getConnection("jdbc:mysql://localhost/test?" +"user=steve&password=blue"); // Noncompliant

String uname = "steve";String password = "blue";conn =

DriverManager.getConnection("jdbc:mysql://localhost/test?" +

"user=" + uname + "&password=" + password); // Noncompliant

Connection conn = null;try {String uname = getEncryptedUser();String password = getEncryptedPass();conn =

DriverManager.getConnection("jdbc:mysql://localhost/test?" + "user=" + uname + "&password=" + password);

Page 46: Sonarqube 20160509

Exception classes should be immutableException classes는 불변해야합니다.

Exception은 에러가 발생하는어플리케이션의상태를표현하는것을 의미한다.

public class MyException extends Exception {private int status; // Noncompliantpublic MyException(String message) {

super(message);}public int getStatus() {

return status;}public void setStatus(int status) {

this.status = status;}

}

public class MyException extends Exception {private final int status; // Compliantpublic MyException(String message, int status) {

super(message);this.status = status;

}public int getStatus() {

return status;}

}

Page 47: Sonarqube 20160509

Exception handlers should preserve the original exceptionException handlers 는 원래 Excepion을 보존한다.

발생된에러를 처리할때, 발생한 예외를그대로 호출한쪽으로전달되어야합니다.// Noncompliant - exception is losttry { /* ... */ }catch (Exception e) { LOGGER.info("context"); }

// Noncompliant - exception is lost (only message is preserved) try { /* ... */ } catch (Exception e) { LOGGER.info(e.getMessage()); }

// Noncompliant - exception is lost try { /* ... */ } catch (Exception e) { throw new RuntimeException("context"); }

try { /* ... */ } catch (Exception e) { LOGGER.info(e); }

try { /* ... */ } catch (Exception e) { throw new RuntimeException(e); }

try {/* ... */

} catch (RuntimeException e) {doSomething();throw e;

} catch (Exception e) {// Conversion into unchecked exception is also

allowedthrow new RuntimeException(e);

}

Page 48: Sonarqube 20160509

Exception types should not be tested using "instanceof" in catch blocks예외 유형은 catch 블록안에서 “instanceof” 를 사용해서테스트 해서는안된다.

일반예외로캐치한다음에유형에 따라서처리하는대신에여러 유형에 맞는 catch 블록에 처리해야 한다.try {/* ... */

} catch (Exception e) {if(e instanceof IOException) { /* ... */ } // Noncompliantif(e instanceof NullPointerException{ /* ... */ } // Noncompliant

}try {/* ... */

} catch (IOException e) { /* ... */ } // Compliant} catch (NullPointerException e) { /* ... */ } // Compliant

Page 49: Sonarqube 20160509

Exceptions should not be thrown from servlet methods예외는 servlet methods에발생되어서는안된다.

public void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException, ServletException {String ip = request.getRemoteAddr();InetAddress addr = InetAddress.getByName(ip); // Noncompliant; getByName(String) throws

UnknownHostException//...

}public void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException, ServletException {try {

String ip = request.getRemoteAddr();InetAddress addr = InetAddress.getByName(ip);//...

}catch (UnknownHostException uhex) {//...

}}

Page 50: Sonarqube 20160509

Exceptions should not be thrown in finally blocks예외 시에 finally 블록에서 thrown 을 하면안된다

Flnally block은 프로그램의수행 중 발생할수 있는 어느문제에 대해서도자원의손상을 막고 원상복구를확실히하기위해 사용된다.즉, try-catch 구문에서예외의 발생여부에 상관없이실행되어야할 코드를 넣는곳이finlly 구문이다.try {/* some work which end up throwing an exception */throw new IllegalArgumentException();

} finally {/* clean up */throw new RuntimeException(); // Noncompliant - will mask the IllegalArgumentException

}try {/* some work which end up throwing an exception */throw new IllegalArgumentException();

} finally {/* clean up */ // Compliant

}

Page 51: Sonarqube 20160509

Generic exceptions should never be thrown일반적인예외는결코 thrown 하면안된다.

public void foo(String bar) throws Throwable { // Noncompliantthrow new RuntimeException("My Message"); // Noncompliant

}public void foo(String bar) {throw new MyOwnRuntimeException("My Message");

}

Page 52: Sonarqube 20160509

HTTP referers should not be relied onhttp referers에의존해서는안된다.

Referers는 공격자에의해수정이 가능하기때문에 referers 값에 대해서신뢰하지말아라.public class MyServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {String referer = request.getHeader("referer"); // Noncompliantif(isTrustedReferer(referer)){//..

}//...

}}

Page 53: Sonarqube 20160509

IP addresses should not be hardcodedIP주소를 하드코딩하지말아라

소스코드에 IP주소를하드 코딩하는것에 대한나쁜 점• 주소가변경될 경우재컴파일해야 함• 모든 환경에서같은주소가 사용되지않는다.(개발, 검증, 운영)• 공격자가코드를디컴파일하여주소를알아낼수 있다.String ip = "127.0.0.1";Socket socket = new Socket(ip, 6667);String ip = System.getProperty("myapplication.ip");Socket socket = new Socket(ip, 6667);

Page 54: Sonarqube 20160509

Math operands should be cast before assignment수학 연산자는사용하기전에캐스팅 해야한다.

연산의경우 결과는항상 int일 것이다.float twoThirds = 2/3; // Noncompliant; int division. Yields 0.0long millisInYear = 1_000*3_600*24*365; // Noncompliant; int multiplication. Yields 1471228928long bigNum = Integer.MAX_VALUE + 2; // Noncompliant. Yields -2147483647long bigNegNum = Integer.MIN_VALUE-1; //Noncompliant, gives a positive result instead of a negative one. Date myDate = new Date(seconds * 1_000); //Noncompliant, won't produce the expected result if seconds > 2_147_483...public long compute(int factor){return factor * 10_000; //Noncompliant, won't produce the expected result if factor > 214_748

}float twoThirds = 2f/3; // 2 promoted to float. Yields 0.6666667long millisInYear = 1_000L*3_600*24*365; // 1000 promoted to long. Yields 31_536_000_000long bigNum = Integer.MAX_VALUE + 2L; // 2 promoted to long. Yields 2_147_483_649long bigNegNum = Integer.MIN_VALUE-1L; // Yields -2_147_483_649Date myDate = new Date(seconds * 1_000L);...public long compute(int factor){return factor * 10_000L;

}

Page 55: Sonarqube 20160509

Member variable visibility should be specified멤버변수의가시성을지정해야한다.

class Ball {String color="red"; // Noncompliant

}enum A {B;int a;

}class Ball {private String color="red"; // Compliant

}enum A {B;private int a;

}

Page 56: Sonarqube 20160509

Neither DES (Data Encryption Standard) nor DESede (3DES) should be usedDES(데이터암호화표준) 도 DESede(3DES) 도 사용하지않는다.

표준 및 미국국립 기술 연구소 (NIST)에 따르면, 데이터 암호화표준 (DES)는 더 이상안전한것으로 간주되지않습니다Cipher c = Cipher.getInstance("DESede/ECB/PKCS5Padding");

Cipher c = Cipher.getInstance("AES/GCM/NoPadding");

Page 57: Sonarqube 20160509

Null pointers should not be dereferenced널포인터는역참조해서는안된다.

일반적으로그 객체가 NULL이될 수 없다’라고하는 가정을위반했을때 발생한다.@CheckForNullString getName() {...}

public boolean isNameEmpty() {return getName().length() == 0; // Noncompliant; the result of getName() could be null, but isn't null-

checked}Connection conn = null;Statement stmt = null;try {conn = DriverManager.getConnection(DB_URL,USER,PASS);stmt = conn.createStatement();// ...

} catch(Exception e) {e.printStackTrace();

} finally {stmt.close(); // Noncompliant; stmt could be null if an exception was thrown in the try{} blockconn.close(); // Noncompliant; conn could be null if an exception was thrown

}

Page 58: Sonarqube 20160509

Only standard cryptographic algorithms should be used단지 표준알고리즘을사용해야한다.

중요한민감한 데이터를디스크에저장하거나외부 전송 시, SW가 해당 데이터를암호화하지않을 경우 민감한데이터가노출될수 있다.

표준알고리즘 : SHA-256, SHA-384, SHA-512MyCryptographicAlgorithm extends MessageDigest {...

}

Page 59: Sonarqube 20160509

Public methods should throw at most one checked exceptionPublic method 에서는 대부분하나의 exception을 체크하여 throw 한다.

public void delete() throws IOException, SQLException { // Noncompliant/* ... */

}public void delete() throws SomeApplicationLevelException {/* ... */

}

Page 60: Sonarqube 20160509

Resources should be closed자원은 닫아야 한다.OutputStream stream = null;try{for (String property : propertyList) {

stream = new FileOutputStream("myfile.txt"); // Noncompliant// ...

}}catch(Exception e){// ...

}finally{stream.close(); // Multiple streams were opened. Only the last is closed.

}OutputStream stream = null;try{stream = new FileOutputStream("myfile.txt");for (String property : propertyList) {

// ...}

}catch(Exception e){// ...

}finally{stream.close();

}

Page 61: Sonarqube 20160509

Throwable and Error should not be caughtThrow 가능 객체 와 Error는 catch에 사용할수 없다.

Throw 가능 객체는 자바의모든 에러와예외의슈퍼클래스입니다.Error는 응용 프로그램에 의해 발생되는 의미하지 않는 모든 에러의슈퍼클래스 입니다. try { /* ... */ } catch (Throwable t) { /* ... */ } try { /* ... */ } catch (Error e) { /* ... */ }try { /* ... */ } catch (RuntimeException e) { /* ... */ }try { /* ... */ } catch (MyException e) { /* ... */ }

Page 62: Sonarqube 20160509

Throwable.printStackTrace(...) should not be calledThrowable.printStackTrace을 호출할수 없습니다.

Throw 가능 객체를 사용하는대신에 Loggers를사용할수 있습니다.사용자는쉽게 logs를 찾을수 있습니다.try {/* ... */

} catch(Exception e) {e.printStackTrace(); // Noncompliant

}try {/* ... */

} catch(Exception e) {LOGGER.log("context", e); // Compliant

}

Page 63: Sonarqube 20160509

Untrusted data should not be stored in sessions신뢰할수 없는 데이터는세션에저장하지말아야 한다.

웹 세션에서데이터는 “신뢰 범위”에서내부로간주됩니다.즉, 신뢰할 수 있는것 입니다. 그러나인증되지않는 사용자로부터입력된 데이터를저장하는것은신뢰의 범위를벗어나는일입니다. 그 데이터를부적절하게사용될 수 있습니다.login = request.getParameter("login");session.setAttribute("login", login); // Noncompliant

Page 64: Sonarqube 20160509

Useless "if(true) {...}" and "if(false){...}" blocks should be removed쓸모없는 If(true)와 if(false)는제거 되야합니다.if (true) { doSomething();

}...if (false) { doSomethingElse();

}

if (2 < 3 ) { ... } // Noncompliant; always false

int i = 0;int j = 0;// ...j = foo();

if (j > 0 && i > 0) { ... } // Noncompliant; always false - i never set after initialization

boolean b = true;//...if (b || !b) { ... } // NoncompliantdoSomething(); ...

Page 65: Sonarqube 20160509

Values passed to OS commands should be sanitizedOS 명령어로전달된값은 제거 되어야한다.public void listContent(String input) {Runtime rt = Runtime.getRuntime();rt.exec("ls " + input); // Noncompliant; input could easily contain extra commands...

}

public void execute(String command, String argument) {ProcessBuilder pb = new ProcessBuilder(command, argument); // Noncompliant...

}

Page 66: Sonarqube 20160509

Web applications should not have a "main" method웹 응용프로그램은 “main” 메소드를사용하지말아야 한다.public class MyServlet extends HttpServlet {public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException

{if (userIsAuthorized(req)) {updatePrices(req);

}}

public static void main(String[] args) { // NoncompliantupdatePrices(req);

}}

Page 67: Sonarqube 20160509

Web applications should use validation filters웹 응용프로그램에서 검증 필터를 사용해야 한다.public class ValidatingHttpRequest extends HttpServletRequestWrapper {// ...

}

public class ValidationFilter implements javax.servlet.Filter {public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {

chain.doFilter(new ValidatingHttpRequest( (HttpServletRequest)request ), response);}

}<filter>

<filter-name>ValidationFilter</filter-name><filter-class>com.myco.servlet.ValidationFilter</filter-class>

</filter>

<filter-mapping><filter-name>ValidationFilter</filter-name><url-pattern>/*</url-pattern>

</filter-mapping>

Page 68: Sonarqube 20160509

"ConcurrentLinkedQueue.size()" should not be usedConcurrentLinkedQueue.size()는사용하지말아라.

큐의 크기를확인하는메소드는일정한시간이 필요로하는데, 큐의 크기가클수록시간이 오래걸릴 수 있다. 그리고큐가 실행 중 변경이되는 경우 결과가정확하지않을수 있다.

그런데, size()를 사용해야할 경우에는큐가비어 있는지확인 하기 위한 isEmpty()를함께 사용해야한다. ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue();//... log.info("Queue contains " + queue.size() + " elements");

Page 69: Sonarqube 20160509

"DateUtils.truncate" from Apache Commons Lang library should not be usedApache commons lang library 중에서 “DateUtils.truncate”는 사용할수 없습니다.

날짜를 truncate 하는 DateUtils.truncate 보다 Java 8에서 도입된 Instant 클래스가훨씬 빠를수 있습니다.public Date trunc(Date date) {return DateUtils.truncate(date, Calendar.SECOND); // Noncompliant

}public Date trunc(Date date) {Instant instant = date.toInstant();instant = instant.truncatedTo(ChronoUnit.SECONDS);return Date.from(instant);

}

Page 70: Sonarqube 20160509

"deleteOnExit" should not be used“deleteOnExit”는사용하지 말아라.

File.deleteOnExit()의 사용은다음과 같은이유로 권장하지않습니다.- 삭제는일반적으로 JVM 종료의 경우에발생하지만, JVM이충돌 또는죽었을 경우에

삭제되지않는다.- 파일 삭제가성공했음에도불구하고 JVM이종료 할 때까지파일정보를보관되면서

메모리가증가File file = new File("file.txt");file.deleteOnExit(); // Noncompliant

Page 71: Sonarqube 20160509

"entrySet()" should be iterated when both the key and value are neededkey와 value가모두필요할 때 entrySet() 을 반복해서사용해야한다.

HashMap에 entrySet 메소드를호출하면키가 들어있는 Set이넘어 옵니다.Set에서 iterator를 뽑아내면 while 문으로루프를돌려서 키를 하나씩가져올수 있습니다.public void doSomethingWithMap(Map<String,Object> map) {

for (String key : map.keySet()) { // Noncompliant; for each key the value is retrievedObject value = map.get(key);// ...

}}public void doSomethingWithMap(Map<String,Object> map) {for (Map.Entry<String,Object> entry : map.entrySet()) {

String key = entry.getKey();Object value = entry.getValue();// ...

}}

Page 72: Sonarqube 20160509

"ResultSet.isLast()" should not be usedResultSet.isLast()를사용하지말아라.

stmt.executeQuery("SELECT name, address FROM PERSON");ResultSet rs = stmt.getResultSet();while (! rs.isLast()) { // Noncompliant// process row}ResultSet rs = stmt.executeQuery("SELECT name, address FROM PERSON");while (! rs.next()) {// process row}

Page 73: Sonarqube 20160509

"URL.hashCode" and "URL.equals" should be avoided“URL.hashCode” 와 “URL.equals”는 피해야 한다.

Equals와 hashCode 메소드는 java.net.URL public void checkUrl(URL url) {Set<URL> sites = new HashSet<URL>(); // Noncompliant

URL homepage = new URL("http://sonarsource.com"); // Compliantif (homepage.equals(url)) { // Noncompliant

// ...}

}public void checkUrl(URL url) {Set<URI> sites = new HashSet<URI>(); // Compliant

URI homepage = new URI("http://sonarsource.com"); // CompliantURI uri = url.toURI();if (homepage.equals(uri)) { // Compliant

// ...}

}

Page 74: Sonarqube 20160509

"wait(...)" should be used instead of "Thread.sleep(...)" when a lock is held“Thread.sleep(…)” 대신에 “wait(…)”의 사용은잠금이유지 된다.

Wait() : 동기화된다중스레드가같은오브젝트에접근하고자할 때 중지시킨다.

Sleep() : 동기화된다중스레드를시간으로중지시킨다.public void doSomething(){synchronized(monitor) {

while(notReady()){Thread.sleep(200);

}process();

}...

}

public void doSomething(){synchronized(monitor) {

while(notReady()){monitor.wait(200);

}process();

}...

}

Page 75: Sonarqube 20160509

Multiple loops over the same set should be combined같은 설정의여러 루프는결합해서사용한다.

public void doSomethingToAList(List<String> strings) {for (String str : strings) {

doStep1(str);}for (String str : strings) { // Noncompliant

doStep2(str);}

}

public void doSomethingToAList(List<String> strings) {for (String str : strings) {

doStep1(str);doStep2(str);

}}

Page 76: Sonarqube 20160509

Objects should not be created only to "getClass"Object를 단지 getClass로 생성하지말아라

getClass의 호출의목적은 객체를생성하는것인데, 객체를생성하게되면 메모리낭비가 발생하므로단순히 class를 사용합니다.MyObject myOb = new MyObject(); // NoncompliantClass c = myOb.getClass();Class c = MyObject.class;

Page 77: Sonarqube 20160509

Sets with elements that are enum values should be replaced with EnumSet열거 값이 있는 elements set는 EnumSet 으로 대체해야 합니다.

public class MyClass {

public enum COLOR {RED, GREEN, BLUE, ORANGE;

}

public void doSomething() {Set<COLOR> warm = new HashSet<COLOR>();warm.add(COLORS.RED);warm.add(COLORS.ORANGE);

}}

public class MyClass {

public enum COLOR {RED, GREEN, BLUE, ORANGE;

}

public void doSomething() {EnumSet<COLOR> warm =

EnumSet.of(COLOR.RED, COLOR.ORANGE);}

}

Page 78: Sonarqube 20160509

String function use should be optimized for single charactersString function은하나의 기호에 적합하다.

String myStr = "Hello World";// ...int pos = myStr.indexOf("W"); // Noncompliant// ...int otherPos = myStr.lastIndexOf("r"); // Noncompliant// ...String myStr = "Hello World";// ...int pos = myStr.indexOf('W'); // ...int otherPos = myStr.lastIndexOf('r');// ...

Page 79: Sonarqube 20160509

Strings should not be concatenated using '+' in a loop문자열은루프에서 ‘+’을 사용하여연결되어서는안된다.

문자열은불변객체입니다. 그래서연결은단순히 기존의문자열 끝에새로운 문자열을추가 하지않습니다. 대신각 루프가 반복되면서첫번째문자열이연결되는문자열형식으로변환됩니다. 이런식으로문자열이길어지면작업의성능의 저하가발생하게됩니다. 따라서 StringBuilder의사용이바람직합니다.String str = "";for (int i = 0; i < arrayOfStrings.length ; ++i) {str = str + arrayOfStrings[i];

}StringBuilder bld = new StringBuilder();for (int i = 0; i < arrayOfStrings.length; ++i) {

bld.append(arrayOfStrings[i]);}String str = bld.toString();

Page 80: Sonarqube 20160509

Synchronized classes Vector, Hashtable, Stack and StringBuffer should not be used동기화(Synchronized) classes는 Vector, Hashtable, Stack and StringBuffer를사용하면 안된다.

Vertor의 경우 무조건동기화이기때문에단일 스레드를사용할경우에는성능저하를가져오게됩니다.

- Vector 대신에 ArrayList 또는 LinkedList를사용- Stack 대신에 Deque를사용- Hashtable 대신에 HashMap 사용- StringBuffer 대신에 StringBuilder 사용Vector cats = new Vector();

ArrayList cats = new ArrayList();

Page 81: Sonarqube 20160509