Thursday, November 24, 2016

Design Pattern - Adapter

Tiếp tục với mẫu thiết kế adapter.

Nó là gì?
 Mẫu adapter chuyển đổi giao diện thành một giao diện khác mà phù hợp với yêu cầu. Giúp kết nối các lớp có giao diện không tương thích để làm việc với nhau

Dùng nó trong trường hợp nào?.
Khi ta muốn chuyển đổi một lớp với một giao diện thành giao diện mà ta mong muốn.
Xậy dựng, mở rộng các phương thức của lớp có sẵn phù hợp với yêu cầu.
Tái sử dụng giao diện cũ. Giảm thiểu việc viết lại mã lệnh.

Dùng nó như thế nào?

Tình Huống:

   Thực tế : Có một công ty muốn mỏ rông công ty bằng cách chuyển địa điểm làm việc. Khi chuyển địa điểm thì có thêm các cơ sở mới.
   Trong Java : giả sử ta đã có lớp với phương thức có sẵn để hiển thị 1 chuồi như sau ra màn hình: void ShowName (String str) với chuỗi đã được chuẩn hóa nhưng chương trình mới yêu cầu ta phải hiển thị một danh sách các chuỗi được chuẩn hóa với giao diện mới. 

- Xử lí tình huống : 

   Tình huống 1) Có người để xuất ý kiến ta sẽ mua toàn bộ các cơ sở vật chất đề phù hợp với môi trường mới. Nhưng có một đề xuất khác là ta sẽ sử dụng lại các công cụ có sẵn của công từ và từ đó sẽ thêm các cơ sở vật chất mới phù hợp.
   Tình huống 2)  Một lập trình viên đề xuất , ta sẽ tạo một lớp hoàn toàn mới để ghi 1 danh sách chuỗi với phương thức để chuẩn hóa. Nhưng không, một lập trình viên khác nêu ý kiến: “Tôi có một giải pháp, tôi sẽ sử dụng mẫu chuyển đổi Adapter để tạo một lớp phù hợp từ lớp có sẵn”. 

Tạo mẫu Adapter đầu tiên :
Đầu tiên lớp có sẵn của ta được mô tả với  1 interface:
  1. public interface IShowName { 
  2.    void showName(String name); 
  3. }
Và một lớp thực thi interface trên :
  1. public class ShowName implements IShowName{
  2.    @Override public void showName(String name){   
  3.       System.out.println(this.standardize(name));
  4.    }
  5.    public String standardize(String name){
  6.       String resuilt = name.trim();
  7.       return name;
  8.    }
  9. }
Và một interface mô tả phương thức phù hợp với chương trình của ta :
  1. public interface IShowListName {
  2.    void showListName(List listName);
  3. }

Và một lớp thực thi interface :
  1. public class ShowListNameAdapter implements IShowListName{
  2.       private ShowName shownName;
  3.       public ShowListNameAdapter(ShowName shownName) {
  4.          this.shownName = shownName;
  5.          }
  6.       @Override
  7.       public void showListName(List listName) {
  8.          for (String name : listName) {
  9.          shownName.showName(name);
  10.       }
  11.    }
  12. }
Thử chạy mẫu Adapter:

  1. public class TestAdapter {
  2.    public static void main(String[] args) {
  3.       ArrayList array = new ArrayList<>();
  4.       array.add(" Teo ");
  5.       array.add(" Ti ");
  6.       array.add(" Ku ");
  7.       IShowListName adapter = new ShowListNameAdapter(new ShowName());    
  8.       adapter.showListName(array); 
  9.    }
  10. }
Kết quả chương trình sẽ hiển thị “Teo”, ”Ti”, “Ku” đã được chuẩn hóa.
Đây chỉ là một ví dụ nhỏ của Adapter pattern. Hy vọng bạn sẽ sớm có cái nhìn tổng quát và hiểu rõ thêm về Adapter pattern.

Tuesday, November 15, 2016

Design Pattern - Proxy


Nó là gì?
 - Mẫu Proxy (người đại diện) đại diện cho 1 chức năng của lớp khác. Bạn có thể hiểu, ta thuê 1 luật sư về đại diện cho ta, người luật sư này có thể dùng các quyền của mình một cách gián tiếp để nói cho các người khác một cách chính xác vì luật sư am hiểu về pháp luật hơn mình.

Khi nào dùng nó?

 - Khi bạn muốn bảo vệ quyền truy xuất vào các chức năng (phương thức) của thực thể.
 - Bổ sung trước khi thực hiện phương thức của thực thể.
 - Tạo đối tượng với chức năng được nâng cao theo yêu cầu.

Dùng nó như thế nào?

 Tôi sẽ xây dựng một ví dụ đơn giản như sau:
- Tôi có 1 inteface mô tả chức năng của một class :


  1. public interface ReadFile { 
  2.      public String readFile(); 
  3. }
}

