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);  

2011/11/18

2011/11/12-17 京都大阪六日遊

耶誕節氣氛漸濃


道頓崛

大阪城

梅田夜景

東福寺楓紅

哲學之道

京都某處楓紅

銀閣寺楓紅

八阪神社

從清水寺遠眺kyoto tower

楓紅配藍天



2011/10/30

Top Ten Idea Killers in Software Development



9. "This is how it was always done"

8. "There isn't enough time to do it right"

7. "This requires core architectural changes"

6. "Management has not prioritized it"

5. "There is already a lot on our plate"

4. "Our software is very complex; we have to be careful about making changes"

3. "No one is asking for it"

2. "We have to have consensus"

And the #1 idea killer in software development is
1. "It can't be done

Subversion Best Practices: Repository Structure


http://blogs.wandisco.com/2011/10/24/subversion-best-practices-repository-structure/?=kt_tw

2011/10/24

Grouping Data in Reports

Report groups are a flexible way to show grouped data based on one or more certain fields, or even on generic expression, that is, a group can be defined based on the specific column.

Here we will build a report to show the list of 違章案件派查明細表, 審理人員 will be grouped together, that is, the manger (suppose the report is for a manager) will know which violation case is reponsible by which 審理人員.

Follow the listed steps:
1. Go to File | New… | Report, select Simple Blue, and press Launch Report Wizard.
2. Set JavaBean as report's datasource: http://albert-myptc.blogspot.com/2011/06/how-toi-make-java-bean-datasource.html
3. Click Report Name | Right Click | Add Report Group, and New Group Wizard. Fill in Group Name | Choose field name | click Next, and Click Finish


4. You can see group header and group footer in your Report Inspector
5. Click group header | check "Start on a new page" and "Reset page number"

6. Report header and column header should all put into group header
7. JavaBean attriubtes will be dragged and dropped into detail band

8. Drag and drop group count variable to summary field

 9. Done.

How to start group data on a new page

Problem
I had some problems as I built a group by report
1. Each group data should start on a new page.
2. page number should be reset



Solution
1. Move report header from title band to group header band

2. Click group header


3. Check two checkboxs, including "Start on a new page" and "Reset page number"


Here has some group options:
Option Description
Name This is the name of the group. You can modify the name by just clicking on the button next to the name.
Start on a new page If this checkbox is checked, then the group starts on a new page.
Start on a new column If this checkbox is checked, then the group starts on a new column.
Reset page number When the group changes, the page number is reset if this option is checked.
Reprint header If you want to reprint the group header on each page, check this option.
Min Height to Start New Page If the value is greater than 0 (zero), it is considered as the minimum height required to keep the group on the current page.
Footer Position This option allows us to specify where to place the group footer. The available place options are Normal, Stack at bottom, Force at bottom, and Collate at bottom.
Keep Together This is a flag that prevents the group from splitting on two separate pages/columns.

Demo
It split to two pages as bellowing:


2011/10/13

How to Prevent a SQL Injection Attack

Reference: http://www.dzone.com/links/r/how_to_prevent_a_sql_injection_attack.html




1. Patch your SQL server regularly
2. Limit the use of dynamic queries
3. Escape user input
4. Store database credentials in a separate file
5. Use the principle of least privilege
6. Turn magic quotes off
7. Disable shells
8. Disable any other DB functionality you don’t need
9. Test your code

2011/10/11

How to add record sequence number in JasperReports

Requirement
I would like to add record sequence number in the first column.


How to do it?
1. Open iReport
2. Utilize the build-in variable, COLUMN_COUNT, drag and drop to specific location.