Total Pageviews

2011/12/31

11 Things every Software Developer should be doing in 2012










1. Get on Twitter
2. Read StackOverflow Daily
3. Start a Blog
4. Get out there
5. Carry around a modern phone
6. Embrace Mobile
7. Learn at least one design pattern
8. Set reachable goals each and every year
9. Learn a different programming language
10. Boost your confidence
11. Read Blogs/Programming Books/Magazine


http://michaelcrump.net/11-things-every-software-developer-should-be-doing-in-2012

2011/12/30

Preventative medicine for Memory leaks in Java


How to avoid memory leaks?

    To avoid memory leaks, We must check our applications to make sure the below:
  • Our app ought to release JDBC ResultSet, Statement, or connections.
  • Our app ought to use a finally block to make sure the objects are released appropriately.
  • Our app ought to release instance or resource objects that are stored in static tables and
  • also perform clean up on serially reusable objects.
    For example, appending an error messages to a Vector defined in a serially reusable object. The app never cleaned the Vector before it was given to the next user. As the object was reused over and over again, error messages accumulated and causes a memory leak that will be difficult to track it down.

http://www.codedairy.com/bestpractices/preventative-medicine-for-memory-leaks-in-java#.TvzFwq_rHJ4.dzone

2011/12/29

Improve Software Quality with Tools and Processes



  1. Choose a suitable process model and apply it correctly, ex. agilescrumiterative and incremental
  2. Control the version of each required source, ex.  SVNCVS and TFS 
  3. Track issues with easy-to-use tools, ex.  JIRA
  4. Perform and manage documentation, ex.  Confluence
  5. Use dependency management tools, ex.  Maven
  6. Use continuous integration, ex.  Hudson
  7. Perform testing and integration testing constantly, ex.  JUnit
  8. Perform unit testing and automatize it, ex.  Hudson with Maven
  9. Collect metrics from production and use results, ex.  CodePro Eclipse plug-in
  10. Follow best practices of coding and control with tools, ex.  Maven Surefire Report plug-in

2011/12/28

善用Oracle提供的function來提升系統效能



有關報表的日期欄位,資料庫是儲存成yyyMMDD or yyyMM。根據現有需求,需formatting成YYY/MM或者是YYY/MM/DD格式,因為效能考量,此類的formatting應在SQL裡頭做,不要放到AP level做。

舉個例子來說

  • 屆滿年月
    • NVL2(NIGT001.APL_LIMIT_YM, SUBSTR(NIGT001.APL_LIMIT_YM,0,3)||'/'||SUBSTR(NIGT001.APL_LIMIT_YM,4,2), ' ')
  • 作業日期
    • NVL2(NIGT001.PRST_PRCD_DATE, SUBSTR(NIGT001.PRST_PRCD_DATE,0,3)||'/'||SUBSTR(NIGT001.PRST_PRCD_DATE,4,2)||'/'||SUBSTR(NIGT001.PRST_PRCD_DATE,6,2), ' ')
 
Oracle相關語法簡介:
 

2011/12/22

Are You Making These 7 Productivity Mistakes?


Mistake #1: Cutting Back on Sleep
Mistake #2: Multi-Tasking
Mistake #3: Doing Everything Yourself
Mistake #4: Focusing Solely on Numbers
Mistake #5: Eating at Your Desk
Mistake #6: Checking Email Frequently
Mistake #7: Pushing Yourself Hard

No output specified for the exporter

Problem
As I would like to export pdf via JasperReports JRExporter, it throw "No output specified for the exporter" exception.

Root Cause
I forgot to set OutputStream to JRExporter parameter, i.e.
1:  JRExporter pdfExporter = new JRPdfExporter();  
2:  pdfExporter.setParameter(JRExporterParameter.OUTPUT_STREAM, outputStream);  
3:  //........  

How to apply 1000 separator in data field

需求
在數字或者是金額等欄位,需要做到千分位隔開,如1000,要顯示1,000

作法
1. 到特定欄位按右鍵,選擇Field Pattern

2. 選擇Number, 將"User 1000 Separator"打勾,再按Apply

3. Check Result




REPORT_COUNT vs. [group name]_COUNT

需求
在產出的報表的每筆資料的第一個column,指定序號


產出結果如下


一般來說,只要將REPORT_COUNT此欄位拉到iReport即可


但是在NIG071此張報表中,若到下一頁,他會把值reset,從1開始

會造成此問題的原因,是因為此報表有用到Report Group


此時,要用Group_Count才行,其命名為則是[group name]_COUNT


結論
1. 如果沒有用到Report Group,請用REPORT_COUNT
2. 如果有用到Report Group,請用[group name]_COUNT

Oracle/PLSQL: Case Statement


Requirement
到NIGT001與NIGT005,根據前端條件輸入結果產出報表

報表內容包含違章編號、統一編號、議程類別等欄位,其中有幾個欄位是經過if-else判斷是得來的,如作業代號、案況、會次等



