Phân rã theo thứ bậc

Bạn không bao giờ nên bắt đầu viết các lớp cho ứng dụng của mình ngay lập tức. Đầu tiên nó cần được thiết kế. Thiết kế nên kết thúc với một kiến ​​trúc chu đáo. Và để có được kiến ​​trúc này, bạn cần phải phân rã hệ thống một cách nhất quán.

Việc phân rã phải được thực hiện theo thứ bậc - đầu tiên, hệ thống được chia thành các mô-đun / hệ thống con chức năng lớn mô tả hoạt động của nó ở dạng chung nhất. Sau đó, các mô-đun kết quả được phân tích chi tiết hơn và được chia thành các mô-đun con hoặc đối tượng.

Trước khi chọn các đối tượng, hãy chia hệ thống thành các khối ngữ nghĩa cơ bản, ít nhất là về mặt tinh thần. Trong các ứng dụng nhỏ, điều này thường rất dễ thực hiện: một vài cấp độ phân cấp là khá đủ, vì trước tiên hệ thống được chia thành các hệ thống con / gói và các gói được chia thành các lớp.

Phân rã theo thứ bậc

Ý tưởng này không tầm thường như nó có vẻ. Ví dụ, bản chất của một “mẫu kiến ​​trúc” phổ biến như Model-View-Controller (MVC) là gì?

Đó là tất cả về việc tách bản trình bày khỏi logic nghiệp vụ . Đầu tiên, bất kỳ ứng dụng người dùng nào cũng được chia thành hai mô-đun - một mô-đun chịu trách nhiệm triển khai chính logic nghiệp vụ (Mô hình) và mô-đun thứ hai chịu trách nhiệm tương tác với người dùng (Giao diện người dùng hoặc Chế độ xem).

Sau đó, hóa ra các mô-đun phải tương tác bằng cách nào đó, vì điều này, họ thêm Bộ điều khiển, có nhiệm vụ quản lý sự tương tác của các mô-đun. Ngoài ra, trong phiên bản di động (cổ điển) của MVC, mẫu Người quan sát được thêm vào để Chế độ xem có thể nhận các sự kiện từ mô hình và thay đổi dữ liệu được hiển thị trong thời gian thực.

Các mô-đun cấp cao điển hình, thu được do sự phân chia đầu tiên của hệ thống thành các thành phần lớn nhất, chính xác là:

  • Lôgic kinh doanh;
  • Giao diện người dùng;
  • Cơ sở dữ liệu;
  • Hệ thống nhắn tin;
  • Vật chứa đối tượng.

Lần chia đầu tiên thường chia toàn bộ ứng dụng thành 2-7 (tối đa 10 phần). Nếu chúng ta chia nhỏ nó thành nhiều phần hơn, thì sẽ có mong muốn nhóm chúng lại và chúng ta sẽ lại nhận được 2-7 mô-đun cấp cao nhất.

Suy giảm chức năng

Việc phân chia thành các mô-đun/hệ thống con được thực hiện tốt nhất dựa trên các nhiệm vụ mà hệ thống giải quyết . Nhiệm vụ chính được chia thành các nhiệm vụ con cấu thành của nó, có thể được giải quyết/thực hiện một cách tự động, độc lập với nhau.

Mỗi mô-đun phải chịu trách nhiệm giải quyết một số nhiệm vụ con và thực hiện chức năng tương ứng của nó . Ngoài mục đích chức năng, mô-đun còn được đặc trưng bởi một tập hợp dữ liệu cần thiết để nó thực hiện chức năng của mình, đó là:

Mô-đun = Chức năng + Dữ liệu cần thiết để thực hiện nó.

Nếu việc phân tách thành các mô-đun được thực hiện chính xác, thì sự tương tác với các mô-đun khác (chịu trách nhiệm về các chức năng khác) sẽ là tối thiểu. Nó có thể là như vậy, nhưng sự vắng mặt của nó không quan trọng đối với mô-đun của bạn.

Mô-đun không phải là một đoạn mã tùy ý, mà là một đơn vị chương trình hoàn chỉnh và có ý nghĩa về mặt chức năng (chương trình con) cung cấp giải pháp cho một tác vụ nhất định và lý tưởng nhất là có thể hoạt động độc lập hoặc trong môi trường khác và được tái sử dụng. Mô-đun phải là một loại "toàn vẹn có khả năng độc lập tương đối trong hành vi và phát triển." (Christopher Alexander)

Do đó, việc phân tách có thẩm quyền trước hết dựa trên việc phân tích các chức năng của hệ thống và dữ liệu cần thiết để thực hiện các chức năng này. Hàm trong trường hợp này không phải là hàm lớp và mô-đun, vì chúng không phải là đối tượng. Nếu bạn chỉ có một vài lớp trong một mô-đun, thì bạn đã lạm dụng nó.

Kết nối mạnh và yếu

Điều rất quan trọng là không lạm dụng nó với mô đun hóa. Nếu bạn đưa cho một người mới bắt đầu một ứng dụng Spring nguyên khối và yêu cầu anh ta chia nó thành các mô-đun, thì anh ta sẽ lấy từng Spring Bean thành một mô-đun riêng biệt và coi như công việc của mình đã hoàn thành. Nhưng không phải vậy.

Tiêu chí chính cho chất lượng phân tách là cách các mô-đun tập trung vào việc giải quyết các nhiệm vụ của chúng và độc lập.

Điều này thường được xây dựng như sau: "Các mô-đun thu được do quá trình phân tách phải được liên hợp bên trong tối đa (độ gắn kết bên trong cao) và liên kết với nhau ở mức tối thiểu (độ liên kết bên ngoài thấp)."

