Datgs' Blog

Quyết chiến quyết thắng !

Archive for the category “OOP”

Design Pattern: Sự khác nhau giữa Bridge và Strategy (Policy)

Nghiên cứu về design pattern, việc nắm vững bản chất của các Pattern là rất quan trọng. Nếu không sẽ rất dễ nhầm lần giữa các Design Patterns với nhau.

Bridge Pattern và Policy Pattern là một ví dụ. Bạn có thể tìm thấy tài liệu về chúng ở khắp nơi trên Google. Chúng hao hao giống nhau nếu bạn cứ dán mắt vào mấy cái Diagram. Và sự thật là phải mất nhiều thời gian mình mới phân biệt được chúng. Vậy sự khác nhau giữa chúngđây là gì:

1. Brige Pattern là để tách rời phần xử lý (giải thuật…) với phần chủ thể (nơi thực thi các giải thuật đó). Phần xử lý hầu như chỉ có tác dụng bên trong phần chủ thể và không bao giờ được sử dụng ở các nơi khác. Ngoài ra các phần xử lý hầu như chỉ sử dụng cho chủ thể tương ứng (ví dụ nếu ta xác định một Bridge giữa 2 class A và A’ thì class A’ sẽ chỉ được xử dụng trong A và không sử dụng trong B (cùng abstract với A)

Đúng như tên gọi của nó, Brige Pattern bao gồm phần Abstract định nghĩa 2 đầu của một cây cầu. Các Implementation triển khai các Abstract đó thành từng cặp, và chỉ dùng theo cặp. Không có mục đích “thay đổi linh hoạt” như Strategy Pattern.

Chú ý là không chỉ là Brige giữa các cặp đôi, mà Bridge có thể mở rộng cho một bộ các “đầu mối” khác nhau nữa.

Ví dụ bạn Abstract của một hoạt động Import dữ liệu bao gồm:
- Phần đọc dữ liệu/ Chuẩn hóa dữ liệu/ Lưu nháp
- Phần validator, đảm bảo dứ liệu tuân thủ business
- Phần Intergration, đưa dữ liệu vào cơ sở dữ liệu thực

Tại sao lại dùng Bridge ở đây. Đơn giản là vì: thứ nhất bạn phải kết nối giữa 3 “đầu cầu” trên. Thứ hai, khi bạn Import Addresses, Import Products… bạn không thể sử dụng Validator của Import Address làm validator của Import Products được.

Hữu ích: bạn có thể dễ dàng thay đổi nâng cấp của Import Addresses mà không cần quan tâm đến business của Import Products có thay đổi hay không. Đây gọi là nâng cấp từng phần.

2. Strategy (Policy) Pattern thì khác, một chủ thể có thể sự dụng linh hoạt khác policy khác nhau.

Đó giải thích tên gọi của nó, “Chiến lược”. Chiến lược gì? Chiến lược sử dụng các triển khai của Abstract. Lúc này tôi có rất nhiều dữ liệu tôi muốn sử dụng Quick Sort, lúc khác tôi chỉ có vài phần từ thôi nên tôi dùng Bubble Sort là đã ok rồi….

Design Pattern – Structural Pattern – Bridge Pattern

Đúng như tên gọi Bridge Pattern, đây là kiểu cấu trúc cầu nối giữa “các bên”, bên thực thi và bên chủ đầu tư :D .

Xem http://nthoai.blogspot.com/2008/05/mot-cau-chuyen-ve-bridge-pattern.html

Đó là một ví dụ cực kỳ thú vị về bridge pattern.

Cũng giống như Adapter pattern, các bên thực thi có cùng nhiệm vụ, nhưng khác ở chỗ kết xuất ra những kết quả khác nhau. Mỗi chủ đầu tư có một yêu cầu kết quả riêng và thường chỉ có một đơn vị thực thi có thể thỏa mãn.

Design Pattern – Creational Pattern – Prototype (nguyên mẫu)

Trong phát triển phần mềm, prototype pattern được sử  dụng khi bạn muốn tạo ra một đối tượng có kiểu đã được quy định bởi một thực thể mẫu bằng cách sao chép thực thể ấy để tạo thành đối tượng mới.

Prototype pattern được sử dụng trong trường hợp:

+ Tránh việc tạo nhiều lớp con cho mỗi đối tượng tạo như của abstract factory pattern
+ Giảm chi phí để tạo ra một đối tượng mới theo “chuẩn”, tức là việc này tăng performance so với việc sử dụng từ khóa new để tạo đối tượng mới

Để cài đặt prototype pattern, tạo ra một clone() method ở lớp cha, và triển khai ở các lớp con.

Agile tổng quan

1) Agile là gì?

