Code ít hơn thì tốt hơn

11:23 PM
Tất cả chúng ta đều nhận thấy rằng viết code quá nhiều có thể là một điều tệ hại, viết code ít hơn có nghĩa là ít sai sót hơn, nhanh tróng hoàn thiện phần mềm và đưa ra thị trường.

     Càng ngày càng nhiều các framework , sản phẩm mã nguồn mở được phát hành, cho phép bạn viết các ứng dụng với càng ít code hơn. Nhưng việc tái sử dụng quan trọng không chỉ vì nó mang nghĩa viết ít mã hơn mà còn bởi vì nó mang nghĩa tận dụng "trí khôn của đám đông". Các framework và các công cụ mã nguồn mở phổ biến — như là Hibernate, Spring, Strust — đang được sử dụng bởi vô số người trên toàn thế giới trong hàng loạt các ứng dụng khác nhau. Phần mềm được kiểm nghiệm và được tôi luyện trong thực tế này không phải là không có sai sót, nhưng bạn có thể an tâm giả định rằng bất cứ vấn đề nảy sinh nào sẽ được tìm thấy sẽ được sửa chữa một cách nhanh chóng và miễn phí.

Điển hình trong đó là apache commons, thư viện này rất tiện lợi, bạn sẽ thấy rằng thời gian và số lần gõ bàn phím mà bạn tiết kiệm rất nhiều.

Apache commons là gì?

Apache Commons là nơi tạo ra và phát triển các thành phần có thể tái sử dụng Java. Đó là nơi các lập trình viên làm việc cùng nhau và chia sẻ trong các dụ án của Apache.

Các lập trình viên luôn nỗ lực để các thư viện có sự phụ thuộc vào thư viện khác là ít nhất, để chúng có thể được triển khai dễ dàng. Các API luôn được giữ ổn định để bạn không phải lo lắng về các thay đổi trong tương lai.

Các project hiện tại của Apache commons.

Components
Attributes Runtime API to metadata attributes such as doclet tags.
BCEL Byte Code Engineering Library - analyze, create, and manipulate Java class files
BeanUtils Easy-to-use wrappers around the Java reflection and introspection APIs.
Betwixt Services for mapping JavaBeans to XML documents, and vice versa.
BSF Bean Scripting Framework - interface to scripting languages, including JSR-223
Chain Chain of Responsibility pattern implemention.
CLI Command Line arguments parser.
Codec General encoding/decoding algorithms (for example phonetic, base64, URL).
Collections Extends or augments the Java Collections Framework.
Compress Defines an API for working with tar, zip and bzip2 files.
Configuration Reading of configuration/preferences files in various formats.
CSV Component for reading and writing comma separated value files.
Daemon Alternative invocation mechanism for unix-daemon-like java code.
DBCP Database connection pooling services.
DbUtils JDBC helper library.
Digester XML-to-Java-object mapping utility.
Discovery Tools for locating resources by mapping service/reference names to resource names.
EL Interpreter for the Expression Language defined by the JSP 2.0 specification.
Email Library for sending e-mail from Java.
Exec API for dealing with external process execution and environment management in Java.
FileUpload File upload capability for your servlets and web applications.
Functor A functor is a function that can be manipulated as an object, or an object representing a single, generic function.
Imaging (previously called Sanselan) A pure-Java image library.
IO Collection of I/O utilities.
JCI Java Compiler Interface
JCS Java Caching System
Jelly XML based scripting and processing engine.
Jexl Expression language which extends the Expression Language of the JSTL.
JXPath Utilities for manipulating Java Beans using the XPath syntax.
Lang Provides extra functionality for classes in java.lang.
Launcher Cross platform Java application launcher.
Logging Wrapper around a variety of logging API implementations.
Math Lightweight, self-contained mathematics and statistics components.
Modeler Mechanisms to create Model MBeans compatible with JMX specification.
Net Collection of network utilities and protocol implementations.
OGNL An Object-Graph Navigation Language
Pool Generic object pooling component.
Primitives Smaller, faster and easier to work with types supporting Java primitive types.
Proxy Library for creating dynamic proxies.
Sanselan (now called Imaging) A pure-Java image library.
SCXML An implementation of the State Chart XML specification aimed at creating and maintaining a Java SCXML engine. It is capable of executing a state machine defined using a SCXML document, and abstracts out the environment interfaces.
Transaction Implementations for multi level locks, transactional collections and transactional file access.
Validator Framework to define validators and validation rules in an xml file.
VFS Virtual File System component for treating files, FTP, SMB, ZIP and such like as a single logical file system.

