Tại sao các ứng dụng lớn vẫn chưa chuyển qua Swift?

Tôi luôn tin rằng Swift là tương lai của lập trình iOS. Vấn đề chỉ là thời điểm và nguyên nhân cản trở chính là tốc độ phát triển chóng mặt của Swift. Đối với các ứng dụng nhỏ thì Swift là ngôn ngữ lý tưởng, nhưng với ứng dụng lớn, sẽ tốn ít nhất 1 năm nữa để Swift thể hiện được vai trò của mình.

Từ “ứng dụng lớn” mà tôi sử dụng ở đây dành cho những hạng mục khác nhau, từ các dòng code, đến số lượng lập trình viên, mức độ phức tạp của ứng dụng hoặc khả năng chịu đựng thấp trước các vấn đề. Đầu năm nay, chuyên gia Ryan Olson, sau khi phân tích biểu đồ Top 100 apps miễn phí trên App Store, chỉ ra rằng 89% ứng dụng không dùng đến Swift. Điều này không đồng nghĩa là chỉ có 11% còn lại đã chấp nhận Swift. Một đội ngũ lập trình ứng dụng mà tôi từng nói chuyện cũng đã bắt đầu thử nghiệm với Swift nhưng ngôn ngữ mặc định trong hầu hết công việc của họ vẫn là Objective-C.

Nếu bạn đang lập trình 1 ứng dụng nhỏ thì có thể ngưng đọc tại đây vì ưu điểm của Swift 3.0 vẫn vượt trội hơn những nguy cơ mà nó gây ra. Tuy nhiên, nếu bạn đang tò mò về những thách thức của các doanh nghiệp lớn, các codebases lớn và các dependencies phức tạp thì bài viết này sẽ giải thích lý do tại sao các dự án vẫn còn đang ngập ngừng trước lựa chọn Swift.

Language Churn

Mỗi cập nhật của Xcode lại dẫn đến những thay đổi về ngôn ngữ và phá đi các dòng code. Thỉnh thoảng bạn để code migrator làm việc, thỉnh thoảng bạn phải chỉnh sửa thủ công. Bạn chỉ có thể quản lý được việc này nếu có dưới 30.000 dòng codes, nhưng hầu hết các ứng dụng trên thế giới lại không như thế. Chẳng hạn, ứng dụng Facebook có 18.000 classes, tương đương với hàng triệu dòng code.

Kết quả hình ảnh cho facebook

Nếu 2% của codebase chuyển sang Swift sẽ là 20.000 dòng codes. Đặc biệt, nó không ở 1 nơi mà sẽ tản ra trong các experiments đã bị vô hiệu hoặc các refactored code cũ vẫn còn đang được sử dụng.

Đội ngũ kĩ sư chịu trách nhiệm migration sẽ mất 1 tuần theo dõi các tác giả gốc, xác thực code đã cập nhật vẫn hoạt động theo đúng kế hoạch.

Dĩ nhiên, công ty không thể ngừng lập trình trong quá trình migration. Mỗi ngày lại có code mới ra đời và xung đột cứ thế tăng lên.

ABI bất ổn

Vấn đề khác, ít được biết đến là sự phát triển bên trong của Swift – quan trọng nhất là Application Binary Interface. Một ABI sẽ nhận diện layout của các cấu trúc dữ liệu, cách các đối số được đẩy lên trên stack, cách các ứng dụng tạo nên các calls hệ thống và những chi tiết khác 99,99% không liên quan đến công việc lập trình hằng ngày.

Swift 3.0 đã dự định sẽ khóa ABI lại, nhưng đội ngũ lập trình Swift đã thông báo gần đây là họ sẽ không làm vậy nữa. Điều này đồng nghĩa với điều gì?

Một ABI gặp vấn đề khi 2 modules code tách biệt cần phải “nói chuyện” với nhau. Ví dụ, C có thể gọi code Ruby miễn là nó thiết lập 1 frame stack theo dự đoán của runtime.

Giả như bạn đã lập trình 1 framework với Swift 2.2 và ứng dụng cũng chạy trên Swift 2.2. Dù cả 2 apps được xây dựng độc lập, chúng vẫn nói chuyện được với nhau, vì chúng đều có thể nói trong cấu trúc ở mức độ thấp.

Giả như bạn chuyển app sang Swift 3.0. Nếu ABI thay đổi để các đối số được đặt ở các vị trí khác nhau trong stack frame thì nhiều khả năng bạn sẽ bị crash. Cách giải quyết duy nhất là compile mọi thứ trong cùng 1 phiên bản Swift. Tích hợp framework vào Swift 3.0 cùng thời điểm với ứng dụng chính.

Không xây dựng 1 SDK trong Swift

Nếu bạn đang xây dựng 1 pre-compiled SDK, ABI không ổn định sẽ khiến mọi thứ trở thành thảm họa. Khi phiên bản mới của Swift được công bố, bạn cần phải recompile ngay lập tức và ra mắt người dùng của bạn phiên bản mới nhất.

Phiên bản mới nhất của SDK là 2.0. Các khách hàng của bạn có thể vẫn đang chạy trên 1.0 vì phiên bản 2.0 có những thay đổi rất lớn. Bạn không chỉ phải tích hợp phiên bản mới nhất của SDK vào Swift mới nhất và bạn cũng phải tích hợp SDK cũ nữa.

Một vấn đề khác có thể ảnh hưởng đến khả năng tiếp nhận SDK là dung lượng tải xuống cao. Vì các thư viện Swift chính không được chia sẻ trên iOS, nên các thư viện này được tích hợp trong ứng dụng. Trong 1 ứng dụng thuần Objective-C, thêm 1 SDK chạy Swift sẽ tốn đến 5 MB.

Kết quả hình ảnh cho tooling in swift language

Để mắt đến các dependencies phức tạp

Các công ty với nhiều ứng dụng thường chia sẻ chung các frameworks nội bộ. Những frameworks này có thể gồm cấu trúc như networking stack hoặc các tính năng thiên về sản phẩm như màn hình đăng nhập.

Bởi vì tất cả các frameworks cần phải chạy cùng 1 phiên bản Swift, nên tất cả các ứng dụng cần chuyển đổi cùng 1 lúc. Một công ty như Facebook cần tích hợp ứng dụng Facebook, Messenger, Groups và tất cả những thứ khác. Việc này đồng nghĩa với việc phối hợp hàng tá đội ngũ và hàng trăm lập trình viên.

Các vấn đề với Tooling

Dù cho các frameworks được compile trong cùng 1 vùng làm việc, LLDB vẫn có vấn đề với các frameworks ngôn ngữ hỗn hợp. Ví dụ, bạn sẽ bị crash nếu bạn thiết lập breakpoint trong network stack (Framework A) sử dụng đối số là model của bạn (Framework B).

Trong các codebases lớn, sử dụng frameworks do chính bạn code được compile trước sẽ giúp giảm đáng kể thời gian lập trình. Đáng tiếc là, bạn phải hy sinh khả năng debug, đổi lấy thời gian lập trình lâu hơn hoặc khi bạn đến thời kì debug, sẽ gặp phải những mục tiêu projects bấp bênh trên cơ sở từng file một.

Khi phối hợp Objective-C và Swift qua nhiều frameworks, bạn có thể khiến SourceKit bị crash như tình trạng xảy ra vào 7/2014 với Swift 1.0. Bạn sẽ mất syntax highlighting và các đoạn code hoàn thiện. Đây là rào cản lớn đối với các lập trình viên Swift hoặc khi dev làm việc với các tên method dài bất tận của Cocoa.

Kết quả hình ảnh cho tooling issue in swift language

Tuy điều này không liên quan nhiều đến ABI, nhưng tính ổn định của ABI vẫn là 1 rào cản.

Khả năng tích hợp hỗ trợ framework

Để gói gọn phần diễn giải về ABI, tôi sẽ không chỉ tập trung vào những điểm bất lợi. ABI ổn định có thể giảm thiểu các rào cản và tình trạng language churn.

Một chiến lược mà tôi từng thấy ở các ứng dụng lớn là dù code không được sử dụng trong bất kì ứng dụng nào khác, phân giải ứng dụng thành các frameworks. Frameworks hỗ trợ testing dễ dàng hơn và làm rõ quyền sở hữu code.

Với 1 ABI ổn định, bạn có thể giữ các frameworks này ở phiên bản Swift cũ và tích hợp chúng từng bước một. Mỗi đội ngũ sẽ chịu trách nhiệm chuyển đổi code của mình.

Kết

Bài viết này không phải để bêu xấu đội ngũ Swift. Đội ngũ Swift đã ưu tiên phát triển ngôn ngữ và hệ sinh thái, thay vì tập trung vào tính ổn định và giải quyết các trường hợp nhỏ nhặt. Đó là sự trả giá hoàn toàn hợp lý.

Mặc dù platform ổn định, các công ty lớn chuyển đổi platforms với tốc độ rất chậm. Adobe tốn 1 thập kỉ để chuyển từ Photoshop từ Carbon sang Cocoa. Thay vì nghiên cứu những ứng dụng lớn, bạn sẽ có được những lời khuyên tốt từ những người chuyển đổi sớm hơn và sẽ không bị ràng buộc bởi cam kết nhiều năm với tính năng ổn định.

Điều quan trọng nữa tôi muốn nhắc lại là: hầu hết những điều tôi đã đề cập có khả năng không phù hợp với trường hợp của bạn. Có thể bạn đang làm việc với 1 codebase nhỏ hơn, các dependencies đơn giản hơn. Nên nhớ, lợi ích Swift 3.0 mang đến luôn lớn những điểm bất lợi.

Nguồn: IDE Academy via Medium

Chia sẻ bài viết ngay