SlideShare uma empresa Scribd logo
1 de 81
Baixar para ler offline
์˜คํ”ˆ์—์Šค์—”์—์Šค
AAํŒ€
์กฐ์˜์„
๏ฝ ์†Œํ”„ํŠธ์›จ์–ด ํ’ˆ์งˆ
๏ฝ ์†Œํ”„ํŠธ์›จ์–ด ๊ตฌํ˜„
๏ฝ SonarQube ๊ธฐ๋Šฅ ๋ฐ ํŠน์ง•
๏ฝ SonarQube ์‚ฌ์šฉ๋ฐฉ๋ฒ•
๏ฝ ์†Œ์Šค ํ’ˆ์งˆ์„ ์œ„ํ•œ ์ฝ”๋”ฉ
๏ฝ Q&A
๏ฝ ๊ธฐ๋Šฅ์  ์š”๊ตฌ์‚ฌํ•ญ(Functional Requirements)
- ์ˆ˜ํ–‰๋  ๊ธฐ๋Šฅ๊ณผ ๊ด€๋ จ๋˜์–ด ์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ ๋ฐ ๊ทธ๋“ค ์‚ฌ์ด์˜ ์ฒ˜๋ฆฌ๊ณผ์ •
- ๋ชฉํ‘œ๋กœ ํ•˜๋Š” ์ œํ’ˆ์˜ ๊ตฌํ˜„์„ ์œ„ํ•ด ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ๊ฐ€์ ธ์•ผ ํ•˜๋Š” ๊ธฐ๋Šฅ
์  ์†์„ฑ
๏ฝ ๋น„๊ธฐ๋Šฅ์  ์š”๊ตฌ์‚ฌํ•ญ(Non-Functional Requirements)
โ—ฆ ์ œํ’ˆ์˜ ํ’ˆ์งˆ ๊ธฐ์ค€ ๋“ฑ์„ ๋งŒ์กฑ์‹œํ‚ค๊ธฐ ์œ„ํ•ด ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ๊ฐ€์ ธ์•ผ ํ•˜
๋Š” ์„ฑ๋Šฅ, ์‚ฌ์šฉ์˜ ์šฉ์˜์„ฑ, ์•ˆ์ „์„ฑ๊ณผ ๊ฐ™์€ ํ–‰์œ„์  ํŠน์„ฑ
โ—ฆ ์‹œ์Šคํ…œ์˜ ๊ธฐ๋Šฅ์— ๊ด€๋ จ๋˜์ง€ ์•Š๋Š” ์‚ฌํ•ญ์„ ๋‚˜ํƒ€๋ƒ„
๊ธฐ๋Šฅ ๋น„๊ธฐ๋Šฅ
ํšจ์œจ์ ์ธ SW ๊ฐœ๋ฐœ ๊ด€๋ฆฌ
๊ฐ€์น˜์žˆ๋Š” SW
๊ณ„ ํš
๋ช…ํ™•ํ•œ ๋ชฉํ‘œ์ˆ˜๋ฆฝ
์ˆ˜ ํ–‰
ํšจ์œจ์ ์ธ ๊ฐœ๋ฐœํ™œ๋™
๊ฒ€ ์ฆ
์ง€์†์ ์ธ ๋ชจ๋‹ˆํ„ฐ๋ง ๋ฐ ํ†ต์žฌ
โ€œ๊ณ„ํš ๊ธฐ๋ฐ˜์˜
์ง€์†์  ๊ฒ€์ฆโ€
โ€œ์‹œ๊ฐ์  ๊ฒ€์ฆ์„
์œ„ํ•œ ์‹œ์Šคํ…œ ํ™œ์šฉโ€
Subversion
Eclipse
Jenkins
Ant,Script
NSIQConllector
PMD,CPPCheck
Emma,gcov
Junit,CPPUnit
Impasse
Redmine
SonarQube
์š”๊ตฌ์‚ฌํ•ญ ํ…Œ์ŠคํŠธ ๊ตฌํ˜„ ํ˜•์ƒ๊ด€๋ฆฌ
1. ์†Œ์Šค์ฝ”๋“œ๋ฅผ ๋ฐ”์ด๋„ˆ๋ฆฌ ํŒŒ์ผ๋กœ ์ปดํŒŒ์ผ ํ•œ๋‹ค.
2. ๋ฐ”์ด๋„ˆ๋ฆฌ ํŒŒ์ผ์„ ๋ฐฐํฌ ํ˜•ํƒœ๋กœ ํŒจํ‚ค์ง• ํ•œ๋‹ค.
3. ๋‹จ์œ„ํ…Œ์ŠคํŠธ(์ปค๋ฒ„๋ฆฌ์ง€ ํฌํ•จ) ์ˆ˜ํ–‰ํ•œ๋‹ค.
4. ์ •์ ๋ถ„์„์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
5. ๋ถ„์„ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํฌํŒ…ํ•œ๋‹ค.
6. ํŒจํ‚ค์ง•ํ•œ ํŒŒ์ผ์„ ํ…Œ์ŠคํŠธ ์„œ๋ฒ„์— ๋ฐฐํฌํ•œ๋‹ค.
๏ฝ SW ๊ตฌํ˜„์€ SW ๊ณตํ•™์˜ ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ํ™œ๋™์œผ๋กœ ์ฝ”๋“œ์ž‘์„ฑ, ๋””๋ฒ„๊น…, SWํ†ตํ•ฉ, ๊ฐœ๋ฐœ
์ž ํ…Œ์ŠคํŒ… ํ™œ๋™๋“ค๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค.
๏ฝ SW ๊ตฌํ˜„ํ•  ๋•Œ ๊ณ ๋ คํ•ด์•ผ ํ•  4๊ฐ€์ง€ ์ฃผ์š”์›์น™
- ์ฝ”๋”ฉ์˜ ๋ณต์žก์„ฑ์„ ์ตœ์†Œํ™”
- ํ–ฅํ›„์— ์ผ์–ด๋‚  ๋ณ€ํ™”๋ฅผ ๊ณ ๋ ค
- ์†Œํ”„ํŠธ์›จ์–ด ๊ตฌํ˜„์€ ๊ฒ€์ฆ์ด ๊ฐ€๋Šฅํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ
- ํ‘œ์ค€์„ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ
๏ฝ ์ฝ”๋”ฉ ๊ทœ์น™์ด๋‚˜ ํ‘œ์ค€์„ ์ˆ˜๋ฆฝํ•˜์—ฌ ๋ชจ๋“  ๊ฐœ๋ฐœ์ž๊ฐ€ ํ”„๋กœ์ ํŠธ์—์„œ ์กฐํ™”๋กญ๊ฒŒ ์ž‘์—…ํ• 
์ˆ˜ ์žˆ๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•ด์„œ ์ข‹์•„์ง„ ์†Œ์Šค ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์€ ๊ฐœ๋ฐœ์ž๊ฐ€ SW ์‹œ
์Šคํ…œ์„ ์ดํ•ดํ•˜๋Š”๋ฐ ์˜ํ–ฅ์„ ๋ฏธ์น˜๊ฒŒ ๋˜๊ณ , ๊ฐ€๋…์„ฑ์ด ํ–ฅ์ƒ๋˜๋ฉด ์ดํ•ด๊ฐ€ ์šฉ์ดํ•ด์ง€๊ณ 
์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์ˆ˜์›”ํ•ด์ง€๋ฉฐ ์ผ๋ฐ˜์ ์œผ๋กœ ์ฝ”๋“œ์˜ ํ’ˆ์งˆ๋„ ์ข‹์•„์ง„๋‹ค.
๏ฝ ํ’ˆ์งˆ ๊ด€๋ฆฌ ๋„๊ตฌ์˜ ์ฃผ์š”๊ธฐ๋Šฅ
๏ƒ˜ ์ž ์žฌ์  ์˜ค๋ฅ˜ ์†Œ์Šค ์ฝ”๋“œ ๊ฒ€์ถœ
๏ƒ˜ ๊ฐœ๋ฐœ ํ‘œ์ค€ ์ค€์ˆ˜
๏ƒ˜ ์‰ฌ์šด ๋ฃฐ ์ƒ์„ฑ ๋ฐ ํŽธ์ง‘
๏ƒ˜ ์ž๋™ ๋ฃฐ ์—…๋ฐ์ดํŠธ
๏ฝ ์ •์  ๋ถ„์„ ๋„๊ตฌ๋ฅผ ํ†ตํ•ด ๊ฒ€์ƒ‰ ๋˜๋Š” ๋‚ด์šฉ
๏ƒ˜ ๊ณต์œ ๋œ ์ฝ”๋”ฉ ์Šคํƒ€์ผ ์œ„๋ฐ˜
๏ƒ˜ ์ž ์žฌ์  ๋ฒ„๊ทธ์˜ ์ฝ”๋”ฉ
๏ƒ˜ ์„ค๊ณ„์ƒ์˜ ๋ฌธ์ œ๊ฐ€ ๋˜๋Š” ์ฝ”๋“œ
๏ƒ˜ ์ค‘๋ณต๋˜๊ณ  ๋ณด์•ˆ์— ์œ„๋ฐ˜๋˜๋Š” ์ฝ”๋“œ
๏ƒ˜ ๋“ฑ๋“ฑโ€ฆโ€ฆ
๏ฝ ์ •์  ๋ถ„์„ ๋„๊ตฌ๋กœ ์†Œ์Šค์ฝ”๋“œ์— ๋Œ€ํ•œ ์ „๋ฐ˜์ ์ธ ํ’ˆ์งˆ
์„ ํ™•๋ณดํ•  ์ˆ˜ ์žˆ๋„๋ก ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ํ†ตํ•ฉ ํ”Œ๋žซํผ
๏ฝ Server / Client ๊ตฌ์กฐ
๏ฝ C/C++/Java ๋“ฑ 15๊ฐœ ์ด์ƒ์˜ ๋‹ค์–‘ํ•œ ํ”„๋กœ๊ทธ๋žจ ์–ธ
์–ด ์ง€์›
๏ฝ ํ”Œ๋Ÿฌ๊ทธ์ธ ์„ค์น˜๋กœ ๋‹ค์–‘ํ•œ ๋„๊ตฌ์™€ ์œ ์—ฐํ•œ ํ†ตํ•ฉ
๏ฝ ์›น ๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ๋‹ค์–‘ํ•œ ๊ฒฐ๊ณผ๋ฅผ ์„œ๋ฒ„์—
์„œ ํ†ตํ•ฉ ๊ด€๋ฆฌ ์šฉ์ด
๏ฝ ํ”„๋กœ์ ํŠธ ์†Œ์Šค ํ’ˆ์งˆ์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ชจ๋‹ˆ
ํ„ฐ๋ง ํˆด์„ ์ œ๊ณตํ•˜๋Š” ์˜คํ”ˆ์†Œ์Šค ํ”Œ๋žซํผ
๏ฝ ๋ณดํ†ต SonarQube๋Š” ๋‹จ๋…์œผ๋กœ ์‚ฌ์šฉ๋˜๊ธฐ ๋ณด๋‹ค๋Š” Jenkins
๊ฐ™์€ CI ์„œ๋ฒ„์™€ ์—ฐ๋™์ด ๋˜์–ด์„œ ์‚ฌ์šฉ์ด ๋˜์–ด์ง€๊ณ  ์žˆ์œผ๋ฉฐ
Java๋ฅผ ํฌํ•จํ•œ 20๊ฐ€์ง€๊ฐ€ ๋„˜๋Š” ํ”„๋กœ๊ทธ๋žจ๋ฐ ์–ธ์–ด๋กœ ์ œ์ž‘๋œ
ํ”„๋กœ์ ํŠธ์˜ ๋ชจ๋‹ˆํ„ฐ๋ง์„ ์ œ๊ณต
๏ฝ Java ๊ธฐ๋ฐ˜์˜ ์ •์ ๋ถ„์„ ํˆด๋กœ์จ, ๋‹ค์–‘ํ•œ ํ•ญ๋ชฉ์— ๋Œ€ํ•ด ๋ถ„์„
๋ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋Š” ํ’ˆ์งˆ๊ด€๋ฆฌ ๋Œ€์‹œ๋ณด๋“œ ํˆด
- ์†Œ์Šค์ฝ”๋“œ๊ด€๋ฆฌ ํ•˜๋Š” ์˜คํ”ˆ์†Œ์Šค๊ธฐ๋ฐ˜์˜ ๋ฌด๋ฃŒํˆด
- ์ž๋ฐ”๊ฒ€์ฆ๋„๊ตฌ(PMD, findbugs, Checkstyle)๊ฐ€ PlugIn
ํ˜•ํƒœ๋กœ ๋“ค์–ด๊ฐ€ ์žˆ์Œ
- ์ค‘๋ณต์ฝ”๋“œ(Squid, CPD) ์ฒดํฌ
- ์ฝ”๋“œ ์ปค๋ฒ„๋ฆฌ์ง€(Cobertura, jaCoCo)
๏ฝ JDK ํ™˜๊ฒฝ์—์„œ ๋™์ž‘, ์›น์„œ๋ฒ„ ๋ฐ DBMS ํ•„์š”
๏ฝ ๋‹ค์–‘ํ•œ OS๋ฅผ ์ง€์› : Windows, Linux, Mac OS X, Unix
๏ฝ DBMS ํ•„์š”
=> Derby(๊ธฐ๋ณธ ์ œ๊ณต), MSSQL, MySQL, Oracle
๏ฝ ์›น์„œ๋ฒ„(WAS : Web Application Server) ํ•„์š”
=> Jetty6, Apache Tomcat
๏ฝ ์ž๋ฐ” ๊ธฐ๋ฐ˜ ํ”„๋กœ๊ทธ๋žจ : JDK 1.5 ์ด์ƒ ํ•„์š”
- 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 ์ž‘์„ฑ๋œ ํ”„๋กœ์ ํŠธ์— ์ ํ•ฉ
- Sonar๋Š” Checkstyle, PMD, FindBugs, Coberbura ๋“ฑ์˜
๋ถ„์„ํˆด ๋“ค์„ ์ด์šฉํ•˜์—ฌ ์†Œ์Šค์˜ ์ •์ ๋ถ„์„์„ ์‹ค์‹œํ•˜๊ณ , ์ด
๋ฅผ ์›น๋ธŒ๋ผ์šฐ์ €๋ฅผ ํ†ตํ•˜์—ฌ ์ „์ฒด์ ์ธ ๋ถ„์„๊ฒฐ๊ณผ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š”
ํˆด
SonarQube
Analysers Eclipse
Database
Server
- Sonar๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋ถ„์„๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Œ
- ์ฝ”๋“œ ์ค‘๋ณต ์ฒดํฌ
- ์ฝ”๋“œ์˜ ํ‘œ์ค€
- ์ฝ”๋“œ coverage
- ์ฝ”๋“œ ๋ณต์žก๋„
- ์ฃผ์„
- ๋””์ž์ธ ๊ณผ ์•„ํ‚คํ…์ณ
- ๊ธฐ๋ณธ์ ์œผ๋กœ๋Š” Java ์–ธ์–ด๋ฅผ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ถ”๊ฐ€ ํ”Œ๋Ÿฌ
๊ทธ์ธ์„ ํ†ตํ•˜์—ฌ ๋‹ค๋ฅธ ๋Œ€๋ถ€๋ถ„์˜ ์–ธ์–ด์— ๋Œ€ํ•ด์„œ๋„ ๊ฒ€์‚ฌ ๊ฐ€
๋Šฅ
๏ฝ JAVA, C/C++๋“ฑ์˜ ๋‹ค์ˆ˜ ํ”„๋กœ๊ทธ๋žจ ์–ธ์–ด ์ง€์›
๏ฝ ํ”Œ๋Ÿฌ๊ทธ์ธ ์„ค์น˜๋กœ ๋‹ค์–‘ํ•œ ๋„๊ตฌ์™€ ์œ ์—ฐํ•œ ํ†ตํ•ฉ
๏ฝ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ถ„์„ ํˆด์„ ํ†ตํ•ฉํ•˜์—ฌ ์—ฌ๋Ÿฌ ํ•ญ๋ชฉ๋“ค์„ ํ•œ๋ฒˆ์— ๊ฒ€
์‚ฌ ๊ฐ€๋Šฅ(Checkstyle, PMD, FindBugs, CPPCheck,
Cobertura ๋“ฑ)
๏ฝ ์›น๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ๋‹ค์–‘ํ•œ ๋ถ„์„ ๊ฒฐ๊ณผ๋“ค์„ ํ™•์ธ ๊ฐ€
๋Šฅ
(๋ฒ„๊ทธ&์ž ์žฌ๋ฒ„๊ทธ์ฒดํฌ, ์ฝ”๋”ฉ ํ‘œ์ค€ ์œ„๋ฐ˜ ์ฒดํฌ,
์ค‘๋ณต ์ฝ”๋“œ ์ฒดํฌ, ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€ ์ฒดํฌ,
์†Œ์Šค ๋ณต์žก๋„ ์ฒดํฌ, ์ฃผ์„ ์ฒ˜๋ฆฌ๋Ÿ‰ ์ฒดํฌ)
๏ฝ ๋ถ„์„์„ ์œ„ํ•œ ์—ฌ๋Ÿฌ ํด๋ผ์ด์–ธํŠธ๋ฅผ ์ œ๊ณต
(Sonar runner, Maven, Ant T ask)
๏ฝ ์ •์  ์ฝ”๋“œ ๋ถ„์„ ๋„๊ตฌ ์„ ์ •๋ถ€ํ„ฐ ์ ์šฉ๊นŒ์ง€ ๋ชจ๋“  ํ”„๋กœ
์„ธ์Šค์— ๊ฐœ๋ฐœ์ž ์ฐธ์—ฌ
๏ฝ ์ฝ”๋“œ์— ์•Œ๋งž์€ ๋„๊ตฌ ์„ ํƒ
๏ฝ ์ƒˆ๋กญ๊ฒŒ ์ž‘์„ฑํ•˜๋Š” ์ฝ”๋“œ์— ์ง‘์ค‘ํ•˜๊ธฐ. ์ด๋ฏธ ์ž‘์„ฑ๋œ ์ฝ”
๋“œ์— ๋„ˆ๋ฌด ์‹ ๊ฒฝ์“ฐ์ง€ ๋ง ๊ฒƒ
๏ฝ ๊ฒฐํ•จ ์ฐพ๋Š”๋ฐ ํ˜ˆ์•ˆ ๋˜์ง€ ๋ง๊ณ  ๊ฐœ๋ฐœ ์ƒ์‚ฐ์„ฑ์— ์ง‘์ค‘
๏ฝ ์ •์ ์ฝ”๋“œ ๋ถ„์„ ๋ฐ ๊ฒฐ๊ณผ์— ๋Œ€ํ•œ ์ด์Šˆ ๊ด€๋ฆฌ๋ฅผ ์ž๋™ํ™”
๏ฝ https://nemo.sonarqube.org/
๏ฝ ์ฝ”๋”ฉ ๊ทœ์น™(Rules)
โ—ฆ Lanauage : Java
โ—ฆ Tag : Security, performance
"@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 deprecated
foo.doTheThing(); // Noncompliant
}
}
"ConcurrentLinkedQueue.size()" should not be used
ConcurrentLinkedQueue.size() ๋ฅผ ์‚ฌ์šฉ์„ ์ž์ œ ํ•ด๋ผ.
ํ•ด๋‹น ๋ช…๋ น๋ฌธ์€ Queue์˜ ํฌ๊ธฐ๊ฐ€ ํด ๊ฒฝ์šฐ ์ž‘์—…์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆด ์ˆ˜๊ฐ€ ์žˆ๋‹ค.
๋˜๋Š” Queue๊ฐ€ ์‹คํ–‰ ์ค‘์— ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒฝ์šฐ ๋˜ํ•œ ๊ฒฐ๊ณผ๊ฐ€ ์ •ํ™•ํ•˜์ง€ ์•Š์„ ์ˆ˜๊ฐ€ ์žˆ๋‹ค.
๋‹จ์ง€, ํฌ๊ธฐ๋งŒ์„ ์œ„ํ•ด์„œ ์ฒดํฌํ•ด์•ผ ํ•  ๊ฒฝ์šฐ isEmpty() ๋ฉ”์†Œ๋“œ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue();
//...
log.info("Queue contains " + queue.size() + " elements");
"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 ...
}
"HttpServletRequest.getRequestedSessionId()" should not be used
- getRequestedSessionId ๋ฉ”์†Œ๋“œ ๋Š”?
: ํด๋ผ์ด์–ธํŠธ๋กœ ๋ถ€ํ„ฐ ์ง€์ •๋œ ์„ธ์…˜ID๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ด๋Š” ์š”์ฒญ์— ๋Œ€ํ•œ ํ˜„์žฌ ์œ ํšจํ•œ ์„ธ์…˜ ID
์™€ ๋™์ผํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„ธ์…˜ ID๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ,์ด ๋ฉ”์†Œ๋“œ๋Š”
null๋ฅผ ๋Œ๋ ค์ฃผ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
์„ธ์…˜ID๊ฐ€ ์–ด๋– ํ•œ HTTP์˜ ์š”์ฒญ์— ์˜ํ•ด ๋ณ€๊ฒฝ์ด ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.
if(isActiveSession(request.getRequestedSessionId()) ){
...
}
"java.lang.Error" should not be extended
Java.lang.Error ํด๋ž˜์Šค์™€ ๊ทธ ์„œ๋ธŒ ํด๋ž˜์Šค ๋“ค์€ ์‹œ์Šคํ…œ์˜ ๋ญ”๊ฐ€ ๋น„์ •์ƒ์ ์ธ ์ƒํ™ฉ์ด ๋ฐœ์ƒ
ํ–ˆ์„ ๊ฒฝ์šฐ ์‚ฌ์šฉ๋œ๋‹ค.
๊ทธ๋ž˜์„œ ์ฃผ๋กœ ์ž๋ฐ” VM์—์„œ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๊ฒƒ์ด๊ณ  ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ์—์„œ ์žก์œผ๋ ค๊ณ  ํ•˜๋ฉด ์•ˆ
๋œ๋‹ค.
OutofMemoryError๋‚˜ ThreadDeath ๊ฐ™์€ ์—๋Ÿฌ๋Š” catch ๋ธ”๋Ÿญ์œผ๋กœ ์žก์•„๋„ ๋Œ€์‘ ๋ฐฉ๋ฒ•์ด
์—†๋‹ค.
๋”ฐ๋ผ์„œ ์‹œ์Šคํ…œ ๋ ˆ๋ฒจ์—์„œ ํŠน๋ณ„ํ•œ ์ž‘์—…์„ ํ•˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ๋ฉด ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ์ด๋Ÿฐ ์—
๋Ÿฌ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋Š” ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š์•„๋„ ๋œ๋‹ค.
public class MyException extends Error { /* ... */ } // Noncompliant
public class MyException extends Exception { /* ... */ } // Compliant
"main" should not "throw" anything
main ๋ฉ”์†Œ๋“œ์—์„œ๋Š” throw ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.
Exception์ด ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ ๋˜์งˆ ๊ณณ์ด ์—†๋‹ค.
public static void main(String args[]) throws Exception { // Noncompliant
public static void main(String args[]) {
"NullPointerException" should not be caught
NullPointerException ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์„ 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;
}
"Object.finalize()" should remain protected (versus public) when
overriding
Object.finalize()๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•  ๋•Œ protected ์ƒํƒœ๋ฅผ ์œ ์ง€ ํ•ด์•ผ ํ•œ๋‹ค.
finalize๋Š” Garbage Collector์— ์˜ํ•ด ํ˜ธ์ถœ ๋ฉ๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ ์–ด๋””์—์„œ๋‚˜ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” public์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์ž˜๋ชป๋œ ๋ฐฉ๋ฒ• ์ž…๋‹ˆ๋‹ค.
๋ณดํ†ต finalize() ๋ฉ”์†Œ๋“œ๋ฅผ override ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ณ , System.gc() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ๊ฐ€๋น„์ง€
์ปฌ๋ ‰์…˜์ด ๋ฐœ์ƒ๋˜๋„๋ก ํ•˜์—ฌ ์ •์˜๋œ finalize() ๋ฉ”์†Œ๋“œ๋ฅผ ์ˆ˜ํ–‰์‹œํ‚จ๋‹ค.
public class MyClass {
@Override
public void finalize() { // Noncompliant
/* ... */
}
}
"public static" fields should be constant
public 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();
...
}
"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();
}
});
//...
"static final" arrays should be "private"
static final ๋ฐฐ์—ด์—” private๋ฅผ ์‚ฌ์šฉํ•ด๋ผ
public static final ๋ฐฐ์—ด ํ•„๋“œ๋ฅผ ๋‘๊ฑฐ๋‚˜, ๋ฐฐ์—ด ํ•„๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ ‘๊ทผ์ž๋ฅผ ์ •์˜ ํ•˜๋ฉด ์•ˆ
๋œ๋‹ค. ๊ทธ๋Ÿฐ ๋ฉค๋ฒ„๋ฅผ ๋‘๋ฉด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฐฐ์—ด ๋‚ด์šฉ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋ฏ€๋กœ, ๋ณด์•ˆ์— ๋ฌธ์ œ
๊ฐ€ ์ƒ๊ธด๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ๊ณ ์น˜๋Š” ์ฒซ๋ฒˆ์งธ๋Š” public์œผ๋กœ ์„ ์–ธ๋˜์—ˆ๋˜ ๋ฐฐ์—ด์€ private์œผ๋กœ ๋ฐ”
๊พธ๊ณ  ๋ณ€๊ฒฝ์ด ๋ถˆ๊ฐ€๋Šฅํ•œ public ๋ฆฌ์ŠคํŠธ๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด๋‹ค.
public class Estate {
// Noncompliant; array contents can be modified
public 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
}
}
๏ฝ ํด๋ž˜์Šค์™€ ๋ฉค๋ฒ„์˜ ์ ‘๊ทผ ๊ถŒํ•œ์€ ์ตœ์†Œํ™” ํ•˜๋ผ
- ๊ฐ ํด๋ž˜์Šค์™€ ๋ฉค๋ฒ„๋Š” ๊ฐ€๋Šฅํ•œ ์ ‘๊ทผ ๋ถˆ๊ฐ€๋Šฅํ•˜๋„๋ก ๋งŒ๋“ค์–ด๋ผ
: ์ •๋ณด์€๋‹‰ ๋˜๋Š” ์บก์Šํ™”๋Š” ์‹œ์Šคํ…œ์„ ๊ตฌ์„ฑํ•˜๋Š” ๋ชจ๋“ˆ ์‚ฌ์ด์˜ ์˜์กด์„ฑ์„ ๋‚ฎ์ถฐ์„œ ๊ฐœ๋ฐœ ์†๋„ ๋ฐ ์œ ์ง€๋ณด
์ˆ˜์— ํšจ์œจ์ ์ด๋‹ค.
- ๊ฐ์ฒดํ•„๋“œ(instance field)๋Š” ์ ˆ๋Œ€๋กœ public์œผ๋กœ ์„ ์–ธํ•˜๋ฉด ์•ˆ๋œ๋‹ค.
: ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ public ํ•„๋“œ๋ฅผ ๊ฐ€์ง„ ํด๋ ˆ์Šค๋Š” ๋‹ค์ค‘ ์Šค๋ ˆ๋“œ์— ์•ˆ์ „ํ•˜์ง€ ์•Š๋‹ค. ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐ
ํ•˜๋Š” final ํ•„๋“œ๋ผ ํ•ด๋„ public์œผ๋กœ ์„ ์–ธํ•˜๋ฉด ํด๋ž˜์Šค ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ ํ‘œํ˜„ ํ˜•ํƒœ๋ฅผ ์œ ์—ฐํ•˜๊ฒŒ ๋ฐ”๊ฟ€ ์ˆ˜
์—†๊ฒŒ ๋œ๋‹ค
- static์œผ๋กœ ์„ ์–ธ๋œ ํ•„๋“œ์—๋„ ๋˜‘๊ฐ™์ด ์ ์šฉ๋˜์ง€๋งŒ ํ•œ๊ฐ€์ง€ ์˜ˆ์™ธ๊ฐ€ ์žˆ๋‹ค. ์–ด๋–ค
์ƒ์ˆ˜๋“ค์ด ํด๋ž˜์Šค๋กœ ์ถ”์ƒํ™”๋œ ๊ฒฐ๊ณผ๋ฌผ์˜ ํ•ต์‹ฌ์  ๋ถ€๋ถ„์„ ๊ตฌ์„ฑํ•œ๋‹ค๊ณ  ํŒ๋‹จ๋˜๋Š”
๊ฒฝ์šฐ, ํ•ด๋‹น ์ƒ์ˆ˜๋“ค์„ public static final ํ•„๋“œ๋“ค๋กœ ์„ ์–ธํ•˜์—ฌ ๊ณต๊ฐœํ•  ์ˆ˜ ์žˆ๋‹ค.
(public static final ํ•„๋“œ๊ฐ€ ์ฐธ์กฐํ•˜๋Š” ๊ฐ์ฒด๋Š” ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅ ๊ฐ์ฒด๋กœ ๋งŒ๋“ค์–ด๋ผ.)
- ๊ธธ์ด๊ฐ€ 0 ์•„๋‹Œ ๋ฐฐ์—ด์€ ์–ธ์ œ๋‚˜ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ, public static final ๋ฐฐ์—ด ํ•„
๋“œ๋ฅผ ๋‘๊ฑฐ๋‚˜, ๋ฐฐ์—ด ํ•„๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ ‘๊ทผ์ž๋ฅผ ์ •์˜ํ•˜๋ฉด ์•ˆ ๋œ๋‹ค. ๊ทธ๋Ÿฐ ๋ฉค๋ฒ„
๋ฅผ ๋‘๋ฉด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฐฐ์—ด ๋‚ด์šฉ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋ฏ€๋กœ, ๋ณด์•ˆ์— ๋ฌธ์ œ๊ฐ€
์ƒ๊ธด๋‹ค.
//๋ณด์•ˆ ๋ฌธ์ œ๋ฅผ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ
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(); }
"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();
}
...
}
Checked Exception should not be thrown
Checked 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 allowed
myMethod1();
}
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;
}
}
}
Cookies should be "secure"
์ฟ ํ‚ค๋Š” secure๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.
setSecure๋Š” ์ฟ ํ‚ค์˜ ๋ณด์•ˆ ์„ค์ •์œผ๋กœ true๋กœ ์„ค์ •ํ•  ๊ฒฝ์šฐ HTTPS๋‚˜ SSL๊ณผ ๊ฐ™์€ secure
protocol ์—์„œ๋งŒ ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๋‹ค.
Cookie c = new Cookie(SECRET, secret); // Noncompliant; cookie is not secure
response.addCookie(c);
Cookie c = new Cookie(SECRET, secret);
c.setSecure(true);
response.addCookie(c);
Credentials should not be hard-coded
์ž๊ฒฉ์ฆ๋ช…์€ ํ•˜๋“œ์ฝ”๋”ฉํ•˜์ง€ ๋ง์•„๋ผ
ํ•˜๋“œ์ฝ”๋”ฉ ํ•  ๊ฒฝ์šฐ ์ปดํŒŒ์ผ๋œ ์‘์šฉํ”„๋กœ๊ทธ๋žจ์—์„œ ๋ฌธ์ž์—ด์„ ์ถ”์ถœํ•˜๊ธฐ ์‰ฝ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
์ž๊ฒฉ์ฆ๋ช…์€ ์•”ํ˜ธํ™”๋œ ์™ธ๋ถ€ ๊ตฌ์„ฑ ํŒŒ์ผ์ด๋‚˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
Connection conn = null;
try {
conn =
DriverManager.getConnection("jdbc:mysql://localh
ost/test?" +"user=steve&password=blue"); //
Noncompliant
String uname = "steve";
String password = "blue";
conn =
DriverManager.getConnection("jdbc:mysql://localh
ost/test?" +
"user=" + uname + "&password=" +
password); // Noncompliant
Connection conn = null;
try {
String uname = getEncryptedUser();
String password = getEncryptedPass();
conn =
DriverManager.getConnection("jdbc:mysql://localh
ost/test?" + "user=" + uname + "&password=" +
password);
Exception classes should be immutable
Exception classes๋Š” ๋ถˆ๋ณ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
Exception์€ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ƒํƒœ๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.
public class MyException extends Exception {
private int status; // Noncompliant
public 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; // Compliant
public MyException(String message, int status) {
super(message);
this.status = status;
}
public int getStatus() {
return status;
}
}
Exception handlers should preserve the original exception
Exception handlers ๋Š” ์›๋ž˜ Excepion์„ ๋ณด์กดํ•œ๋‹ค.
๋ฐœ์ƒ๋œ ์—๋Ÿฌ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ, ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ๋ฅผ ๊ทธ๋Œ€๋กœ ํ˜ธ์ถœํ•œ ์ชฝ์œผ๋กœ ์ „๋‹ฌ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
// Noncompliant - exception is lost
try { /* ... */ }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
allowed
throw new RuntimeException(e);
}
Exception types should not be tested using "instanceof" in catch
blocks
์˜ˆ์™ธ ์œ ํ˜•์€ catch ๋ธ”๋ก ์•ˆ์—์„œ โ€œinstanceofโ€ ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ…Œ์ŠคํŠธ ํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค.
์ผ๋ฐ˜์˜ˆ์™ธ๋กœ ์บ์น˜ํ•œ ๋‹ค์Œ์— ์œ ํ˜•์— ๋”ฐ๋ผ์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๋Œ€์‹ ์— ์—ฌ๋Ÿฌ ์œ ํ˜•์— ๋งž๋Š” catch ๋ธ”
๋ก์— ์ฒ˜๋ฆฌ ํ•ด์•ผ ํ•œ๋‹ค.
try {
/* ... */
} catch (Exception e) {
if(e instanceof IOException) { /* ... */ } // Noncompliant
if(e instanceof NullPointerException{ /* ... */ } // Noncompliant
}
try {
/* ... */
} catch (IOException e) { /* ... */ } // Compliant
} catch (NullPointerException e) { /* ... */ } // Compliant
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) {
//...
}
}
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
}
Generic exceptions should never be thrown
์ผ๋ฐ˜์ ์ธ ์˜ˆ์™ธ๋Š” ๊ฒฐ์ฝ” thrown ํ•˜๋ฉด ์•ˆ๋œ๋‹ค.
public void foo(String bar) throws Throwable { // Noncompliant
throw new RuntimeException("My Message"); // Noncompliant
}
public void foo(String bar) {
throw new MyOwnRuntimeException("My Message");
}
HTTP referers should not be relied on
http referers์— ์˜์กดํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค.
Referers๋Š” ๊ณต๊ฒฉ์ž์— ์˜ํ•ด ์ˆ˜์ •์ด ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— referers ๊ฐ’์— ๋Œ€ํ•ด์„œ ์‹ ๋ขฐํ•˜์ง€ ๋ง
์•„๋ผ.
public class MyServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String referer = request.getHeader("referer"); // Noncompliant
if(isTrustedReferer(referer)){
//..
}
//...
}
}
IP addresses should not be hardcoded
IP์ฃผ์†Œ๋ฅผ ํ•˜๋“œ์ฝ”๋”ฉ ํ•˜์ง€ ๋ง์•„๋ผ
์†Œ์Šค์ฝ”๋“œ์— 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);
Math operands should be cast before assignment
์ˆ˜ํ•™ ์—ฐ์‚ฐ์ž๋Š” ์‚ฌ์šฉํ•˜๊ธฐ ์ „์— ์บ์ŠคํŒ… ํ•ด์•ผ ํ•œ๋‹ค.
์—ฐ์‚ฐ์˜ ๊ฒฝ์šฐ ๊ฒฐ๊ณผ๋Š” ํ•ญ์ƒ int์ผ ๊ฒƒ์ด๋‹ค.
float twoThirds = 2/3; // Noncompliant; int division. Yields 0.0
long millisInYear = 1_000*3_600*24*365; // Noncompliant; int multiplication. Yields 1471228928
long bigNum = Integer.MAX_VALUE + 2; // Noncompliant. Yields -2147483647
long 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.6666667
long millisInYear = 1_000L*3_600*24*365; // 1000 promoted to long. Yields 31_536_000_000
long bigNum = Integer.MAX_VALUE + 2L; // 2 promoted to long. Yields 2_147_483_649
long bigNegNum = Integer.MIN_VALUE-1L; // Yields -2_147_483_649
Date myDate = new Date(seconds * 1_000L);
...
public long compute(int factor){
return factor * 10_000L;
}
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;
}
Neither DES (Data Encryption Standard) nor DESede (3DES) should be
used
DES(๋ฐ์ดํ„ฐ ์•”ํ˜ธํ™” ํ‘œ์ค€) ๋„ DESede(3DES) ๋„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.
ํ‘œ์ค€ ๋ฐ ๋ฏธ๊ตญ ๊ตญ๋ฆฝ ๊ธฐ์ˆ  ์—ฐ๊ตฌ์†Œ (NIST)์— ๋”ฐ๋ฅด๋ฉด, ๋ฐ์ดํ„ฐ ์•”ํ˜ธํ™” ํ‘œ์ค€ (DES)๋Š” ๋” ์ด์ƒ
์•ˆ์ „ํ•œ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค
Cipher c = Cipher.getInstance("DESede/ECB/PKCS5Padding");
Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
Null pointers should not be dereferenced
๋„ํฌ์ธํ„ฐ๋Š” ์—ญ์ฐธ์กฐํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค.
์ผ๋ฐ˜์ ์œผ๋กœ ๊ทธ ๊ฐ์ฒด๊ฐ€ NULL์ด ๋  ์ˆ˜ ์—†๋‹คโ€™๋ผ๊ณ  ํ•˜๋Š” ๊ฐ€์ •์„ ์œ„๋ฐ˜ํ–ˆ์„ ๋•Œ ๋ฐœ์ƒํ•œ๋‹ค.
@CheckForNull
String 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{} block
conn.close(); // Noncompliant; conn could be null if an exception was thrown
}
Only standard cryptographic algorithms should be used
๋‹จ์ง€ ํ‘œ์ค€ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.
์ค‘์š”ํ•œ ๋ฏผ๊ฐํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋””์Šคํฌ์— ์ €์žฅํ•˜๊ฑฐ๋‚˜ ์™ธ๋ถ€ ์ „์†ก ์‹œ, SW๊ฐ€ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ์•”ํ˜ธ
ํ™”ํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ ๋ฏผ๊ฐํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋…ธ์ถœ๋  ์ˆ˜ ์žˆ๋‹ค.
ํ‘œ์ค€์•Œ๊ณ ๋ฆฌ์ฆ˜ : SHA-256, SHA-384, SHA-512
MyCryptographicAlgorithm extends MessageDigest {
...
}
Public methods should throw at most one checked exception
Public method ์—์„œ๋Š” ๋Œ€๋ถ€๋ถ„ ํ•˜๋‚˜์˜ exception์„ ์ฒดํฌํ•˜์—ฌ throw ํ•œ๋‹ค.
public void delete() throws IOException, SQLException { // Noncompliant
/* ... */
}
public void delete() throws SomeApplicationLevelException {
/* ... */
}
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();
}
Throwable and Error should not be caught
Throw ๊ฐ€๋Šฅ ๊ฐ์ฒด ์™€ Error๋Š” catch์— ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.
Throw ๊ฐ€๋Šฅ ๊ฐ์ฒด๋Š” ์ž๋ฐ”์˜ ๋ชจ๋“  ์—๋Ÿฌ์™€ ์˜ˆ์™ธ์˜ ์Šˆํผํด๋ž˜์Šค ์ž…๋‹ˆ๋‹ค.
Error๋Š” ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์— ์˜ํ•ด ๋ฐœ์ƒ๋˜๋Š” ์˜๋ฏธํ•˜์ง€ ์•Š๋Š” ๋ชจ๋“  ์—๋Ÿฌ์˜ ์Šˆํผํด๋ž˜์Šค ์ž…๋‹ˆ๋‹ค.
try { /* ... */ } catch (Throwable t) { /* ... */ }
try { /* ... */ } catch (Error e) { /* ... */ }
try { /* ... */ } catch (RuntimeException e) { /* ... */ }
try { /* ... */ } catch (MyException e) { /* ... */ }
Throwable.printStackTrace(...) should not be called
Throwable.printStackTrace์„ ํ˜ธ์ถœํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
Throw ๊ฐ€๋Šฅ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹ ์— Loggers๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์‚ฌ์šฉ์ž๋Š” ์‰ฝ๊ฒŒ logs๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
try {
/* ... */
} catch(Exception e) {
e.printStackTrace(); // Noncompliant
}
try {
/* ... */
} catch(Exception e) {
LOGGER.log("context", e); // Compliant
}
Untrusted data should not be stored in sessions
์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋Š” ๋ฐ์ดํ„ฐ๋Š” ์„ธ์…˜์— ์ €์žฅํ•˜์ง€ ๋ง์•„์•ผ ํ•œ๋‹ค.
์›น ์„ธ์…˜์—์„œ ๋ฐ์ดํ„ฐ๋Š” โ€œ์‹ ๋ขฐ ๋ฒ”์œ„โ€์—์„œ ๋‚ด๋ถ€๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค.
์ฆ‰, ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ ์ž…๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ์ธ์ฆ๋˜์ง€ ์•Š๋Š” ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ์ž…๋ ฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š”๊ฒƒ์€ ์‹ ๋ขฐ์˜ ๋ฒ”์œ„๋ฅผ ๋ฒ—
์–ด๋‚˜๋Š” ์ผ์ž…๋‹ˆ๋‹ค. ๊ทธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ€์ ์ ˆํ•˜๊ฒŒ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
login = request.getParameter("login");
session.setAttribute("login", login); // Noncompliant
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) { ... } // Noncompliant
doSomething();
...
Values passed to OS commands should be sanitized
OS ๋ช…๋ น์–ด๋กœ ์ „๋‹ฌ๋œ ๊ฐ’์€ ์ œ๊ฑฐ ๋˜์–ด์•ผ ํ•œ๋‹ค.
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
...
}
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) { // Noncompliant
updatePrices(req);
}
}
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>
"ConcurrentLinkedQueue.size()" should not be used
ConcurrentLinkedQueue.size()๋Š” ์‚ฌ์šฉํ•˜์ง€ ๋ง์•„๋ผ.
ํ์˜ ํฌ๊ธฐ๋ฅผ ํ™•์ธํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋Š” ์ผ์ •ํ•œ ์‹œ๊ฐ„์ด ํ•„์š”๋กœ ํ•˜๋Š”๋ฐ, ํ์˜ ํฌ๊ธฐ๊ฐ€ ํด์ˆ˜๋ก ์‹œ
๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆด ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ๊ฐ€ ์‹คํ–‰ ์ค‘ ๋ณ€๊ฒฝ์ด ๋˜๋Š” ๊ฒฝ์šฐ ๊ฒฐ๊ณผ๊ฐ€ ์ •ํ™•ํ•˜์ง€ ์•Š์„
์ˆ˜ ์žˆ๋‹ค.
๊ทธ๋Ÿฐ๋ฐ, size()๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๊ฒฝ์šฐ์—๋Š” ํ๊ฐ€ ๋น„์–ด ์žˆ๋Š”์ง€ ํ™•์ธ ํ•˜๊ธฐ ์œ„ํ•œ isEmpty()๋ฅผ
ํ•จ๊ป˜ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.
ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue();
//...
log.info("Queue contains " + queue.size() + " elements");
"DateUtils.truncate" from Apache Commons Lang library should not be
used
Apache 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);
}
"deleteOnExit" should not be used
โ€œdeleteOnExitโ€๋Š” ์‚ฌ์šฉํ•˜์ง€ ๋ง์•„๋ผ.
File.deleteOnExit()์˜ ์‚ฌ์šฉ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด์œ ๋กœ ๊ถŒ์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
- ์‚ญ์ œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ JVM ์ข…๋ฃŒ์˜ ๊ฒฝ์šฐ์— ๋ฐœ์ƒํ•˜์ง€๋งŒ, JVM์ด ์ถฉ๋Œ ๋˜๋Š” ์ฃฝ์—ˆ์„ ๊ฒฝ์šฐ์—
์‚ญ์ œ๋˜์ง€ ์•Š๋Š”๋‹ค.
- ํŒŒ์ผ ์‚ญ์ œ๊ฐ€ ์„ฑ๊ณตํ–ˆ์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  JVM์ด ์ข…๋ฃŒ ํ•  ๋•Œ๊นŒ์ง€ ํŒŒ์ผ์ •๋ณด๋ฅผ ๋ณด๊ด€๋˜๋ฉด์„œ
๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ฆ๊ฐ€
File file = new File("file.txt");
file.deleteOnExit(); // Noncompliant
"entrySet()" should be iterated when both the key and value are
needed
key์™€ 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 retrieved
Object 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();
// ...
}
}
"ResultSet.isLast()" should not be used
ResultSet.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
}
"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"); // Compliant
if (homepage.equals(url)) { // Noncompliant
// ...
}
}
public void checkUrl(URL url) {
Set<URI> sites = new HashSet<URI>(); // Compliant
URI homepage = new URI("http://sonarsource.com"); // Compliant
URI uri = url.toURI();
if (homepage.equals(uri)) { // Compliant
// ...
}
}
"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();
}
...
}
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);
}
}
Objects should not be created only to "getClass"
Object๋ฅผ ๋‹จ์ง€ getClass๋กœ ์ƒ์„ฑํ•˜์ง€ ๋ง์•„๋ผ
getClass์˜ ํ˜ธ์ถœ์˜ ๋ชฉ์ ์€ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ธ๋ฐ, ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ฒŒ ๋˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„
๊ฐ€ ๋ฐœ์ƒํ•˜๋ฏ€๋กœ ๋‹จ์ˆœํžˆ class๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
MyObject myOb = new MyObject(); // Noncompliant
Class c = myOb.getClass();
Class c = MyObject.class;
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);
}
}
String function use should be optimized for single characters
String 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');
// ...
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();
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();
Sonarqube 20160509