AS-IS
現有VB/Cobol在NIG335的作法是:
1. 在VB裡頭到NIGT001撈資料出來
2. 根據找出來的資料往後拋到Cobol,在根據撈出來的值來判斷,以下是Cobol程式片段

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
EVALUATE WK-PRCD-STUS  
 WHEN "33"  
   IF WK-UPD-JDGF-STUS = "50"  
     MOVE "4"     TO RPT-CASE-STUS(RECORD-CNT)  
     MOVE "50"    TO RPT-PRCD-STUS(RECORD-CNT)  
   ELSE   
     MOVE "1"     TO RPT-CASE-STUS(RECORD-CNT)  
     MOVE "33"    TO RPT-PRCD-STUS(RECORD-CNT)  
   END-IF   
    MOVE WK-PRCD-MK(1:4)  
      TO RPT-MTGNO(RECORD-CNT)  
  WHEN "36"  
    IF WK-UPD-JDGF-STUS = "50"  
      MOVE "5"     TO RPT-CASE-STUS(RECORD-CNT)  
      MOVE "50"    TO RPT-PRCD-STUS(RECORD-CNT)  
    ELSE  
      MOVE "2"     TO RPT-CASE-STUS(RECORD-CNT)  
      MOVE "36"    TO RPT-PRCD-STUS(RECORD-CNT)  
    END-IF   
    MOVE WK-PRCD-MK(1:4)  
      TO RPT-MTGNO(RECORD-CNT)      
  WHEN "50"  
    MOVE "6" TO RPT-CASE-STUS(RECORD-CNT)  
    MOVE "50" TO RPT-PRCD-STUS(RECORD-CNT)  
    MOVE WK-PRCD-MK(8:4)  
      TO RPT-MTGNO(RECORD-CNT)      
  WHEN OTHER  
    MOVE "3" TO RPT-CASE-STUS(RECORD-CNT)  
    MOVE "18" TO RPT-PRCD-STUS(RECORD-CNT)  
    MOVE SPACES     TO RPT-MTGNO(RECORD-CNT)      
END-EVALUATE. 


TO-BE
以過去的作法來說,挺沒效率的,他需要每筆資料for-loop出來,在按照條件,給予不同的值。以此段程式來說,可以用Oracle內建的CASE statement,如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
SELECT....,  
CASE WHEN NIGT005.PRCD_STUS = '33' and NIGT001.UPD_JDGF_STUS = '50' THEN '4'       
   WHEN NIGT005.PRCD_STUS = '33' and NIGT001.UPD_JDGF_STUS <> '50' THEN '1'       
   WHEN NIGT005.PRCD_STUS = '36' and NIGT001.UPD_JDGF_STUS = '50' THEN '5'       
   WHEN NIGT005.PRCD_STUS = '36' and NIGT001.UPD_JDGF_STUS <> '50' THEN '2'       
   WHEN NIGT005.PRCD_STUS = '50' THEN '6'       
   ELSE '3'     END as CASE_STUS,   --案況  
CASE WHEN NIGT005.PRCD_STUS = '33' and NIGT001.UPD_JDGF_STUS = '50' THEN '50'       
   WHEN NIGT005.PRCD_STUS = '33' and NIGT001.UPD_JDGF_STUS <> '50' THEN '33'       
    WHEN NIGT005.PRCD_STUS = '36' and NIGT001.UPD_JDGF_STUS = '50' THEN '50'       
    WHEN NIGT005.PRCD_STUS = '36' and NIGT001.UPD_JDGF_STUS <> '50' THEN '36'       
    WHEN NIGT005.PRCD_STUS = '50' THEN '50'       
    ELSE '18'     END as PRCD_STUS,   --作業代號  
 CASE WHEN NIGT005.PRCD_STUS = '33' THEN SUBSTR(NIGT005.PRCD_MK, 1, 4)       
    WHEN NIGT005.PRCD_STUS = '36' THEN SUBSTR(NIGT005.PRCD_MK, 1, 4)       
    WHEN NIGT005.PRCD_STUS = '50' THEN SUBSTR(NIGT005.PRCD_MK, 8, 4)       
    ELSE ''     END AS MTG_NO --會次  
 FROM NIGT001, NIGT005  
 WHERE ....  


Benefits
這樣的作法有幾個好處
1. 將這些if-else statement放到SQL中去處理,降低程式複雜度,也減少處理出錯的風險
2. 將這些if-else statement放到SQL中去處理,會得到最好的處理速度與效能(相較於用Java程式處理)

Oracle/PLSQL: Case Statement - http://www.techonthenet.com/oracle/functions/case.php

2011/12/20

HashMap vs. LinkHashMap

Problem

在報表的開發上,剛好遇到一個問題,我同時要餵資料給兩張iReport template(i.e. P1, P2),然後後端用for loop將裡頭的資料抓出來,原本的方式:
1:  Map dataMap = new HashMap ();  
2:  dataMap.put("NIG071P1", p1Data);  
3:  dataMap.put("NIG071P2", p2Data);  

但是此方式,並沒有如預期的依照順序產生P1, P2,反而是先印出P2、再印出P1,這是因為HashMap並不會根據你insert的順序來將資料抓出來

Solution

改用LinkedHashMap (Hash table and linked list implementation of the Map interface, with predictable iteration order. This implementation differs from HashMap in that it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is normally the order in which keys were inserted into the map (insertion-order). )。
這是一個會根據我們insert的順序來把資料抓出來的Map,改寫如下,即可解決上述的問題:
1:  //LinkedHashMap defines the iteration ordering,   
2:  //which is normally the order in which keys were   
3:  //inserted into the map (insertion-order)  
4:  Map dataMap = new LinkedHashMap ();  
5:  dataMap.put("NIG071P1", p1Data);  
6:  dataMap.put("NIG071P2", p2Data);