Tính gắn kết cao, tính gắn kết cao hoặc "sự gắn kết" trong mô-đun, cho biết rằng mô-đun tập trung vào giải quyết một vấn đề hẹp và không tham gia vào việc thực hiện các chức năng không đồng nhất hoặc các trách nhiệm không liên quan.

Sự gắn kết đặc trưng cho mức độ mà các nhiệm vụ được thực hiện bởi mô-đun có liên quan với nhau.

Hệ quả của Sự gắn kết cao là Nguyên tắc Trách nhiệm Đơn lẻ - nguyên tắc đầu tiên trong năm nguyên tắc RẮN , theo đó bất kỳ đối tượng / mô-đun nào chỉ nên có một trách nhiệm và không được có nhiều hơn một lý do để thay đổi nó.

Khớp nối thấp , khớp nối lỏng lẻo, có nghĩa là các mô-đun mà hệ thống được chia thành, nếu có thể, phải độc lập hoặc khớp nối lỏng lẻo với nhau. Họ có thể tương tác, nhưng đồng thời biết về nhau càng ít càng tốt.

Mỗi mô-đun không cần biết mô-đun kia hoạt động như thế nào, nó được viết bằng ngôn ngữ gì và hoạt động như thế nào. Thông thường, để tổ chức sự tương tác của các mô-đun như vậy, một vùng chứa nhất định được sử dụng để tải các mô-đun này vào đó.

Với thiết kế phù hợp, nếu bạn thay đổi một mô-đun, bạn sẽ không phải chỉnh sửa các mô-đun khác hoặc những thay đổi này sẽ ở mức tối thiểu. Khớp nối càng lỏng lẻo thì càng dễ viết/hiểu/mở rộng/sửa chữa chương trình.

Người ta tin rằng các mô-đun được thiết kế tốt nên có các thuộc tính sau:

  • Tính toàn vẹn và đầy đủ của chức năng - mỗi mô-đun thực hiện một chức năng, nhưng thực hiện tốt và đầy đủ chức năng đó, mô-đun độc lập thực hiện đầy đủ các hoạt động để thực hiện chức năng của nó.
  • Một đầu vào và một đầu ra - ở đầu vào, mô-đun chương trình nhận một bộ dữ liệu ban đầu nhất định, thực hiện quá trình xử lý có ý nghĩa và trả về một bộ dữ liệu kết quả, nghĩa là nguyên tắc IPO tiêu chuẩn được triển khai - đầu vào -\u003e quy trình -\u003e đầu ra.
  • Độc lập logic - kết quả công việc của mô-đun chương trình chỉ phụ thuộc vào dữ liệu ban đầu, nhưng không phụ thuộc vào công việc của các mô-đun khác.
  • Liên kết thông tin yếu với các phân hệ khác - nên hạn chế tối đa việc trao đổi thông tin giữa các phân hệ nếu có thể.

Người mới bắt đầu rất khó hiểu cách giảm khả năng kết nối của các mô-đun hơn nữa. Một phần kiến ​​​​thức này đi kèm với kinh nghiệm, một phần - sau khi đọc những cuốn sách thông minh. Nhưng tốt nhất là phân tích kiến ​​trúc của các ứng dụng hiện có.

Thành phần thay vì kế thừa

Phân tách năng lực là một loại nghệ thuật và là một nhiệm vụ khó khăn đối với hầu hết các lập trình viên. Sự đơn giản là lừa dối ở đây, và những sai lầm phải trả giá đắt.

Điều xảy ra là các mô-đun chuyên dụng được kết hợp chặt chẽ với nhau và không thể phát triển độc lập. Hoặc không rõ chức năng của mỗi người trong số họ. Nếu bạn gặp sự cố tương tự, thì rất có thể việc phân vùng thành các mô-đun đã được thực hiện không chính xác.

Phải luôn rõ ràng vai trò của mỗi mô-đun . Tiêu chí đáng tin cậy nhất để phân tách được thực hiện chính xác là nếu các mô-đun là các chương trình con độc lập và có giá trị có thể được sử dụng tách biệt với phần còn lại của ứng dụng (và do đó có thể được sử dụng lại).

Khi phân tách một hệ thống, bạn nên kiểm tra chất lượng của nó bằng cách tự đặt câu hỏi: "Mỗi mô-đun thực hiện nhiệm vụ gì?", "Các mô-đun có dễ kiểm tra không?", "Có thể tự sử dụng các mô-đun đó không?" hay ở môi trường khác?"ảnh hưởng đến người khác?"

Bạn cần cố gắng giữ cho các mô-đun càng độc lập càng tốt . Như đã đề cập trước đó, đây là một tham số quan trọng để phân tách thích hợp . Do đó, nó phải được thực hiện theo cách mà các mô-đun ban đầu phụ thuộc yếu vào nhau. Nếu bạn đã thành công, thì bạn thật tuyệt.

Nếu không, thì tất cả cũng không bị mất ở đây. Có một số kỹ thuật và mẫu đặc biệt cho phép bạn giảm thiểu hơn nữa và làm suy yếu các liên kết giữa các hệ thống con. Ví dụ: trong trường hợp MVC, mẫu Người quan sát được sử dụng cho mục đích này, nhưng có thể có các giải pháp khác.

Có thể nói, các kỹ thuật tách rời cấu thành "bộ công cụ của kiến ​​trúc sư" chính. Chỉ cần hiểu rằng chúng ta đang nói về tất cả các hệ thống con và cần phải làm suy yếu kết nối ở tất cả các cấp của hệ thống phân cấp , nghĩa là không chỉ giữa các lớp mà còn giữa các mô-đun ở mỗi cấp độ phân cấp.