Mais conteรบdo relacionado

Mais procurados

TDD&Refactoring Day 02: TDD
TDD&Refactoring Day 02: TDDTDD&Refactoring Day 02: TDD
TDD&Refactoring Day 02: TDD
Suwon Chae
ย 
C Language II
C Language IIC Language II
C Language II
Suho Kwon
ย 
๋ฆฐ ์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ๋ฐœ(Lean software development)
๋ฆฐ ์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ๋ฐœ(Lean software development)๋ฆฐ ์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ๋ฐœ(Lean software development)
๋ฆฐ ์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ๋ฐœ(Lean software development)
์˜๊ธฐ ๊น€
ย 

Mais procurados (18)

ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ By googletest 1์žฅ ๋‹ค์ค‘ ํ†ตํ™”๋ฅผ ์ง€์›ํ•˜๋Š” money ๊ฐ์ฒด
ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ By googletest   1์žฅ ๋‹ค์ค‘ ํ†ตํ™”๋ฅผ ์ง€์›ํ•˜๋Š” money ๊ฐ์ฒดํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ By googletest   1์žฅ ๋‹ค์ค‘ ํ†ตํ™”๋ฅผ ์ง€์›ํ•˜๋Š” money ๊ฐ์ฒด
ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ By googletest 1์žฅ ๋‹ค์ค‘ ํ†ตํ™”๋ฅผ ์ง€์›ํ•˜๋Š” money ๊ฐ์ฒด
ย 
TEST?
TEST?TEST?
TEST?
ย 
ํ…Œ์ŠคํŠธ ์ž๋™ํ™”์™€ TDD(ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ๋ฐฉ๋ฒ•๋ก )
ํ…Œ์ŠคํŠธ ์ž๋™ํ™”์™€ TDD(ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ๋ฐฉ๋ฒ•๋ก )ํ…Œ์ŠคํŠธ ์ž๋™ํ™”์™€ TDD(ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ๋ฐฉ๋ฒ•๋ก )
ํ…Œ์ŠคํŠธ ์ž๋™ํ™”์™€ TDD(ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ๋ฐฉ๋ฒ•๋ก )
ย 
TDD&Refactoring Day 02: TDD
TDD&Refactoring Day 02: TDDTDD&Refactoring Day 02: TDD
TDD&Refactoring Day 02: TDD
ย 
C++๊ณผ TDD
C++๊ณผ TDDC++๊ณผ TDD
C++๊ณผ TDD
ย 
ํ–‰๋ณตํ•œ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ_ํ…Œ์ŠคํŠธ_์ผ€์ด์Šค
ํ–‰๋ณตํ•œ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ_ํ…Œ์ŠคํŠธ_์ผ€์ด์Šคํ–‰๋ณตํ•œ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ_ํ…Œ์ŠคํŠธ_์ผ€์ด์Šค
ํ–‰๋ณตํ•œ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ_ํ…Œ์ŠคํŠธ_์ผ€์ด์Šค
ย 
C Language II
C Language IIC Language II
C Language II
ย 
ํ…Œ์Šคํ„ฐ๊ฐ€ ๋งํ•˜๋Š” ํ…Œ์ŠคํŠธ์ฝ”๋“œ ์ž‘์„ฑ ํŒ๊ณผ ์‚ฌ๋ก€
ํ…Œ์Šคํ„ฐ๊ฐ€ ๋งํ•˜๋Š” ํ…Œ์ŠคํŠธ์ฝ”๋“œ ์ž‘์„ฑ ํŒ๊ณผ ์‚ฌ๋ก€ํ…Œ์Šคํ„ฐ๊ฐ€ ๋งํ•˜๋Š” ํ…Œ์ŠคํŠธ์ฝ”๋“œ ์ž‘์„ฑ ํŒ๊ณผ ์‚ฌ๋ก€
ํ…Œ์Šคํ„ฐ๊ฐ€ ๋งํ•˜๋Š” ํ…Œ์ŠคํŠธ์ฝ”๋“œ ์ž‘์„ฑ ํŒ๊ณผ ์‚ฌ๋ก€
ย 
์• ์ž์ผ ํ…Œ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค์™€ ์‚ฌ๋ก€๋“ค (๋ถ€์ œ: ํ˜‘์—…์˜ ํž˜)
์• ์ž์ผ ํ…Œ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค์™€ ์‚ฌ๋ก€๋“ค (๋ถ€์ œ: ํ˜‘์—…์˜ ํž˜)์• ์ž์ผ ํ…Œ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค์™€ ์‚ฌ๋ก€๋“ค (๋ถ€์ œ: ํ˜‘์—…์˜ ํž˜)
์• ์ž์ผ ํ…Œ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค์™€ ์‚ฌ๋ก€๋“ค (๋ถ€์ œ: ํ˜‘์—…์˜ ํž˜)
ย 
๋ฆฐ ์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ๋ฐœ(Lean software development)
๋ฆฐ ์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ๋ฐœ(Lean software development)๋ฆฐ ์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ๋ฐœ(Lean software development)
๋ฆฐ ์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ๋ฐœ(Lean software development)
ย 
IoT ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ Embedded C์—์„œ TDD๋ฅผ ํ•ด๋ณด์ž
IoT ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ Embedded C์—์„œ TDD๋ฅผ ํ•ด๋ณด์žIoT ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ Embedded C์—์„œ TDD๋ฅผ ํ•ด๋ณด์ž
IoT ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ Embedded C์—์„œ TDD๋ฅผ ํ•ด๋ณด์ž
ย 
์œ„ํ—˜๊ธฐ๋ฐ˜ํ…Œ์ŠคํŠธ์ ‘๊ทผ ํ…Œ์ŠคํŠธ๊ณ„ํš ์‚ฌ๋ก€
์œ„ํ—˜๊ธฐ๋ฐ˜ํ…Œ์ŠคํŠธ์ ‘๊ทผ ํ…Œ์ŠคํŠธ๊ณ„ํš ์‚ฌ๋ก€์œ„ํ—˜๊ธฐ๋ฐ˜ํ…Œ์ŠคํŠธ์ ‘๊ทผ ํ…Œ์ŠคํŠธ๊ณ„ํš ์‚ฌ๋ก€
์œ„ํ—˜๊ธฐ๋ฐ˜ํ…Œ์ŠคํŠธ์ ‘๊ทผ ํ…Œ์ŠคํŠธ๊ณ„ํš ์‚ฌ๋ก€
ย 
Tdd with JUnit 1
Tdd with JUnit 1Tdd with JUnit 1
Tdd with JUnit 1
ย 
The Introduction to Refactoring
The Introduction to Refactoring The Introduction to Refactoring
The Introduction to Refactoring
ย 
Work With Engineer
Work With EngineerWork With Engineer
Work With Engineer
ย 
testing for agile?, agile for testing
testing for agile?, agile for testingtesting for agile?, agile for testing
testing for agile?, agile for testing
ย 
2010 SW Testing Trend
2010 SW Testing Trend2010 SW Testing Trend
2010 SW Testing Trend
ย 
์• ์ž์ผ ํ•˜๋ผ
์• ์ž์ผ ํ•˜๋ผ์• ์ž์ผ ํ•˜๋ผ
์• ์ž์ผ ํ•˜๋ผ
ย 

