Ở phần này chúng ta sẽ tìm hiểu về IoC và cách để implement nó. Đây là bước đầu tiên để đạt được mục tiêu làm giảm sự phụ thuộc giữa các lớp ứng dụng. Các bước được minh họa theo follow sau:
Ở phần này chúng ta sẽ tìm hiểu về IoC và cách để implement nó. Đây là bước đầu tiên để đạt được mục tiêu làm giảm sự phụ thuộc giữa các lớp ứng dụng. Các bước được minh họa theo follow sau:
Chắc hẳn các thuật ngữ Inversion of Control (IoC), Dependency Inversion Principle (DIP), Dependency Injection (DI), và IoC containers không còn xa lạ với nhiều người. Tuy nhiên không dễ để làm rõ sự khác nhau giữa các khái niệm này.
Loạt bài viết này cố gắng mang đến cho các bạn cái nhìn tổng quan nhất, với mong muốn cùng các bạn khám phá kiến thức về IoC, DIP, DI..
Lập trình đôi (tiếng Anh: Pair Programming) là kiểu lập trình đòi hỏi hai kỹ sư phần mềm cùng tham gia một nỗ lực lập trình chung trên một máy trạm, nghĩa là chỉ có một màn hình, một bàn phím. Mỗi người thực hiện việc mà người kia hiện không làm. Ví dụ, người này gõ các bộ test đơn vị (unit test), người kia nghĩ về các lớp đầu vào (input) sẽ thỏa mãn bộ test đó; hoặc người này viết mã còn người kia quan sát để hướng dẫn hoặc kiểm lỗi. Người ta khuyên rằng hai người nên luân phiên đổi vai trò, khoảng nửa giờ một lần. Xem thêm
Xuất phát từ mấy vấn đề nên muốn cover lại kiến thức về static và singleton.
– Một là để hiểu rõ thêm vấn đề
– Hai là làm rõ thêm vấn đề
Vậy static có đặc điểm gì? Khi nào nên dùng nó?
Singleton thì sao? Dùng thế nào? Các vấn đề cần lưu ý khi sử dụng?
Định nghĩa: một class static sẽ không cho bạn tạo một cài đặt. Nghĩa là bạn sẽ không thể sử dụng từ khoá new để tạo object. Muốn sử dụng methods và properties cần khai báo thêm từ khoá static và gọi trực tiếp bằng tên lớp. Xem thêm
Đầu tiên chúng ta bắt đầu với bài toán quản lý sản phẩm với các nghiệp vụ phức tạp. Ví dụ hệ thống quản lý sản phẩm của các trang thương mại điện tử (Amazon, shoppe, tiki..).
Với bất kì sản phẩm phần mềm nào, chúng ta đều có chung mục đích thiết kế:
– DRY (Don’t Repeat Yourself), các nghiệp vụ được phân tách rõ ràng, cô đọng và tập trung cao.
– Có thể mở rộng, sửa đổi các thành phần độc lập.
– Linh hoạt trong việc phát triển.
– Dễ dàng test và bảo trì. Xem thêm
Để hình dung rõ hơn, lần này chúng ta sẽ xem xét bài toán thực tế khi quản trị hệ thống muốn xóa một đơn hàng. Chúng ta cần xóa dữ liệu ở 2 bảng Orders và OrderDetails.
Theo cách làm thông thường, chúng ta sẽ xóa dữ liệu bảng OrderDetails trước, sau đó xóa dữ liệu bảng Orders. Với cách làm này rủi ro xảy ra nếu sau khi xóa dữ liệu bảng OrderDetails xong, một exception xảy ra (ví dụ kinh điển là mất mạng) lúc này dữ liệu bảng Orders chưa được xóa, dẫn tới việc không đảm bảo tính toàn vẹn dữ liệu và có thể gây lỗi hệ thống khi truy xuất đơn hàng.
Để giải quyết bài toán này. Chúng ta sử dụng pattern UnitOfWork, thực hiện việc xóa dữ liệu ở 2 bảng trong cùng 1 transaction. Bất kì ngoại lệ nào xảy ra, dữ liệu sẽ được rollback. Nếu thao tác xóa dữ liệu thành công, transaction sẽ được commit.
Trong bài viết này, chúng ta sẽ cùng thảo luận về Unit of Work Design Pattern.
Nội dung chính:
- Lợi ích khi sử dụng Unit of Work design pattern?
Work và Unit
trong ứng dụng phần mềm.- Logical transaction! = Physical CRUD.
- So sánh với một transaction.
- Ý tưởng việc implement UOW.
- Code demo C#
Khái niệm UOW
- First it maintains in-memory updates.
- Second it sends these in-memory updates as one transaction to the database.
Giải thích
– Thứ 1: uow quản lý các trạng thái cập nhật dữ liệu trong bộ nhớ.
– Thứ 2: uow thực hiện cập nhật tất cả dữ liệu trong bộ nhớ “như là – một transaction” vào database.
Từ khái niệm trên, chúng ta rút ra được lợi ích khi sử dụng uow
- Quản lý danh sách các đối tượng logic nghiệp vụ được thay đổi trong một transaction.
- Khi một transaction được complete, tất cả thay đổi sẽ được gửi tới database như một
big unit of work
Một cách đơn giản để định nghĩa Work
là: "Thực hiện một vài tác vụ".
Các tác vụ ở đây có thể là Thêm, Sửa, Xóa dữ liệu.
Chúng ta có thể cùng xem một ví dụ về việc ứng dụng quản lý khách hàng. Khi chúng ta thêm/sửa/xóa khách hàng trong database, đó là một unit.
Kịch bản đơn giản của chúng ta đó là:
1 customer CRUD = 1 unit of work
Trong bài toán thực tế, một khách hàng có thể có nhiều địa chỉ giao hàng khác nhau (địa chỉ nhà, địa chỉ cơ quan…).
Tiếp theo ví dụ trên, chúng ta xem xét ông khách hàng Shiv. Giả sử ông này có 2 địa chỉ, vậy khi thay đổi thông tin của khách hàng Shiv này, chúng ta cần thay đổi 3 bản ghi. Xem xét kịch bản như sau:
3 Customer CRUD = 1 Logical unit of work
Trong các dự án thực tế, chúng ta có thể đưa nhiều tác vụ khác nhau vào một unit of work.
Một ví dụ đơn giản khác, đó chính là bài toán rút tiền tại cây ATM. Khi khách hàng thực hiện rút tiền, ngân hàng cập nhật thông tin bảng giao dịch, cập nhật số dư khách hàng, gửi tin nhắn, in hóa đơn.. Tất cả các tác vụ đó có thể đưa vào một UOW
Một UOW sẽ rất khác với một transaciton database. UOW chỉ gửi những bản ghi được thay đổi tới database mà không phải tất cả các bản ghi!
Điều này có nghĩa là gì?
Ví dụ ứng dụng của bạn lấy từ DB ra 3 bản ghi dữ liệu, nhưng chỉ thay đổi 2 trong 3 bản ghi đó. UOW chỉ gửi 2 bản ghi được thay đổi này tới DB để tiến hành cập nhật. Việc này giúp tối ưu performance cho hệ thống của bạn.
Tóm lại
1 Unit of work = Modified records in a transaction
Bước 1: Tạo Interface
Theo phần trước đã thảo luận, chúng ta biết rằng UOW theo dõi và quản lý những thay đổi trong các đối tượng nghiệp vụ.
Bây giờ hãy xem xét bài toán với rất nhiều các đối tượng nghiệp vụ với nhiều kiểu khác nhau. Ví dụ bạn có thể có customer, suplier, account…Các đối tượng này chính là các entities mà UOW quan tâm và xử lý.
Xem xét kiến trúc sau
Với thiết kế UOW tracking nhiều đối tượng, chúng ta có thể giảm thiểu rất nhiều số mã trùng lặp.
Đầu tiên chúng ta tạo interface IEntity
như sau:
public interface IEntity { int Id { set; get; } void Insert(); void Update(); List<IEntity> Load(); }
Các đối tượng Customer, Supplier, Order sẽ implement interface này, theo kiến trúc đơn giản như sau:
Bước 2: Implement the IEntity interface
public class Customer : IEntity { private int _CustomerCode = 0; public int Id { get { return _CustomerCode; } set { _CustomerCode = value; } } private string _CustomerName = ""; public string CustomerName { get { return _CustomerName; } set { _CustomerName = value; } } public void Insert() { DataAccess obj = new DataAccess(); obj.InsertCustomer(_CustomerCode, CustomerName); } public List<IEntity> Load() { DataAccess obj = new DataAccess(); Customer o = new Customer(); SqlDataReader ds = obj.GetCustomer(Id); while (ds.Read()) { o.CustomerName = ds["CustomerName"].ToString(); } List<IEntity> Li = (new List<Customer>()).ToList<IEntity>(); Li.Add((IEntity) o); return Li; } public void Update() { DataAccess obj = new DataAccess(); obj.UpdateCustomer(_CustomerCode, CustomerName); } } Xem thêm