Dependency và cách xử lý những xung đột về phiên bản nhờ Semantic Versioning sẽ được trình bày trong phần đầu tiên của loạt bài về semver.
Welcome to hell
Chúng ta không còn xa lạ với dependency hell – khi mà các thư viện mà project phụ thuộc (dependency) xung đột về phiên bản (version requirement conflicts). Việc bảo trì và phát triển các project có sử dụng các dependency, do đó, cũng trở nên khó khăn và nguy hiểm hơn.
Một ví dụ nhỏ cho dependency hell từ npm.
Giả sử ta có 3 modules: A, B và C. A cần module B phiên bản v1.0. C cũng cần module B nhưng v2.0.
Ứng dụng của chúng ta cần cả A và C
Vậy chính xác thì phiên bản nào của B sẽ được sử dụng?

Chính việc thiếu các quy tắc về số hiệu các phiên bản (versioning) là nguồn gốc dẫn đến dependency hell.

Semantic Versioning: The Escape
Semantic Versioning?
Semantic Versioning, gọi tắt là semver, là mô tả kỹ thuật (specification) vềversioning và các nguyên tắc liên quan.
Summary
Theo semver, mỗi phiên bản sẽ được định dạng (format) với 3 thành phần chính: MAJOR.MINOR.PATCH.
Thay đổi:
  • Phiên bản MAJOR khi có những thay đổi không còn tương thích với API cũ
  • Phiên bản MINOR khi có những tính năng được bổ sung nhưng vẫn đảm bảo sự tương thích như phiên bản trước (backwards-compatible)
  • Phiên bản PATCH khi có những bản vá, bug fix nhưng vẫn đảm bảo sự tương thích.
Các nhãn thêm vào cho những bản release sớm như: rc (Release candidate),alphabeta, ..vv hoặc build metadata có thể coi là extension cho format trên.
Ví dụ: 2.0.0-rc.1 hay 1.0.0-beta+exp.sha.5114f85
Một ví dụ lược lại từ semver-ftw

Giả sử ta bán pizza – phiên bản 1.0.0. Khi thêm một loại hương vị mới, ví dụ pepperoni(), phiên bản của pizza cần tăng lên 1.1.0 (new feature). Hương vị này không được ngon cho lắm, ta thay đổi lại một chút, phiên bản sau của pizza là 1.1.1(bug fix). Sau một thời gian kinh doanh, ta quyết định loại bỏ loại pizza pepperoni()này. Lúc đó, phiên bản của pizza sẽ là 2.0.0 (breaking change)

Đứng dưới vai trò là khách hàng, bằng việc xem xét các phiên bản của pizza, ta có thể đưa ra được những quyết định phù hợp. Ví dụ, người mua muốn ăn pepperoni(), sau khi xem xét, họ thấy phiên bản của pizza hiện tại là 1.1.8, họ có thể đặt hàng và biết chắc chắn chiếc bánh họ mua là chiếc có pepperoni()
Specification
Semver 2.0.0 bao gồm 11 quy tắc, vui lòng xem thêm tại:http://semver.org/spec/v2.0.0.html#semantic-versioning-specification-semver
Các package được khuyến khích đặt tên phiên bản theo các quy tắc này.
Đôi khi bạn sẽ thấy các project trên github có các tag dưới dạng vMAJOR.MINOR.PATCH, ví dụ v1.0.1. Theo ý kiến cá nhân, các hệ thống version control như gitsubversion khuyến khích đặt tên tag với prefix v. Các ký tự như v và = sẽ được bỏ qua khi phân giải (resolve) dependency.
Version Range
Trích npm/node-semver

A version range is a set of comparators which specify versions that satisfy the range.
A comparator is composed of an operator and a version.

Các primitive operators bao gồm: <, <=, >, >=, = (mặc định). Ví dụ, >=1.2.7 sẽ phù hợp (match) với các version 1.2.7, 1.2.8, 2.5.3 và 1.3.9, không match 1.2.6 hay 1.1.0
Bạn có thể nhóm các comparator bằng khoảng trắng để tạo thành một comparator set. Điều này tương đương phép giao (intersection). Ví dụ, >=1.2.7 <1.3.0.
Bạn cũng có thể dùng phép hợp (union) với ||. Ví dụ, 1.2.7 || >=1.2.9 <2.0.0 sẽ match 1.2.7, 1.2.9 và 1.4.6 nhưng không bao gồm 1.2.8 hay 2.0.0

Hết phần I
Ở phần đầu của bài viết, mình đã trình bày về dependency hellsemver và một vài định nghĩa đơn giản của version range. Ở phần sau của bài viết, mình sẽ tiếp tục với các định nghĩa version range nâng cao và các practical use của chúng. Hi vọng các bạn sẽ đón đọc.
Đào Vinh Hiển
Tin liên quan: