Mã phụ thuộc là ma quỷ.

Sự phụ thuộc của bạn sẽ đốt cháy bạn mọi lúc.
Thay đổi liên tục là một ngôi sao duy nhất trên làng - Heraclitus (Philosopher)

Các công cụ, thư viện và khung mà chúng ta sử dụng để xây dựng các ứng dụng web của chúng ta ngày nay khác rất nhiều so với các công cụ chúng ta đã sử dụng chỉ một vài năm trước đây.

Trong một vài năm ngắn ngủi kể từ bây giờ, hầu hết các công nghệ này sẽ thay đổi đáng kể một lần nữa. Tuy nhiên, nhiều người trong chúng ta biến chúng thành một phần trung tâm, không thể tách rời trong các ứng dụng của mình.

Chúng tôi nhập khẩu, sử dụng và kế thừa từ các khuôn khổ của tháng như thể tất cả chúng sẽ tồn tại và không thay đổi mãi mãi. Vâng, họ không phải là họ. Và đó là một vấn đề.

Sau hơn 20 năm phát triển, thiết kế và kiến ​​trúc các ứng dụng web, tôi đã đến để đánh giá cao hai sự thật quan trọng:

  1. Sự phụ thuộc bên ngoài là mối đe dọa lớn đối với sự ổn định và khả năng tồn tại lâu dài của bất kỳ ứng dụng nào.
  2. Nó ngày càng khó khăn - nếu không nói là không thể - để xây dựng bất kỳ loại ứng dụng không tầm thường nào mà không tận dụng các phụ thuộc bên ngoài.

Bài viết này là về việc hòa giải hai sự thật này để các ứng dụng của chúng tôi có cơ hội sống sót lâu dài nhất.

Lỗ thỏ thực sự rất sâu.

Nếu chúng ta bắt đầu nghĩ về tất cả những điều mà các ứng dụng web của chúng ta phụ thuộc vào nó thì dễ dàng nghĩ ra hàng tá hoặc hơn trước khi chúng ta nhận được mã:

  • Quyền lực
  • Kết nối
  • Bức tường lửa
  • DNS
  • Phần cứng máy chủ (CPU, Đĩa, Ram, Nhận)
  • Làm mát
  • Nền tảng ảo hóa
  • Nền tảng container
  • Hệ điều hành
  • Nền tảng máy chủ web
  • Nền tảng máy chủ ứng dụng
  • Trình duyệt web

Là những nhà phát triển, rất tốt để nhận thức được những điều này, nhưng ở đó, chúng tôi thường không thể làm gì nhiều với chúng. Vì vậy, bây giờ, hãy bỏ qua chúng và bỏ qua chúng.

Trong mã, có ba loại phụ thuộc:

1. Phụ thuộc chúng tôi kiểm soát

Đây là mã được viết và sở hữu bởi chúng tôi hoặc tổ chức của chúng tôi.

2. Phụ thuộc chúng tôi không kiểm soát được

Đây là mã được viết bởi nhà cung cấp bên thứ ba hoặc cộng đồng phần mềm nguồn mở.

3. Phụ thuộc một khi đã loại bỏ

Đây là các phụ thuộc mã phụ thuộc vào mã bên thứ ba của chúng tôi phụ thuộc vào. (Nói rằng nhanh gấp ba lần!)

Chúng tôi sẽ nói chuyện chủ yếu về sự phụ thuộc mà chúng tôi không kiểm soát.

Sự phụ thuộc mà chúng ta kiểm soát và phụ thuộc một khi đã loại bỏ vẫn có thể gây ra đau đầu, nhưng trong trường hợp phụ thuộc mà chúng ta kiểm soát, chúng ta sẽ có thể can thiệp trực tiếp và giảm thiểu mọi vấn đề.

Trong trường hợp phụ thuộc một khi đã loại bỏ, chúng ta thường có thể dựa vào bên thứ ba để chăm sóc nó cho chúng ta, vì họ cũng phụ thuộc vào những điều này.

Tại sao phụ thuộc mã của bên thứ ba là tốt

Một phần lớn ứng dụng web của bạn tồn tại để giải quyết các vấn đề phổ biến: xác thực, ủy quyền, truy cập dữ liệu, xử lý lỗi, điều hướng, ghi nhật ký, mã hóa, hiển thị danh sách các mục, xác thực nhập liệu, v.v.

Bất kể bạn sử dụng ngăn xếp công nghệ nào, có một cơ hội tốt là các giải pháp chung cho các vấn đề này tồn tại và có sẵn dưới dạng các thư viện mà bạn có thể dễ dàng có được và cắm vào cơ sở mã của mình. Viết bất kỳ thứ gì trong số này hoàn toàn từ đầu thường là lãng phí thời gian.

Bạn muốn tập trung vào mã giải quyết một vấn đề không phổ biến hoặc giải quyết một vấn đề phổ biến theo cách không phổ biến. Đó là những gì làm cho ứng dụng của bạn có giá trị: mã thực hiện các quy tắc kinh doanh duy nhất cho ứng dụng của bạn - nước sốt bí mật.

Thuật toán xếp hạng trang và tìm kiếm của Google, bộ lọc dòng thời gian của Facebook, Bộ lọc Netflix được đề xuất cho bạn phần Thuật toán và thuật toán nén dữ liệu.

Mã của bên thứ ba - dưới dạng thư viện - cho phép bạn nhanh chóng triển khai các tính năng được hàng hóa hóa trong ứng dụng của mình, để bạn có thể tập trung vào nước sốt bí mật của bạn.

Tại sao phụ thuộc mã của bên thứ ba là xấu

Hãy xem bất kỳ ứng dụng web không tầm thường nào được xây dựng trong vài năm qua và bạn sẽ hoàn toàn kinh ngạc trước số lượng mã thực sự đến từ thư viện của bên thứ ba. Điều gì xảy ra nếu một hoặc nhiều thư viện của bên thứ ba thay đổi mạnh mẽ, hoặc biến mất hoặc phá vỡ?

Nếu nó là mã nguồn mở, có lẽ bạn có thể tự sửa nó. Nhưng làm thế nào để bạn hiểu tất cả các mã trong thư viện mà bạn không sở hữu? Một lý do lớn tại sao bạn sử dụng một thư viện ở nơi đầu tiên là để có được những lợi ích của mã mà không phải lo lắng về tất cả các chi tiết. Nhưng bây giờ bạn đã bị mắc kẹt. Bạn đã hoàn toàn gắn kết tài sản của mình với những sự phụ thuộc mà bạn không thể sở hữu và không nên kiểm soát.

Đừng lo lắng, đến cuối bài viết này, bạn sẽ tìm thấy một hy vọng mới.

Có lẽ bạn nghĩ tôi phóng đại, hoặc nói theo quan điểm học thuật thuần túy. Hãy để tôi đảm bảo với bạn - Tôi có hàng tá ví dụ về các khách hàng hoàn toàn tự giật mình bằng cách nhúng mã của bên thứ ba quá chặt vào ứng dụng của họ. Đây chỉ là một ví dụ gần đây

Một khách hàng cũ của tôi đã xây dựng ứng dụng của họ bằng cách sử dụng nhà cung cấp dịch vụ Backend-as-a-Service do Facebook sở hữu, được gọi là Parse. Họ đã sử dụng thư viện máy khách JavaScript do Parse cung cấp để sử dụng dịch vụ Parse. Trong quá trình này, họ đã liên kết chặt chẽ tất cả các mã của họ - bao gồm cả mã bí mật sốt bí mật - vào thư viện này.

Ba tháng sau khi khách hàng của tôi ra mắt sản phẩm ban đầu - ngay khi họ bắt đầu có được sức hút tốt với những khách hàng thực sự, trả tiền - Parse tuyên bố nó sẽ ngừng hoạt động.

Bây giờ thay vì tập trung vào việc lặp lại sản phẩm của họ và phát triển cơ sở khách hàng của họ, khách hàng của tôi đã phải tìm ra cách chuyển sang phiên bản Parse tự lưu trữ, nguồn mở hoặc thay thế hoàn toàn Parse.

Sự gián đoạn này gây ra cho một ứng dụng non trẻ, quá lớn đến nỗi khách hàng của tôi cuối cùng đã loại bỏ hoàn toàn ứng dụng.

Cân bằng giữa cái tốt và cái xấu

Cách đây vài năm, giải pháp tiếp theo của tôi để khắc phục rủi ro trong khi vẫn giữ được lợi ích của các thư viện bên thứ ba là bọc chúng bằng Mô hình bộ điều hợp.

Về cơ bản, bạn bọc mã bên thứ ba trong một lớp hoặc mô-đun bộ điều hợp mà bạn đã viết. Điều này sau đó hoạt động để hiển thị các chức năng của các thư viện bên thứ ba theo cách mà bạn kiểm soát.

Sử dụng mẫu này, nếu thư viện hoặc khung của bên thứ ba thay đổi hoặc biến mất, bạn chỉ phải sửa một chút mã bộ điều hợp. Phần còn lại của ứng dụng của bạn vẫn còn nguyên.

Sơ đồ mô hình bộ điều hợp từ Dofactory.com

Điều này nghe có vẻ tốt trên giấy. Khi bạn có các phụ thuộc khép kín chỉ cung cấp một vài chức năng, điều này sẽ thực hiện thủ thuật. Nhưng mọi thứ có thể trở nên xấu xí nhanh chóng.

Bạn có thể tưởng tượng việc phải bọc toàn bộ thư viện React (bao gồm cả JSX) trước khi sử dụng bất kỳ thư viện nào không? Làm thế nào về việc gói jQuery, hoặc Angular hoặc khung công tác Spring trong Java? Điều này nhanh chóng trở thành một cơn ác mộng.

Những ngày này tôi đề nghị một cách tiếp cận nhiều sắc thái hơn

Đối với mỗi phụ thuộc bạn muốn thêm vào cơ sở mã của mình, hãy đánh giá mức độ rủi ro mà nó sẽ đưa ra bằng cách nhân hai yếu tố:

  1. Khả năng phụ thuộc sẽ thay đổi một cách vật chất.
  2. Mức độ thiệt hại mà một sự thay đổi quan trọng đối với sự phụ thuộc sẽ gây ra cho ứng dụng của bạn.

Thư viện hoặc khung của bên thứ ba ít có khả năng thay đổi khi một số hoặc tất cả những điều sau đây là đúng:

  • Nó đã được khoảng vài năm và đã có một vài phiên bản chính.
  • Nó được sử dụng rộng rãi bởi nhiều ứng dụng thương mại.
  • Nó có sự hỗ trợ tích cực của một tổ chức lớn - tốt nhất là một công ty hoặc tổ chức tên hộ gia đình.

Thư viện hoặc khung của bên thứ ba sẽ ít gây thiệt hại cho ứng dụng của bạn khi một số hoặc tất cả những điều sau đây là đúng:

  • Nó chỉ được sử dụng bởi một phần nhỏ trong ứng dụng của bạn, thay vì được sử dụng xuyên suốt.
  • Mã phụ thuộc vào nó không phải là một phần của nước sốt bí mật mà tôi đã nói trước đó.
  • Loại bỏ nó đòi hỏi những thay đổi tối thiểu đối với cơ sở mã của bạn.
  • Toàn bộ ứng dụng của bạn rất nhỏ và có thể được viết lại nhanh chóng. (Hãy cẩn thận với điều này - nó hiếm khi đúng trong thời gian dài.)

Điều gì đó càng nguy hiểm, bạn càng có nhiều khả năng nên bọc nó hoặc tránh nó hoàn toàn.

Khi nói đến mã thực sự là trọng tâm của đề xuất giá trị của ứng dụng của bạn, thì nên dùng nước sốt bí mật của bạn. Làm cho mã đó độc lập nhất có thể. Nếu bạn thực sự cần sử dụng một phụ thuộc, hãy xem xét tiêm nó hơn là trực tiếp tham khảo nó. Ngay cả sau đó, hãy cẩn thận.

Đôi khi, điều này có nghĩa là nói không có thư viện đối với thư viện của bên thứ ba mà bạn cho là thực sự hay bạn thực sự muốn sử dụng vì lý do này hay lý do khác. Hãy mạnh mẽ. Tin tôi đi, nó sẽ trả hết. Chỉ cần hỏi tất cả những người đầu tư mạnh vào phiên bản đầu tiên của Angular, hoặc khách hàng cũ của tôi, người đã sử dụng Parse ở mọi nơi. Nó không vui. Tin tôi đi.

Nói về niềm vui, hãy xem điều này

Biểu đồ phụ thuộc cho thám hiểm TinyTag

Hình trên là biểu đồ phụ thuộc cho một ứng dụng có tên TinyTag Explorer.

Tạo biểu đồ phụ thuộc cho các ứng dụng hiện tại của bạn là một cách tuyệt vời để hiểu mức độ rủi ro được giới thiệu bởi các phụ thuộc của bạn. Tôi đã tập hợp một danh sách các công cụ miễn phí để tạo các biểu đồ tương tự như trên bằng nhiều ngôn ngữ bao gồm JavaScript, C #, Java, PHP và Python. Bạn có thể lấy nó ở đây.

Giúp tôi giúp người khác

Tôi muốn giúp đỡ nhiều nhà phát triển nhất có thể bằng cách chia sẻ kiến ​​thức và kinh nghiệm của tôi với họ. Xin hãy giúp tôi bằng cách nhấp vào nút ❤ giới thiệu (trái tim xanh) bên dưới.

Cuối cùng, don không quên lấy danh sách các trình tạo biểu đồ phụ thuộc miễn phí tại đây.