Viết phần mềm trong 15′ – Nguyễn Minh Hải

Tóm tắt:

Bài viết này giới thiệu sơ lược cấu trúc cơ bản của một phần mềm để giúp tăng năng suất của lập trình viên.

Các chủ đề sau sẽ được đề cập:

Component-centric development

Layers

o Data Access Layer

o Business Object Layer

o Presentation Layer

Design patterns

Copyright:

Tác giả Nguyễn Minh Hải xin phép giữ trọn quyền tác giả đối với bài viết này. Tuy nhiên, độc giả có thể sang, chép, lưu truyền cho các bạn khác mà không cần phải xin phép tác giả (với điều kiện nguyên văn bài viết phải được giữ nguyên)

Cảnh báo:

Software Architecture chưa bao giờ là lĩnh vực hấp dẫn cả, khi nào cũng khô như ngói. Tác giả chỉ mạn phép dùng ngôn ngữ “cây nhà lá vườn” để giúp các bạn mới học tiếp xúc thêm. Sai sót là không thể tránh khỏi. Và hy vọng các bạn sẽ không ngủ gục khi chỉ mới đọc xong trang một.

Read on at your own risk. You’ve been warned !!! J

Component-Centric:

Software Engineering phát triển rất nhanh, tuy nhiên vẫn còn ở giai đoạn chập chững tập đi mà thôi. Để thiết kế và phát triển một phần mềm tiêu tốn rất nhiều tài nguyên, nhưng sau đó thì không sử dụng lại được nữa. Lấy ví dụ, để viết chương trình quản lý kho, bạn sẽ phải xử lý SQL, tạo form, tạo report, security. Sau đó, khách hàng yêu cầu viết chương trình kế tóan thì bạn lại phải viết lại những yêu cầu trên… từ đầu. Nếu thiết kế xe ô tô cũng giống như thiết kế phần mềm thì khi thiết kế model 2006, bạn sẽ phải xây lại đường đi riêng, thiết kế lại bánh xe, đèn, vô lăng, vv…

Bạn nghĩ sao nếu như thiết kế một phần mềm mới cũng đơn giản như thiết kế một cái tivi? Chẳng hạn như bạn chỉ việc gắn bộ nguồn, mạch bắt sóng, mạch điều khiển, gắn đèn hình vào là xong. Bạn không cần phải đi thiết kế lại từng phần chi tiết tỉ mỉ làm gì cả. Giả sử bạn không thiết kế tivi nữa mà xoay sang thiết kế máy tính xách tay thì cũng thế, chỉ việc gắn bộ nguồn, đèn hình, mạch điều khiển. Điểm hay là ở chỗ một con transistor trong laptop hay tivi thì cũng y như nhau mà thôi.

Quay lại ví dụ viết chương trình quản lý kho, giả sử ta có một máy tính siêu thông minh thì chỉ việc bảo nó: gắn cục Security A101, cục Data 2.0, cục Web GUI 8.1 rồi dán nhãn My Big Soft vào đó rồi nó tự động làm hết mọi chuyện cho ta. Rất tiếc, đây chỉ là ước mơ, còn thực tế thì mỗi developer hằng ngày vẫn phải còng lưng viết code như những cái máy đến mờ mắt, viết đi viết lại, viết tới viết lui như một điệp khúc bất tận.

May thay, Component-centric đang ngày nhiều hơn và thông minh hơn. Nếu bạn là dân Java, hãy nghĩ đến Java Beans. Nếu bạn là dân .NET, hãy nghĩ đến Application Block, đến Web-parts. Hay đơn giản hơn, ai cũng đã gặp nhiều lần: UI controls (button, label, listbox, checkbox, …)

Một component không phải là một class, và component-centric cũng không phải là OOP (Object Oriented Programming). Class đơn thuần chỉ là gom nhiều code có cùng mục đích vào chung một chỗ. OOP là xem vấn đề như một hoặc nhiều đối tượng (có thuộc tính, có method) để phân lọai mối quan hệ của chúng. Còn component-centric có nghĩa là lập trình để mỗi phần mang tính độc lập, có thể thay thế, có thể tái sử dụng lại cho những vấn đề khác nhau.

