2024-04-03 23:28 — 4 phút đọc

[Design principles] - Phần 3: Design principles là gì? Thành phần (composition) ưu tiên hơn thừa kế (inheritance).

#design-principles#how-to#software-architecture


Nguyên tắc thiết kế phần mềm

  1. Đóng gói những thứ có thể dễ dàng thay đổi. (Encapsulate What Varies)
  2. Lập trình hướng interface, không hướng implementation. (Program to an interface, not an implementation)
  3. Thành phần ưu tiên hơn thừa kế. (Favor composition over inheritance)

Thừa kế có lẽ là cách dễ dàng và rõ ràng nhất để sử dụng lại code của bạn giữa các classes. Nếu bạn có 2 classes có chung một số phần code, bạn có thể tạo ra một class cha và đặt code chung vào đó. Tuy nhiên, thừa kế không phải lúc nào cũng là cách tốt nhất để sử dụng lại code của bạn. Mọi thứ sẽ rõ ràng là phức tạp hơn khi chương trình của bạn có nhiều classes con và nhiều levels của thừa kế. Dưới đây là một vài vấn đề đó:

  • Một subclass không thể không implement các methods của superclass: Nếu bạn có một superclass với một số methods, bạn phải implement tất cả các methods đó trong subclass. Điều này có nghĩa là bạn phải implement một số methods mà bạn không cần trong subclass của bạn.

  • Một subclass không thể thay đổi behavior của superclass: Nếu bạn muốn thay đổi behavior của một superclass, bạn phải thay đổi behavior của tất cả các subclasses của nó. Điều này có thể dẫn đến việc thay đổi behavior của một subclass mà bạn không muốn thay đổi.

  • Sự kế thừa phá sự đóng gói của superclass bởi vì các chi tiết bên trong superclass có thể được truy cập từ con. Có tình huống ngược lại khi một lập trình viên cố gắng làm cho superclass nhận biết được các chi tiết của subclass.

  • Các subclass được liên kết quá chặt chẽ với superclass mọi thay đổi của superclass đều dẫn đến phá hỏng tính liên kết của các subclass.

  • Cố gắng sử dụng code kế thừa có thể dẫn đến việc phân cấp kế thừa song song. Việc thừa kế thường diễn ra trong một chiều duy nhất. Nhưng bất cứ khi nào có hai hoặc nhiều chiều, bạn phải tạo ra nhiều kết hợp lớp, làm phình to hệ thống phân cấp lớp đến một kích thước vô lý.

Có một giải pháp thay thế cho việc kế thừa đó là sử dụng composition. Trong khi kế thừa “là a” mối quan hệ giữa các classes (Car là một Transport), Composition “có một” mối quan hệ (Car có một Engine). Composition cho phép bạn sử dụng code của một class trong một class khác mà không cần thừa kế từ class đó. Điều này giúp bạn giảm sự phụ thuộc giữa các classes và giúp bạn dễ dàng mở rộng và thay đổi code của mình.

Tôi nên đề cập nguyên tắc này cũng áp dụng cho aggregate một biến thể của composition nơi mà một Object có thể phụ thuộc vào một object khác mà không quản lý bất kì lifecycle của object đó. Đây là một ví dụ: một chiếc xe có một người lái, nhưng người đó cũng có thể lái một chiếc xe khác hoặc cũng có thể đi bộ mà không cần xe.

Ví dụ

Hãy tưởng tượng rằng bạn cần phải tạo ra một danh mục ứng dụng cho một nhà sản xuất xe hơi. Công ty đó có thể sản xuất xe hơi hoặc xe tải, chúng chạy bằng điện hoặc gas, tất cả chúng đều có thể tự động điều khiển hoặc điều khiển bằng tay.

Anh 1INHERITANCE: mở rộng một class theo nhiều chiều (loại hàng hóa × loại động cơ × loại dẫn đường) có thể dẫn đến sự bùng nổ tổ hợp của các subclass.

Như bạn thấy mỗi một tham số bổ xung dẫn đến việc nhân số lượng các subclass. Có rất nhiều code bị trùng giữa các subclass và rất khó để thêm một loại mới của xe vào hệ thống.

Bạn có thể giải quyết vấn đề này với thành phần. Thay vì các đối tượng xe hơi tự thực hiện một hành vi, họ có thể ủy thác nó cho đối tượng khác.

Lợi ích bổ sung là bạn có thể thay thế một hành vi trong thời gian chạy. Ví dụ, bạn có thể thay thế một đối tượng động cơ được liên kết với một đối tượng xe hơi chỉ bằng cách gán một đối tượng động cơ khác cho chiếc xe.

Anh 2COMPOSITION: các “kích thước” khác nhau của chức năng được trích xuất theo hệ thống phân cấp lớp riêng của chúng.

Cấu trúc của các lớp này tương tự như mô hình Strategy pattern, mà chúng ta sẽ đi qua sau này.


aitu avatar

Hi! Tôi là Tuyên — Hiện tại tôi đang làm Software Architect, Senior developer tại một công ty nhỏ ở Hà Nội. Tôi cảm thấy thích thú, đam mê, yêu thích với việc viết lách và chia sẻ những kiến thức mà tôi biết. Hãy đọc nhiều hơn tại blogs và tới about để biết thêm về tôi nhé.