Tiếp theo tạo class User triển khai interface trên:

  1. public class User implements ReadFile{
  2.       private String name; //Tên của người dùng 
  3.       public User(String name) { 
  4.            this.name = name; 
  5.       } @Override public String readFile() { //Phương thức đọc file            return name + "readed"; 
  6.       } 
  7.  }

Và một class Proxy đại diện cho lớp User:
  1. public class UserProxy implements ReadFile{ 
  2.       private ReadFile instance; 
  3.       private String name; 
  4.       public UserProxy (String name){ 
  5.            this.name = name; 
  6.       } 
  7.       @Override 
  8.        public String readFile() { 
  9.             if(name.equals("ok")){ //nêu tên người dùng là ok thì mới thực hiện phương thức của lớp User, không thì báo lỗi!                           if(instance ==null){ 
  10.                     instance = new User(name); 
  11.                   }
  12.                 return instance.readFile(); 
  13.             } 
  14.           return "You can't read file"; 
  15.         } 
  16.  }


Thử chạy chương trình test như sau :
  1. public class Main {
  2.     public static void main(String[] args) { 
  3.         UserProxy user1 = new UserProxy("ok");
  4.         System.out.println(user1.readFile());
  5.         UserProxy user2 = new UserProxy("hello"); 
  6.         System.out.println(user2.readFile()); 
  7.      } 
  8. }


Kết quả :
ok readed
You can't read file

Trên chỉ là một ví dụ nhỏ về proxy, nó còn có rất nhiều cách dùng khác. Hy vọng bạn có thể nắm bắt được các mẫu thiết kế pattern bởi nó thực sự cần thiết đối với một lập trình viên.

Monday, July 18, 2016

Refactoring - Tái cấu trúc mã nguồn - Giới thiệu

Hôm nay mình xin giới thiệu một "kỹ thuật" khá quan trọng là Refactoring. Vậy nó là gì ?

- Theo mình hiểu thì Refactoring là tái cấu trúc, tổ chức lại mã nguồn mà không làm thay đổi hành vi của nó. Bạn có thể hình dung, phần mềm của mình là 1 căn phòng ngủ, refactoring có nghĩa là trang trí, thay đổi vị trí của các đồ dùng trong phòng ngủ để nó đẹp hơn, thoải mái hơn nhưng bản chất nó vẫn là phòng ngủ chứ không phải là phòng khách hay phòng bếp.


+ Vậy tại sao bạn nên refactoring? 

- Nó giúp cải thiện cấu trúc thiết kế phần mềm của bạn.
- Giúp mã nguồn của bạn dễ hiểu hơn.
- Nó giúp bạn có thể tìm thấy nguyên nhân dẽ dàng hơn khi phần mềm của bạn dính lỗi.
- Ngoài ra nó giúp bạn viết phần mềm nhanh hơn.


+ Khi nào mình nên  refactoring ?

- Khi bạn cần thêm một funciton.
- Khi bạn cần sửa một lỗi xuất hiện trong phần mềm.
- Và khi bạn review lại mã nguồn.


+ Khi nào bạn không nên refactoring ?

- Khi mã nguồn của bạn phải làm việc hầu như là chính xác trước khi bạn refactoring. Nếu mã nguồn của bạn chưa hoạt động chính xác hoặc chưa chạy được. Bạn không nên refactoring.
- Khi phần mềm của bạn đã đến deadline.

+ Một số vấn đề với refactoring :
- Khi bạn làm việc với database: Khi phần mềm của bạn làm việc với db, nó đã có một quan hệ chặt chẽ với db. Việc sử dụng refactoring làm bạn phải thay đổi cấu trúc của DB.
- Thay đổi interface : khi bạn đã public interface của bạn, việc tái cấu trúc lại nó cũng là một vấn đề.
- Khi bạn thay đổi thiết kế, việc refactoring gặp rất nhiều khó khăn, hầu như bạn phải đập và viết lại mới.

+ Vậy mã nguồn như thế nào là mã nguồn chưa tốt, cần refactoring ? 

- Có rất nhiều cách nhận biết mã nguồn của bạn chưa tốt (bẩn hay "bóc mùi"), sau đây là một số cách nhận biết cơ bản :
      - Duplicated Code : code của bạn có sự trùng lặp, khi có một đoạn mã với chức năng giống hệt được viết tại 2 nơi khác nhau.
      - Long Method : phương thức của bạn quá dài - tính theo số dòng code.
      - Large Class : Khi class của bạn chứa các phương thức và thuộc tính của như một class khác. Lấy một ví dụ : bạn có một class làm việc với DB nhưng class đó lại chứa những phương thức cũng như thuộc tính của class hiển thị View cho người dùng.
      - Long Parameter List : Khi phương thức của bạn có quá nhiều tham số.
      - Primitive Obsession : Khi bạn dùng các kiểu nguyên thủy để đại diện cho thực thể. Ví dụ bạn có một danh sách người chơi, bạn dùng các 1 mảng các con số như 1, 2, 3 để đại diện cho các người chơi, như vậy bạn đã mắc lỗi này.
      - Switch Statements : Bạn nên cần thần khi làm việc với các câu lệnh switch. Bơi nó là nơi rất dẽ xuất hiện code "bẩn".

