Tác giả: Kealan Parr
Sự phụ thuộc là một phần rất phổ biến của bất kỳ cơ sở code tốt nào. Và điều quan trọng là phải xử lý rõ ràng mọi vấn đề trong code của bên thứ ba mà chương trình của bạn dựa vào để hoạt động.
Có nhiều cách để nhận và cập nhật code của bên thứ ba. Và tôi đã đọc một cái gì đó gần đây mà nó dễ dàng trở thành cách yêu thích của tôi để làm điều này, vì vậy tôi đã phải chia sẻ nó.
Tính trừu tượng
Các nhà phát triển thường sử dụng sự trừu tượng của code để đơn giản hóa một hệ thống. Trừu tượng là một cách ẩn code phức tạp bên trong một cái gì đó và chúng thường cung cấp một giao diện dễ sử dụng.
Về cơ bản, chúng tôi không buộc người sử dụng code phải lo lắng về các chi tiết triển khai. Họ chỉ có thể gọi hàm và sẽ nhận được câu trả lời của họ – họ không phải lo lắng về những gì hàm đang làm “chui”.
Đó là điểm mạnh của việc trừu tượng hóa các chi tiết trong code của bạn. Bạn có thể trừu tượng hóa mọi thứ trong vô số cấu trúc dữ liệu hoặc cấu trúc code. Và bạn có thể trừu tượng hóa các chi tiết triển khai bên trong một nguyên mẫu, lớp, hàm hoặc hơn thế nữa.
Nếu bạn phải hiểu từng dòng code trong một danh sách dữ liệu code quá lớn (giả sử cơ sở code có 2 triệu dòng) thì bạn sẽ không bao giờ có thể bắt đầu viết code được. Bạn có thể tạo một bộ code có thể sử dụng lại, đơn giản để hiểu và dễ dàng thay đổi bằng cách trừu tượng hóa các chi tiết nhất định thành các mô-đun chính xác / tách code của bạn ra.
Shimming
Shimming là hành động đặt một thứ gì đó trước thứ khác để chặn dữ liệu đang được truyền qua.
Hãy xem một ví dụ về cách nó hoạt động.
Giả sử một ngân hàng có API thực sự cũ không chấp nhận JSON do một số lỗi kỹ thuật kế thừa. Thay vào đó, nó chỉ có thể chấp nhận XML. Chúng tôi sẽ gọi đây là LegacyAPI .
Nhưng rất nhiều devs muốn sử dụng API ngân hàng này muốn gửi JSON. Ngân hàng từ chối thay đổi LegacyAPI vì nó quá rủi ro và có thể phá vỡ API. Vì vậy, phần lớn hệ thống của họ phụ thuộc vào nó, và họ không thể mạo hiểm thực hiện nhiều phát triển mới và gỡ bỏ những phần lớn của hệ thống nếu họ mắc lỗi.
Họ luôn luôn có thể Shim LegacyAPI nếu họ không muốn làm phát triển mới trên nó. Họ có thể làm điều này bằng cách tạo một API nằm “trước” LegacyAPI. Chúng tôi sẽ gọi nó là NewAPI .
Từ “phía trước” chỉ có nghĩa là thứ tự của người đầu tiên xử lý yêu cầu mạng. Bởi “phía trước”, chúng tôi có nghĩa là NewAPI sẽ là người đầu tiên nhận được các yêu cầu mạng.
Bạn sẽ nói với các nhà phát triển rằng bây giờ họ có thể nhấn NewAPI với JSON như họ muốn và NewAPI sẽ biến JSON thành XML cho LegacyAPI và cả hai bên đều có thể hài lòng.
Ngân hàng hiện có thể mở rộng dịch vụ của họ (ví dụ: họ có thể chấp nhận JSON) thông qua NewAPI mà không cần thay đổi API kế thừa cũ mà họ đã cảnh giác khi thay đổi.
Đây chỉ là một ví dụ của việc shimming. Và chỉ để xem lại, về cơ bản nó là thêm một cái gì đó vào phía trước một cái gì đó khác để hoạt động như một người đàn ông ở giữa để truyền dữ liệu cho một thứ khác.
Xem thêm Khái niệm về OOD – Object oriented design
Tại sao nên shimming tính trừu tượng khi coding?
Vấn đề
Bất cứ khi nào chúng tôi cần quản lý các phần phụ thuộc, cần đảm bảo rằng chúng tôi ngăn code của bên thứ ba “rò rỉ” trên toàn bộ code chính của chúng tôi. Leaking đồng nghĩa với việc code phụ thuộc được nhập nhiều lần đến những nơi khác nhau cần nó trong code của bạn.
Nếu bạn để một phần phụ thuộc “xâm chiếm” source code, nghĩa là bạn đang ngày càng trở nên gắn bó chặt chẽ với nó hơn. Điều này có thể (đôi khi!) Có nghĩa là bạn sẽ bị buộc phải viết mã theo hướng mà thư viện lựa chọn khi bạn kết hợp chặt chẽ với nó. Dẫn đến chi phí nhận thức đáng kể khi bạn ngày càng cố gắng làm cho thư viện này hoạt động trong code của bạn, nhưng nó không phù hợp với phần còn lại của các quyết định kiến trúc của bạn.
Điều này có thể làm cho bất kỳ quá trình tái cấu trúc nào bạn cần thực hiện mất nhiều thời gian hơn so với việc tách biệt nó. Ví dụ, nếu phụ thuộc thay đổi, nó sẽ cần phải chấp nhận những đối số nào để tạo một đối tượng trong phụ thuộc?
Ngoài việc khó giữ cho bản dựng hoạt động tốt với phần phụ thuộc, nếu nó không còn phù hợp với nhu cầu hoặc bạn tìm thấy một thư viện tốt hơn để thay thế nó, thì việc tái cấu trúc của bạn trở nên khó khăn hơn nhiều để thực sự loại bỏ nó.
Giải pháp
Để thử và ngăn chặn tất cả những điều trên xảy ra, trước tiên, hãy đặt bất kỳ phụ thuộc nào chúng ta cần vào các mô-đun của riêng chúng, nơi chúng chỉ được tham chiếu một lần trong codebase của bạn.
Đây thực chất chính là shim. Bất cứ khi nào cần sự phụ thuộc của bên thứ ba, bạn chỉ cần nhập mô-đun trình bao bọc mà chúng tôi đặt xung quanh nó, để nó cung cấp một cấp độ trước khi chúng tôi gọi vào phần phụ thuộc bên thứ ba của mình.
Shim cho phép chúng tôi làm cho các biến phụ thuộc trở nên trừu tượng. Các nhà phát triển có nhu cầu sử dụng phụ thuộc bên thứ ba chỉ có thể sử dụng một assumption. Bạn sẽ đặt các đối số thành giá trị mặc định hợp lý và cố gắng loại bỏ càng nhiều chi tiết triển khai phức tạp càng tốt.
Bất kỳ nơi nào khác cần sự phụ thuộc này sẽ chỉ tải module và sau đó có thể được đưa vào khi cần thiết. Một lý do lớn mà chúng ta đã thảo luận là nó ngăn sự phụ thuộc của bạn và mã của bạn không bị kết hợp quá chặt chẽ với nhau.
Điều này hoạt động khi bạn chỉ có nó trong một module duy nhất. Sau đó, bạn chỉ phải thay đổi một module cho nhiều nơi khác để có quyền truy cập vào thứ gì đó. Điều này cho phép chúng tôi thực hiện các thay đổi dễ dàng hơn nhiều và giữ cho sự tách biệt rõ ràng về các mối quan tâm trong code.
Ở đây chúng tôi chỉ nói về một sự phụ thuộc – nhưng bạn có thể thấy điều này có thể tồi tệ hơn thế nào nếu chẳng hạn như bạn đang dựa vào 25 thư viện tùy chỉnh khác và bạn cần hiểu cách chúng hoạt động. Đây thường sẽ là một cơ sở code khá mỏng manh.
Hi vọng bài viết này sẽ mang đến cho bạn một cái nhìn tổng quan hơn về các vấn đề liên quan đến shimming và duy trì sự phụ thuộc.
Phỏng dịch theo bài viết gốc tại freecodecamp.org
Có thể bạn quan tâm:
- Prototype pattern – một trong những pattern phổ biến nhất
- Giới thiệu về Clean Architecture – Phần 2
- Cách để npm packages chạy trong browser
Xem thêm Việc làm Developer hấp dẫn trên TopDev