Giả sử bây giờ bạn phải viết trò chơi Snake. (User điều khiển con rắn chạy ăn mồi, mỗi khi ăn được cục mồi thì con rắn dài ra thêm một đọan).

1/ Class: nếu bạn là dân “rồ” thì có lẽ bạn chỉ cần viết 1, cùng lắm là 2 class để viết trò chơi tí hon này.

2/ OOP: bạn sẽ bắt đầu viết các class: Snake, Food, Player.

3/ Component-centric: bạn chả viết gì cả J

Bạn sẽ ngồi phân tích xem đâu là điểm chung, đâu là điểm riêng, đâu là phần chi tiết chỉ áp dụng riêng cho trò chơi này, đâu là phần bạn có thể abstract nó. Có lẽ bạn sẽ thiết kế ra các component sau: Game Engine, Graphic Engine, Rule Engine, Resouces Manager, User Controller, vv…

Ah, như vậy sau khi thiết kế xong, trò Snake chỉ là sản phẩm phụ mà thôi. Với những component sẵn có, bạn dư sức có thể viết DOOM 2006.

Component-centric development và cao hơn nữa là software-manufacturing đang được đầu tư và phát triển rất nhiều. Nếu bạn có hứng thú, hãy tham khảo thêm:

Microsoft Application Block

Enterprise Java Bean

Java Frameworks and Components: Accelerate Your Web Application Development – Michael Nash. Cambridge University Press 2003 ISBN: 0521520592

N-Tier Layer

Nếu như Component là từng bộ phận nhỏ, đóng vai trò như một “black-box”, ta chỉ quan tâm tới chức năng của nó là chính, thì Layer lại giống như một bản mạch in gồm nhiều components đã được thiết kế sẵn. Lấy ví dụ như Graphics Card. Mở các máy PC hiện tại ra bạn sẽ thấy lọai card này. Điểm thú vị là bạn không phải “se duyên” với cái card ấy mãi mãi. Khi nào túi tiền rủng rỉnh, bạn có thể mua card khác mới hơn, nhanh hơn, xịn hơn để gắn vào và quên béng mất cái card cũ (hoặc rao bán chợ trời). Có khi nào bạn suy nghĩ lại và ngạc nhiên tại sao cái máy tính cũ kỹ đời 1998 của mình lại có khả năng chấp nhận card 3D đời 2006 không? Thật là một kỳ quan, bạn nhỉ?

Software cũng thế, nếu thiết kế chia một software ra thành nhiều layer thì sẽ tăng tính tái sử dụng, và quan trọng nhất là: chịu đựng được với thay đổi trong tương lai. Bạn hãy nghĩ thế này nhé: nếu Windows mà được thiết kế tốt hơn thì bạn đã có thể chơi game của Windows, chạy web server của Linux, và chạy chương trình đồ họa của Macintosh ngay trong hệ điều hành Windows.

Bài viết này sẽ đề cập đến 3 layer cơ bản nhất mà đa số các chương trình từ bé đến khổng lồ, từ bài tập của sinh viên đến game online kinh phí hàng trăm triệu đô đều cần phải có.

Data Access Layer

Nếu bạn biết “Select * from Products Where CustID = @ID” nghĩa là gì nhưng bạn không cần phải dùng đến nó mỗi ngày thì bạn may mắn quá, bạn có thể bỏ qua phần này.

Nếu bạn không những biết mà còn thuộc nằm lòng đến 80% T-SQL 92, hoặc bạn nằm mơ cũng nghĩ đến SQL, đến StoreProc, đến Triggers, thì bạn rất cần phải dùng đến DAL. Có lẽ 90% developers, nhất là ở Việt Nam trong thời điểm hiện tại, rơi vào trường hợp này.

Trước hết, hãy nói Data Access Object là gì đã. Khi lập trình cơ sở dữ liệu, bạn phải lặp đi lặp lại thao tác sau:

Create connection

Create SQL command

Execute SQL

Process results