Trên đây là hơn 40 dự án hiện tại của apache commons. Hi vọng có ích cho bạn.

Tăng tốc Web java bằng Caching System

7:59 PM

Bộ nhớ đệm

Bộ nhớ đệm thường được sử dụng để tối ưu hóa việc tải dữ liệu cho các ứng dụng trên nền web. Nó rất thích hợp để caching những dữ liệu được truy cập nhiều nhưng ít bị thay đổi và những dữ liệu được truy cập nhiều vào một thời điểm nhưng sau đó lại ít được dùng đến.

Thông thường các ứng dụng được kết nối đến một cơ sở dữ liệu, thực hiện truy vấn và phân tích kết quả trả về. Bộ nhớ đệm duy trì một tập các đối tượng được tái sử dụng mà không cần truy vấn lại cơ sở dữ liệu. Các úng dụng java thường bị hạn chế về tài nguyên có sẵn trong JVM.Trong đó quý nhất là bộ nhớ, vì vậy phải thật thận trọng khi sử dụng bộ nhớ đệm. Để hiểu hơn về bộ nhớ đệm chúng ta làm một ví dụ với JSC.

Java Caching System

Đơn giản và mạnh mẽ, là một sản phẩm mã nguồn mở được phát hành thông qua các tiểu dự án Apache Jakarta. Nó cung cấp các tính năng tiêu chuẩn mà bạn mong đợi của một hệ thống bộ nhớ đệm, chẳng hạn như bộ nhớ đệm trong RAM và các thuật toán lựa chọn loại bỏ các đối tượng từ bộ nhớ đệm. Nó cũng cung cấp các tính năng cao cấp hơn nhiều, chẳng hạn như bộ nhớ đệm ổ cứng lập chỉ mục và bộ nhớ đệm phân tán.

JCS có cấu trúc giống như mảng, trong đó dữ liệu được lưu trữ trong bộ nhớ cache như một cặp tên và giá trị. JCS phân vùng bộ nhớ cache vào từng khu vực. Mỗi khu vực có cấu hình riêng của mình cũng như các thiết lập của riêng của các cặp tên-giá trị. Mỗi khu vực có thể:
  • Có kích thước khác nhau.
  • Được thực hiện khác nhau.
  • Chứa dữ liệu khác nhau.

Làm việc với JCS.

Thư viện cần thiết.

Bạn downlaod JCS tại: http://commons.apache.org/jcs/

Cần thêm 2 thư viện nữa:

Code.

Đầu tiên bạn cần có một file cấu hìn
Đó là một file properties file: cache.ccf
Nội dung:

# DEFAULT CACHE REGION
jcs.default=DC jcs.default.cacheattributes=org.apache.jcs.engine.CompositeCacheAttributes jcs.default.cacheattributes.MaxObjects=1000 jcs.default.cacheattributes.MemoryCacheName= org.apache.jcs.engine.memory.lru.LRUMemoryCache jcs.default.cacheattributes.UseMemoryShrinker=true jcs.default.cacheattributes.MaxMemoryIdleTimeSeconds=3600 jcs.default.cacheattributes.ShrinkerIntervalSeconds=60 jcs.default.elementattributes=org.apache.jcs.engine.ElementAttributes jcs.default.elementattributes.IsEternal=false jcs.default.elementattributes.MaxLifeSeconds=21600 jcs.default.elementattributes.IdleTime=1800 jcs.default.elementattributes.IsSpool=true jcs.default.elementattributes.IsRemote=true jcs.default.elementattributes.IsLateral=true

