±à¼ÍƼö: |
±¾ÎÄÀ´×ÔÓÚibm£¬ÎÄÖÐÍÆ³çµÄ¾ÍÊÇЧÂÊ£¬ÈçºÎ¼õÉÙºÄʱ¹ý³ÌµÄÈßÓà¶È£¬¸ü¿ìËÙµØÖ´ÐÐËüÃÇ£¬²¢ÇÒ½«ÂÛÊöÔõÑù¸ü
ÓÐЧµØÖ´ÐÐËüÃÇ¡£ |
|
ÔÚ¹ýÈ¥µÄ¼¸ÄêÀÎÒÔø¿´¹ýºÜ¶àÏîÄ¿µÄ´óÁ¿Ô´´úÂ룬´Ó¾«ÃÀµÄÉè¼Æµ½ÏñÊÇÓýº´ø°ó¶¨µ½Ò»ÆðµÄ´úÂë¡£ÎÒд¹ýеĴúÂëҲά»¤¹ýÆäËû¿ª·¢ÈËÔ±µÄÔ´´úÂë¡£ÎÒϲ»¶±àдеĴúÂ룬µ«Ò²Ï²»¶²ÉÓÃһЩÏÖÓеĴúÂ룬ÒÔijÖÖ·½·¨½«Æä¼ò»¯»ò½«Öظ´µÄ´úÂëÌáÈ¡µ½Ò»¸ö¹«¹²ÀàÖС£ÔÚÎÒÔçÆÚµÄ¹¤×÷ÉúÑÄÖУ¬Ðí¶àÈ˶¼ÈÏΪÈç¹û²»±àдеĴúÂë¾Í²»»áÓкõÄЧÂÊ¡£ÐҺã¬ÔÚ
20 ÊÀ¼Í 90 Äê´úÄ©£¬Martin Fowler ±àдÁË RefactoringÒ»Ê飨²Î¼û ²Î¿¼×ÊÁÏ£©£¬ËüʹµÃÔÚ²»¸Ä±äÍⲿÐÐΪµÄǰÌáϸĽøÏÖÓдúÂë³ÉΪ¿ÉÄÜ¡£
¹ØÓÚ±¾ÏµÁÐ
×÷Ϊ¿ª·¢ÈËÔ±£¬ÎÒÃÇÖÂÁ¦ÓÚΪÓû§×Ô¶¯»¯Á÷³Ì£»µ«Ðí¶à¿ª·¢ÈËÔ±ÊèºöÁË×Ô¶¯»¯ÎÒÃÇ×Ô¼ºµÄ¿ª·¢Á÷³ÌµÄ»ú»á¡£Îª´Ë£¬ÎÒÃDZàдÁË
Èÿª·¢×Ô¶¯»¯ÏµÁÐÎÄÕ£¬×¨ÃÅ̽ÌÖÈí¼þ¿ª·¢Á÷³Ì×Ô¶¯»¯µÄʵ¼ùÓ¦Óã¬ÎªÄú½éÉÜ ºÎʱÒÔ¼° ÈçºÎ³É¹¦Ó¦ÓÃ×Ô¶¯»¯¡£
ÖØ¹¹µÄÒ»¸öµäÐÍ·½·¨ÊÇÔÚÒýÈëдúÂë»ò¸ü¸Ä·½·¨Ê±¶ÔÏÖÓдúÂë×ö³öССµÄ±ä¶¯¡£¸Ã¼¼ÇÉÃæÁÙµÄÌôÕ½ÔÚÓÚÒ»¸ö¿ª·¢ÍŶӵĿª·¢ÈËÔ±µÄÓ¦Ó÷½·¨²»Ò»Ö£¬²¢ÇÒºÜÈÝÒ×´íÊ§ÖØ¹¹µÄ»ú»á¡£ÕâÒ²ÕýÊÇÎÒÌᳫʹÓþ²Ì¬·ÖÎö¹¤¾ßʶ±ð±àÂëÎ¥¹æµÄÔÒòËùÔÚ¡£ÓÐÁËÕâЩ¹¤¾ß£¬Äú¾ÍÄܹ»´Ó×ÜÌåÉÏÁ˽â´úÂë¿â£¬²¢ÇÒ´¦ÓÚÀà»ò·½·¨µÄ¼¶±ð¡£ÐÒÔ˵ÄÊÇ£¬ÔÚ
Java?³ÌÐòÉè¼ÆÖУ¬Äú¿ÉÒÔÑ¡ÔñµÄ¿ÉÃâ·ÑÏÂÔØµÄ¿ªÔ´¾²Ì¬·ÖÎö¹¤¾ßºÜ¶à£ºCheckStyle¡¢PMD¡¢FindBugs¡¢JavaNCSS¡¢JDepend
µÈµÈ¡£
ÔÚ±¾ÎÄÖУ¬Äú½«Ñ§Ï°ÈçºÎ£º
ʹÓà CheckStyle ¶ÈÁ¿ Ȧ¸´ÔÓ¶È£¨cyclomatic complexity£©£¬²¢ÌṩÖîÈç
Replace Conditional with PolymorphismÖ®ÀàµÄÖØ¹¹£¬ÒÔ´ËÀ´¼õÉÙ Ìõ¼þ¸´ÔÓ¶È´úÂëζµÀ
ʹÓà CheckStyle ÆÀ¹À ´úÂëÖØ¸´ÂÊ£¬²¢ÌṩÖîÈç Pull Up MethodÖ®ÀàµÄÖØ¹¹£¬ÒÔ´ËÀ´ÒƳý
ÖØ¸´´úÂë
ʹÓà PMD£¨»ò JavaNCSS£©¼ÆËã Ô´´úÂëÐУ¬²¢ÌṩÖîÈç Extract MethodÖ®ÀàµÄÖØ¹¹£¬ÒÔ´ËÀ´µ»¯
´óÀà´úÂëζµÀ
ʹÓà CheckStyle£¨»ò JDepend£©È·¶¨Ò»¸öÀàµÄ ´«³öñîºÏ¶È£¨efferent coupling£©£¬²¢ÌṩÖîÈç
Move MethodÖ®ÀàµÄÖØ¹¹£¬ÒÔ´ËÀ´³ýµô ¹ý¶àµÄµ¼Èë´úÂëζµÀ
ÎÒ½«Ê¹ÓÃÈçϵÄͨÓøñʽÀ´¼ì²éÿһÖÖ´úÂëζµÀ£º
ÃèÊö¿ÉÒÔָʾ³ö´úÂëÀïÃæµÄÎÊÌâµÄζµÀ
¶¨Òå¿ÉÒÔÕÒµ½¸ÃζµÀµÄ¶ÈÁ¿·½·¨
չʾ¿ÉÒÔ¶ÈÁ¿´úÂëζµÀµÄ¹¤¾ß
ÌṩÓÃÓÚÐÞ¸´´úÂëζµÀµÄÖØ¹¹ºÍģʽ£¨ÔÚijЩÇé¿öÏ£©
ʵÖÊÉÏ£¬Õâ¸ö·½·¨ÌṩÁËÒ»¸öÕÒµ½ºÍÐÞ¸´Õû¸ö´úÂë¿âÖеĴúÂëζµÀµÄÒ»¸ö¿ò¼Ü¡£ÕâÑùÄú¾Í¿ÉÒÔ¸üºÃµØÁ˽⵽´úÂë¿âÖнÏΣÏյIJ¿·Ö£¬È»ºóÔÙ×ö³ö¸ü¸Ä¡£¸üºÃµÄÊÇ£¬ÎÒ»¹»áÏòÄúչʾÈçºÎ½«Õâ¸ö·½·¨¼¯³Éµ½×Ô¶¯¹¹½¨ÖС£
ÄúµÄ´úÂëÓРô£¿
Ëùν´úÂëζµÀÆäʵֻÊÇÒ»ÖÖ Ìáʾ£¬ÌáʾһЩÄÚÈÝ¿ÉÄÜ´æÔÚ´íÎ󡣺ÍģʽÀàËÆ£¬´úÂëζµÀÌṩÁËÒ»¸öͨÓôʻã±í£¬Äú¿ÉÒÔÓÃËüÀ´¿ìËÙʶ±ðÕâЩÀàÐ͵ÄDZÔÚÎÊÌâ¡£ÔÚÎÄÕÂÖÐ
ÕæÊµµØÊ¾·¶´úÂëζµÀÊǺÜÓÐÄѶȵģ¬ÒòΪËü¿ÉÄܰüÀ¨ºÜ¶àÐдúÂ룬ÕâÑù¾Í¹ý·ÖµØ¼Ó´óÁËÎÄÕÂµÄÆª·ù¡£Òò´Ë£¬ÎÒ»áÖ»Õë¶ÔÆäÖеÄһЩζµÀ½øÐÐʾ·¶£¬È»ºóÄú¾Í¿ÉÒÔ¸ù¾Ý²é¿´Ìض¨´úÂëζµÀµÄ¾Ñé½øÐÐÍÆ¶Ï£¬Ê¶±ð³öÊ£ÓàµÄ´úÂëζµÀ¡£
Ìõ¼þ¸´ÔÓ¶È
ζµÀ£ºÌõ¼þ¸´ÔÓ¶È
¶ÈÁ¿£ºÈ¦¸´ÔÓ¶È
¹¤¾ß£ºCheckStyle¡¢JavaNCSS ÒÔ¼° PMD
ÖØ¹¹£ºReplace Conditional with Polymorphism¡¢Extract Method
ζµÀ
Ìõ¼þ¸´ÔÓ¶È¿ÉÒÔÒÔ¼¸ÖÖ²»Í¬µÄ·½Ê½³öÏÖÔÚÔ´´úÂëÖС£ÕâÖÖ´úÂëζµÀµÄÒ»¸öÀý×Ó¾ÍÊǺ¬Óжà¸öÌõ¼þÓï¾ä£¬Èç if¡¢while»òÕß
forÓï¾ä¡£ÁíÒ»ÖÖÌõ¼þ¸´ÔÓ¶ÈÊÇÒÔ switchÓï¾äµÄÐÎʽ³ÊÏÖ³öÀ´µÄ£¬ÈçÇåµ¥ 1 Ëùʾ£º
Çåµ¥ 1. ʹÓà switchÓï¾äÀ´Ö´ÐÐÌõ¼þÐÐΪ
...
switch
(beerType) {
case
LAGER:
System.out.println("Ingredients
are...");
...
break;
case
BROWNALE:
System.out.println("Ingredients
are...");
...
break;
case
PORTER
System.out.println("Ingredients
are...");
...
break;
case
STOUT:
System.out.println("Ingredients
are...");
...
break;
case
PALELAGER:
System.out.println("Ingredients
are...");
...
break;
...
default:
System.out.println("INVALID.");
...
break;
}
... |
switchÓï¾ä±¾Éí²¢Ã»Óв»Íס£µ«µ±Ò»¸öÓï¾ä°üº¬Ì«¶àµÄÑ¡ÔñºÍ´úÂëʱ£¬Ëü¾Í¿ÉÄܰµÊ¾ÓÐÐèÒªÖØ¹¹µÄ´úÂë¡£
¶ÈÁ¿
Ҫȷ¶¨Ìõ¼þ¸´ÔÓ¶È´úÂëζµÀ£¬ÐèҪȷ¶¨·½·¨µÄ Ȧ¸´ÔÓ¶È¡£È¦¸´ÔÓ¶ÈÊÇÒ»ÖÖ¶ÈÁ¿·½·¨£¬ÓÉ Thomas McCabe
ÓÚ 1975 Ä궨Ò塣Ȧ¸´ÔÓ¶ÈÊý£¨Cyclomatic Complexity Number£¬CCN£©¶ÈÁ¿Ò»¸ö·½·¨ÖÐijһ·¾¶µÄÊýÁ¿¡£ÎÞÂÛÒ»¸ö·½·¨ÖÐÓжàÉÙÌõ·¾¶£¬ËüµÄÆðʼ
CNN ¶¼´Ó 1 ¿ªÊ¼¡£Ã¿Ò»¸öÌõ¼þ¹¹Ô죬Èç if¡¢switch¡¢whileºÍ forÓï¾ä£¬¶¼±»·ÖÅäÒ»¸ö
1 ÖµºÍÒ쳣·¾¶¡£Ò»¸ö·½·¨µÄ×ÜµÄ CCN ±íÃ÷ÁËËüµÄ¸´ÔÓ¶È¡£ºÜ¶àÈËÈÏΪµ± CCN Ϊ 10 »ò³¬¹ý
10 ʱ£¬¾Í±íÃ÷¸Ã·½·¨¹ýÓÚ¸´ÔÓ¡£
¹¤¾ß
CheckStyle¡¢JavaNCSS¡¢ÒÔ¼° PMD ¶¼ÊǶÈÁ¿È¦¸´ÔӶȵĿªÔ´¹¤¾ß¡£Çåµ¥ 2 չʾÁËÓÃ
XML ¶¨ÒåµÄ CheckStyle ¹æÔòÎļþµÄÒ»¸ö´úÂëÆ¬¶Ï¡£CyclomaticComplexityÄ£¿é¶¨ÒåÁËÒ»¸ö·½·¨µÄ
CCN µÄ×î´óÏÞ¶È¡£
Çåµ¥ 2. ÅäÖà CheckStyle£¬²éÕÒȦ¸´ÔÓ¶ÈΪ 10 »ò´óÓÚ 10 µÄ·½·¨
<module
name="CyclomaticComplexity">
<property
name="max"
value="10"/>
</module> |
ÓÃÇåµ¥ 2 µÄ CheckStyle ¹æÔòÎļþ¡¢Çåµ¥ 3 µÄ Gant Àý×ÓÀ´Ê¾·¶ÈçºÎ½« CheckStyle
×÷Ϊһ¸ö×Ô¶¯¹¹½¨µÄÒ»²¿·ÖÀ´ÔËÐС££¨²Î¼û ʲôÊÇ Gant £¿²à±ßÀ¸£©£º
Çåµ¥ 3. ʹÓà Gant ½Å±¾À´Ö´ÐÐ CheckStyle ¼ì²é
target(findHighCcn:"Finds
method with a high cyclomatic complexity number"){
Ant.mkdir(dir:"target/reports")
Ant.taskdef(name:"checkstyle",
classname:"com.puppycrawl.tools.checkstyle.CheckStyleTask",
classpathref:"build.classpath")
Ant.checkstyle(shortFilenames:"true",
config:"config/checkstyle/cs_checks.xml",
failOnViolation:"false",
failureProperty:"checks.failed", classpathref:"libdir")
{
formatter(type:"xml",
tofile:"target/reports/checkstyle_report.xml")
formatter(type:"html",
tofile:"target/reports/checkstyle_report.html")
fileset(dir:"src"){
include(name:"**/*.java")
}
}
} |
ʲôÊÇ Gant £¿
Gant ÊÇÒ»¸ö×Ô¶¯¹¹½¨¹¤¾ß£¬ËüÌṩÁËÒ»¸öÖ§³Ö¹¹½¨ÒÀÀµ¹ØÏµµÄ±í´ïÄÜÁ¦Ç¿µÄ±à³ÌÓïÑÔ¡£¿ª·¢ÈËÔ±ÀûÓà Groovy
±à³ÌÓïÑÔµÄÇ¿´ó¹¦Äܱàд Gant ½Å±¾¡£ÓÉÓÚ Gant Ìṩ¶Ô Ant µÄ API µÄÍêÈ«·ÃÎÊ£¬ËùÒÔÈκοÉÒÔÔËÐÐÓÚ
Ant µÄ¶«Î÷¶¼¿ÉÒÔ´Ó Gant ½Å±¾ÔËÐС££¨²Î¼û ¡°Óà Gant ¹¹½¨Èí¼þ¡± ½Ì³Ì£¬Á˽â Gant¡££©
Çåµ¥ 3 ÖÐµÄ Gant ½Å±¾´´½¨ÁËͼ 1 ÖÐչʾµÄ CheckStyle ±¨¸æ¡£¸ÃͼÏÂÃæµÄ²¿·Öָʾ³öÁËÒ»¸ö·½·¨µÄ
CheckStyle Ȧ¸´ÔÓ¶ÈÎ¥¹æ¡£
ͼ 1. CheckStyle ±¨¸æ¸ù¾Ý¹ý¸ßµÄ CCN À´Ö¸Ê¾Ò»ÖÖ·½·¨Ê§°Ü

ÖØ¹¹
ͼ 2 ΪÓà UML ±íʾµÄ Replace Conditional with PolymorphismÖØ¹¹£º
ͼ 2. ÓöàÌ¬Ìæ´úÌõ¼þÓï¾ä

ÔÚͼ 2 ÖУ¬ÎÒ£º
´´½¨ÁËÒ»¸ö½Ð×ö BeerTypeµÄ Java ½çÃæ
¶¨ÒåÁËÒ»¸öͨÓÃµÄ showIngredients()·½·¨
Ϊÿһ¸ö BeerType´´½¨ÁËÒ»¸öʵÏÖÀà
ΪÁËʹÎÄÕ±£³Ö¼ò½à£¬ÎÒ½öΪÿһ¸öÀàÌṩһ¸ö·½·¨µÄʵÏÖ¡£ÏÔÈ»£¬´´½¨Ò»¸ö½çÃæµÄ·½·¨¿ÉÄܲ»Ö»Ò»¸ö¡£Öع¹Äܹ»Ê¹´úÂë¸üÒ×ÓÚά»¤£¬Èç
Replace Conditional with Polymorphism ºÍ Extract Method£¨±¾ÎÄÉԺ󽫻áÌÖÂÛ£©¡£
ÖØ¸´´úÂë
ζµÀ£ºÖظ´´úÂë
¶ÈÁ¿£º´úÂëÖØ¸´ÂÊ
¹¤¾ß£ºCheckStyle¡¢PMD
ÖØ¹¹£ºExtract Method¡¢Pull Up Method¡¢Form Template Method¡¢Substitute
Algorithm
ζµÀ
ÖØ¸´´úÂë¿ÉÄÜÔÚ´úÂë¿âÖÐÇÄÈ»·¢Éú¡£ÓÐʱ£¬¸´ÖÆÕ³ÌùijЩ´úÂëÒª±È½«¸ÃÐÐΪ·º»¯µ½ÁíÒ»¸öÀà¸ü¼òµ¥¡£µ«¸´ÖÆÕ³ÌùµÄ·½·¨´æÔÚÒ»¸öÎÊÌ⣬¼´ËüÇ¿ÖÆ½«´úÂë¸´ÖÆ¶à·Ý£¬²¢ÇÒÐèҪά»¤¡£¶øÇÒµ±¸´ÖƳöµÄ´úÂë·¢ÉúÇá΢µÄ±ä»¯¶øÒý·¢ÐÐΪ²»Ò»ÖÂʱ£¬¾Í»á·¢Éú¸ü²»Òײì¾õµÄÎÊÌ⣬¾ßÌåÈ¡¾öÓÚÄĸö·½·¨ÔÚÖ´ÐиÃÐÐΪ¡£Çåµ¥
4 ÊÇÒ»¸ö¹Ø±Õ´úÂë¿âÁ¬½ÓµÄ´úÂëʾÀý£¬ÏàͬµÄ´úÂë³öÏÖÔÚÁ½ÖÖ·½·¨ÖУº
Çåµ¥ 4. ÖØ¸´´úÂë
public
Collection findAllStates(String sql) {
...
try
{
if
(resultSet != null) {
resultSet.close();
}
if
(stmt != null) {
stmt.close();
}
if
(conn != null) {
conn.close();
}
catch
(SQLException se) {
throw
new RuntimeException(se);
}
}
...
}
...
public
int create(String sql, Beer beer) {
...
try
{
if
(resultSet != null) {
resultSet.close();
}
if
(stmt != null) {
stmt.close();
}
if
(conn != null) {
conn.close();
}
catch
(SQLException se) {
throw
new RuntimeException(se);
}
}
...
} |
ÎÒÓÐÐÔÄܸüºÃµÄ IDE
ËäÈ»ÔÚ±¾ÎĵÄÀý×ÓÖÐÎÒʹÓà Gant À´ÔËÐвéÕÒÌØ¶¨Î¶µÀµÄ¹¤¾ß£¬µ«ÊÇʹÓà IDE ҲͬÑù¿ÉÒÔ½â¾öÕâЩÎÊÌâ¡£Eclipse
IDE ¾ÍÓкܶྲ̬·ÖÎö¹¤¾ßµÄ²å¼þ¡£µ«ÎÒÈÔÈ»ÍÆ¼öʹÓÃ×Ô¶¯¹¹½¨¹¤¾ß£¬ÒòΪÕâÑù¿ÉÒÔÔÚÆäËû»·¾³ÖÐÔËÐм¯³É¹¹½¨£¬ÎÞÐèʹÓÃ
IDE¡£
¶ÈÁ¿
²éÕÒÖØ¸´´úÂëµÄ¶ÈÁ¿·½·¨ÊÇÔÚ´úÂë¿âÖеÄÀàµÄÄÚ²¿ºÍÆäËûÀàÖ®¼äËÑË÷´úÂëÖØ¸´¡£Ã»Óй¤¾ßµÄ»°£¬Àà¼äµÄÖØ¸´¾Í¸üÄÑÆÀ¹À¡£ÓÉÓÚ¸´ÖƵĴúÂëͨ³£¶¼»á·¢ÉúһЩÇá΢µÄ±ä»¯£¬Òò´Ë²»½öÒª¶ÈÁ¿ÍêÈ«ÏàͬµÄ´úÂ룬¶øÇÒÒª¶ÈÁ¿
ÏàËÆµÄ´úÂ룬Á½Õß¶¼ºÜÖØÒª¡£
¹¤¾ß
PMD µÄ Copy/Paste Detector£¨CPD£©Óë CheckStyle ÕâÁ½ÖÖ¿ªÔ´¹¤¾ß¿ÉÒÔÓÃÓÚÔÚÕû¸ö
Java ´úÂë¿âÖвéÕÒÏàËÆµÄ´úÂë¡£Çåµ¥ 5 ÖÐµÄ CheckStyle ÅäÖÃÎļþÀý×Óʾ·¶ÁËÈçºÎʹÓÃ
StrictDuplicateCodeÄ£¿é£º
Çåµ¥ 5. ʹÓà CheckStyle ÕÒµ½ÖÁÉÙ 10 ÐÐÖØ¸´´úÂë
<module
name="StrictDuplicateCode">
<property
name="min"
value="10"/>
</module> |
Çåµ¥ 5 ÖÐµÄ minÊôÐÔÉèÖÃÁË CheckStyle ½«»á±ê¼Ç³öµÄ×îÐ¡ÖØ¸´ÐÐÊý£¬ÒÔ¹©²éÔÄ¡£ÔÚÕâÑùµÄÇé¿öÏ£¬Ëü½«Ö»Ö¸Ê¾³öÄÇЩÖÁÉÙÓÐ
10 ÐÐÀàËÆ»òÖØ¸´µÄ´úÂë¿é¡£
ͼ 3 չʾÁË×Ô¶¯¹¹½¨ÔËÐкó£¬Çåµ¥ 5 ÖеÄÄ£¿éÉèÖõĽá¹û£º
ͼ 3. CheckStyle ±¨¸æÖ¸Ê¾´úÂëÖØ¸´¶È¹ý¸ß
CheckStyle ±¨¸æÖ¸Ê¾´úÂëÖØ¸´¶È¹ý¸ß
ÖØ¹¹
ÔÚÇåµ¥ 6 ÖУ¬ÎÒÓÃÁË Çåµ¥ 4ÖеÄÖØ¸´´úÂ룬ʹÓÃÁË Pull Up MethodÖØ¹¹À´½µµÍÖØ¸´¶È
¡ª½«ÐÐΪ´Ó½Ï´ó·½·¨ÌáÈ¡µ½Ò»¸ö³éÏóÀà·½·¨ÖУº
Çåµ¥ 6. Pull Up Method
...
}
finally {
closeDbConnection(rs,
stmt, conn);
}
... |
²»ÒªÍü¼Ç±àд²âÊÔ³ÌÐò
ÈκÎʱºò¸Ä±äÏÖÓдúÂ룬Äú¶¼ÐèÒªÓÃÖîÈç JUnit ÕâÑùµÄ¿ò¼Ü±àдÏàÓ¦µÄ×Ô¶¯²âÊÔ³ÌÐò¡£ÐÞ¸ÄÏÖÓдúÂëÊÇ´æÔÚ·çÏյģ»¶ø½«Õâ¸ö·çÏÕ½µµ½×îµÍµÄÒ»ÖÖ·½·¨¾ÍÊÇͨ¹ý²âÊÔÀ´ÑéÖ¤¸ÃÐÐΪÔÚÏÖÔںͽ«À´¶¼ÓÐЧ¡£
ÖØ¸´´úÂëÊÇÄÑÒÔ±ÜÃâµÄ¡£ÎÒÓÀÔ¶²»»á½¨ÒéÒ»¸öÍŶÓȥŬÁ¦ÊµÏÖʲô ÎÞÖØ¸´Ö®ÀàµÄÄ¿±ê£¬ÕâÊDz»ÇÐʵ¼ÊµÄ¡£È»¶ø£¬È·±£´úÂë¿âÖеÄÖØ¸´´úÂë²»»áÔö¶àÕâÑùµÄÄ¿±êÊÇ¿ÉÒÔʵÏֵġ£Ê¹ÓÃÖîÈç
PMD µÄ CPD »ò CheckStyle ÕâÑùµÄ¾²Ì¬·ÖÎö¹¤¾ß£¬ÄúÄܹ»½«Õû¸ö·ÖÎö¹ý³Ì×÷Ϊ×Ô¶¯¹¹½¨µÄÒ»²¿·Ö£¬³ÖÐø·ÖÎö£¬È·¶¨´úÂëÖØ¸´¶È¸ßµÄÇøÓò¡£
³¤·½·¨£¨´óÀࣩ
ζµÀ£º³¤·½·¨£¨´óÀࣩ
¶ÈÁ¿£ºÔ´´úÂëÐÐÊý£¨SLOC£©
¹¤¾ß£ºPMD¡¢JavaNCSS¡¢CheckStyle
ÖØ¹¹: Extract Method¡¢Replace Temp with Query¡¢Introduce
Parameter Object¡¢Preserve Whole Object¡¢Replace Method
with Method Object
ζµÀ
ÎÒÒ»Ö±ÔÚ³¢ÊÔ¼á³ÖµÄÒ»Ìõ¾Ñé·¨ÔòÊǽ«·½·¨ÏÞÖÆÔÚ 20 Ðлò 20 ÐÐÒÔÄÚ¡£µ±È»£¬Õâ¸öÔÔòÒ²¿ÉÄÜ»áÓÐÀýÍ⣬µ«Èç¹ûÎҵķ½·¨³¬¹ý
20 Ðеϰ£¬ÎҾͻá¸ü×ÐϸµØÈ¥Á˽âËü¡£Í¨³£Çé¿öÏ£¬³¤·½·¨ºÍÌõ¼þ¸´ÔÓ¶ÈÊÇϢϢÏà¹ØµÄ¡£¶ø´óÀàÓ볤·½·¨Ö®¼äÓÖÓÐ×űØÈ»µÄÁªÏµ¡£ÎÒ¿ÉÒÔ¸øÄúչʾһ¸ö
2200 Ðеķ½·¨£¬Õâ¸ö·½·¨ÊÇÎÒÔÚÐèҪά»¤µÄÒ»¸öÏîÄ¿ÉÏ·¢Ïֵġ£ÎÒ½«Õû¸öº¬ÓÐ 25000 ÐеĴúÂëµÄÀà´òÓ¡Á˳öÀ´£¬ÈÃÎÒµÄͬÊÂÀ´ÕÒ³öÀïÃæµÄ´íÎó¡£Õâô˵°É£¬µ±ÎÒ°Ñ´òÓ¡³öÀ´µÄ´úÂëÑØ×Å×ßÀȾíÆðÀ´µÄʱºò£¬ËûÃǾÍÒѾͬÒâÎҵĿ´·¨ÁË¡£
Çåµ¥ 7 ÖиßÁÁÏÔʾµÄ²¿·ÖչʾÁËÒ»¸ö³¤·½·¨´úÂëζµÀʾÀýµÄһС²¿·Ö£º
Çåµ¥ 7. ³¤·½·¨´úÂëζµÀ
public
void saveLedgerInformation() {
...
try
{
if
(ledger.getId() != null && filename
== null) {
getLedgerService().saveLedger(ledger);
}
else {
accessFiles().decompressFiles(files,
filenames);
}
if
(!files.get(0).equals(upload)) {
upload
= files.get(0);
filename
= filenames.get(0);
}
if
(invalidFiles.isUnsupported(filename)) {
setError(fileName,
message.getMessage());
}
else {
LedgerFile
entryFile = accessFiles().add(upload, filename);
if
(fileType != null && FileType.valueOf(fileType)
!= null) {
entryFile.setFileType(FileType.valueOf(fileType));
}
getFileManagementService().saveLedger(ledger,
entryFile);
if
(!FileStatus.OPENED.equals(entryFile.getFileStatus()))
{
getFileManagementService().importLedgerDetails(ledger);
}
if
(uncompressedFiles.size() > 1) {
Helper.saveMessage(getText("ledger.file"));
}
if
(user.getLastName() != null) {
SearchInfo
searchInfo = ServiceLocator.getSearchInfo();
searchInfo.setLedgerInfo(null);
isValid
= false;
setDefaultValues();
resetSearchInfo();
if
(searchInfoValid && ledger != null)
{
isValid
= true;
}
}
}
catch (InvalidDataFileException e) {
ResultType
result = e.getResultType();
for
(ValidationMessage message : result.getMessages())
{
setError(fileName,
message.getMessage());
}
ledger.setEntryFile(null);
}
... |
¶ÈÁ¿
ÔÚ¹ýÈ¥µÄ¼¸ÄêÀSLOC ¶ÈÁ¿·½·¨±»ÎóÈÏΪÊǸßЧÂʵÄÏóÕ÷¡£¾¡¹ÜÎÒÃǶ¼ÖªµÀ£¬²¢²»Ò»¶¨ÊÇÐÐÊýÔ½¶àÔ½ºÃ¡£µ«Ëµµ½¸´ÔÓ¶È£¬SLOC
¿ÉÊÇÒ»¸öÓÐÓõĶÈÁ¿·½·¨¡£Ò»¸ö·½·¨£¨»òÀࣩµÄÐÐÊýÔ½¶à£¬½«À´Î¬»¤Æä´úÂë¾Í¿ÉÄÜÔ½ÄÑ¡£
¹¤¾ß
Çåµ¥ 8 ÖеĽű¾Îª³¤·½·¨£¨´óÀࣩÕÒµ½ÁË SLOC ¶ÈÁ¿·½·¨£º
Çåµ¥ 8. ʶ±ð¹ý´óµÄÀàºÍ·½·¨µÄ Gant ½Å±¾
target(findLongMethods:"runs
static code analysis"){
Ant.mkdir(dir:"target/reports")
Ant.taskdef(name:"pmd",
classname:"net.sourceforge.pmd.ant.PMDTask",
classpathref:"build.classpath")
Ant.pmd(shortFilenames:"true"){
codeSizeRules.each{
rfile ->
ruleset(rfile)
}
formatter(type:"xml",
tofile:"target/reports/pmd_report.xml")
formatter(type:"html",
tofile:"target/reports/pmd_report.html")
fileset(dir:"src"){
include(name:"**/*.java")
}
}
} |
ÎÒÓÖʹÓÃÁË Gant ·ÃÎÊ Ant API À´Ö´ÐÐ Ant ÈÎÎñ¡£ÔÚÇåµ¥ 8 ÖУ¬ÎÒµ÷Óà PMD ¾²Ì¬·ÖÎö¹¤¾ßÀ´ËÑË÷´úÂë¿âÖеij¤·½·¨¡£PMD£¨Á¬Í¬
JavaNCSS Óë CheckStyle£©Ò²¿ÉÒÔÓÃÓÚ²éÕÒ³¤·½·¨¡¢´óÀàÒÔ¼°ÆäËû´úÂëζµÀ¡£
ÖØ¹¹
Çåµ¥ 9 չʾÁËÓà Extract MethodÖØ¹¹À´¼õÉÙ Çåµ¥ 7Öеij¤·½·¨´úÂëζµÀµÄÒ»¸öÀý×Ó¡£½«Çåµ¥
7 µÄ·½·¨ÖеÄÐÐΪÌáÈ¡µ½Çåµ¥ 9 µÄ´úÂëÖÐÒÔºó£¬ÎҾͿÉÒÔ´ÓÇåµ¥ 7 µÄ saveLedgerInformation()·½·¨Öе÷ÓÃн¨µÄ
isUserValid()·½·¨ÁË£º
Çåµ¥ 9. Extract Method ÖØ¹¹
private
boolean isUserValid(User user) {
boolean
isValid = false;
if
(user.getLastName() != null) {
SearchInfo
searchInfo = ServiceLocator.getSearchInfo();
searchInfo.setLedgerInfo(null);
setDefaultValues();
resetSearchInfo();
if
(searchInfoValid && ledger != null)
{
isValid
= true;
}
}
return
isValid;
} |
ͨ³££¬³¤·½·¨ºÍ´óÀàÒ²°µÊ¾×Å´æÔÚÆäËû´úÂëζµÀ£¬ÈçÌõ¼þ¸´ÔӶȺÍÖØ¸´´úÂë¡£Òò´Ë£¬ÕÒµ½ÕâЩ³¤·½·¨ºÍ´óÀàÒ²¾Í¿ÉÒÔÐÞ¸´ÆäËûµÄÎÊÌâÁË¡£
Ì«¶àµ¼Èë
ζµÀ£ºÌ«¶àµ¼Èë
¶ÈÁ¿£º´«³öñîºÏ£¨Ã¿¸öÀàµÄÉȳö£¨fan-out£©£©
¹¤¾ß£ºCheckStyle
ÖØ¹¹£ºMove Method¡¢Extract Class
ζµÀ
Ì«¶àµ¼Èë±íÃ÷Ò»¸öÀà¹ý¶àµØÒÀÀµÓÚÆäËûµÄÀà¡£Äú»á×¢Òâµ½£¬ÓÉÓÚÒ»¸öÀàÓëºÜ¶àÆäËûµÄÀàñîºÏµÃÌ«½ôÃÜ£¬ÐÞ¸ÄÕâ¸öÀà»áµ¼Ö±ØÐë¶ÔºÜ¶àÆäËûµÄÀà½øÐÐÐ޸ģ¬Õâʱ¾Í˵Ã÷Õâ¸öÀà´æÔÚÕâÖÖ´úÂëζµÀÁË¡£Çåµ¥
10 ÖеĶà¸öµ¼Èë¾ÍÊÇÒ»¸öÀý×Ó£º
Çåµ¥ 10. Ò»¸öÀàÖеĶà¸öµ¼Èë
import
com.integratebutton.search.SiteQuery;
import
com.integratebutton.search.OptionsQuery;
import
com.integratebutton.search.UserQuery;
import
com.integratebutton.search.VisitsQuery;
import
com.integratebutton.search.SiteQuery;
import
com.integratebutton.search.DateQuery;
import
com.integratebutton.search.EvaluationQuery;
import
com.integratebutton.search.RangeQuery
import
com.integratebutton.search.BuildingQuery;
import
com.integratebutton.search.IPQuery;
import
com.integratebutton.search.SiteDTO;
import
com.integratebutton.search.UrlParams;
import
com.integratebutton.search.SiteUtil;
import
java.text.DateFormat;
import
java.text.ParseException;
import
java.text.SimpleDateFormat;
import
java.util.ArrayList;
import
java.util.Calendar;
import
java.util.Collection;
import
java.util.Collections;
import
java.util.Date;
import
java.util.HashMap;
import
java.util.List;
import
java.util.Map;
import
org.apache.log4j.Logger;
... |
¶ÈÁ¿
ÕÒµ½´øÓÐÌ«¶àÔðÈεÄÀàµÄÒ»¸ö·½·¨¾ÍÊÇͨ¹ý ´«³öñîºÏ¶ÈÁ¿·½·¨£¬ÒàÖ¸ Éȳö¸´ÔÓ¶È¡£Éȳö¸´ÔӶȸø±»·ÖÎöµÄÀàËùÒÀ¸½µÄÿһ¸öÀำֵ
1¡£
¹¤¾ß
Çåµ¥ 11 չʾÁËÒ»¸öÓà CheckStyle ÉèÖÃ×î´óÉȳö¸´ÔÓ¶ÈÊýµÄÀý×Ó£º
Çåµ¥ 11. ʹÓà CheckStyle ÉèÖÃ×î´óÉȳö¸´ÔÓ¶È
<module
name="ClassFanOutComplexity">
<property
name="max"
value="10"/>
</module> |
Refactoring to Patterns
¹¤³§·½·¨Ä£Ê½ÊÇÓ¦ÓÃÖØ¹¹Ê±¿ÉÒÔʵÏֵĶàÖÖÉè¼ÆÄ£Ê½Ö®Ò»¡£Óù¤³§·½·¨´´½¨ÀàÎÞÐèÏÔʽ¶¨ÒåÕýÔÚ´´½¨µÄʵ¼ÊµÄÀà¡£Õâ¸öģʽ¿ÉÒÔʹ½çÃæ±ÈʵÏÖÀà¸ü¼òµ¥¡£µ±¸ù¾Ý´úÂëζµÀʵÏÖÖØ¹¹Ê±£¬ÄúÒ²¿ÉÒÔʹÓÃÆäËûµÄÉè¼ÆÄ£Ê½£»²Î¼û
²Î¿¼×ÊÁϲ鿴רÃÅÑо¿Õâ¸ö¸ÅÄîµÄÊé¼®µÄÁ´½Ó¡£
ÖØ¹¹
ÐÞ¸´ÓÉÓÚÌ«¶àµ¼Èë¶øÒý·¢µÄñîºÏ¹ý½ôµÄ·½·¨ÓкܶàÖÖ¡£¶ÔÓÚÖîÈç Çåµ¥ 10ÖÐÄÇÑùµÄ´úÂëÀ´Ëµ£¬¿ÉÓõÄÖØ¹¹¾Í°üÀ¨
Move MethodÖØ¹¹£º½«·½·¨´Óµ¥¶ÀµÄ *QueryÀàÒÆ¶¯µ½ Java ½çÃæ£¬²¢¶¨ÒåËùÓÐ QueryÀà±ØÐëʵÏÖµÄͨÓ÷½·¨¡£È»ºóÔÙʹÓÃ
¹¤³§·½·¨Ä£Ê½£¬ÕâÑùñîºÏ¶È¾ÍÓë½çÃæÏà¹ØÁªÁË¡£
ͨ¹ýʹÓà Gant ×Ô¶¯¹¹½¨½Å±¾Ö´ÐÐ CheckStyle Ant ÈÎÎñ£¬ÎÒ¿ÉÒÔËÑË÷´úÂë¿â£¬²éÕÒ¹ý¶àÒÀÀµÓÚÆäËûÀàµÄÀà¡£µ±ÐÞ¸ÄÕâЩÀàÖеĴúÂëʱ£¬¾ÍÄܹ»ÊµÏÖÌØ¶¨µÄÖØ¹¹£¨±ÈÈç
Move Method£©ºÍÌØ¶¨µÄÉè¼ÆÄ£Ê½£¬ÒÔÖ𲽸Ľø¿Éά»¤ÐÔ¡£
ÖØ¹¹¡¡Òª¾¡ÔçÇÒÒª¾³£½øÐÐ
³ÖÐø¼¯³É£¨Continuous Integration£¬CI£©¾ÍÊǾ³£¼¯³É±ä¸ü¡£ÕýÈçÆäµäÐ͵ÄʵÏÖ·½Ê½Ò»Ñù£¬Ã¿µ±¶ÔÏîÄ¿µÄ°æ±¾¿ØÖÆ´¢´æ¿â×ö³öÒ»¸ö¸ü¸Äʱ£¬ÔËÐÐÓÚ¶ÀÁ¢»úÆ÷ÉϵÄ×Ô¶¯
CI ·þÎñÆ÷¾Í»á´¥·¢Ò»¸ö×Ô¶¯¹¹½¨¡£ÎªÁËÈ·±£ Çåµ¥ 3ºÍ Çåµ¥ 8ÖеĽű¾¿ÉÒÔÔÚ¶ÔÊý¾Ý¿â×ö³ö¸ü¸ÄʱһÖµØÔËÐУ¬ÄúÐèÒªÅäÖÃÒ»¸öÖîÈç
Hudsona ÕâÑùµÄ CI ·þÎñÆ÷£¨²Î¼û ²Î¿¼×ÊÁÏ£©¡£Hudson ÊÇÒÔ WAR ÎļþµÄÐÎʽ·¢²¼µÄ£¬Äú¿ÉÒÔ½«Ëü·ÅÈëÈκÎ
Java Web ÈÝÆ÷ÖС£
ÓÉÓÚ Çåµ¥ 3ºÍ Çåµ¥ 8ÖеÄÀý×ÓʹÓÃÁË Gant£¬ÏÂÃæÎҾͼòÒª½éÉÜÒ»ÏÂÅäÖà Hudson CI ·þÎñÆ÷ÒÔÔËÐÐ
Gant ½Å±¾µÄ²½Ö裺
ÔÚ Hudson µÄÒDZí°åÉÏΪ Hudson °²×° Gant ²å¼þ£ºÊ×ÏÈÑ¡Ôñ Manage Hudson£¬ÔÙÑ¡Ôñ
Manage Plugins£¬È»ºóÑ¡Ôñ AvailableÑ¡Ï¡£ÔÚÕâ¸öÑ¡ÏÉÏÑ¡ÖÐ Gant ²å¼þ¸´Ñ¡¿ò£¬È»ºóµ¥»÷
Install°´Å¥¡£
ÖØÐÂÆô¶¯ Web ÈÝÆ÷£¨ÀýÈ磬Tomcat£©¡£
Ñ¡Ôñ Manage Hudson£¬È»ºóÑ¡Ôñ Configure System¡£ÔÚ Gant installation²¿·Ö£¬¼üÈëÒ»¸öΩһµÄÃû³ÆÒÔ¼°
Groovy °²×°µ½ÔËÐÐ Hudson µÄ»úÆ÷ÉϵÄλÖᣱ£´æËù×÷¸ü¸Ä¡£
·µ»Øµ½ÒDZí°å£¨Ñ¡Ôñ HudsonÁ´½Ó£©£¬Ñ¡ÔñÒ»¸ö existing Hudson Job£¬ÔÙÑ¡Ôñ Configure£¬È»ºóµ¥»÷
Add build step°´Å¥£¬Ñ¡Ôñ Invoke Gant scriptÑ¡Ïî¡£
ÅäÖà Hudson£¬Ê¹ÆäÔËÐÐʹÓà Gant ±àдµÄ×Ô¶¯¹¹½¨½Å±¾¡£Ò»µ©ÖîÈ糤·½·¨ºÍÌõ¼þ¸´ÔÓ¶ÈÕâÑùµÄ´úÂëζµÀ±»ÒýÈëµ½´úÂë¿âÖУ¬ÄúÁ¢¿Ì¾Í»áµÃµ½ÓëËüÃÇÏà¹ØµÄ¶ÈÁ¿·½·¨µÄ·´À¡¡£
ÆäËûζµÀÓëÖØ¹¹
²¢·ÇËùÓеÄζµÀ¶¼ÓÐÏà¹ØµÄ¶ÈÁ¿·½·¨¡£µ«ÊÇ£¬¾²Ì¬·ÖÎö¹¤¾ßÄܹ»½Ò¶µÄζµÀ²»Ö¹ÎÒËùʾ·¶µÄÕâЩ¡£±í 1 ÁоÙÁËÆäËûµÄ´úÂëζµÀ¡¢¹¤¾ß¡¢ÒÔ¼°¿ÉÄܵÄÖØ¹¹Àý×Ó£º
±í 1. ÆäËûζµÀÓëÖØ¹¹

±¾ÎÄÌṩÁËÒ»ÖÖʹ´úÂëζµÀÓëÒ»ÖÖ¶ÈÁ¿·½·¨Ïà¹ØµÄģʽ£¬ÕâÖÖ¶ÈÁ¿·½·¨¿ÉÒÔÅäÖÃΪͨ¹ý×Ô¶¯¾²Ì¬·ÖÎö¹¤¾ß±ê¼Ç¡£Äú¿ÉÒÔʹÓûò²»Ê¹ÓÃÌØ¶¨µÄÉè¼ÆÄ£Ê½À´½øÐÐÖØ¹¹¡£ÕâΪÄúÌṩÁËÒ»¸öÒÔ¿ÉÖØ¸´µÄ·½Ê½Ò»ÖµزéÕÒºÍÐÞ¸´´úÂëζµÀµÄ¿ò¼Ü¡£ÎÒ¼áÐű¾ÎĵÄÀý×ÓÒ²ÓÐÖúÓÚÄúʹÓþ²Ì¬·ÖÎö¹¤¾ßÀ´²éÕÒ±¾ÎÄÎ´Éæ¼°µ½´úÂëζµÀ¡£
|