1.    INTRODUCTION

OOP (lập trình hướng đối tượng) là một kỹ năng không thể không biết đối với mọi lập trình viên. Trong các trường ĐH ở Việt Nam, các bạn sinh viên được học về lập trình hướng đối tượng vào khoảng năm 2 đại học. Ở đó, các thầy cô sẽ dạy các đặc trưng cơ bản của OOP như tính đa hình, tính kế thừa, tính đóng gói… và làm đồ án.

Sau khi học xong môn này, các bạn sinh viên tiếp tục bị hành với hàng loạt các môn học khác, cộng với sự hấp dẫn của các công nghệ mới như lập trình mobile, games… Đối với OOP, đa phần các bạn sẽ dừng lại ở mức: define class và khởi tạo object mà ít khi sử dụng đến các concept khác như abstract class, interface, inheritance…

Trong môi trường làm việc thực tế, chúng ta sẽ học được thêm một kiến thức mới nữa: khách hàng (hay thậm chí là sếp) là những người thích thay đổi, và chúng ta (developer) phải luôn đáp ứng được sự thay đổi đó, một câu trả lời “không thể” có thể gây ra những hậu quả khôn lường. Chính vì lẽ đó nên trong quy trình phát triển phần mềm, khâu phân tích và thiết kế là cực kỳ quan trọng. Người thiết kế phải làm thế nào để kiến trúc phần mềm có thể dễ dàng đáp ứng với thay đổi nhất. Và để làm được điều đó thì cần phải có kiến thức rất sâu rộng trong hướng đối tượng, vận dụng linh hoạt các đặc trưng của OOP. Nói lang mang nãy giờ hơi nhiều nhưng mà túm cái váy lại thì để thiết kế một phần mềm có độ linh hoạt cao thì cần phải áp dụng thuần thục các kiến thức sau:

  • Design pattern
  • Áp dụng linh hoạt các nguyên tắc (principle) trong thiết kế và lập trình

Về nguyên tắc thì có rất nhiều, bài viết này sẽ giới thiệu về SOLID – 5 nguyên tắc do Michale Feathers giới thiệu và được đặt tên bởi Robert C. Martin (nguồn Wiki).

Lưu ý: mục đích của bài viết này là giới thiệu khái quát, giúp người đọc biết đến sự tồn tại của cái gọi là “SOLID”. Sau này khi cần các bạn sẽ tự biết nên tìm hiểu chuyên sâu ở đâu (kinh nghiệm cá nhân của tui).

2.    DETAIL

SOLID là bộ 5 nguyên tắc giúp cho người kỹ sư có thể thiết kế phần mềm có kiến trúc “tốt”, bao gồm:

  • S = SRP (Single Responsibility Principle)
  • O = OCP (Open closed principle)
  • L = LSP (Liskov substitution principle)
  • I = ISP (Internet service provider😀 – j/k: it stands for Interface segregation principle)
  • D = DIP (Dependency inversion principle)

2.1  SRP – Single responsibility principle

Phát biểu EN: Every software module should have only one reason to change

Phát biểuVN: module trong phần mềm chỉ nên có một lý do duy nhất khi cần thực hiện thay đổi

  • Module: class, function
  • Lý do thay đổi: responsibility

Ở đây “responsibility” cần hiểu là vai trò của một module trong một ngữ cảnh (context) cụ thể. Ví dụ với class EmployeeDB thì responsibility của nó sẽ là các hoạt động tương tác với cơ sở dữ liệu về NHÂN VIÊN, đối với class EmployeeReport thì sẽ chỉ thực hiện các việc liên quan đến report về NHÂN VIÊN.

Diễn giải chi tiết: http://www.codeproject.com/Articles/723631/SOLID-Principles-in-Laymans-Terms-Single-Responsib)

Ví dụ:

clip_image002

Ở class Logger như trên có method GenereateLoggingStatistics() dùng để đưa ra các phân tích dựa vào dữ liệu log. Như vậy giả sử ta cần thay đổi structure của log message hoặc muốn ghi log thêm vào chỗ nào đó, ta sẽ edit class Logger – LÝ DO THAY ĐỔI 1. Bây giờ ta muốn điều chỉnh giải thuật để sinh ra các phân tích từ dữ liệu log, ta cũng thay đổi trong class Logger – LÝ DO THAY ĐỔI 2 => SRP Failed

Giải pháp: tách ra 2 class riêng biệt, một cho logging và 1 cho statistics.

2.2   OCP – Open Closed Principle

Phát biểu EN: Software modules should be closed for modifications but open for extensions

Phát biểu VN: ~_~, hiểu nôm na thì software module không nên dễ dàng thay đổi mà chỉ nên mở rộng tính năng (hoặc sometime override). Nói chung là tốt hơn hết thì đừng dịch ra hay hơn :3

Giải pháp để implement nguyên tắc này:

  • Sử dụng tính kế thừa (abstract class, interface), tính đa hình (virtual, override)
  • Nếu là dân .NET thì có thể dùng extension method

Ví dụ (xem chi tiết http://www.codeproject.com/Articles/703634/SOLID-architecture-principles-using-simple-Csharp):

clip_image004

Với class Customer, trong thực tế tùy vào loại khách hàng (khách hàng thân thiết, vãng lai…) mà sẽ được discount khác nhau, mà nếu implement như trên thì fail, mỗi lần sếp định nghĩa thêm một loại khách hàng thì vào đây thay đổi à K. Vậy nên có thể viết lại như hình bên dưới để tuân theo OCP.

clip_image006

clip_image008

3.    TẠM KẾT

Đọc vậy nhiều rồi, đọc nhiều quá tẩu hỏa nhập ma, nếu bạn siêng thì tìm hiểu tiếp bằng google hoặc vào mấy cái link codeproject tham khảo, nếu không thì… chờ bài viết tiếp theo😀.

pic6