Là phương pháp phát triển phần mềm chú trọng vào sự tiến hóa, phát triển của nó theo thời gian (xây dựng bồi đắp thêm, mở rộng thêm) với sự kế thừa tối đa, hiệu chỉnh lại cho phù hợp và tránh phải bắt đầu làm một thành phần nào đó lại từ đầu.

Bản chất của Agile chính là tạo nên những sự thay đổi theo thời gian.

Vì vậy Agile chia dự án thành các giai đoạn nhỏ, mỗi một giai đoạn sẽ tập chung phát triển một phần mềm hoàn chỉnh, bao gồm: lấy yêu cầu, phân tích, thiết kế, code, test, fixbugs và documentation.

Trong Agile, coi trọng nhất là các giao tiếp trực tiếp giữa các đối tượng tham gia dự án, hơn là qua các tài liệu… Nhất là việc giao tiếp giữa đội dự án với khách hàng.

2) Công việc thường xuyên với Agile

Refactoring code: tức là chỉnh sửa lại code, mở rộng tính năng mà không phải code lại từ đầu

Developer testing: người phát triển tự tay test phần mềm do mình làm ra

3) Các giá trị mà Agile hướng tới

a) Tính cá thể & tính tương tác

Agile coi trọng tương tác giữa các cá nhân hơn là việc sử dụng các quy trình và công cụ để áp đặt cho tất cả các thành viên.

Thật vậy, với agile, không có gì gọi là đầy đủ ngay từ đầu, các vấn đề sẽ được phát hiện ngay trong quá trình phát triển phầm mềm, được xây đắp, khắc phục dần dần. Cho nên các thành viên càng có môi trường cộng tác tốt, sẽ càng nảy sinh nhiều vấn đề, phần mềm càng hoàn thiện.

b) Sản xuất phần mềm

Mục đích của agile là các phần mềm, tạo ra các phiên bản chạy được. Nói như vậy không phải là agile phủ nhận vai trò của “tài liệu đầy đủ”. Nhưng với agile, khi chưa có tài liệu đầy đủ, đã phải có phiên bản chạy được. Việc chạy đúng hay sai là vấn đề thời gian, khi mà phần mềm có thể thay đổi theo các yêu cầu của khách hàng.

Nói cách khác, phần mềm sẽ có đồng thời với việc củng cố các tài liệu mô tả.

c) Cộng tác với khách hàng

Cũng như đã nói ở trên, với agile, không có gì gọi là đầy đủ ngay từ đầu, việc cộng tác tốt với khách hàng là một nguồn bổ sung chủ yếu cho các thiếu sót của phiên bản cũ, để ra đời các phiên bản mới.

Theo phương pháp phát triển cũ, phải mất nhiều thời gian phân tích, thiết kế mới cho ra đời một mớ các tài liệu dự án. Sau đó, phải thương lượng với khách hàng cẩn thận rồi mới bắt tay vào làm. Khách hàng sẽ rất cẩn trọng, bởi mọi thay đổi trong quá trình phát triển của họ (và giả sử rằng thay đổi này rất quan trọng) cũng khiến cho họ mất thời gian và tiền bạc thể thảo luận lại với bên phát triển. Với agile thì không, bởi vì những “thay đổi” là bản chất của agile.

d) Phản ứng với các thay đổi

Bản chất của agile chính là tạo nên những sự thay đổi theo thời gian. Vì vậy khả năng phản ứng với các thay đổi là đỏi hỏi hết sức quan trọng. Trong agile, các kế hoạch chỉ là phần “chết”. Còn nội dung của kế hoạch sẽ được cập nhật hết sức linh hoạt để phù hợp với các thay đổi.

