Orthogonality

1. Orthogonality là gì?

Hai thực thể là orthogonal nếu một cái bị thay đổi thì không ảnh hưởng gì tới cái kia.

2. Có lợi ích gì?

Các component được implement độc lập, không ảnh hưởng tới nhau, yêu cầu thay đổi thì chỉ cần thay thế sửa đổi một cái. Nắm được thay đổi này ảnh hưởng tới những cái gì.

  • Tăng hiệu suất công việc:
    • Dễ thay đổi, dễ kiểm soát, code nhỏ dễ implement (dễ nắm được contrains)
    • Reusable
    • Dễ dàng kết hợp các component để tạo component cao hơn.
  • Giảm rủi ro:
    • Một module bị lỗi, không ảnh hưởng tới module khác
    • Fix một module nhỏ dễ hơn là một module lớn phức tạp
    • Dễ test

3 Làm sao để phát hiện/implement?

Thiết kế component độc lập, có một mục đích.
Một số cách là implement theo modular, component-based hoặc layers.
Không để code phụ thuộc vào thứ mà nó không kiểm soát.

Coding

  • Tránh coupling thing: luôn giữ module độc lập, không để lộ ra những thứ không cần thiết vào các module khác, không phụ thuộc vào implement của module khác.
  • Tránh global data: global state rất nguy hiểm và khó test nhất. Singleton cũng vậy, do một module thay đổi global data sẽ có thể làm ảnh hưởng tới các module khác.

Testing

  • Làm sao để biết module không phụ thuộc vào module khác. Cách đơn giản là viết test cho nó. Khi viết test sẽ cần phải setup môi trường cho nó, nếu module phụ thuộc vào module khác thì sẽ phải setup module khác đó. Nếu khi setup test, mà mình thấy phải setup quá nhiều có nghĩa là code mình đang bị coupling.
  • Unit test có thể được xem là client đầu tiên sử dụng module đó, nên mình có thể lấy được feedback ngay và luôn.

Ví dụ so sánh Orthogonality trong OOP với Functional Programming

#TODO viết ví dụ

Reversibilty

Đa phần khi implement mình chưa biết cách đó đã đúng hay chưa, dùng thư viện đó đã đúng hay chưa, dùng thuật toán đó ok hay chưa. Do đó sẽ phải thay đổi nhiều. Khi đó nếu mình giữ code decoupled và tuân theo DRY principle, mình có thể dễ dàng thay thế khi cần.
Do đó, khi implement một feature nên viết ra flow của nó, cái nào mình chưa chắc chắn, cái nào không phụ thuộc vào sự không chắc chắn đó. Tránh trường hợp tạo một pull request một nùi, đồng nghĩa đang ám chỉ mình đang để code hoặc tư tưởng bị coupling lúc code.

Đối với cái API/third-party do mình không kiểm soát được, nên mình tạo một abstract layer giữa code mình implement và third-party (ví dụ tạo DB service, để tránh việc code gọi trực tiếp mongoose API) vì sau này mình có thể thay thế sử dụng thư viện khác thay thế mongonose, lúc này mình chỉ cần sửa lại các implement trong DB service, mà không làm thay đổi code trong client.