Vùng cache mặc định xác định cấu hình mặc định cho tất cả các vùng cache, trừ khi nó được ghi đè một cách rõ ràng bởi một trong các khu vực khác.

Tiếp theo là một vùng cache được xác định trước (được người dùng định nghĩa), ở đây tôi định nghĩa vùng simple mà tôi sẽ sử dụng.

# AVAILABLE SIMPLE CACHES
jcs.simple.DC=
     org.apache.jcs.simple.disk.indexed.IndexedDiskCacheFactory
jcs.simple.DC.attributes=
     org.apache.jcs.simple.disk.indexed.IndexedDiskCacheAttributes
jcs.simple.DC.attributes.DiskPath=c:/temp
jcs.simple.DC.attributes.MaxPurgatorySize=10000000
jcs.simple.DC.attributes.MaxKeySize=1000000
jcs.simple.DC.attributes.MaxRecycleBinSize=5000
jcs.simple.DC.attributes.OptimizeAtRemoveCount=300000
jcs.simple.DC.attributes.ShutdownSpoolTimeLimit=60
 
Vị trí để file cache.

jcf cache file
Tiếp theo bạn cần một file để quản lý cache:

File: Cache.java
package org.ewing.jcs.cache;
import org.apache.jcs.JCS;
import org.apache.jcs.access.exception.CacheException;
public class Cache {
    private static JCS jcsCache;
    private final static String JCS_CACHE = "simple";
    public Cache() {
        try {
            jcsCache = JCS.getInstance(JCS_CACHE);
        } catch (CacheException e) {
            e.printStackTrace();
        }
    }
    public static Object get(String id) throws CacheException {
        if (jcsCache == null) {
            jcsCache = JCS.getInstance(JCS_CACHE);
            return null;
        } 
        Object result = jcsCache.get(id);
        return result;
    }
    public static void put(String id, Object obj) throws CacheException {
        if (jcsCache == null) {
            jcsCache = JCS.getInstance(JCS_CACHE);
        }
        try {
            jcsCache.put(id, obj);
        } catch (CacheException e) {
            throw new CacheException();
        }
    }
}

Đây là một class đơn giản để đọc và nghi dữ liệu vào cache.
Với đọc:

    public static Object get(String id) throws CacheException {
        if (jcsCache == null) {
            jcsCache = JCS.getInstance(JCS_CACHE);
            return null;
        } 
        Object result = jcsCache.get(id);
        return result;
    }
Và ghi dữ liệu:
   public static void put(String id, Object obj) throws CacheException {
        if (jcsCache == null) {
            jcsCache = JCS.getInstance(JCS_CACHE);
        }
        try {
            jcsCache.put(id, obj);
        } catch (CacheException e) {
            throw new CacheException();
        }
    }
Một servlet đơn giản sủ dụng cache:

package org.ewing.jcs.service;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.jcs.access.exception.CacheException;
import org.ewing.jcs.cache.Cache;

/**
 * Servlet implementation class Service
 */
@WebServlet("/Service")
public class Service extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public Service() {
        super();

    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
     *      response)
     */
    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        System.out.println("this is test");
        String id = request.getParameter("txtName");
        String input = request.getParameter("txtInput");
        String cache = request.getParameter("txtCache");
        String result = "";
        if ((input != null) && (!input.equals("")) && (cache != null)
                && (!cache.equals(""))) {
            System.out.println("put");
            try {
                Cache.put(input, cache);
            } catch (CacheException e) {

                e.printStackTrace();
            }
        } else {
            System.out.println("get");
            try {
                result = (String) Cache.get(id);
            } catch (CacheException e) {
                e.printStackTrace();
            }
        }
        System.out.println(result);
        request.setAttribute("result", result);
        RequestDispatcher dispatcher = request.getRequestDispatcher("index.jsp");
        dispatcher.forward(request, response);

    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
     *      response)
     */
    protected void doPost(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

File index.jsp
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
    <%
        String result = (String)request.getAttribute("result");
        if(result != null && !result.equals("")){
            out.print("Ket qua: " + result);
        }
    %>
    <form action="./Service" method="get">
        <div style="margin: 50px auto;">
            <div>
                id:  <input type="text" name="txtInput" />
            </div>
            <br />
            <div>
                value:  <input type="text" name="txtCache" />
            </div>
            <br /> <br /> <input type="submit" value="submit">
        </div>
    </form>
    <br />
    <br />
    <form action="./Service" method="get">
        <div style="margin: 50px auto;">
            <input type="text" name="txtName" /> <br /> <br /> <input
                type="submit" value="submit">
        </div>
    </form>
</body>
</html>
Project:

project jcs


Lợi ích chính của một bộ nhớ đệm là đối tượng có thể được lấy từ bộ nhớ nhanh hơn được tải từ một nguồn dữ liệu bên ngoài như cơ sở dữ liệu nằm hoặc trên mạng. Nhược điểm là cache có thể dùng một lượng đáng kể bộ nhớ. Nếu các đối tượng và các mẫu sử dụng không được phân tích kỹ lưỡng, bộ nhớ đệm có thể tạo một nút cổ chai vào ứng dụng của bạn. Bộ nhớ cache chỉ phù hợp khi bạn phân tích tốt các đối tượng của bạn khi đó JCS là một lựa chọn tuyệt vời.

Eclipse cơ bản

7:13 PM
Eclipse là một trong những IDE lập trình java tốt nhất, mạnh  mẽ, mềm dẻo. Eclipse có thể dùng để phát triển PHP, Ruby và Groovy, C và C++. Chính bản thân mình chỉ dùng eclipse để code Java, PHP, C. với plugin thích hợp mình có thể tối ưu để dùng với mule esb, spring.

Trước khi bắt đầu.
Bạn cần cài đặt:

Eclipse: 
Bạn download tại : http://www.eclipse.org/downloads/
Chọn phiên bản phù hợp với mình.

Môi trường chạy Java (JRE-Java Runtime Environment):
Eclipse tự thân là một úng dụng java vì vậy bạn cần JRE. Để phát triển java bạn cần thêm JDK.
Có thể download ở đây: http://www.oracle.com/technetwork/java/javase/downloads/index.html.

Cài đặt. 
Đầu tiên bạn cần cài đặt JDK. Việc này rất đơn giản bạn cứ làm theo hướn dẫn.
Tiếp theo cấu hình biến JAVA_HOME.
 
Vào System Properties ->Advance-> Environment Variables

 

Thêm biến JAVA_HOME với value lđường dẫn tới thư mục cài JDK của bạn.

Cài đặt eclipse:
Bạn chỉ cần giải nén ra một thư mục bất kỳ.

Vậy là bạn đã có IDE để lập trình java.

Cài đặt plugin cho eclipse 

Bạn vào Help -> Install New Software..
Bạn có thể cài đặt plugin bằng url hoặc file nén bạn download về.
Tham khảo thêm về eclipse tại http://wiki.eclipse.org/Main_Page 



Code style

2:12 AM
Từ khi học viết những dòng code đầu tiên cho đến khi chở thành một lập trình viên 7 năm kinh nghiệm ít quan tâm đến code style và conding convention. Từ khi học code java từ 2003 đến giờ java vẫn thế coding convention vẫn vậy như một lối mòn cứ thế đặt tên class, hàm và biến.
Có lẽ bạn không quan tâm mấy đến nó nếu không dùng nhiều ngôn ngữ lập trình, tôi cũng vậy. Thời gian gần đây do phải liên tục dùng chuyển đổi dùng Java, PHP và C. Tôi mới cảm nhận được sự khác biệt tạo nên phong cách của từng ngôn ngữ.
Hãy xem một lập trình viên C viết code java:

static Vector<Log> get_logs() {
        Vector<Logs> logs = new Vector<Logs>();
        Log log;
        String sender, receiver, momt;
        long timestamp;
        long my_id;
        int processed_flag = Log.MSG_STATUS.NOT_PROCESSED.ordinal();
        Timestamp first_processed;
        System.out.println(str_conn);
        Connection conn;
        boolean is_add_to_list = false;
        try {
            conn = DriverManager.getConnection(str_conn, username, password);
            Statement statement = conn.createStatement();
            ResultSet result;
            String sqlCmd = "...";
            result = statement.executeQuery(sqlCmd);
            now = new Date();
            ts_now = new Timestamp(now.getTime());
            while (result.next()) {
                my_id = result.getLong("...");
                sender = result.getString("...");
                receiver = result.getString("...");
                momt = result.getString("...");
                timestamp = result.getLong("...");
                processed_flag = result.getInt("...");
                first_processed = result.getTimestamp("...");
                is_add_to_list = false;
                if (run_a) {
                    if (getOperator(sender) == OPERATOR.A
                            || getOperator(receiver) == OPERATOR.A) {
                        is_add_to_list = true;
                    }
                }
                if (run_m) {
                    if (getOperator(sender) == OPERATOR.M
                            || getOperator(receiver) == OPERATOR.M)
                        is_add_to_list = true;
                }
                if (run_v) {
                    if (getOperator(sender) == OPERATOR.V
                            || getOperator(receiver) == OPERATOR.V)
                        is_add_to_list = true;
                }
                if (run_b) {
                    if (getOperator(sender) == OPERATOR.B
                            || getOperator(receiver) == OPERATOR.B)
                        is_add_to_list = true;
                }
                if (is_add_to_list) {
                    if (processed_flag == Log.MSG_STATUS.NOT_PROCESSED
                            .ordinal()) {
                        first_processed = ts_now;
                        lstFirstProcessed.add(my_id);
                    }
                    log = new Log(sender, receiver, timestamp, my_id,
                            processed_flag, momt, first_processed);
                    logss.add(log);
                }
            }
            result.close();
            statement.close();
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
           return logs;
    }
Các lập trình viên C luôn luôn trí tuệ. Họ dùng quá nhiều cờ để định trạng thái hoạt động của các hàm. Nhiều lúc nhìn tróng cả mặt mà không hiểu luồng hoạt động như thế nào. Debug thật đau khổ không biết lúc nào cái cờ nó true hay false.

static void read_messages_from_bearerbox(void)
{
    time_t start, t;
    int secs;
    int total = 0;
    int ret;
    Msg *msg;

    start = t = time(NULL);
    while (program_status != shutting_down) {
        /* block infinite for reading messages */
        ret = read_from_bearerbox(&msg, INFINITE_TIME);
        if (ret == -1) {
            error(0, "Bearerbox is gone, restarting");
            program_status = shutting_down;
            restart = 1;
            break;
        } else if (ret == 1) /* timeout */
            continue;
        else if (msg == NULL) /* just to be sure, may not happens */
            break;

    if (msg_type(msg) == admin) {
        if (msg->admin.command == cmd_shutdown) {
        info(0, "Bearerbox told us to die");
        program_status = shutting_down;
        } else if (msg->admin.command == cmd_restart) {
        info(0, "Bearerbox told us to restart");
        restart = 1;
        program_status = shutting_down;
        }
        /*
         * XXXX here should be suspend/resume, add RSN
         */
        msg_destroy(msg);
    } else if (msg_type(msg) == sms) {
        if (total == 0)
        start = time(NULL);
        total++;
        gwlist_produce(smsbox_requests, msg);
    } else if (msg_type(msg) == ack) {
        if (!immediate_sendsms_reply)
        delayed_http_reply(msg);
        msg_destroy(msg);
    } else {
        warning(0, "Received other message than sms/admin, ignoring!");
        msg_destroy(msg);
    }
    }
    secs = difftime(time(NULL), start);
    info(0, "Received (and handled?) %d requests in %d seconds "
         "(%.2f per second)", total, secs, (float)total / secs);
}
Bạn ngĩ thế nào khi đọc cái phương thức này trong một file có khoảng 3600 dòng code.