Destaque

Java script ์‹ ์ž…๊ต์œก
Java script ์‹ ์ž…๊ต์œกJava script ์‹ ์ž…๊ต์œก
Java script ์‹ ์ž…๊ต์œก
์ค€์„ฑ ํ™ฉ
ย 
์ƒˆ ์ง์› ๊ต์œก
์ƒˆ ์ง์› ๊ต์œก์ƒˆ ์ง์› ๊ต์œก
์ƒˆ ์ง์› ๊ต์œก
gahae
ย 
[KGC2011_๋ฐ•๋ฏผ๊ทผ] ์‹ ์ž… ๊ฒŒ์ž„ ๊ฐœ๋ฐœ์ž๊ฐ€ ์•Œ์•„์•ผ ํ•  ๊ฒƒ๋“ค
[KGC2011_๋ฐ•๋ฏผ๊ทผ] ์‹ ์ž… ๊ฒŒ์ž„ ๊ฐœ๋ฐœ์ž๊ฐ€ ์•Œ์•„์•ผ ํ•  ๊ฒƒ๋“ค[KGC2011_๋ฐ•๋ฏผ๊ทผ] ์‹ ์ž… ๊ฒŒ์ž„ ๊ฐœ๋ฐœ์ž๊ฐ€ ์•Œ์•„์•ผ ํ•  ๊ฒƒ๋“ค
[KGC2011_๋ฐ•๋ฏผ๊ทผ] ์‹ ์ž… ๊ฒŒ์ž„ ๊ฐœ๋ฐœ์ž๊ฐ€ ์•Œ์•„์•ผ ํ•  ๊ฒƒ๋“ค
MinGeun Park
ย 
์ขŒ์ถฉ์šฐ๋Œ ORM ๊ฐœ๋ฐœ๊ธฐ | Devon 2012
์ขŒ์ถฉ์šฐ๋Œ ORM ๊ฐœ๋ฐœ๊ธฐ | Devon 2012์ขŒ์ถฉ์šฐ๋Œ ORM ๊ฐœ๋ฐœ๊ธฐ | Devon 2012
์ขŒ์ถฉ์šฐ๋Œ ORM ๊ฐœ๋ฐœ๊ธฐ | Devon 2012
Daum DNA
ย 
Si ํ”„๋กœ์ ํŠธ์—์„œ ๋ฐ”๋ผ๋ณด๋Š”...traditional vs agile
Si ํ”„๋กœ์ ํŠธ์—์„œ ๋ฐ”๋ผ๋ณด๋Š”...traditional vs agileSi ํ”„๋กœ์ ํŠธ์—์„œ ๋ฐ”๋ผ๋ณด๋Š”...traditional vs agile
Si ํ”„๋กœ์ ํŠธ์—์„œ ๋ฐ”๋ผ๋ณด๋Š”...traditional vs agile
Kiwon Kyung
ย 

Destaque (20)

SVN์—์„œ GIT์œผ๋กœ ์ „ํ™˜ํ•˜๊ธฐ
SVN์—์„œ GIT์œผ๋กœ ์ „ํ™˜ํ•˜๊ธฐSVN์—์„œ GIT์œผ๋กœ ์ „ํ™˜ํ•˜๊ธฐ
SVN์—์„œ GIT์œผ๋กœ ์ „ํ™˜ํ•˜๊ธฐ
ย 
Softskills
SoftskillsSoftskills
Softskills
ย 
์‹ ์ž…์›น๊ฐœ๋ฐœ์ž๊ต์œก
์‹ ์ž…์›น๊ฐœ๋ฐœ์ž๊ต์œก์‹ ์ž…์›น๊ฐœ๋ฐœ์ž๊ต์œก
์‹ ์ž…์›น๊ฐœ๋ฐœ์ž๊ต์œก
ย 
2015.03.25 ํ…Œํฌ๋‹ˆ์ปฌ ์„ธ๋ฏธ๋‚˜ - SonarQube๋ฅผ ํ™œ์šฉํ•œ ์ฝ”๋“œ ํ’ˆ์งˆ ์‹œ๊ฐํ™”(๊น€๋ชจ์„ธ)
2015.03.25 ํ…Œํฌ๋‹ˆ์ปฌ ์„ธ๋ฏธ๋‚˜ - SonarQube๋ฅผ ํ™œ์šฉํ•œ ์ฝ”๋“œ ํ’ˆ์งˆ ์‹œ๊ฐํ™”(๊น€๋ชจ์„ธ)2015.03.25 ํ…Œํฌ๋‹ˆ์ปฌ ์„ธ๋ฏธ๋‚˜ - SonarQube๋ฅผ ํ™œ์šฉํ•œ ์ฝ”๋“œ ํ’ˆ์งˆ ์‹œ๊ฐํ™”(๊น€๋ชจ์„ธ)
2015.03.25 ํ…Œํฌ๋‹ˆ์ปฌ ์„ธ๋ฏธ๋‚˜ - SonarQube๋ฅผ ํ™œ์šฉํ•œ ์ฝ”๋“œ ํ’ˆ์งˆ ์‹œ๊ฐํ™”(๊น€๋ชจ์„ธ)
ย 
SonarQube ๋กœ Unity ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ
SonarQube ๋กœ Unity ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌSonarQube ๋กœ Unity ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ
SonarQube ๋กœ Unity ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ
ย 
๋ฆฌ๋ˆ…์Šค ํ™˜๊ฒฝ์—์„œ SonarQube ๊ฐ„๋‹จํ•˜๊ฒŒ ์‚ฌ์šฉํ•ด๋ณด๊ธฐ
๋ฆฌ๋ˆ…์Šค ํ™˜๊ฒฝ์—์„œ SonarQube ๊ฐ„๋‹จํ•˜๊ฒŒ ์‚ฌ์šฉํ•ด๋ณด๊ธฐ๋ฆฌ๋ˆ…์Šค ํ™˜๊ฒฝ์—์„œ SonarQube ๊ฐ„๋‹จํ•˜๊ฒŒ ์‚ฌ์šฉํ•ด๋ณด๊ธฐ
๋ฆฌ๋ˆ…์Šค ํ™˜๊ฒฝ์—์„œ SonarQube ๊ฐ„๋‹จํ•˜๊ฒŒ ์‚ฌ์šฉํ•ด๋ณด๊ธฐ
ย 
Sonar ์„ค์น˜
Sonar ์„ค์น˜Sonar ์„ค์น˜
Sonar ์„ค์น˜
ย 
2015 Newguest presentation wide OT
2015 Newguest presentation wide OT2015 Newguest presentation wide OT
2015 Newguest presentation wide OT
ย 
Java script ์‹ ์ž…๊ต์œก
Java script ์‹ ์ž…๊ต์œกJava script ์‹ ์ž…๊ต์œก
Java script ์‹ ์ž…๊ต์œก
ย 
์ƒˆ ์ง์› ๊ต์œก
์ƒˆ ์ง์› ๊ต์œก์ƒˆ ์ง์› ๊ต์œก
์ƒˆ ์ง์› ๊ต์œก
ย 
devon2013: ์‚ฌ๋‚ดGit์ €์žฅ์†Œ๊ฐœ๋ฐœ์‚ฌ๋ก€
devon2013: ์‚ฌ๋‚ดGit์ €์žฅ์†Œ๊ฐœ๋ฐœ์‚ฌ๋ก€devon2013: ์‚ฌ๋‚ดGit์ €์žฅ์†Œ๊ฐœ๋ฐœ์‚ฌ๋ก€
devon2013: ์‚ฌ๋‚ดGit์ €์žฅ์†Œ๊ฐœ๋ฐœ์‚ฌ๋ก€
ย 
Sonarqube
SonarqubeSonarqube
Sonarqube
ย 
Static Code Analysis and Cppcheck
Static Code Analysis and CppcheckStatic Code Analysis and Cppcheck
Static Code Analysis and Cppcheck
ย 
[KGC2011_๋ฐ•๋ฏผ๊ทผ] ์‹ ์ž… ๊ฒŒ์ž„ ๊ฐœ๋ฐœ์ž๊ฐ€ ์•Œ์•„์•ผ ํ•  ๊ฒƒ๋“ค
[KGC2011_๋ฐ•๋ฏผ๊ทผ] ์‹ ์ž… ๊ฒŒ์ž„ ๊ฐœ๋ฐœ์ž๊ฐ€ ์•Œ์•„์•ผ ํ•  ๊ฒƒ๋“ค[KGC2011_๋ฐ•๋ฏผ๊ทผ] ์‹ ์ž… ๊ฒŒ์ž„ ๊ฐœ๋ฐœ์ž๊ฐ€ ์•Œ์•„์•ผ ํ•  ๊ฒƒ๋“ค
[KGC2011_๋ฐ•๋ฏผ๊ทผ] ์‹ ์ž… ๊ฒŒ์ž„ ๊ฐœ๋ฐœ์ž๊ฐ€ ์•Œ์•„์•ผ ํ•  ๊ฒƒ๋“ค
ย 
์ขŒ์ถฉ์šฐ๋Œ ORM ๊ฐœ๋ฐœ๊ธฐ | Devon 2012
์ขŒ์ถฉ์šฐ๋Œ ORM ๊ฐœ๋ฐœ๊ธฐ | Devon 2012์ขŒ์ถฉ์šฐ๋Œ ORM ๊ฐœ๋ฐœ๊ธฐ | Devon 2012
์ขŒ์ถฉ์šฐ๋Œ ORM ๊ฐœ๋ฐœ๊ธฐ | Devon 2012
ย 
์Šคํ”„๋ง๊ตฐ์‚ด์—†์ด์„ธํŒ…ํ•˜๊ธฐ(The way to setting the Spring framework for web.)
์Šคํ”„๋ง๊ตฐ์‚ด์—†์ด์„ธํŒ…ํ•˜๊ธฐ(The way to setting the Spring framework for web.)์Šคํ”„๋ง๊ตฐ์‚ด์—†์ด์„ธํŒ…ํ•˜๊ธฐ(The way to setting the Spring framework for web.)
์Šคํ”„๋ง๊ตฐ์‚ด์—†์ด์„ธํŒ…ํ•˜๊ธฐ(The way to setting the Spring framework for web.)
ย 
Si ํ”„๋กœ์ ํŠธ์—์„œ ๋ฐ”๋ผ๋ณด๋Š”...traditional vs agile
Si ํ”„๋กœ์ ํŠธ์—์„œ ๋ฐ”๋ผ๋ณด๋Š”...traditional vs agileSi ํ”„๋กœ์ ํŠธ์—์„œ ๋ฐ”๋ผ๋ณด๋Š”...traditional vs agile
Si ํ”„๋กœ์ ํŠธ์—์„œ ๋ฐ”๋ผ๋ณด๋Š”...traditional vs agile
ย 
Istqb 3-์ •์ ํ…Œ์ŠคํŒ…๊ธฐ๋ฒ•-2015
Istqb 3-์ •์ ํ…Œ์ŠคํŒ…๊ธฐ๋ฒ•-2015Istqb 3-์ •์ ํ…Œ์ŠคํŒ…๊ธฐ๋ฒ•-2015
Istqb 3-์ •์ ํ…Œ์ŠคํŒ…๊ธฐ๋ฒ•-2015
ย 
Agile - SCRUM์„ ํ†ตํ•œ ๊ฐœ๋ฐœ๊ด€๋ฆฌ
Agile - SCRUM์„ ํ†ตํ•œ ๊ฐœ๋ฐœ๊ด€๋ฆฌAgile - SCRUM์„ ํ†ตํ•œ ๊ฐœ๋ฐœ๊ด€๋ฆฌ
Agile - SCRUM์„ ํ†ตํ•œ ๊ฐœ๋ฐœ๊ด€๋ฆฌ
ย 
Istqb 4-ํ…Œ์ŠคํŠธ์„ค๊ณ„๊ธฐ๋ฒ•-2015-1
Istqb 4-ํ…Œ์ŠคํŠธ์„ค๊ณ„๊ธฐ๋ฒ•-2015-1Istqb 4-ํ…Œ์ŠคํŠธ์„ค๊ณ„๊ธฐ๋ฒ•-2015-1
Istqb 4-ํ…Œ์ŠคํŠธ์„ค๊ณ„๊ธฐ๋ฒ•-2015-1
ย 