+ Hy vọng qua bài viết này bạn sẽ có cái nhìn khái quán về refactoring . Bài viết dựa trên slide của thầy Nguyễn Ngọc Tú .  Download slide tại : http://www.mediafire.com/?7s55au5tp3kwfch
   

Tuesday, June 7, 2016

J2EE - Basic component of struts 2

- Các component chủ yếu của Struts 2 bao gồm :
     - Action : là component của server, là tầng gọi tất cả các xử lí logic, bussiness để xử lí request của người dùng. Và nó sẽ tương tác trực tiếp với các model, cũng như cung cấp dữ liệu cho View.
     - Interceptor : Interceptor tương tự như servlet filter. Interceptor được gọi trước khi action được gọi và sau khi action xử lí xong.
     - The value stack : là nơi chứa tất cả các thông tin cần thiết.
     - The OGNL : The object graph navigation language, giúp lấy dữ liệu từ value stack. Ngoài ra nó còn giúp chuyển đổi và truyền dữ liệu.
     - Validation : cung cấp khả năng validation các dữ liệu.

Monday, June 6, 2016

J2EE - Design Pattern MVC

Là mẫu thiết kế ứng dụng theo 3 tầng : View - Model - Controller. Mỗi phần có một chức năng, nhiệm vụ riêng biệt với các phần khác.

- Tại sau cần phải tách ứng dụng của mình thành 3 phần ?
     - Thứ nhất : làm như vật sẽ dẽ dàng trong công việc quản lí code. Bởi các thành phần này tách biệt lẫn nhau. Sự ràng buộc của nó rất ít. 
     - Thức hai : dẽ dàng nâng cấp, bảo trì.Bởi vì các thành phần MVC là các thành phần đọc lập và mỗi thành phần đảm nhiệm một chức năng, cũng như nhiệm vụ riêng biệt.

- Thành phần trong MVC : như tên gọi của nó thì ta có 3 thành phần:
     - View : là tầng hiển thị các component tương tác với người dùng. Tức và phần giao diện mà người dùng có thể nhìn thấy.
     - Model : là tầng chứa bussiness, logic của ứng dụng. 
     - Controller : nhiệm vụ điều hướng các yêu cầu của người dùng tương ứng với các model.

- MVC làm việc như thế nào ?
     - Đầu tiên thông qua View, người dùng sẽ gửi 1 request lên server. Và yêu cầu này sẽ được gửi đến Controller.

     - Tiếp theo controller sẽ chuyển dữ liệu của request vào model. Và model sẽ xử lí và truyền dữ liệu lên View.

     - Sau khi view đã có dữ liệu từ model. Nó sẽ transforms thành các output tương ứng. Và cuối cũng trả về response cho người dùng.

Sunday, June 5, 2016

J2EE - Giới thiệu tổng quan về Framework Struts 2

- Đầu tiên mình xin nói qua một chút khái niệm cũng như đặc điểm của một framework :
     - Framework là một tập hợp của các interface và các class giúp phát triển một ứng dụng.
     - Một framework cung cấp cách phương thức sử dụng ở nhiều trường hợp khác nhau.
     - Vai trò của một framework, framework cung cấp sẵn các công cụ, các phương thức cho một công việc nào đó cụ thể.
     - Đặc điểm của một framework :
           - Dễ dàng cho việc nâng cấp và bảo trì.
           - Có khả năng mở rộng và dẽ sử dụng.
           - Cho phép tái sử dụng code.

- Tiếp theo mình sẽ giới thiệu struts 2:
      - Struts 2 : là một open resource được phát triển với Craig McClanahan và được hỗ trợ The Apache Software Foundation.
       - Struts 2 : là một framework theo mô hình MVC. Dựa trên Struts 1 và là cải thiện của struts 1. Struts 2 việc định nghĩa các thành phần trở nên đơn gian và sáng sủa hơn.
       - Mô hình làm việc của Struts 2 :

     - Trong struts 2 là chỉ bao gồm 1 controller và controller này có thể chứa các controller khác.
     - Sau khi nhận request của người dùng, controller sẽ xác định xem sẽ gọi đến Action nào.Sau đó dữ liệu truyền vào model.
     - Sau đó Action sẽ chuyển hướng đến View và View sẽ lấy dữ liệu từ model và trả về response cho người dùng.
     - Mô hình chi tiết hơn :

          - Khi người dùng có 1 request lên server. Thì request sẽ chuyển đến ActionMapper và sau đó nó sẽ đi qua các filter.
           - Sau đó nó sẽ đọc file struts.xml, tùy thuộc vào config trong file struts.xml. ActionProxy sẽ chuyển đến Action tương ứng. Trước khi gọi Action thì nó sẽ các gọi các interceptor nếu có. Sau đó nó gọi đến Action thật sự và nó trả về resuilt.
          - Sau khi có Resuilt nó sẽ định hướng đến View, sau đó nó tiếp tục đi qua các interceptor và trả về Response cho người dùng.