Dependency Injection with Spring.Net p1
Posted On Friday, May 16, 2008 at at 1:35 PM by Unknown(Bài viết dịch từ bài Dependency Injection with Spring.Net của David Consdorf, thêm hành thêm tiêu rồi nấu lại bởi Nguyễn Thoại )
Introduction:
- Spring.Net là một framework hỗ trợ nhiều chức năng cho những ứng dụng .NET. Phần nhân chính của Spring.Net là Dependency Injection hay còn được biết đến với tên gọi Inversion of Control(IoC). Tôi có bổ sung đoạn giới thiệu vui về 2 mẫu design pattern Factory. Ngoài ra, với những đoạn code mẫu mà tác giả cung cấp (ở các phần sau), hi vọng các bạn sẽ có một cái nhìn cơ bản về Spring.Net và có thể áp dụng nó cho những ứng dụng của mình.
Spring.Net: Overview
- Spring.Net là một framework nguồn mở cung cấp một tập các components giúp người lập trình áp dụng được những kĩ thuật nổi tiếng như Dependency Injection và Aspect-Oriented Programming. Bộ Spring.Net được chuyển từ phiên bản Java của Spring framework. Ngày nay, phiên bản Java của Spring đã được sử dụng rất thành công trong rất nhiều ứng dụng. Cùng với sự thành công của người anh em Spring Java, sự xuất thiện của Spring.Net chỉ là vấn đề thời gian. Thực sự như vậy, kể từ khi ra đời, Spring.Net đang chiếm được sự ủng hộ nhiệt tình của cộng đồng .NET
- Các chức năng của Spring.NET:
- Dependency Injection
- Aspect-Oriented Programming
- Data access support including support for NHibenrate (ORM framework)
- Web Framework
- Integration Testing
- Validation Framework
- Dynamic Reflection
- Threading and Concurrency Support
- Object Pooling
- Expression Evaluation
- Services
- Và nhiều chức năng khác...
- Cùng với sự đóng góp của cộng đồng, Spring.Net đang dần phát triển với nhiều chức năng mới đang được bổ sung thêm. Loạt bài viết này chỉ hi vọng truyền tải được chức năng thứ nhất cho các bạn. Chúng ta cũng cần lưu ý rằng Spring.Net cũng như một chiếc hộp gồm nhiều công cụ trong đó. Bạn không cần thiết phải sử dụng hết mọi thứ trong chiếc hộp này. Chúng ta có thể kết hợp một số chức năng và sử dụng những gì cần thiết cho ứng dụng của mình. Ngoài ra, Spring.Net còn được chia ra thành nhiều assemblies riêng và chúng ta không cần phải nhúng toàn bộ framework Spring vào chương trình.
Dependency Injection with a Factory Pattern
- Thành phần chính của Spring.Net là Dependency Injection(DI) còn được biết đến như Inversion of Control (IoC). Ý tưởng cơ bản của Dependency Injection là làm giảm sự phụ thuộc của những đối tượng (Objects) trong hệ thống. Dependency Injection cho người lập trình khả năng thiết kế những chương trình, trong đó các đối tượng (Objects) có thể tự thiết lập mối quan hệ đến những đối tượng khác mà nó cần. Thậm chí cho phép những tiến trình (processes) có sử dụng đối tượng làm công việc này. Mục tiêu chính của DI là hướng tới tính Loose Coupling, vì vậy nhóm những đối tượng (objects) nên làm việc độc lập với nhau, tập trung trên những behavior của chúng mà không cần biết những nhóm đối tượng khác (reference tới) sẽ làm việc như thế nào cũng như được thiết lập (construct) như thế nào.
- Để hiểu kĩ hơn về khái niệm Dependency Injection, chúng ta sẽ nhìn lại những thiết kế truyền thống của DI bằng cách sử dụng các lớp factory. Được mô tả kĩ trong các tài liệu Design Patternc có 2 mẫu thiết kế factory: Abstract Factory Pattern và Factory Method Pattern. Xin được sử dụng câu chuyện sau để giải thích cho dễ hiểu:
- Thị trường chứng khoán Việt Nam những tháng đầu năm 2008 vô cùng ảm đạm, tôi thấy mình đua đòi đầu tư chứng khoán vô những ngành bất động sản, tài chính không ổn chút nào. Trong khi đó tình hình lương thực thực phẩm trên thế giới vô cùng HOT. Sau nhiều ngày suy nghĩ,tôi quyết định đổ tiền đầu tư vô ngành thực phẩm bánh kẹo .Tôi sẽ mở một cơ sở sản xuất bánh. Trong nhóm sản phẩm bánh mì, tôi quyết định đầu tư làm bánh hambơgơ và bánh mì Sài Gòn đặc ruột thơm bơ . Như vậy phải mua máy để làm bánh, tôi vay họ hàng mua 2 cái máy sẽ làm ra 2 loại bánh trên, một máy chuyên để làm bánh mì Sài Gòn và một máy chuyên làm ra bánh hambơgơ, nhà máy của tôi sẽ thay phiên bật 2 máy đó vào các ngày chẳn và lẽ trong tuần để làm bánh, ngày nào cần làm bánh loại nào thì bật máy loại đó. Và sơ đồ nhà máy tôi như sau:
Hình 1: Abstract Factory Pattern
Bản thiết kế:
abstract class MayLamBanh
{
public static MayLamBanh ChonMayLamBanh()
{
bool ngayChan = KiemTraNgayChanLe();
if (ngayChan == true)
{
return new MayLamBanhhamburger();
}
else
{
return new MayLamBanhMiSaiGon();
}
}
public abstract Banh LamBanh();
}
class MayLamBanhhamburger : MayLamBanh {
public override Banh LamBanh() {
return new BanhHamburger();
}
}
class MayLamBanhMiSaiGon : MayLamBanh {
public override Banh LamBanh()
{
return new BanhMiSaiGon();
}
}
abstract class Banh {
}
class BanhHamburger : Banh {
}
class BanhMiSaiGon : Banh {
}
public class NhaMay {
public static void main(String[] args) {
MayLamBanh factory = MayLamBanh.ChonMayLamBanh();
Banh banh = factory.LamBanh();
}
}
- Như vậy khi áp dụng Abstract Factory Pattern là bạn tạo ra những lớp CFactory, tất cả những CFactory này sẽ implement cùng 1 interface IFactory, khi đó instance factory thuộc kiểu nào sẽ làm ra product tương ứng.
- Quay lại chuyện làm bánh, sau một thời gian tôi kiểm toán sổ sách và thấy rằng tiền lời không nhiều. Chi phí quản lý và bảo trì hai cái máy quá tốn kém trong khi đối thủ cạnh tranh thì ngày càng tạo ra sản phẩm đa dạng. Giờ nếu muốn làm ra sản phẩm bánh kem để cạnh tranh thì phải mua thêm máy khác vừa tốn kém lại tốn chi phí bảo trì. Tôi đọc báo Dân Trí và phát hiện rằng các chú kĩ sư cơ khí Việt Nam vừa chế ra một cái máy đa năng có thể tạo ra đủ loại bánh. Chỉ cần thêm vào công thức vào là máy có thể làm ra bánh theo ý muốn. Khi đó tuỳ tỉ lệ đường, tỉ lệ bột, tỉ lệ bột nở, tỉ lệ nước mà sẽ tạo ra loại bánh theo công thức. Tôi khoái quá, bán rẻ ngay 2 cái máy dỏm và vay thêm chút đỉnh mua cái máy đa năng đó về. Các chú kĩ sư cơ khí giao cho tôi bản thiết kế mới như sau:
Hình 2: Factory Method Pattern
Bản thiết kế:
class MayLamBanhDaNang : MayLamBanh
{
public Banh LamBanh(double soLuongDuong, double soLuongBot, double soLitNuoc)
{
if (soLuongDuong / soLuongBot){
return new BanhHamburger();
}
else
{
return new BanhMiSaiGon();
}
}
}
- Nhờ và cái máy này, xưởng sản xuất của tôi ăn nên làm ra và chuẩn bị lên đời thành công ty cổ phần bánh kẹo nước giải khát BSG (Bánh Mỳ Sài Gòn)
- Như vậy Factory Method Pattern là mấu thiết kế mà bạn tạo ra một interface IFactory có khai báo hàm tạo ra những product (Object). Sau đó bạn để trách nhiệm tạo ra product loại nào cho lớp CFactory implement IFactory của bạn.
Define an interface for creating an object, but let the subclasses decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses.
- Tóm lại, factory là một hoặc nhiều đối tượng chịu trách nhiệm tạo ra những đối tượng khác mà chương trình sử dụng. Nói chung, ứng dụng sẽ không biết gì về cách tạo ra những đối tượng nó cần, thay vào đó nó chỉ nên biết đến những đối tượng đó thông qua 1 interface. Bằng cách đóng gói (encapsulation) những cài đặt (implementation) và thiết lập (construct) cho lớp trong factory, chương trình của chúng ta có thể sử dụng những gì nó cần mà không biết đối tượng cụ thể nào đang được gọi, đối tượng đó được tạo ra như thể nào cũng như những đối tượng đó làm gì.
- Trong những ứng dụng lớn với khả năng hỗ trợ nhiều thiết lập, cấu hình, factories còn có thể đóng vai trò như bộ phận trung tâm thực hiện việt thay đổi những cấu hình đó. Ví dụ, nếu bạn cần chuyển đổi nhiều database component truy xuất dữ liệu MySQL và thay thế chúng bằng những component mới truy xuất dữ liệu Oracle, tất cả những gì bạn cần làm là đổi lớp factory và chuyển nó sang những component Oracle. Phần còn lại của ứng dụng sẽ không bị ảnh hưởng, bởi vì tất cả những component database đều được cài đặt (implement) từ cùng 1 interface, gồm các hàm truy xuất, lưu cũng như cập nhật và xoá dữ liệu. Còn làm cách nào mà những component đó làm việc bên dưới và loại database nào mà chúng truy xuất thực sự không quan trọng.
-----------------------------------------------------------------------------------
Vậy trong cái nhà máy làm bánh củ chuối ở trên thì DI thể hiện ở chỗ nào? Dependency Injection ở điểm sau: thời còn 2 cái máy làm 2 loại bánh, tôi thích làm ra loại nào thì tôi xài cái máy ấy. Bây giờ bánh mì SàiGòn đặc ruột thơm bơ của tôi ế ẩm vì không cạnh tranh nổi với mấy người làm bánh mì bán dạo bằng xe đạp. Cho nên tôi muốn chuyển qua sản xuất thêm bánh bao. Tôi có thể thuê hoặc mua mới một cái máy làm bánh bao tự động về để ở một chỗ trong xưởng mà không cần phải đập xây lại nhà máy sản xuất, không cần tổ chức lại khâu đóng hộp phân phối. Tôi cũng chẳng cần phải bán đi cái máy làm bánh mì Sài Gòn vì biết đâu tương lai mấy cha bán bánh mì dạo đổi sang bán keo dính duột, lúc đấy thì bật lại máy làm bánh mì để đa dạng sản xuất. Nhưng kinh doanh quả là không đơn giản với những người hiền lành, nghe lời mấy bạn kĩ sư cơ khí mua cái máy đa năng làm bánh tôi mới ôm hận. Tuy cái máy đó làm được nhiều loại bánh nhưng tốc độ làm bánh vừa chậm lại còn hao điện, ngoài ra lượng hao hụt nguyên vật liệu quá lớn khiến giá thành sản phẩm quá cao không cạnh tranh nổi với Kinh Đô Bakery. Tôi lại mang tính chủ quan, nghĩ rằng với một cái máy này là đủ nên không có máy dự phòng. Bây giờ tôi muốn thay máy khác cũng phải đợi đến lúc có máy thì mới đưa vào sử dụng chứ không thể ngừng sản xuất. Tôi quyết định liều thuê đám kĩ sư chất lượng cao vừa tốt nghiệp đại học làm riêng cho tôi một cái máy dựa trên bản thiết kế ban đầu, làm sao cho ít hao điện và nguyên vật liệu, tốc độ làm bánh nhanh hơn. 1 tháng sau đó tôi đã có được cái máy mới như mong muốn, tôi thuê xe ôm chở máy vào xưởng đặt một chỗ thoáng mát, bật điện máy mới và shut down máy cũ. Thế là dây chuyền làm bánh của tôi chạy liên tục chỉ mất một chút thời gian bật tắt mà không phải ngừng sản xuất trong thời gian dài. Tuy vậy hệ thống của tôi vẫn có chút bất tiện. Như các bạn thấy lúc mới mở phân xưởng, tôi sử dụng 2 cái máy để làm bánh. Lúc cần làm bánh hambơgơ tôi phải vào phân sưởng tắt điện máy làm bánh mì và bật điện máy kia. Đến khi có cái máy đa năng, thình thoảng lại phải chạy đến xưởng để đổi công thức làm bánh. Thật là phiền khi chạy đi chạy lại, ngừng toàn nhà máy để thay đổi. Thật may lúc trước ở công ty cũ tôi có quen một tay rất rành về hệ thống mạng điều khiển từ xa, hắn tư vấn cho tôi một hệ thống gọi là Spring cài đặt nối mạng máy làm bánh với hệ thống máy tính, tôi chỉ cần ngồi ở nhà click chuột là nhà máy của tôi sẽ làm ra bánh khác mà không cần phải ngừng hoạt động hay khởi động lại dây chuyền hoặc chạy vô phân xưởng để đổi công thức. Bị lừa lần trước tôi không tin tưởng nên lên mạng google vài cú, và tôi tìm được thông tin rằng mấy tay sản xuất kẹo dừa bên Java Indonesia đã sử dụng hệ thống Spring bên đấy mấy năm nay rồi và rất thành công.
(Các bạn đang xem phần 1)
Hi anh, em có đọc một số bài viết của anh...Anh viết rất hay và ví dụ rất dễ hiểu...Tuy vậy em có 1 thắc mắc mong đc anh giải đáp, đó là: Trong bài viết "Phỏng vấn 2 mấu thiết kế Abstract Factory và Factory Method" anh có nói là: Abstract tạo ra các Products nhờ vào sự kết hợp các đối tượng còn bác Factory Method thì làm nhờ vào sự kế thừa...Em vẫn chưa hiểu rõ lắm điều này trong 2 ví dụ(bản thiết kế) về nhà máy bánh mỳ của anh...liệu anh có thể giải thích kỹ hơn về vấn đề này được không???
Thank anh!
Chào bạn.
Abstract Factory tạo các sản phẩm bằng cách kết hợp các đối tượng còn Factory Method thì tạo ra các đối tượng nhờ vào Inheritance. Ví dụ về nhà máy của mình chỉ để nêu bật vấn đề, tuy không phải là ví dụ rõ ràng nhất nhưng nó cũng giúp bạn hiểu được sự khác nhau của 2 loại factory.
Bạn cuộn xuống phía dưới bài viết phỏng vấn 2 loại factory:http://nthoai.blogspot.com/2008/06/abstract-factory-and-factory-method.html, ở 2 dòng cuối cùng của Factory Method và Abstract Factory có 2 cái link, bạn hover chuột lên sẽ thấy lời giải thích :D, bạn sẽ hiểu trường hợp nào nên sử dụng cách nào.
-Factory Method tạo sản phẩm nhờ vào inheritance: có nghĩa là nó ko tạo 1 đối tượng cụ thể, return type của method Factory là 1 kiểu trừu tượng, ko phải là một kiểu cụ thể. Nếu xem trong trường hợp cái máy làm bánh đa năng thì return type là IBanh. Và các kiểu cụ thể là Bánh Mì Sài Gòn và Bánh Hambuger.
- Abstract Factory tạo nhiều sản phẩm nhờ vào sự kết hợp các object(đối tượng) : có nghĩa là khi cần tạo ra các đối tượng khác nhau, client sẽ sử dụng 1 object nào đó thuộc kiểu IFactory và gọi hàm tạo của object đó. Nhờ vào cơ chế polymorphism nên object Factory của bạn thuộc kiểu nào thì nó sẽ tạo ra sản phẩm tương ứng. Vì vậy trong ví dụ về 2 loại máy làm bánh thì 2 loại máy đó chính là các kiểu cụ thể của lớp trừu tượng IMayLamBanh. Kết hợp các đối tượng ở đây có nghĩa là lớp client sẽ sử dụng các đối tượng thuộc các lớp Factory để tạo ra sản phẩm mong muốn.
Hì hì, bài phỏng vấn này quen lắm, anh đọc trong cuốn Head First Design Pattern phải không?
Blog của anh ấn tượng lắm.
ha ha, hay lắm, em cũng bị trường hợp không phân biệt đc 2 thằng này, tks
Chào bác, em cũng vừa mới bị sa cơ lỡ vận ở HN, đang tính đường vào HCM City thử kiếm kế mưu sinh.
giá mà Việt Nam có khoảng 10 blog chia sẻ kinh nghiệm lập trình thế này thì cuộc sống này có phải là nơi tốt đẹp hơn không!
Em đang nghiên cứu kiến trúc của S#arp Architect from: http://www.sharparchitecture.net/. Đọc những articels này của bác giúp em thấu đáo hơn về kiến trúc này. Cảm ơn rất nhiều.
Hi anh, tôi cũng đang trên đường lập nghiệp, đang search về máy làm bánh bao, thì thấy mô hình của anh, và máy làm bánh đa năng, biết rằng đây là bí mật kinh doanh, nhưng nếu có thể anh cho tôi xin thông tin về nơi cung cấp máy. Ym của tôi duy_vo84. Cám ơn anh trước
Rất hay!
Cách viết của anh rất đơn giản, hình tượng, dễ hiểu, cảm ơn anh nhiều :)
anh Thoai Nguyen ơi, em rất thích đọc các bài viết của anh về Spring.NET. Anh có thời gian rảnh viết 1 bài về Object Pooling trong Spring.NET được không hả anh :D