Chán quá, bugs nhiều quá. Database bạn dùng là relational, mọi thứ đều trong table, table, table. Trong khi đó, bạn lại thích lập trình OOP cơ. Thế là bằng cách này hay cách khác, cho dù bạn biết hay không biết, bạn sẽ quay sang làm theo kiểu sau: định nghĩa class chuyên nói chuyện với database. Lấy ví dụ như class sau:

Class ProductDAO

{

Connection GetConnection();

bool Insert(int ID, string Name);

DataSet GetAllProducts();

DataSet GetProductByName(string Name);

Bool Delete(int ID);

}

Phương pháp bạn vừa làm chính là Data Access Object. Bạn có thể viết tay, bạn cũng có thể dùng các công cụ như CodeSmith để làm giùm bạn. Xin chúc mừng !!! Bạn đã đỡ khổ hơn trước nhiều rồi đấy.

Nhưng mà, cũng xin… chia buồn với bạn luôn. Bạn nghĩ sao nếu database bên dưới thay đổi? Bạn sẽ dùng CodeSmith để generate lại ư? Thế mấy cái business logic của bạn khi generate lại đi tong hết thì sao? Thế lỡ năm sau CodeSmith dẹp tiệm thì sao, bạn phải sửa lại bằng tay à? Thế lỡ database không phải của bạn, mà bạn phải integrate vào database bự xự có sẵn của khách hàng thì sao? Chua đấy bạn ạ. Chưa kể là dùng Data Access Object làm tăng số lượng class lên rất nhiều (cứ mỗi table trong database cần ít nhất 1 class, thậm chí có thể là 3, 4 classes). Mỗi class cần ít nhất 4 method (Create, Read, Update, Delete). Chưa kể là mỗi kiểu select khác nhau lại phải viết method mới. Điều này đồng nghĩa với việc testing cũng tăng lên đến chóng mặt.

Bạn nghĩ sao nếu bạn chỉ cần định nghĩa một class thế này:

Class Product

{

Int ID;

String Name;

String Description;

}

Xong, chỉ có thế thôi !!! Nếu cần thêm sản phẩm mới vào database thì làm như sau:

Product p = new Product();

p.Name = “ Some product”;

Database.AddNew(p);

Nếu cần query một sản phẩm thì chỉ cần thế này:

Product p = Database.Get(typeof(Product), Name = “ProductA”);

Rất đơn giản, phải không bạn? Cái đẹp là ở chỗ nếu có thêm nhiều table nữa thì cũng thế, bạn chả phải viết thêm nhiều methods chi cho mệt cả, chỉ định nghĩa class của bạn ở mức đơn giản nhất. Và khóai nhất là bạn không cần phải viết thêm một mớ test để kiểm tra việc truy xuất class đó.

Đây chính là chức năng chính của Data Access Layer.

Nếu thích, bạn có thể tham khảo:

Data Access Layer trong Microsoft Application Block

O/R Mapping (Object-to-Relational Mapping): Wilson O/R for .NET, ORM.Net, Object Space

Java Persistence for Relational Databases – Richard Sperko. Apress 2003 – ISBN:1590590716

Lưu ý: Persistence Layer về cơ bản có cùng tính năng như Data Access Layer. Tuy nhiên, Persistence Layer có khái niệm và cách thức thực hiện khác với DAL một tí, mỗi lọai có cái hay và cái dở riêng.

Business Object Layer

Business Object rất thú vị ở chỗ chương trình nào cũng cần có nó, nhưng lại chẳng có framework hay standard chuẩn nào cho bạn cả. Đơn giản là vì business object thay đổi xòanh xọach tùy theo yêu cầu cụ thể của từng business khác nhau.

Trong đa số trường hợp, Business Object sẽ được thiết kế rất gần giống với Data Object (chỉ chứa dữ liệu hoặc nói chuyện với cơ sở dữ liệu), chỉ khác ở chỗ thêm vào đó một ít validation rule và business rule (ví dụ: nếu tài khỏan chỉ có 1.000 thì không cho phép rút 1 triệu đồng).