Semelhante a Sonarqube 20160509

Cygnus unit test
Cygnus unit testCygnus unit test
Cygnus unit test
Sung Jae Park
ย 
์นด์‚ฌ ๊ณต๊ฐœ์„ธ๋ฏธ๋‚˜1ํšŒ W.E.L.C.
์นด์‚ฌ ๊ณต๊ฐœ์„ธ๋ฏธ๋‚˜1ํšŒ  W.E.L.C.์นด์‚ฌ ๊ณต๊ฐœ์„ธ๋ฏธ๋‚˜1ํšŒ  W.E.L.C.
์นด์‚ฌ ๊ณต๊ฐœ์„ธ๋ฏธ๋‚˜1ํšŒ W.E.L.C.
Ryan Park
ย 
Robot framework แ„‹แ…ณแ†ฏ แ„‹แ…ตแ„‹แ…ญแ†ผแ„’แ…กแ†ซ แ„€แ…ตแ„‚แ…ณแ†ผ แ„แ…ฆแ„‰แ…ณแ„แ…ณ แ„Œแ…กแ„ƒแ…ฉแ†ผแ„’แ…ช
Robot framework แ„‹แ…ณแ†ฏ แ„‹แ…ตแ„‹แ…ญแ†ผแ„’แ…กแ†ซ แ„€แ…ตแ„‚แ…ณแ†ผ แ„แ…ฆแ„‰แ…ณแ„แ…ณ แ„Œแ…กแ„ƒแ…ฉแ†ผแ„’แ…ชRobot framework แ„‹แ…ณแ†ฏ แ„‹แ…ตแ„‹แ…ญแ†ผแ„’แ…กแ†ซ แ„€แ…ตแ„‚แ…ณแ†ผ แ„แ…ฆแ„‰แ…ณแ„แ…ณ แ„Œแ…กแ„ƒแ…ฉแ†ผแ„’แ…ช
Robot framework แ„‹แ…ณแ†ฏ แ„‹แ…ตแ„‹แ…ญแ†ผแ„’แ…กแ†ซ แ„€แ…ตแ„‚แ…ณแ†ผ แ„แ…ฆแ„‰แ…ณแ„แ…ณ แ„Œแ…กแ„ƒแ…ฉแ†ผแ„’แ…ช
Jaehoon Oh
ย 
Eclipse RCP 1/2
Eclipse RCP 1/2Eclipse RCP 1/2
Eclipse RCP 1/2
cho hyun jong
ย 

Semelhante a Sonarqube 20160509 (20)

Cygnus unit test
Cygnus unit testCygnus unit test
Cygnus unit test
ย 
Java ์œ ์ง€๋ณด์ˆ˜ ๊ฐ€๋Šฅํ•œ ๊ฐœ๋ฐœ ์›์น™
Java ์œ ์ง€๋ณด์ˆ˜ ๊ฐ€๋Šฅํ•œ ๊ฐœ๋ฐœ ์›์น™Java ์œ ์ง€๋ณด์ˆ˜ ๊ฐ€๋Šฅํ•œ ๊ฐœ๋ฐœ ์›์น™
Java ์œ ์ง€๋ณด์ˆ˜ ๊ฐ€๋Šฅํ•œ ๊ฐœ๋ฐœ ์›์น™
ย 
์œ ์ง€๋ณด์ˆ˜ ๊ฐ€๋Šฅํ•œ ๊ฐœ๋ฐœ ์›์น™
์œ ์ง€๋ณด์ˆ˜ ๊ฐ€๋Šฅํ•œ ๊ฐœ๋ฐœ ์›์น™์œ ์ง€๋ณด์ˆ˜ ๊ฐ€๋Šฅํ•œ ๊ฐœ๋ฐœ ์›์น™
์œ ์ง€๋ณด์ˆ˜ ๊ฐ€๋Šฅํ•œ ๊ฐœ๋ฐœ ์›์น™
ย 
์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ์„  ๊ทธ๋ฃน(Sig) ๊ฐœ๋ฐœ ์›์น™
์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ์„  ๊ทธ๋ฃน(Sig) ๊ฐœ๋ฐœ ์›์น™์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ์„  ๊ทธ๋ฃน(Sig) ๊ฐœ๋ฐœ ์›์น™
์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ์„  ๊ทธ๋ฃน(Sig) ๊ฐœ๋ฐœ ์›์น™
ย 
Android unit testing
Android unit testingAndroid unit testing
Android unit testing
ย 
์นด์‚ฌ ๊ณต๊ฐœ์„ธ๋ฏธ๋‚˜1ํšŒ W.E.L.C.
์นด์‚ฌ ๊ณต๊ฐœ์„ธ๋ฏธ๋‚˜1ํšŒ  W.E.L.C.์นด์‚ฌ ๊ณต๊ฐœ์„ธ๋ฏธ๋‚˜1ํšŒ  W.E.L.C.
์นด์‚ฌ ๊ณต๊ฐœ์„ธ๋ฏธ๋‚˜1ํšŒ W.E.L.C.
ย 
Node.js ๊ธฐ๋ณธ
Node.js ๊ธฐ๋ณธNode.js ๊ธฐ๋ณธ
Node.js ๊ธฐ๋ณธ
ย 
Robot framework แ„‹แ…ณแ†ฏ แ„‹แ…ตแ„‹แ…ญแ†ผแ„’แ…กแ†ซ แ„€แ…ตแ„‚แ…ณแ†ผ แ„แ…ฆแ„‰แ…ณแ„แ…ณ แ„Œแ…กแ„ƒแ…ฉแ†ผแ„’แ…ช
Robot framework แ„‹แ…ณแ†ฏ แ„‹แ…ตแ„‹แ…ญแ†ผแ„’แ…กแ†ซ แ„€แ…ตแ„‚แ…ณแ†ผ แ„แ…ฆแ„‰แ…ณแ„แ…ณ แ„Œแ…กแ„ƒแ…ฉแ†ผแ„’แ…ชRobot framework แ„‹แ…ณแ†ฏ แ„‹แ…ตแ„‹แ…ญแ†ผแ„’แ…กแ†ซ แ„€แ…ตแ„‚แ…ณแ†ผ แ„แ…ฆแ„‰แ…ณแ„แ…ณ แ„Œแ…กแ„ƒแ…ฉแ†ผแ„’แ…ช
Robot framework แ„‹แ…ณแ†ฏ แ„‹แ…ตแ„‹แ…ญแ†ผแ„’แ…กแ†ซ แ„€แ…ตแ„‚แ…ณแ†ผ แ„แ…ฆแ„‰แ…ณแ„แ…ณ แ„Œแ…กแ„ƒแ…ฉแ†ผแ„’แ…ช
ย 
๊ตฌ๊ธ€ํ…Œ์ŠคํŠธ
๊ตฌ๊ธ€ํ…Œ์ŠคํŠธ๊ตฌ๊ธ€ํ…Œ์ŠคํŠธ
๊ตฌ๊ธ€ํ…Œ์ŠคํŠธ
ย 
TDD.JUnit.์กฐ๊ธˆ๋”.์•Œ๊ธฐ
TDD.JUnit.์กฐ๊ธˆ๋”.์•Œ๊ธฐTDD.JUnit.์กฐ๊ธˆ๋”.์•Œ๊ธฐ
TDD.JUnit.์กฐ๊ธˆ๋”.์•Œ๊ธฐ
ย 
Eclipse RCP 1/2
Eclipse RCP 1/2Eclipse RCP 1/2
Eclipse RCP 1/2
ย 
Okjsp 13์ฃผ๋…„ ๋ฐœํ‘œ์ž๋ฃŒ: ์ƒ์กด ํ”„๋กœ๊ทธ๋ž˜๋ฐ Test
Okjsp 13์ฃผ๋…„ ๋ฐœํ‘œ์ž๋ฃŒ: ์ƒ์กด ํ”„๋กœ๊ทธ๋ž˜๋ฐ TestOkjsp 13์ฃผ๋…„ ๋ฐœํ‘œ์ž๋ฃŒ: ์ƒ์กด ํ”„๋กœ๊ทธ๋ž˜๋ฐ Test
Okjsp 13์ฃผ๋…„ ๋ฐœํ‘œ์ž๋ฃŒ: ์ƒ์กด ํ”„๋กœ๊ทธ๋ž˜๋ฐ Test
ย 
4-1. javascript
4-1. javascript4-1. javascript
4-1. javascript
ย 
Backend Master | 3.2.1 Test - JUnit
Backend Master | 3.2.1 Test - JUnitBackend Master | 3.2.1 Test - JUnit
Backend Master | 3.2.1 Test - JUnit
ย 
ํˆฌ๋น„์›จ์–ด AgitarOne Junit ๋‹จ์œ„ํ…Œ์ŠคํŠธ์ž๋™ํ™” ์†”๋ฃจ์…˜์†Œ๊ฐœ_201608_v1.2
ํˆฌ๋น„์›จ์–ด AgitarOne Junit ๋‹จ์œ„ํ…Œ์ŠคํŠธ์ž๋™ํ™” ์†”๋ฃจ์…˜์†Œ๊ฐœ_201608_v1.2ํˆฌ๋น„์›จ์–ด AgitarOne Junit ๋‹จ์œ„ํ…Œ์ŠคํŠธ์ž๋™ํ™” ์†”๋ฃจ์…˜์†Œ๊ฐœ_201608_v1.2
ํˆฌ๋น„์›จ์–ด AgitarOne Junit ๋‹จ์œ„ํ…Œ์ŠคํŠธ์ž๋™ํ™” ์†”๋ฃจ์…˜์†Œ๊ฐœ_201608_v1.2
ย 
Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005
ย 
ๅ›žๅ›ฝๅŽปๅ“ชไนฐๆฏ•ไธš่ฏๅŠž่ฟช่‚ฏๅคงๅญฆๆฏ•ไธš่ฏDeakinๆฏ•ไธš่ฏไนฆใ€Qๅพฎ202-661-4433ใ€‘ Deakinๅ”ฎๆพณๆดฒๆฏ•ไธš่ฏๅŽŸ็‰ˆๆ–ฐๆฏ•ไธš่ฏไนฆๅ‡บๅ”ฎๅ„ๅ›ฝๆฏ•ไธš่ฏไนฐๆพณๆดฒๆฏ•ไธš่ฏ็š„ไปท...
ๅ›žๅ›ฝๅŽปๅ“ชไนฐๆฏ•ไธš่ฏๅŠž่ฟช่‚ฏๅคงๅญฆๆฏ•ไธš่ฏDeakinๆฏ•ไธš่ฏไนฆใ€Qๅพฎ202-661-4433ใ€‘ Deakinๅ”ฎๆพณๆดฒๆฏ•ไธš่ฏๅŽŸ็‰ˆๆ–ฐๆฏ•ไธš่ฏไนฆๅ‡บๅ”ฎๅ„ๅ›ฝๆฏ•ไธš่ฏไนฐๆพณๆดฒๆฏ•ไธš่ฏ็š„ไปท...ๅ›žๅ›ฝๅŽปๅ“ชไนฐๆฏ•ไธš่ฏๅŠž่ฟช่‚ฏๅคงๅญฆๆฏ•ไธš่ฏDeakinๆฏ•ไธš่ฏไนฆใ€Qๅพฎ202-661-4433ใ€‘ Deakinๅ”ฎๆพณๆดฒๆฏ•ไธš่ฏๅŽŸ็‰ˆๆ–ฐๆฏ•ไธš่ฏไนฆๅ‡บๅ”ฎๅ„ๅ›ฝๆฏ•ไธš่ฏไนฐๆพณๆดฒๆฏ•ไธš่ฏ็š„ไปท...
ๅ›žๅ›ฝๅŽปๅ“ชไนฐๆฏ•ไธš่ฏๅŠž่ฟช่‚ฏๅคงๅญฆๆฏ•ไธš่ฏDeakinๆฏ•ไธš่ฏไนฆใ€Qๅพฎ202-661-4433ใ€‘ Deakinๅ”ฎๆพณๆดฒๆฏ•ไธš่ฏๅŽŸ็‰ˆๆ–ฐๆฏ•ไธš่ฏไนฆๅ‡บๅ”ฎๅ„ๅ›ฝๆฏ•ไธš่ฏไนฐๆพณๆดฒๆฏ•ไธš่ฏ็š„ไปท...
ย 
The Future of .NET and C#
The Future of .NET and C#The Future of .NET and C#
The Future of .NET and C#
ย 
[์˜คํ”ˆ์†Œ์Šค์ปจ์„คํŒ…]Fault Tolerance Architecture by Netflix
[์˜คํ”ˆ์†Œ์Šค์ปจ์„คํŒ…]Fault Tolerance Architecture by Netflix[์˜คํ”ˆ์†Œ์Šค์ปจ์„คํŒ…]Fault Tolerance Architecture by Netflix
[์˜คํ”ˆ์†Œ์Šค์ปจ์„คํŒ…]Fault Tolerance Architecture by Netflix
ย 
[๊ธฐ๋ณธ๊ณผ์ •] ์ฝ”๋“œ ํ…Œ์ŠคํŠธ์™€ ์ปค๋ฒ„๋ฆฌ์ง€ ๊ธฐ๋ณธ ๊ต์œก(๊ฐœ๋…)
[๊ธฐ๋ณธ๊ณผ์ •] ์ฝ”๋“œ ํ…Œ์ŠคํŠธ์™€ ์ปค๋ฒ„๋ฆฌ์ง€ ๊ธฐ๋ณธ ๊ต์œก(๊ฐœ๋…)[๊ธฐ๋ณธ๊ณผ์ •] ์ฝ”๋“œ ํ…Œ์ŠคํŠธ์™€ ์ปค๋ฒ„๋ฆฌ์ง€ ๊ธฐ๋ณธ ๊ต์œก(๊ฐœ๋…)
[๊ธฐ๋ณธ๊ณผ์ •] ์ฝ”๋“œ ํ…Œ์ŠคํŠธ์™€ ์ปค๋ฒ„๋ฆฌ์ง€ ๊ธฐ๋ณธ ๊ต์œก(๊ฐœ๋…)
ย 

Sonarqube 20160509

  • 2. ๏ฝ ์†Œํ”„ํŠธ์›จ์–ด ํ’ˆ์งˆ ๏ฝ ์†Œํ”„ํŠธ์›จ์–ด ๊ตฌํ˜„ ๏ฝ SonarQube ๊ธฐ๋Šฅ ๋ฐ ํŠน์ง• ๏ฝ SonarQube ์‚ฌ์šฉ๋ฐฉ๋ฒ• ๏ฝ ์†Œ์Šค ํ’ˆ์งˆ์„ ์œ„ํ•œ ์ฝ”๋”ฉ ๏ฝ Q&A
  • 3. ๏ฝ ๊ธฐ๋Šฅ์  ์š”๊ตฌ์‚ฌํ•ญ(Functional Requirements) - ์ˆ˜ํ–‰๋  ๊ธฐ๋Šฅ๊ณผ ๊ด€๋ จ๋˜์–ด ์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ ๋ฐ ๊ทธ๋“ค ์‚ฌ์ด์˜ ์ฒ˜๋ฆฌ๊ณผ์ • - ๋ชฉํ‘œ๋กœ ํ•˜๋Š” ์ œํ’ˆ์˜ ๊ตฌํ˜„์„ ์œ„ํ•ด ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ๊ฐ€์ ธ์•ผ ํ•˜๋Š” ๊ธฐ๋Šฅ ์  ์†์„ฑ ๏ฝ ๋น„๊ธฐ๋Šฅ์  ์š”๊ตฌ์‚ฌํ•ญ(Non-Functional Requirements) โ—ฆ ์ œํ’ˆ์˜ ํ’ˆ์งˆ ๊ธฐ์ค€ ๋“ฑ์„ ๋งŒ์กฑ์‹œํ‚ค๊ธฐ ์œ„ํ•ด ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ๊ฐ€์ ธ์•ผ ํ•˜ ๋Š” ์„ฑ๋Šฅ, ์‚ฌ์šฉ์˜ ์šฉ์˜์„ฑ, ์•ˆ์ „์„ฑ๊ณผ ๊ฐ™์€ ํ–‰์œ„์  ํŠน์„ฑ โ—ฆ ์‹œ์Šคํ…œ์˜ ๊ธฐ๋Šฅ์— ๊ด€๋ จ๋˜์ง€ ์•Š๋Š” ์‚ฌํ•ญ์„ ๋‚˜ํƒ€๋ƒ„ ๊ธฐ๋Šฅ ๋น„๊ธฐ๋Šฅ
  • 4. ํšจ์œจ์ ์ธ SW ๊ฐœ๋ฐœ ๊ด€๋ฆฌ ๊ฐ€์น˜์žˆ๋Š” SW ๊ณ„ ํš ๋ช…ํ™•ํ•œ ๋ชฉํ‘œ์ˆ˜๋ฆฝ ์ˆ˜ ํ–‰ ํšจ์œจ์ ์ธ ๊ฐœ๋ฐœํ™œ๋™ ๊ฒ€ ์ฆ ์ง€์†์ ์ธ ๋ชจ๋‹ˆํ„ฐ๋ง ๋ฐ ํ†ต์žฌ โ€œ๊ณ„ํš ๊ธฐ๋ฐ˜์˜ ์ง€์†์  ๊ฒ€์ฆโ€ โ€œ์‹œ๊ฐ์  ๊ฒ€์ฆ์„ ์œ„ํ•œ ์‹œ์Šคํ…œ ํ™œ์šฉโ€
  • 6. 1. ์†Œ์Šค์ฝ”๋“œ๋ฅผ ๋ฐ”์ด๋„ˆ๋ฆฌ ํŒŒ์ผ๋กœ ์ปดํŒŒ์ผ ํ•œ๋‹ค. 2. ๋ฐ”์ด๋„ˆ๋ฆฌ ํŒŒ์ผ์„ ๋ฐฐํฌ ํ˜•ํƒœ๋กœ ํŒจํ‚ค์ง• ํ•œ๋‹ค. 3. ๋‹จ์œ„ํ…Œ์ŠคํŠธ(์ปค๋ฒ„๋ฆฌ์ง€ ํฌํ•จ) ์ˆ˜ํ–‰ํ•œ๋‹ค. 4. ์ •์ ๋ถ„์„์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. 5. ๋ถ„์„ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํฌํŒ…ํ•œ๋‹ค. 6. ํŒจํ‚ค์ง•ํ•œ ํŒŒ์ผ์„ ํ…Œ์ŠคํŠธ ์„œ๋ฒ„์— ๋ฐฐํฌํ•œ๋‹ค.
  • 7. ๏ฝ SW ๊ตฌํ˜„์€ SW ๊ณตํ•™์˜ ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ํ™œ๋™์œผ๋กœ ์ฝ”๋“œ์ž‘์„ฑ, ๋””๋ฒ„๊น…, SWํ†ตํ•ฉ, ๊ฐœ๋ฐœ ์ž ํ…Œ์ŠคํŒ… ํ™œ๋™๋“ค๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค. ๏ฝ SW ๊ตฌํ˜„ํ•  ๋•Œ ๊ณ ๋ คํ•ด์•ผ ํ•  4๊ฐ€์ง€ ์ฃผ์š”์›์น™ - ์ฝ”๋”ฉ์˜ ๋ณต์žก์„ฑ์„ ์ตœ์†Œํ™” - ํ–ฅํ›„์— ์ผ์–ด๋‚  ๋ณ€ํ™”๋ฅผ ๊ณ ๋ ค - ์†Œํ”„ํŠธ์›จ์–ด ๊ตฌํ˜„์€ ๊ฒ€์ฆ์ด ๊ฐ€๋Šฅํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ - ํ‘œ์ค€์„ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ ๏ฝ ์ฝ”๋”ฉ ๊ทœ์น™์ด๋‚˜ ํ‘œ์ค€์„ ์ˆ˜๋ฆฝํ•˜์—ฌ ๋ชจ๋“  ๊ฐœ๋ฐœ์ž๊ฐ€ ํ”„๋กœ์ ํŠธ์—์„œ ์กฐํ™”๋กญ๊ฒŒ ์ž‘์—…ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•ด์„œ ์ข‹์•„์ง„ ์†Œ์Šค ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์€ ๊ฐœ๋ฐœ์ž๊ฐ€ SW ์‹œ ์Šคํ…œ์„ ์ดํ•ดํ•˜๋Š”๋ฐ ์˜ํ–ฅ์„ ๋ฏธ์น˜๊ฒŒ ๋˜๊ณ , ๊ฐ€๋…์„ฑ์ด ํ–ฅ์ƒ๋˜๋ฉด ์ดํ•ด๊ฐ€ ์šฉ์ดํ•ด์ง€๊ณ  ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์ˆ˜์›”ํ•ด์ง€๋ฉฐ ์ผ๋ฐ˜์ ์œผ๋กœ ์ฝ”๋“œ์˜ ํ’ˆ์งˆ๋„ ์ข‹์•„์ง„๋‹ค.
  • 8. ๏ฝ ํ’ˆ์งˆ ๊ด€๋ฆฌ ๋„๊ตฌ์˜ ์ฃผ์š”๊ธฐ๋Šฅ ๏ƒ˜ ์ž ์žฌ์  ์˜ค๋ฅ˜ ์†Œ์Šค ์ฝ”๋“œ ๊ฒ€์ถœ ๏ƒ˜ ๊ฐœ๋ฐœ ํ‘œ์ค€ ์ค€์ˆ˜ ๏ƒ˜ ์‰ฌ์šด ๋ฃฐ ์ƒ์„ฑ ๋ฐ ํŽธ์ง‘ ๏ƒ˜ ์ž๋™ ๋ฃฐ ์—…๋ฐ์ดํŠธ ๏ฝ ์ •์  ๋ถ„์„ ๋„๊ตฌ๋ฅผ ํ†ตํ•ด ๊ฒ€์ƒ‰ ๋˜๋Š” ๋‚ด์šฉ ๏ƒ˜ ๊ณต์œ ๋œ ์ฝ”๋”ฉ ์Šคํƒ€์ผ ์œ„๋ฐ˜ ๏ƒ˜ ์ž ์žฌ์  ๋ฒ„๊ทธ์˜ ์ฝ”๋”ฉ ๏ƒ˜ ์„ค๊ณ„์ƒ์˜ ๋ฌธ์ œ๊ฐ€ ๋˜๋Š” ์ฝ”๋“œ ๏ƒ˜ ์ค‘๋ณต๋˜๊ณ  ๋ณด์•ˆ์— ์œ„๋ฐ˜๋˜๋Š” ์ฝ”๋“œ ๏ƒ˜ ๋“ฑ๋“ฑโ€ฆโ€ฆ
  • 9. ๏ฝ ์ •์  ๋ถ„์„ ๋„๊ตฌ๋กœ ์†Œ์Šค์ฝ”๋“œ์— ๋Œ€ํ•œ ์ „๋ฐ˜์ ์ธ ํ’ˆ์งˆ ์„ ํ™•๋ณดํ•  ์ˆ˜ ์žˆ๋„๋ก ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ํ†ตํ•ฉ ํ”Œ๋žซํผ ๏ฝ Server / Client ๊ตฌ์กฐ ๏ฝ C/C++/Java ๋“ฑ 15๊ฐœ ์ด์ƒ์˜ ๋‹ค์–‘ํ•œ ํ”„๋กœ๊ทธ๋žจ ์–ธ ์–ด ์ง€์› ๏ฝ ํ”Œ๋Ÿฌ๊ทธ์ธ ์„ค์น˜๋กœ ๋‹ค์–‘ํ•œ ๋„๊ตฌ์™€ ์œ ์—ฐํ•œ ํ†ตํ•ฉ ๏ฝ ์›น ๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ๋‹ค์–‘ํ•œ ๊ฒฐ๊ณผ๋ฅผ ์„œ๋ฒ„์— ์„œ ํ†ตํ•ฉ ๊ด€๋ฆฌ ์šฉ์ด
  • 10. ๏ฝ ํ”„๋กœ์ ํŠธ ์†Œ์Šค ํ’ˆ์งˆ์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ชจ๋‹ˆ ํ„ฐ๋ง ํˆด์„ ์ œ๊ณตํ•˜๋Š” ์˜คํ”ˆ์†Œ์Šค ํ”Œ๋žซํผ ๏ฝ ๋ณดํ†ต SonarQube๋Š” ๋‹จ๋…์œผ๋กœ ์‚ฌ์šฉ๋˜๊ธฐ ๋ณด๋‹ค๋Š” Jenkins ๊ฐ™์€ CI ์„œ๋ฒ„์™€ ์—ฐ๋™์ด ๋˜์–ด์„œ ์‚ฌ์šฉ์ด ๋˜์–ด์ง€๊ณ  ์žˆ์œผ๋ฉฐ Java๋ฅผ ํฌํ•จํ•œ 20๊ฐ€์ง€๊ฐ€ ๋„˜๋Š” ํ”„๋กœ๊ทธ๋žจ๋ฐ ์–ธ์–ด๋กœ ์ œ์ž‘๋œ ํ”„๋กœ์ ํŠธ์˜ ๋ชจ๋‹ˆํ„ฐ๋ง์„ ์ œ๊ณต
  • 11. ๏ฝ Java ๊ธฐ๋ฐ˜์˜ ์ •์ ๋ถ„์„ ํˆด๋กœ์จ, ๋‹ค์–‘ํ•œ ํ•ญ๋ชฉ์— ๋Œ€ํ•ด ๋ถ„์„ ๋ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋Š” ํ’ˆ์งˆ๊ด€๋ฆฌ ๋Œ€์‹œ๋ณด๋“œ ํˆด - ์†Œ์Šค์ฝ”๋“œ๊ด€๋ฆฌ ํ•˜๋Š” ์˜คํ”ˆ์†Œ์Šค๊ธฐ๋ฐ˜์˜ ๋ฌด๋ฃŒํˆด - ์ž๋ฐ”๊ฒ€์ฆ๋„๊ตฌ(PMD, findbugs, Checkstyle)๊ฐ€ PlugIn ํ˜•ํƒœ๋กœ ๋“ค์–ด๊ฐ€ ์žˆ์Œ - ์ค‘๋ณต์ฝ”๋“œ(Squid, CPD) ์ฒดํฌ - ์ฝ”๋“œ ์ปค๋ฒ„๋ฆฌ์ง€(Cobertura, jaCoCo)
  • 12. ๏ฝ JDK ํ™˜๊ฒฝ์—์„œ ๋™์ž‘, ์›น์„œ๋ฒ„ ๋ฐ DBMS ํ•„์š” ๏ฝ ๋‹ค์–‘ํ•œ OS๋ฅผ ์ง€์› : Windows, Linux, Mac OS X, Unix ๏ฝ DBMS ํ•„์š” => Derby(๊ธฐ๋ณธ ์ œ๊ณต), MSSQL, MySQL, Oracle ๏ฝ ์›น์„œ๋ฒ„(WAS : Web Application Server) ํ•„์š” => Jetty6, Apache Tomcat ๏ฝ ์ž๋ฐ” ๊ธฐ๋ฐ˜ ํ”„๋กœ๊ทธ๋žจ : JDK 1.5 ์ด์ƒ ํ•„์š”
  • 13. - 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 ์ž‘์„ฑ๋œ ํ”„๋กœ์ ํŠธ์— ์ ํ•ฉ
  • 14. - Sonar๋Š” Checkstyle, PMD, FindBugs, Coberbura ๋“ฑ์˜ ๋ถ„์„ํˆด ๋“ค์„ ์ด์šฉํ•˜์—ฌ ์†Œ์Šค์˜ ์ •์ ๋ถ„์„์„ ์‹ค์‹œํ•˜๊ณ , ์ด ๋ฅผ ์›น๋ธŒ๋ผ์šฐ์ €๋ฅผ ํ†ตํ•˜์—ฌ ์ „์ฒด์ ์ธ ๋ถ„์„๊ฒฐ๊ณผ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ํˆด SonarQube Analysers Eclipse Database Server
  • 15. - Sonar๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋ถ„์„๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Œ - ์ฝ”๋“œ ์ค‘๋ณต ์ฒดํฌ - ์ฝ”๋“œ์˜ ํ‘œ์ค€ - ์ฝ”๋“œ coverage - ์ฝ”๋“œ ๋ณต์žก๋„ - ์ฃผ์„ - ๋””์ž์ธ ๊ณผ ์•„ํ‚คํ…์ณ - ๊ธฐ๋ณธ์ ์œผ๋กœ๋Š” Java ์–ธ์–ด๋ฅผ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ถ”๊ฐ€ ํ”Œ๋Ÿฌ ๊ทธ์ธ์„ ํ†ตํ•˜์—ฌ ๋‹ค๋ฅธ ๋Œ€๋ถ€๋ถ„์˜ ์–ธ์–ด์— ๋Œ€ํ•ด์„œ๋„ ๊ฒ€์‚ฌ ๊ฐ€ ๋Šฅ
  • 16. ๏ฝ JAVA, C/C++๋“ฑ์˜ ๋‹ค์ˆ˜ ํ”„๋กœ๊ทธ๋žจ ์–ธ์–ด ์ง€์› ๏ฝ ํ”Œ๋Ÿฌ๊ทธ์ธ ์„ค์น˜๋กœ ๋‹ค์–‘ํ•œ ๋„๊ตฌ์™€ ์œ ์—ฐํ•œ ํ†ตํ•ฉ ๏ฝ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ถ„์„ ํˆด์„ ํ†ตํ•ฉํ•˜์—ฌ ์—ฌ๋Ÿฌ ํ•ญ๋ชฉ๋“ค์„ ํ•œ๋ฒˆ์— ๊ฒ€ ์‚ฌ ๊ฐ€๋Šฅ(Checkstyle, PMD, FindBugs, CPPCheck, Cobertura ๋“ฑ) ๏ฝ ์›น๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ๋‹ค์–‘ํ•œ ๋ถ„์„ ๊ฒฐ๊ณผ๋“ค์„ ํ™•์ธ ๊ฐ€ ๋Šฅ (๋ฒ„๊ทธ&์ž ์žฌ๋ฒ„๊ทธ์ฒดํฌ, ์ฝ”๋”ฉ ํ‘œ์ค€ ์œ„๋ฐ˜ ์ฒดํฌ, ์ค‘๋ณต ์ฝ”๋“œ ์ฒดํฌ, ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€ ์ฒดํฌ, ์†Œ์Šค ๋ณต์žก๋„ ์ฒดํฌ, ์ฃผ์„ ์ฒ˜๋ฆฌ๋Ÿ‰ ์ฒดํฌ) ๏ฝ ๋ถ„์„์„ ์œ„ํ•œ ์—ฌ๋Ÿฌ ํด๋ผ์ด์–ธํŠธ๋ฅผ ์ œ๊ณต (Sonar runner, Maven, Ant T ask)
  • 17. ๏ฝ ์ •์  ์ฝ”๋“œ ๋ถ„์„ ๋„๊ตฌ ์„ ์ •๋ถ€ํ„ฐ ์ ์šฉ๊นŒ์ง€ ๋ชจ๋“  ํ”„๋กœ ์„ธ์Šค์— ๊ฐœ๋ฐœ์ž ์ฐธ์—ฌ ๏ฝ ์ฝ”๋“œ์— ์•Œ๋งž์€ ๋„๊ตฌ ์„ ํƒ ๏ฝ ์ƒˆ๋กญ๊ฒŒ ์ž‘์„ฑํ•˜๋Š” ์ฝ”๋“œ์— ์ง‘์ค‘ํ•˜๊ธฐ. ์ด๋ฏธ ์ž‘์„ฑ๋œ ์ฝ” ๋“œ์— ๋„ˆ๋ฌด ์‹ ๊ฒฝ์“ฐ์ง€ ๋ง ๊ฒƒ ๏ฝ ๊ฒฐํ•จ ์ฐพ๋Š”๋ฐ ํ˜ˆ์•ˆ ๋˜์ง€ ๋ง๊ณ  ๊ฐœ๋ฐœ ์ƒ์‚ฐ์„ฑ์— ์ง‘์ค‘ ๏ฝ ์ •์ ์ฝ”๋“œ ๋ถ„์„ ๋ฐ ๊ฒฐ๊ณผ์— ๋Œ€ํ•œ ์ด์Šˆ ๊ด€๋ฆฌ๋ฅผ ์ž๋™ํ™”
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27. ๏ฝ https://nemo.sonarqube.org/ ๏ฝ ์ฝ”๋”ฉ ๊ทœ์น™(Rules) โ—ฆ Lanauage : Java โ—ฆ Tag : Security, performance
  • 28. "@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 deprecated foo.doTheThing(); // Noncompliant } }
  • 29. "ConcurrentLinkedQueue.size()" should not be used ConcurrentLinkedQueue.size() ๋ฅผ ์‚ฌ์šฉ์„ ์ž์ œ ํ•ด๋ผ. ํ•ด๋‹น ๋ช…๋ น๋ฌธ์€ Queue์˜ ํฌ๊ธฐ๊ฐ€ ํด ๊ฒฝ์šฐ ์ž‘์—…์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆด ์ˆ˜๊ฐ€ ์žˆ๋‹ค. ๋˜๋Š” Queue๊ฐ€ ์‹คํ–‰ ์ค‘์— ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒฝ์šฐ ๋˜ํ•œ ๊ฒฐ๊ณผ๊ฐ€ ์ •ํ™•ํ•˜์ง€ ์•Š์„ ์ˆ˜๊ฐ€ ์žˆ๋‹ค. ๋‹จ์ง€, ํฌ๊ธฐ๋งŒ์„ ์œ„ํ•ด์„œ ์ฒดํฌํ•ด์•ผ ํ•  ๊ฒฝ์šฐ isEmpty() ๋ฉ”์†Œ๋“œ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue(); //... log.info("Queue contains " + queue.size() + " elements");
  • 30. "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 ... }
  • 31. "HttpServletRequest.getRequestedSessionId()" should not be used - getRequestedSessionId ๋ฉ”์†Œ๋“œ ๋Š”? : ํด๋ผ์ด์–ธํŠธ๋กœ ๋ถ€ํ„ฐ ์ง€์ •๋œ ์„ธ์…˜ID๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ด๋Š” ์š”์ฒญ์— ๋Œ€ํ•œ ํ˜„์žฌ ์œ ํšจํ•œ ์„ธ์…˜ ID ์™€ ๋™์ผํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„ธ์…˜ ID๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ,์ด ๋ฉ”์†Œ๋“œ๋Š” null๋ฅผ ๋Œ๋ ค์ฃผ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์„ธ์…˜ID๊ฐ€ ์–ด๋– ํ•œ HTTP์˜ ์š”์ฒญ์— ์˜ํ•ด ๋ณ€๊ฒฝ์ด ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. if(isActiveSession(request.getRequestedSessionId()) ){ ... }
  • 32. "java.lang.Error" should not be extended Java.lang.Error ํด๋ž˜์Šค์™€ ๊ทธ ์„œ๋ธŒ ํด๋ž˜์Šค ๋“ค์€ ์‹œ์Šคํ…œ์˜ ๋ญ”๊ฐ€ ๋น„์ •์ƒ์ ์ธ ์ƒํ™ฉ์ด ๋ฐœ์ƒ ํ–ˆ์„ ๊ฒฝ์šฐ ์‚ฌ์šฉ๋œ๋‹ค. ๊ทธ๋ž˜์„œ ์ฃผ๋กœ ์ž๋ฐ” VM์—์„œ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๊ฒƒ์ด๊ณ  ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ์—์„œ ์žก์œผ๋ ค๊ณ  ํ•˜๋ฉด ์•ˆ ๋œ๋‹ค. OutofMemoryError๋‚˜ ThreadDeath ๊ฐ™์€ ์—๋Ÿฌ๋Š” catch ๋ธ”๋Ÿญ์œผ๋กœ ์žก์•„๋„ ๋Œ€์‘ ๋ฐฉ๋ฒ•์ด ์—†๋‹ค. ๋”ฐ๋ผ์„œ ์‹œ์Šคํ…œ ๋ ˆ๋ฒจ์—์„œ ํŠน๋ณ„ํ•œ ์ž‘์—…์„ ํ•˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ๋ฉด ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ์ด๋Ÿฐ ์— ๋Ÿฌ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋Š” ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š์•„๋„ ๋œ๋‹ค. public class MyException extends Error { /* ... */ } // Noncompliant public class MyException extends Exception { /* ... */ } // Compliant
  • 33. "main" should not "throw" anything main ๋ฉ”์†Œ๋“œ์—์„œ๋Š” throw ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. Exception์ด ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ ๋˜์งˆ ๊ณณ์ด ์—†๋‹ค. public static void main(String args[]) throws Exception { // Noncompliant public static void main(String args[]) {
  • 34. "NullPointerException" should not be caught NullPointerException ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์„ 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; }
  • 35. "Object.finalize()" should remain protected (versus public) when overriding Object.finalize()๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•  ๋•Œ protected ์ƒํƒœ๋ฅผ ์œ ์ง€ ํ•ด์•ผ ํ•œ๋‹ค. finalize๋Š” Garbage Collector์— ์˜ํ•ด ํ˜ธ์ถœ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์–ด๋””์—์„œ๋‚˜ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” public์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์ž˜๋ชป๋œ ๋ฐฉ๋ฒ• ์ž…๋‹ˆ๋‹ค. ๋ณดํ†ต finalize() ๋ฉ”์†Œ๋“œ๋ฅผ override ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ณ , System.gc() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜์ด ๋ฐœ์ƒ๋˜๋„๋ก ํ•˜์—ฌ ์ •์˜๋œ finalize() ๋ฉ”์†Œ๋“œ๋ฅผ ์ˆ˜ํ–‰์‹œํ‚จ๋‹ค. public class MyClass { @Override public void finalize() { // Noncompliant /* ... */ } }
  • 36. "public static" fields should be constant public 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(); ... }
  • 37. "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(); } }); //...
  • 38. "static final" arrays should be "private" static final ๋ฐฐ์—ด์—” private๋ฅผ ์‚ฌ์šฉํ•ด๋ผ public static final ๋ฐฐ์—ด ํ•„๋“œ๋ฅผ ๋‘๊ฑฐ๋‚˜, ๋ฐฐ์—ด ํ•„๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ ‘๊ทผ์ž๋ฅผ ์ •์˜ ํ•˜๋ฉด ์•ˆ ๋œ๋‹ค. ๊ทธ๋Ÿฐ ๋ฉค๋ฒ„๋ฅผ ๋‘๋ฉด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฐฐ์—ด ๋‚ด์šฉ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋ฏ€๋กœ, ๋ณด์•ˆ์— ๋ฌธ์ œ ๊ฐ€ ์ƒ๊ธด๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ๊ณ ์น˜๋Š” ์ฒซ๋ฒˆ์งธ๋Š” public์œผ๋กœ ์„ ์–ธ๋˜์—ˆ๋˜ ๋ฐฐ์—ด์€ private์œผ๋กœ ๋ฐ” ๊พธ๊ณ  ๋ณ€๊ฒฝ์ด ๋ถˆ๊ฐ€๋Šฅํ•œ public ๋ฆฌ์ŠคํŠธ๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด๋‹ค. public class Estate { // Noncompliant; array contents can be modified public 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 } }
  • 39. ๏ฝ ํด๋ž˜์Šค์™€ ๋ฉค๋ฒ„์˜ ์ ‘๊ทผ ๊ถŒํ•œ์€ ์ตœ์†Œํ™” ํ•˜๋ผ - ๊ฐ ํด๋ž˜์Šค์™€ ๋ฉค๋ฒ„๋Š” ๊ฐ€๋Šฅํ•œ ์ ‘๊ทผ ๋ถˆ๊ฐ€๋Šฅํ•˜๋„๋ก ๋งŒ๋“ค์–ด๋ผ : ์ •๋ณด์€๋‹‰ ๋˜๋Š” ์บก์Šํ™”๋Š” ์‹œ์Šคํ…œ์„ ๊ตฌ์„ฑํ•˜๋Š” ๋ชจ๋“ˆ ์‚ฌ์ด์˜ ์˜์กด์„ฑ์„ ๋‚ฎ์ถฐ์„œ ๊ฐœ๋ฐœ ์†๋„ ๋ฐ ์œ ์ง€๋ณด ์ˆ˜์— ํšจ์œจ์ ์ด๋‹ค. - ๊ฐ์ฒดํ•„๋“œ(instance field)๋Š” ์ ˆ๋Œ€๋กœ public์œผ๋กœ ์„ ์–ธํ•˜๋ฉด ์•ˆ๋œ๋‹ค. : ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ public ํ•„๋“œ๋ฅผ ๊ฐ€์ง„ ํด๋ ˆ์Šค๋Š” ๋‹ค์ค‘ ์Šค๋ ˆ๋“œ์— ์•ˆ์ „ํ•˜์ง€ ์•Š๋‹ค. ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐ ํ•˜๋Š” final ํ•„๋“œ๋ผ ํ•ด๋„ public์œผ๋กœ ์„ ์–ธํ•˜๋ฉด ํด๋ž˜์Šค ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ ํ‘œํ˜„ ํ˜•ํƒœ๋ฅผ ์œ ์—ฐํ•˜๊ฒŒ ๋ฐ”๊ฟ€ ์ˆ˜ ์—†๊ฒŒ ๋œ๋‹ค - static์œผ๋กœ ์„ ์–ธ๋œ ํ•„๋“œ์—๋„ ๋˜‘๊ฐ™์ด ์ ์šฉ๋˜์ง€๋งŒ ํ•œ๊ฐ€์ง€ ์˜ˆ์™ธ๊ฐ€ ์žˆ๋‹ค. ์–ด๋–ค ์ƒ์ˆ˜๋“ค์ด ํด๋ž˜์Šค๋กœ ์ถ”์ƒํ™”๋œ ๊ฒฐ๊ณผ๋ฌผ์˜ ํ•ต์‹ฌ์  ๋ถ€๋ถ„์„ ๊ตฌ์„ฑํ•œ๋‹ค๊ณ  ํŒ๋‹จ๋˜๋Š” ๊ฒฝ์šฐ, ํ•ด๋‹น ์ƒ์ˆ˜๋“ค์„ public static final ํ•„๋“œ๋“ค๋กœ ์„ ์–ธํ•˜์—ฌ ๊ณต๊ฐœํ•  ์ˆ˜ ์žˆ๋‹ค. (public static final ํ•„๋“œ๊ฐ€ ์ฐธ์กฐํ•˜๋Š” ๊ฐ์ฒด๋Š” ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅ ๊ฐ์ฒด๋กœ ๋งŒ๋“ค์–ด๋ผ.) - ๊ธธ์ด๊ฐ€ 0 ์•„๋‹Œ ๋ฐฐ์—ด์€ ์–ธ์ œ๋‚˜ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ, public static final ๋ฐฐ์—ด ํ•„ ๋“œ๋ฅผ ๋‘๊ฑฐ๋‚˜, ๋ฐฐ์—ด ํ•„๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ ‘๊ทผ์ž๋ฅผ ์ •์˜ํ•˜๋ฉด ์•ˆ ๋œ๋‹ค. ๊ทธ๋Ÿฐ ๋ฉค๋ฒ„ ๋ฅผ ๋‘๋ฉด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฐฐ์—ด ๋‚ด์šฉ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋ฏ€๋กœ, ๋ณด์•ˆ์— ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธด๋‹ค.
  • 40. //๋ณด์•ˆ ๋ฌธ์ œ๋ฅผ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ 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(); }
  • 41. "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(); } ... }
  • 42. Checked Exception should not be thrown Checked 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 allowed myMethod1(); }
  • 43. 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; } } }
  • 44. Cookies should be "secure" ์ฟ ํ‚ค๋Š” secure๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. setSecure๋Š” ์ฟ ํ‚ค์˜ ๋ณด์•ˆ ์„ค์ •์œผ๋กœ true๋กœ ์„ค์ •ํ•  ๊ฒฝ์šฐ HTTPS๋‚˜ SSL๊ณผ ๊ฐ™์€ secure protocol ์—์„œ๋งŒ ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๋‹ค. Cookie c = new Cookie(SECRET, secret); // Noncompliant; cookie is not secure response.addCookie(c); Cookie c = new Cookie(SECRET, secret); c.setSecure(true); response.addCookie(c);
  • 45. Credentials should not be hard-coded ์ž๊ฒฉ์ฆ๋ช…์€ ํ•˜๋“œ์ฝ”๋”ฉํ•˜์ง€ ๋ง์•„๋ผ ํ•˜๋“œ์ฝ”๋”ฉ ํ•  ๊ฒฝ์šฐ ์ปดํŒŒ์ผ๋œ ์‘์šฉํ”„๋กœ๊ทธ๋žจ์—์„œ ๋ฌธ์ž์—ด์„ ์ถ”์ถœํ•˜๊ธฐ ์‰ฝ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ž๊ฒฉ์ฆ๋ช…์€ ์•”ํ˜ธํ™”๋œ ์™ธ๋ถ€ ๊ตฌ์„ฑ ํŒŒ์ผ์ด๋‚˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Connection conn = null; try { conn = DriverManager.getConnection("jdbc:mysql://localh ost/test?" +"user=steve&password=blue"); // Noncompliant String uname = "steve"; String password = "blue"; conn = DriverManager.getConnection("jdbc:mysql://localh ost/test?" + "user=" + uname + "&password=" + password); // Noncompliant Connection conn = null; try { String uname = getEncryptedUser(); String password = getEncryptedPass(); conn = DriverManager.getConnection("jdbc:mysql://localh ost/test?" + "user=" + uname + "&password=" + password);
  • 46. Exception classes should be immutable Exception classes๋Š” ๋ถˆ๋ณ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Exception์€ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ƒํƒœ๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. public class MyException extends Exception { private int status; // Noncompliant public 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; // Compliant public MyException(String message, int status) { super(message); this.status = status; } public int getStatus() { return status; } }
  • 47. Exception handlers should preserve the original exception Exception handlers ๋Š” ์›๋ž˜ Excepion์„ ๋ณด์กดํ•œ๋‹ค. ๋ฐœ์ƒ๋œ ์—๋Ÿฌ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ, ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ๋ฅผ ๊ทธ๋Œ€๋กœ ํ˜ธ์ถœํ•œ ์ชฝ์œผ๋กœ ์ „๋‹ฌ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. // Noncompliant - exception is lost try { /* ... */ }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 allowed throw new RuntimeException(e); }
  • 48. Exception types should not be tested using "instanceof" in catch blocks ์˜ˆ์™ธ ์œ ํ˜•์€ catch ๋ธ”๋ก ์•ˆ์—์„œ โ€œinstanceofโ€ ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ…Œ์ŠคํŠธ ํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค. ์ผ๋ฐ˜์˜ˆ์™ธ๋กœ ์บ์น˜ํ•œ ๋‹ค์Œ์— ์œ ํ˜•์— ๋”ฐ๋ผ์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๋Œ€์‹ ์— ์—ฌ๋Ÿฌ ์œ ํ˜•์— ๋งž๋Š” catch ๋ธ” ๋ก์— ์ฒ˜๋ฆฌ ํ•ด์•ผ ํ•œ๋‹ค. try { /* ... */ } catch (Exception e) { if(e instanceof IOException) { /* ... */ } // Noncompliant if(e instanceof NullPointerException{ /* ... */ } // Noncompliant } try { /* ... */ } catch (IOException e) { /* ... */ } // Compliant } catch (NullPointerException e) { /* ... */ } // Compliant
  • 49. 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) { //... } }
  • 50. 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 }
  • 51. Generic exceptions should never be thrown ์ผ๋ฐ˜์ ์ธ ์˜ˆ์™ธ๋Š” ๊ฒฐ์ฝ” thrown ํ•˜๋ฉด ์•ˆ๋œ๋‹ค. public void foo(String bar) throws Throwable { // Noncompliant throw new RuntimeException("My Message"); // Noncompliant } public void foo(String bar) { throw new MyOwnRuntimeException("My Message"); }
  • 52. HTTP referers should not be relied on http referers์— ์˜์กดํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค. Referers๋Š” ๊ณต๊ฒฉ์ž์— ์˜ํ•ด ์ˆ˜์ •์ด ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— referers ๊ฐ’์— ๋Œ€ํ•ด์„œ ์‹ ๋ขฐํ•˜์ง€ ๋ง ์•„๋ผ. public class MyServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String referer = request.getHeader("referer"); // Noncompliant if(isTrustedReferer(referer)){ //.. } //... } }
  • 53. IP addresses should not be hardcoded IP์ฃผ์†Œ๋ฅผ ํ•˜๋“œ์ฝ”๋”ฉ ํ•˜์ง€ ๋ง์•„๋ผ ์†Œ์Šค์ฝ”๋“œ์— 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);
  • 54. Math operands should be cast before assignment ์ˆ˜ํ•™ ์—ฐ์‚ฐ์ž๋Š” ์‚ฌ์šฉํ•˜๊ธฐ ์ „์— ์บ์ŠคํŒ… ํ•ด์•ผ ํ•œ๋‹ค. ์—ฐ์‚ฐ์˜ ๊ฒฝ์šฐ ๊ฒฐ๊ณผ๋Š” ํ•ญ์ƒ int์ผ ๊ฒƒ์ด๋‹ค. float twoThirds = 2/3; // Noncompliant; int division. Yields 0.0 long millisInYear = 1_000*3_600*24*365; // Noncompliant; int multiplication. Yields 1471228928 long bigNum = Integer.MAX_VALUE + 2; // Noncompliant. Yields -2147483647 long 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.6666667 long millisInYear = 1_000L*3_600*24*365; // 1000 promoted to long. Yields 31_536_000_000 long bigNum = Integer.MAX_VALUE + 2L; // 2 promoted to long. Yields 2_147_483_649 long bigNegNum = Integer.MIN_VALUE-1L; // Yields -2_147_483_649 Date myDate = new Date(seconds * 1_000L); ... public long compute(int factor){ return factor * 10_000L; }
  • 55. 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; }
  • 56. Neither DES (Data Encryption Standard) nor DESede (3DES) should be used DES(๋ฐ์ดํ„ฐ ์•”ํ˜ธํ™” ํ‘œ์ค€) ๋„ DESede(3DES) ๋„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. ํ‘œ์ค€ ๋ฐ ๋ฏธ๊ตญ ๊ตญ๋ฆฝ ๊ธฐ์ˆ  ์—ฐ๊ตฌ์†Œ (NIST)์— ๋”ฐ๋ฅด๋ฉด, ๋ฐ์ดํ„ฐ ์•”ํ˜ธํ™” ํ‘œ์ค€ (DES)๋Š” ๋” ์ด์ƒ ์•ˆ์ „ํ•œ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค Cipher c = Cipher.getInstance("DESede/ECB/PKCS5Padding"); Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
  • 57. Null pointers should not be dereferenced ๋„ํฌ์ธํ„ฐ๋Š” ์—ญ์ฐธ์กฐํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ๊ทธ ๊ฐ์ฒด๊ฐ€ NULL์ด ๋  ์ˆ˜ ์—†๋‹คโ€™๋ผ๊ณ  ํ•˜๋Š” ๊ฐ€์ •์„ ์œ„๋ฐ˜ํ–ˆ์„ ๋•Œ ๋ฐœ์ƒํ•œ๋‹ค. @CheckForNull String 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{} block conn.close(); // Noncompliant; conn could be null if an exception was thrown }
  • 58. Only standard cryptographic algorithms should be used ๋‹จ์ง€ ํ‘œ์ค€ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. ์ค‘์š”ํ•œ ๋ฏผ๊ฐํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋””์Šคํฌ์— ์ €์žฅํ•˜๊ฑฐ๋‚˜ ์™ธ๋ถ€ ์ „์†ก ์‹œ, SW๊ฐ€ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ์•”ํ˜ธ ํ™”ํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ ๋ฏผ๊ฐํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋…ธ์ถœ๋  ์ˆ˜ ์žˆ๋‹ค. ํ‘œ์ค€์•Œ๊ณ ๋ฆฌ์ฆ˜ : SHA-256, SHA-384, SHA-512 MyCryptographicAlgorithm extends MessageDigest { ... }
  • 59. Public methods should throw at most one checked exception Public method ์—์„œ๋Š” ๋Œ€๋ถ€๋ถ„ ํ•˜๋‚˜์˜ exception์„ ์ฒดํฌํ•˜์—ฌ throw ํ•œ๋‹ค. public void delete() throws IOException, SQLException { // Noncompliant /* ... */ } public void delete() throws SomeApplicationLevelException { /* ... */ }
  • 60. 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(); }
  • 61. Throwable and Error should not be caught Throw ๊ฐ€๋Šฅ ๊ฐ์ฒด ์™€ Error๋Š” catch์— ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค. Throw ๊ฐ€๋Šฅ ๊ฐ์ฒด๋Š” ์ž๋ฐ”์˜ ๋ชจ๋“  ์—๋Ÿฌ์™€ ์˜ˆ์™ธ์˜ ์Šˆํผํด๋ž˜์Šค ์ž…๋‹ˆ๋‹ค. Error๋Š” ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์— ์˜ํ•ด ๋ฐœ์ƒ๋˜๋Š” ์˜๋ฏธํ•˜์ง€ ์•Š๋Š” ๋ชจ๋“  ์—๋Ÿฌ์˜ ์Šˆํผํด๋ž˜์Šค ์ž…๋‹ˆ๋‹ค. try { /* ... */ } catch (Throwable t) { /* ... */ } try { /* ... */ } catch (Error e) { /* ... */ } try { /* ... */ } catch (RuntimeException e) { /* ... */ } try { /* ... */ } catch (MyException e) { /* ... */ }
  • 62. Throwable.printStackTrace(...) should not be called Throwable.printStackTrace์„ ํ˜ธ์ถœํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. Throw ๊ฐ€๋Šฅ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹ ์— Loggers๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋Š” ์‰ฝ๊ฒŒ logs๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. try { /* ... */ } catch(Exception e) { e.printStackTrace(); // Noncompliant } try { /* ... */ } catch(Exception e) { LOGGER.log("context", e); // Compliant }
  • 63. Untrusted data should not be stored in sessions ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋Š” ๋ฐ์ดํ„ฐ๋Š” ์„ธ์…˜์— ์ €์žฅํ•˜์ง€ ๋ง์•„์•ผ ํ•œ๋‹ค. ์›น ์„ธ์…˜์—์„œ ๋ฐ์ดํ„ฐ๋Š” โ€œ์‹ ๋ขฐ ๋ฒ”์œ„โ€์—์„œ ๋‚ด๋ถ€๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ธ์ฆ๋˜์ง€ ์•Š๋Š” ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ์ž…๋ ฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š”๊ฒƒ์€ ์‹ ๋ขฐ์˜ ๋ฒ”์œ„๋ฅผ ๋ฒ— ์–ด๋‚˜๋Š” ์ผ์ž…๋‹ˆ๋‹ค. ๊ทธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ€์ ์ ˆํ•˜๊ฒŒ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. login = request.getParameter("login"); session.setAttribute("login", login); // Noncompliant
  • 64. 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) { ... } // Noncompliant doSomething(); ...
  • 65. Values passed to OS commands should be sanitized OS ๋ช…๋ น์–ด๋กœ ์ „๋‹ฌ๋œ ๊ฐ’์€ ์ œ๊ฑฐ ๋˜์–ด์•ผ ํ•œ๋‹ค. 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 ... }
  • 66. 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) { // Noncompliant updatePrices(req); } }
  • 67. 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>
  • 68. "ConcurrentLinkedQueue.size()" should not be used ConcurrentLinkedQueue.size()๋Š” ์‚ฌ์šฉํ•˜์ง€ ๋ง์•„๋ผ. ํ์˜ ํฌ๊ธฐ๋ฅผ ํ™•์ธํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋Š” ์ผ์ •ํ•œ ์‹œ๊ฐ„์ด ํ•„์š”๋กœ ํ•˜๋Š”๋ฐ, ํ์˜ ํฌ๊ธฐ๊ฐ€ ํด์ˆ˜๋ก ์‹œ ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆด ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ๊ฐ€ ์‹คํ–‰ ์ค‘ ๋ณ€๊ฒฝ์ด ๋˜๋Š” ๊ฒฝ์šฐ ๊ฒฐ๊ณผ๊ฐ€ ์ •ํ™•ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ, size()๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๊ฒฝ์šฐ์—๋Š” ํ๊ฐ€ ๋น„์–ด ์žˆ๋Š”์ง€ ํ™•์ธ ํ•˜๊ธฐ ์œ„ํ•œ isEmpty()๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue(); //... log.info("Queue contains " + queue.size() + " elements");
  • 69. "DateUtils.truncate" from Apache Commons Lang library should not be used Apache 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); }
  • 70. "deleteOnExit" should not be used โ€œdeleteOnExitโ€๋Š” ์‚ฌ์šฉํ•˜์ง€ ๋ง์•„๋ผ. File.deleteOnExit()์˜ ์‚ฌ์šฉ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด์œ ๋กœ ๊ถŒ์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. - ์‚ญ์ œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ JVM ์ข…๋ฃŒ์˜ ๊ฒฝ์šฐ์— ๋ฐœ์ƒํ•˜์ง€๋งŒ, JVM์ด ์ถฉ๋Œ ๋˜๋Š” ์ฃฝ์—ˆ์„ ๊ฒฝ์šฐ์— ์‚ญ์ œ๋˜์ง€ ์•Š๋Š”๋‹ค. - ํŒŒ์ผ ์‚ญ์ œ๊ฐ€ ์„ฑ๊ณตํ–ˆ์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  JVM์ด ์ข…๋ฃŒ ํ•  ๋•Œ๊นŒ์ง€ ํŒŒ์ผ์ •๋ณด๋ฅผ ๋ณด๊ด€๋˜๋ฉด์„œ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ฆ๊ฐ€ File file = new File("file.txt"); file.deleteOnExit(); // Noncompliant
  • 71. "entrySet()" should be iterated when both the key and value are needed key์™€ 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 retrieved Object 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(); // ... } }
  • 72. "ResultSet.isLast()" should not be used ResultSet.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 }
  • 73. "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"); // Compliant if (homepage.equals(url)) { // Noncompliant // ... } } public void checkUrl(URL url) { Set<URI> sites = new HashSet<URI>(); // Compliant URI homepage = new URI("http://sonarsource.com"); // Compliant URI uri = url.toURI(); if (homepage.equals(uri)) { // Compliant // ... } }
  • 74. "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(); } ... }
  • 75. 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); } }
  • 76. Objects should not be created only to "getClass" Object๋ฅผ ๋‹จ์ง€ getClass๋กœ ์ƒ์„ฑํ•˜์ง€ ๋ง์•„๋ผ getClass์˜ ํ˜ธ์ถœ์˜ ๋ชฉ์ ์€ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ธ๋ฐ, ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ฒŒ ๋˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„ ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฏ€๋กœ ๋‹จ์ˆœํžˆ class๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. MyObject myOb = new MyObject(); // Noncompliant Class c = myOb.getClass(); Class c = MyObject.class;
  • 77. 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); } }
  • 78. String function use should be optimized for single characters String 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'); // ...
  • 79. 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();
  • 80. 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();