4) Triển khai Agile

a) XP (10-20)

Hình thức “tự tổ chức” (self-organization) là một đặc điểm chung của các dự án theo triết lí Agile.
Trong một dự án phần mềm, những hiểu biết về sản phẩm luôn được nắm giữ bởi nhiều cá nhân. XP thừa nhận thực tế này bằng cách tạo ra một nhóm làm việc hỗn hợp với đầy đủ các vai trò cần thiết. Một đội dự án XP thường bao gồm các thành viên sau đây:

Đại diện khách hàng (chịu trách nhiệm về requirement)

Người quản lý sản phẩm (chịu trách nhiệm về sản phẩm, định hướng sản phẩm, thứ tự ưu tiên các tính năng).

Các chuyên gia nghiệp vụ (chịu trách nhiệm về lĩnh vực mà phần mềm đang hướng tới)

Thiết kế giao diện

Lập trình viên

Tester

Quản lý dự  án (hướng dẫn các developer, kết nối các hoạt động thông suốt)

b) Scrum (8)

Scrum là một quy trình triển khai agile, trong đó mỗi một giai đoạn phát triển tính năng không vượt quá 30 ngày. Cái tên scrum xuất phát từ bộ môn Rugby (bóng bầu dục). Mỗi một sprint như là một hiệp thi đấu.

Cùng chung ý tưởng đó, scrum đề ra các yêu cầu để có thể được hoàn thành trong vòng 30 ngày. Một tính năng cụ thể không được công nhận như đang được hoàn thành cho đến khi nó được phân tích, thiết kế, mã hoá, kiểm tra, refactor, và tài liệu hóa.

Một sprint gọi là thành công nếu nó triển khai được tất cả các tính năng trong yêu cầu.

Nếu như có một tính năng nào đó chưa được triển khai đầy đủ, nó sẽ được hold lại và chuyển tới sprint sau.

c) Crystal Orange (20-4o)

Tiếp tục tìm hiểu..

d) DSDM (*)

Tiếp tục tìm hiểu

Hình thức “tự tổ chức” (self-organization) là một đặc điểm chung của các dự án theo triết lí Agile.
Trong một dự án phần mềm, những hiểu biết về sản phẩm luôn được nắm giữ bởi nhiều cá nhân. XP thừa nhận thực tế này bằng cách tạo ra một nhóm làm việc hỗn hợp với đầy đủ các vai trò cần thiết. Một đội dự án XP thường bao gồm các thành viên sau đây:

Design Pattern – Behavior Pattern – Stragety (Policy) Pattern

Là mẫu thiết kế “chiến lược” sử dụng các giải thuật khi chạy chương trình.
Trong các ngôn ngữ lập trình không hỗ trợ tính đa hình, vấn đề liên quan đến Design Pattern này được điều khiển bởi các mẫu phản chiếu (tham chiếu), giống như con trỏ (pointer).

Mẫu này không thấy ngay được trong các ngôn ngữ lập trình hàm (first-class function).

Mẫu này rất hữu dụng trong các tình huống cần phải thay đổi động các giải thuật (sử dụng các giải thuật khác nhau) trên một ứng dụng.

Ví dụ (có thể xem ở link này: http://www.cumps.be/design-patterns-strategy-pattern/) là một ví dụ rất hay về Stragety Pattern. Trong đó mô tả các đối tượng trong một game với chung một phương thức nhưng với cách thực hiện khác nhau.

Hoặc có thể xem http://en.wikipedia.org/wiki/Strategy_pattern có rất nhiều mã nguồn ví dụ bạn có thể tham khảo.

Design Pattern – Creational Pattern – Factory Method

1) Một phương án giải quyết vấn đề tạo object.

2) Câu hỏi là: Làm sao để tạo object mà không cần phải chỉ rõ class cụ thể của object đó là gì?

3) Lợi ích: cho phép chỉ rõ “nội dung” của đối tượng cần tạo. Thường sử dụng các hàm static.

4) Ví dụ về hàm tạo theo cách đặt tên mô tả:

class Complex
{
     public static Complex fromCartesian(double real, double imag) {
         return new Complex(real, imag);
     }

     public static Complex fromPolar(double modulus, double angle) {
         return new Complex(modulus * cos(angle), modulus * sin(angle));
     }

     private Complex(double a, double b) {
         //...
     }
}

Complex c = Complex.fromPolar(1, pi); // Same as fromCartesian(-1, 0)

5) Ví dụ về hàm tạo theo các đóng gói:

public interface ImageReader {
    public DecodedImage getDecodedImage();
}

public class GifReader implements ImageReader {
    public DecodedImage getDecodedImage() {
        return decodedImage;
    }
}

public class JpegReader implements ImageReader {
    // ....
}
public class ImageReaderFactory {
    public static ImageReader getImageReader(InputStream is) {
        int imageType = determineImageType(is);

        switch(imageType) {
            case ImageReaderFactory.GIF:
                return new GifReader(is);
            case ImageReaderFactory.JPEG:
                return new JpegReader(is);
            // etc.
        }
    }
}

6) Hạn chế:

- Nếu hàm tạo (construct method) của class là private, sẽ không tạo được object bằng hàm tạo, mà buộc phải sử dụng hàm factory.
- Không thể mở rộng (kế thừa thêm nữa) ở các subclass nếu hàm tạo là private.
- Không còn đúng cho các subclass. Nếu có subclass gọi hàm factory, nó trả về instance của class chứ khôngphải là nó.

- Giải quyết: cần phải có sự hỗ trợ thêm nữa của các ngôn ngữ lập trình.

Syntax của ngôn ngữ lập trình

Về mặt hình thức thì đúng là các ngôn ngữ giống nhau về syntax. Có thể gọi đó là trào lưu cũng được. Trước đây khi ngôn ngữ C ra đời, nó được trào đón và thực sự vượt hẳn lên trên Pascal trong việc phát triển các hệ thống. Và đẩy Pascal trở về đúng vị trí của nó: một cuốn sách giáo khoa về lập trình. Và các ngôn ngữ sau này, thông thường là Like C.

Những phá cách theo kiểu Python không phải là không được chào đón. Tuy nhiên Like C vẫn được ưa thích hơn cả. Theo chủ quan của anh, và có lẽ cũng là của các lập trình viên khác là có lẽ là vì nó “vừa đủ”. Vừa đủ ngắn và vừa đủ dài (hình thức bao gồm keyword, operator …). C cũng vừa đủ giản đơn cho người mới học lập trình, và cũng đủ phức tạp để thể hiện được ý tưởng của các giải thuật cơ bản. Nó khó học hơn pascal một chút (một chút thôi), nhưng viết mã đơn giản hơn Pascal gấp nhiều lần. Vì vậy lựa chọn C là hợp lý.

Các ngôn ngữ sau này hầu hết được sinh ra từ ngôn ngữ C (tức là xây dựng nên từ các dòng code C).

Về mặt nội dung, mỗi ngôn ngữ lập trình là một công cụ với mục đích cụ thể. Không có ngôn ngữ nào ra đời chỉ để “cho vui”. Sự khác nhau và giống nhau của các ngôn ngữ là ở chỗ “nó được sử dụng để làm gì?”.

Và cũng vì đó là một công cụ, một công cụ dành cho con người sử dụng. Cho nên, không nên nghĩ rằng cái này khó lắm, cái kia khó lắm không học được đâu !!! Mà nên nghĩ rằng cái này chưa biết, cái kia biết rồi. Cũng từa tựa như là việc sử dụng MS Word vậy thôi.

So sánh như vậy là hơi khập khiễng, bởi vì MS Word là công cụ ứng dụng dành cho nhân viên văn phòng (rộng hơn là everybody), còn ngôn ngữ lập trình là công cụ đa năng (và chỉ một số đối tượng được chuyên môn hóa mới có thể tiếp cận được).

Quan trọng nhất của việc sử dụng ngôn ngữ lập trình là tư duy logic, tư duy ở cấp độ con số.

C# Generics

Kiểu mảng cũ

using System;

using System.Collections;

namespace TestApp {

class Test {

[STAThread]

static void Main(string[] args) {

ArrayList list = new ArrayList();

list.Add(3);

list.Add(4);

//list.Add(5.0);

int total = 0;

foreach(int val in list) {

total = total + val;

}

Console.WriteLine( “Total is {0}”, total);

}

}

}

Generics

List<int> aList = new List<int>();

aList.Add(3);

aList.Add(4);

// aList.Add(5.0);

int total = 0;

foreach(int val in aList) {

total = total + val;

}

Console.WriteLine(“Total is {0}”, total);

Viết generics class

//MyList.cs

#region Using directives

using System;

using System.Collections.Generic;

using System.Text;

#endregion

namespace CLRSupportExample {

public class MyList<T> {

private static int objCount = 0;

public MyList() { objCount++; }

public int Count {

get { return objCount; }

}

}

}

//Program.cs

#region Using directives

using System;

using System.Collections.Generic;

using System.Text;

#endregion

namespace CLRSupportExample {

class SampleClass {}

class Program {

static void Main(string[] args) {

MyList<int> myIntList = new MyList<int>();

MyList<int> myIntList2 = new MyList<int>();

MyList<double> myDoubleList = new MyList<double>();

MyList<SampleClass> mySampleList = new MyList<SampleClass>();

Console.WriteLine(myIntList.Count);

Console.WriteLine(myIntList2.Count);

Console.WriteLine(myDoubleList.Count);

Console.WriteLine(mySampleList.Count);

Console.WriteLine( new MyList<sampleclass>().Count);

Console.ReadLine();

}

}

}

Methods với Generics

public class Program {

public static void Copy<T>(List<T> source, List<T> destination){

foreach (T obj in source) {

destination.Add(obj);

}

}

static void Main(string[] args)

{

List<int> lst1 = new List<int>();

lst1.Add(2);

lst1.Add(4);

List<int> lst2 = new List<int>();

Copy(lst1, lst2);

Console.WriteLine(lst2.Count);

}

}

Singleton design pattern

Singleton là một design pattern khá là sơ đẳng. Kiểu lập trình này trong OOP cho phép khởi tạo đối tượng một lần (ví dụ như tạo kết nối với CSDL chẳng hạn, bạn chỉ cần mở kết nối một lần và thực hiện rất nhiều truy vấn trên cùng kết nối đó. Chứ không cần cứ mối truy vấn lại kết nối lại một lần.

Trong C#, Singleton được cài đặt như  sau

class Singleton

{

/* biến static instance, tạo instance một lần ở đây, những lần sau sẽ sử dụng lại*/

private static Singleton instance;

private static int numOfReference;

private string code;


private Singleton()

{

numOfReference = 0;

code = “Maasoom Faraz”;

}


public static Singleton GetInstance()

{

/* rất đơn giản, nếu instance đã tồn tại thì trả về , ngược lại một instance mới sẽ được tạo ra và trả về */


if(instance == null)

{

instance = new Singleton();

}

numOfReference++;

return instance;

}


public static int Reference
{

get { return numOfReference; }

}

public string Code
{

get { return code; }

set { code = value;}

}

}

Observed Pattern Design

public class Parent
{    
     public String Name { getset; }
     public void OnChildCry(Child c){
        Console.WriteLine(this.Name + ” heard “ + c.Name + ” cry”);
    }
}

public class Child
{
    public Child()
    {
        Parents = new List<Parent>();
    }
    public String Name { getset; }
    public List<Parent> Parents { getset; }

     public void Cry()
   {
        foreach(Parent p in Parents)
            p.OnChildCry(this);
    }
}

 class Program
{
    static void Main(string[] args)
    {
        Parent Ralph = new Parent { Name = “Ralph” };
        Child Billy = new Child { Name = “Billy” };
        Parent Mary = new Parent { Name = “Mary” };
         Billy.Parents.Add(Ralph);
        Billy.Parents.Add(Mary);
         Billy.Cry();
         Console.Read();
    }
}

Post Navigation

Follow

Get every new post delivered to your Inbox.