Tuy nhiên, có những vấn đề lặp đi lặp lại mà business nào cũng phải gặp, chẳng hạn như: transaction, distribution, validation. Khi thiết kế Business Object, một architect bao giờ cũng đau đầu với những câu hỏi chẳng hạn như: nên stored proc hay không? Nên validate ở đâu (trong DBMS, trong server, hay trong client)? Object của tui như thế có scalable không, có nhanh hay không? Vv.. và vv…

Business Object Layer là một lớp abstraction cho phép giải quyết những vấn đề thường gặp khi thiết kế business logic. Với một framework tốt, Business Object Layer đóng vai trò rất quan trọng vì nó là “sợi chỉ đỏ xuyên suốt các layers”.

Vì nhiệm vụ của Business Object rất đa dạng và cũng có nhiều khó khăn khác nhau nên Business Object Layer thường được đóng gói với tên gọi Application Frameworks. Lập trình viên bình thường và những project vừa và nhỏ ít có cơ hội tiếp xúc. Những framework thương mại chủ yếu dành cho các project lớn và đòi hỏi phải học chuyên sâu. Những framework này cũng thường “overkill” với project nhỏ. Tuy nhiên, nếu đơn giản hóa vấn đề thì khi bạn tự viết một Business Object Layer cho bản thân sẽ tăng năng suất của bạn lên rất cao.

Tài liệu tham khảo:

C- C# Expert Business Object

(Cuốn này hơi khó kiếm, nhưng là sách quý nên có)

Presentation Layer

Hồi lúc trước, mình là tín đồ của nàng Athena xinh đẹp (nói cách khác là dân ghiền Delphi). Khi chuyển sang C#, mình đã thất vọng tràn trề. Lẽ ra trong Delphi thiết kế một form có master/detail view chỉ mất 1 phút thì trong C#, mình phải mất 2 trang code (hồi lúc mới học thì mất cả tuần vì không hiểu làm sao để sử dụng cái datagrid). Sau đó, chuyển sang ASP.NET thì … càng đau khổ hơn nữa.

Tại sao ta lại phải khổ thế nhỉ? Viết form cực kỳ chua. (Hỏi mấy em lập trình Java với AWT thì biết). Với các ngôn ngữ hiện đại ngày nay thì ta có designer làm sẵn cho, chỉ việc kéo thả bụp bụp là xong. Các bộ controls thương mại hiện giờ có rất nhiều, mỗi người một vẻ. Với những bộ lớn chẳng hạn như của ComponentOne, Janus System, họ gắn luôn mác Presentation Layer vào sản phẩm của họ. Có lý phần nào vì đó là những component phục vụ cho việc trình bày thông tin.

Nhưng mà, vẫn còn nhiều vấn đề tồn đọng:

1/ Lệ thuộc vào control nhất định. Hãy quên chuyện thay thế grid của Winform bằng grid của Developer Express mà không cần phải sửa lại code đi nhé. Nhiều khi không chỉ sửa code mà bạn cần phải mướn developer khác để sử dụng UI controls mới.

2/ Không có chuẩn. Mỗi bộ controls là một framework mới cần phải học và không tương thích gì với nhau cả. Đừng mơ có chuyện viết code năm nay, 2 năm sau quay lại thay giao diện cái rẹt.

3/ Logic code và UI code quyện lẫn vào nhau. Visual Studio 2005 cố gắng giúp (lừa) bạn tránh chuyện này bằng partial class, chia code thành 2 file (bắt chước asp.net, file aspx riêng, file code-behind riêng)

4/ Visual rất luộm thuộm. Bạn nghĩ sao nếu bạn viết chương trình đồng hồ Analog (có kim giờ, phút, giây quay vòng vòng), nhưng ngày mai bạn thích đồng hồ Digital (chỉ hiển thị số). Bạn có thể nào giữ y nguyên logic code, chỉ cần thay visual elements cái rẹt trong 5 giây không? Quên chuyện đó đi.

5/ Data-binding: Rất phiền. Những control sẵn có khiến cho bạn trở thành gà công nghiệp và lệ thuộc vào nó. Điều đáng buồn là khi bạn cần binding phức tạp một tí thì vẫn cứ phải “chân lấm tay bùn”, quay trở lại viết code từng dòng một, xử lý event từng chỗ một.

Những năm gần đây xu hướng Declarative Programming gây được nhiều sự chú ý. Lấy ví dụ như thay vì viết code tạo form như sau:

Button b = new Button();

b.SetBounds(100,100,50,25);

b.Text = “Click me”;

b.Click += new EventHandler(b_OnClick);

Thì ta có thể tạo một file XML như sau:

<Button Location=”100,100” Size=”50,25”>Click me</Button>

Rất giống lập trình web, phải không bạn? Vâng, web chính là thuở ban đầu của declarative programming. Bạn thử tưởng tượng cũng một file XML đó, bạn có thể dùng làm windows application, bạn có thể dùng làm webform, có thể dùng cho Flash, có thể dùng cho Macintosh thì sao?

Có mà nằm mơ !

Hẳn bạn sẽ thốt lên như thế. Vâng, rất tiếc rằng ở thời điểm hiện tại chưa có Presentation Layer nào thực hiện được mơ ước “write once, display anywhere”. Tuy nhiên, ít ra thì bạn không còn phải viết code từng dòng bằng tay nữa, bạn có thể nhờ Presentation Layer để tự validate inputs, tự generate forms, tự layout, vv…

Để xem thêm về lĩnh vực này, bạn hãy research các chủ đề sau:– – Avalon, MyXaml, XAML, XAMLon

Flex

XUL

Design Patterns

Design patterns nôm na ra là cách thức giải quyết cho những vấn đề thường gặp. Điều đáng buồn là các sách về design patterns khô như ngói, nhạt như vôi. Nhưng tin vui: design pattern là công cụ sẽ giúp bạn tăng lương lên gấp đôi (hoặc gấp trăm lần). Đơn giản vì design pattern chính là kinh nghiệm xương máu của những architect đi trước đúc kết ra được. Khi bạn học design pattern, bạn sẽ có những kinh nghiệm vượt trước năng lực của mình.

Tài liệu để đọc về design pattern hiện có rất nhiều. Mình chỉ mạn phép góp ý với các bạn một câu khi học về lĩnh vực này: “hãy nắm lấy ý tưởng là chính, đừng chú trọng vào code”. Nếu bạn chỉ nhìn vào code ví dụ, bạn sẽ dễ bị “tẩu hỏa nhập ma”, sẽ bị lệ thuộc vào code, nhìn thấy cái nào cũng na ná nhau, và tệ hại nhất là chẳng biết áp dụng vào cho cái gì khác ngòai ví dụ ra.

Tài liệu để tham khảo:

www.dofactory.com

www.c2.com

C

C# Design Pattern – A tutorial

Software Architecture Design Patterns in Java – Partha Kuchana

Về layers và thiết kế ở mức cao một tí, đọc các sách sau:

Enterprise Solution Patterns Using Microsoft.NET version 2.0 – MS Press

.NET Patterns: Architecture, Design, and Process – Christian Thilmany – Addison Wesley ISBN: 0-32-113002-2

Kết luận

Viết bài này mình cứ sợ “múa rìu qua mắt thợ” bởi vì người tài giỏi của Việt Nam cũng có rất nhiều. Tuy nhiên, có nhiều bạn cứ nói mình mãi là hãy viết đi, và qua thực tế đi dạy học được một thời gian, mình thấy những bạn sinh viên mới ra trường biết rất ít về thiết kế phần mềm, dẫn đến hậu quả là các bạn ấy đa phần giống như gà công nghiệp, và hiển nhiên code của các bạn cũng như một tô mì ăn liền: ăn đỡ đói thì được, còn ăn nhiều thì hơi ngán.

Hy vọng bài viết này sẽ giúp các bạn có được một số gợi ý để đào sâu nghiên cứu thêm. Chúc các bạn luôn giữ niềm đam mê lập trình của mình.

– Nguyễn Minh Hải

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: