So sánh Objective-C và Swift trong iOS development
Qua bài này các bạn sẽ nắm được các khía cạnh của 2 ngôn ngữ phổ biến nhất trong lập trình iOS: Objective-C và Swift:
- Tiểu sử Objective-C
- Tiểu sử Swift
- So sánh syntax
- So sánh performance!
- Ưu và nhược điểm của Objective-C
- Ưu và nhược điểm của Swift
- Sự khác biệt nổi bật
- Quản lý bộ nhớ
- Khi nào chọn Objective-C hoặc Swift
- Mức độ phổ biến năm 2024
Tiểu sử Objective-C
Objective-C được phát triển vào đầu những năm 1980 bởi công ty Stepstone (ban đầu là công ty Gnu) do Brad Cox và Tom Love sáng lập. Tích hợp các khái niệm lập trình hướng đối tượng từ Smalltalk, cho phép các nhà phát triển viết các chương trình linh hoạt và hiệu quả hơn. Objective-C đã trở thành ngôn ngữ chính để phát triển ứng dụng trên các platform của Apple sau khi Apple mua lại NeXT, công ty mà Cox và Love làm việc.
Đặc điểm của Objective-C Dù tuổi đời rất cao, nhưng nhờ khả năng tương thích với cả ngôn ngữ Swift và C, Objective-C vẫn còn phổ biến cho đến ngày nay với cộng đồng lớn và lâu đời. Một trong những thử thách "chật vật" với lập trình viên Objective-C đó là con trỏ và quản lý bộ nhớ thủ công, tuy nhiên đây lại là điểm mạnh ở ngôn ngữ Swift
Objective-C kết hợp các tính năng từ hai ngôn ngữ lập trình: C và Smalltalk. Do đó, nó có cú pháp phức tạp và dài dòng. Cú pháp hướng đối tượng được lấy từ Smalltalk, trong khi cú pháp cho các thao tác không hướng đối tượng lại giống như C. Objective-C sử dụng dynamic typing và message passing, các class được chia thành hai block codes: interface và implement, nằm trong các file riêng biệt. Objective-C là một ngôn ngữ mạnh mẽ, nhưng do kế thừa từ các ngôn ngữ cũ, nó có cảm giác cổ điển, cồng kềnh và khó tiếp cận với người mới so với Swift.
- Dynamic typing: kiểu của 1 object được check tại thời điểm runtime, không phải buildtime, cho phép mã nguồn linh hoạt. Khi khởi tạo 1 object không cần xác định cụ thể kiểu của nó.
id someObject = [[NSObject alloc] init];
- Message passing: Là cơ chế gọi 1 hàm trong 1 object. Thay vì gọi trực tiếp tới hàm đó, sẽ gửi 1 message tới object, trong thời gian runtime, object đó sẽ xác định hàm nào được executed, giống với cách gọi 1 hàm trong ngôn ngữ Smalltalk.
[someObject performSelector:@selector(someMethod)];
Tiểu sử Swift
Swift là ngôn ngữ "con ruột" của Apple, được phát triển năm 2010 bởi Chris Lattner - 1 nhân viên của Apple và chính thức giới thiệu tới cộng đồng năm 2014. Được cải tiến từ Objective-C với mục đích là dễ dàng hơn trong việc implement, maintaing code trên các nền tảng iOS, macOS, tvOS, watchOS, và Linux app development.
Swift nhận được sự ủng hộ của các developer và nhanh chóng trở nên phổ biến vì syntax đơn giản, dễ hiểu, tính năng hiện đại và khả năng quản lý bộ nhớ tự động. Là ngôn ngữ bậc cao tương tự như Python, JavaScript, ... giúp viết phần mềm hiệu quả trên mobile, desktop, iPad, TV, apple watch thậm chí là server, phù hợp cho các mã nguồn performance-sensitive và có cơ chế phát hiện bug sớm để fix sớm.
var welcomeMessage: String
var red, green, blue: Double
let cat = "🐱"; print(cat)
// Prints "🐱"
Đặc điểm của Swift Swift 6.0 được giới thiệu năm 2024, luôn được Apple quan tâm giới thiệu các tính năng mới trong mỗi sự kiện WWDC, các tính năng nổi bật của Swift như:
-
Type Inference: Tự suy luận kiểu cho phép developer không cần khai báo kiểu cụ thể, chỉ cần cung cấp giá trị khởi tạo, Swift sẽ tự suy luận kiểu cho biến đó, hoàn toàn ngắn gọn hơn Objective-C và C
let meaningOfLife = 42 // meaningOfLife is inferred to be of type Int let pi = 3.14159 // pi is inferred to be of type Double let anotherPi = 3 + 0.14159 // anotherPi is also inferred to be of type Double
-
Type safe: Swift sẽ check kiểu của biến tại thời điểm compile time - biên dịch, điều đó có nghĩa là bạn phải chắc chắn kiểu của 1 biến. VD 1 biến có kiểu là
Int
, bạn không thể gán biến đó thànhString
. Swift sẽ báo lỗi không đúng kiểu ngay tại thời điểm biên dịch, giúp bạn phát hiện lỗi sớm và fix tại thời điểm coding.var sheepName = "sheep" // String sheep = 10 // show error as 10 is Int
-
Optional: Đại diện cho 2 trường hợp: hoặc là có giá trị của 1 kiểu chỉ định và có thể unwrap optional để sử dụng giá trị đó, hoặc là không có giá trị. Ví dụ, bạn muốn convert 1 giá trị
String
sang giá trịInt
như "123" -> 123, tuy nhiên sẽ có nhữngString
không thể convert được sangInt
như "hello World", lúc này optional là giải pháp. Giá trịInt
được convert có thể có giá trị làInt
, hoặc không có giá trị gì cả.let possibleNumber = "123" let convertedNumber = Int(possibleNumber) // The type of convertedNumber is "optional Int" or Int?
-
Generic: Là tính năng cho phép bạn viết code linh hoạt, tái sử dụng function và type, có phép làm việc với tất cả kiểu, object mà phù hợp với yêu cầu mà bạn định nghĩa. Cho phép lập trình viên tránh được code trùng lặp và định nghĩa, thể hiện được mục đích trừu tượng.
VD: Muốn hoán đổi 2 giá trị cùng kiểu:
- Không dùng generic, với mỗi kiểu, ta phải viết 1 func mới.
func swapTwoInts(_ a: inout Int, _ b: inout Int) { let temporaryA = a a = b b = temporaryA } func swapTwoStrings(_ a: inout String, _ b: inout String) { let temporaryA = a a = b b = temporaryA } func swapTwoDoubles(_ a: inout Double, _ b: inout Double) { let temporaryA = a a = b b = temporaryA }
- Áp dụng generic, chỉ còn 1 func tái sử dụng cho tất cả func trên
func swapTwoValues<T>(_ a: inout T, _ b: inout T) { let temporaryA = a a = b b = temporaryA }
- Không dùng generic, với mỗi kiểu, ta phải viết 1 func mới.
-
High order function: Nôm na là thực hiện biến đổi các phần tử trên cùng 1 phép tính, hay technical hơn thì là trừu tượng hoá các logic lặp đi lặp lại và chỉ tập trung vào phép biến đổi nào đang sử dụng, giúp code ngắn gọn và dễ đọc hơn. Đi ngay vào VD nhé cho dễ hình dung nhé.
let numbers = [1, 2, 3, 4, 5] let squaredNumbers = numbers.map { $0 * $0 } print(squaredNumbers) // Output: [1, 4, 9, 16, 25] let evenNumbers = numbers.filter { $0 % 2 == 0 } print(evenNumbers) // Output: [2, 4] let sum = numbers.reduce(0) { $0 + $1 } print(sum) // Output: 15 let sum = numbers .map { $0 * $0 } .filter { $0 % 2 != 0 } .reduce(0, +) print(sum) // Output: 35
So sánh syntax
Cú pháp của Objective-C khét tiếng là phức tạp và dài dòng. Nó bao gồm nhiều dấu ngoặc vuông [ ]
và dấu chấm phẩy ;
, gây khó khăn cho lập trình viên khi tập trung vào phần cốt lõi của mã nguồn. Ngược lại, Swift có cú pháp ngắn gọn, xúc tích hơn, giống như tiếng Anh đơn giản, giúp dễ hiểu, dễ học, dễ tiếp cận cho người mới hơn. Swift giúp không chỉ tăng tốc quá trình phát triển mà còn giảm bug tiềm ẩn, phát hiện lỗi nhanh qua trình biên dịch.
Đặc biệt Objective-C tồn tại 2 file mã nguồn cho mỗi đối tượng là file interface .h
và file implement .m
, gây mất thời gian hoặc thấm chí confused cho người mới. Swift đã tinh giảm xuống chỉ còn 1 file duy nhất, developer chỉ cần quan tâm tới file implement source code,/
- Syntax của Objective-C
#import <Foundation/Foundation.h> @interface Greeter : NSObject - (void)greet; @end @implementation Greeter - (void)greet { NSLog(@"Hello, World!"); } @end Greeter *greeter = [[Greeter alloc] init]; [greeter greet];
- Syntax của Swift
import Foundation class Greeter { func greet() { print("Hello, World!") } } let greeter = Greeter() greeter.greet()
So sánh performance
Tính năng của ngôn ngữ lập trình ảnh hưởng rất lớn đến các khía cạnh kinh doanh của phát triển ứng dụng iOS, đặc biệt là về tốc độ phát triển phần mềm. Khi so sánh Swift với Objective-C, phát triển ứng dụng với Swift nhanh hơn. Vì sao?
- Generics và Higher-Order Functions: giúp Swift viết code clean và dễ tái sử dụng hơn.
- Optionals và Type Inference: giúp Swift đảm bảo tính đúng đắn của mã nguồn, phát hiện lỗi ngay tại thời điểm biên dịch.
- Syntax ngắn gọn hơn: giúp Swift không cần tạo 2 file interface và implement của một đối tượng, giúp lập trình viên viết ít dòng mã hơn nhưng đạt được cùng kết quả.
Kết hợp lại, những yếu tố này làm cho việc phát triển ứng dụng nhanh hơn với Swift. Theo kinh nghiệm của tôi và các đồng nghiệp lập trình viên iOS, điều này không chỉ là lý thuyết mà còn là thực tế quan sát được. Có những so sánh được chỉ ra, với Apple khẳng định rằng các ứng dụng viết bằng Swift nhanh hơn tới 2,6 lần so với Objective-C!
Tất nhiên, hiệu suất ngôn ngữ trong phát triển ứng dụng iOS cũng có thể bị ảnh hưởng bởi các yếu tố như tối ưu hóa quản lý bộ nhớ (RC) và việc sử dụng cùng SDK iOS và trình biên dịch LLVM. Tuy nhiên, các tính năng hiện đại và cấu trúc hiệu quả của Swift làm cho nó trở thành lựa chọn nhanh hơn và hiệu quả hơn cho phát triển ứng dụng tổng thể.
Ưu và nhược điểm của Objective-C
Ưu điểm của Objective-C
- Tính đến năm 2024, Objetive-C đã hơn 40 tuổi, và được kiểm chứng "gừng càng già càng cay": Có hàng triệu source code, OSS library, framework đi kèm tài liệu chi tiết. Các câu hỏi liên quan đến Objective-C đều có câu trả lời trên Stack Overflow.
- Tương thích tốt với C và C++: Là phần mở rộng của C, Objective-C hoạt động mượt mà với mã C và C++.
- Ngôn ngữ ổn định: Phát triển ứng dụng bằng Objective-C không đòi hỏi phải chuyển đổi ngôn ngữ mới sau vài tháng.
Nhược điểm của Objective-C
- Tuổi đời quá già, không đú lại được so với Gen G: Nhiều thư viện và công cụ của Objective-C không còn được duy trì, upgrade version mới, hoặc bị deprecated do bị Swift thay thế.
- Khó học: Khác biệt so với các ngôn ngữ lập trình hiện đại và quản lý bộ nhớ phức tạp hơn Swift.
- Số lượng lập trình viên biết sử dụng đang giảm: Hầu hết lập trình viên iOS mới bắt đầu bằng Swift, còn lập trình viên có kinh nghiệm với Objective-C thường cũng biết Swift hoặc sẵn sàng học.
- Dễ bị hack hơn: Objective-C đã tồn tại hàng thập kỷ, công cụ reverse engineering cũng phát triển mạnh, có thể bị đảo ngược mã nguồn.
Ưu và nhược điểm của Swift
Ưu điểm của Swift
- An toàn hơn: Các tính năng như generics, optionals và type inference giúp ứng dụng phát triển bằng Swift ít lỗi và crash hơn so với Objective-C.
- Là con đẻ của Apple: Apple liên tục cải tiến Swift, thêm tính năng mới và hỗ trợ các nhà phát triển. WWDC hàng năm (Apple’s annual Worldwide Developers Conference) luôn có các technical speak about Swift. Thậm chí, có cả buổi tech talk về sử dụng Swift làm ngôn ngữ backend.
- Có famework SwiftUI mạnh mẽ cho giao diện mới: Giới thiệu năm 2019, SwiftUI cho phép xây dựng giao diện người dùng nhanh chóng và dễ dàng, có thể thay thế UIKit (Objective-C chỉ có UIKit để xây dựng UI).
- Được ưa chuộng hơn: Theo khảo sát Stack Overflow 2022, 63% nhà phát triển iOS yêu thích Swift, trong khi hơn 76% không thích Objective-C.
- Swift Package Manager: Công cụ quản lý dependencies và thư viện bên thứ ba, thay thế CocoaPods và Carthage.
Nhược điểm của Swift
- Tương đối mới: Cập nhật thường xuyên có thể gây ra không tương thích với các phiên bản iOS cũ hơn, đôi khi phải bỏ hỗ trợ cho các thiết bị cũ.
- Hỗ trợ đa nền tảng chưa hoàn thiện: Hỗ trợ tốt cho các nền tảng của Apple, Linux và Windows, nhưng ứng dụng đa nền tảng vẫn tốt hơn khi dùng React Native, Flutter hoặc Xamarin(1/5/2024, Microsoft ngừng hỗ trợ và cập nhập Xamarin).
Sự khác biệt nổi bật
Tiêu chí | Objective-C | Swift |
---|---|---|
Cấu trúc file của khai báo lớp | Interface và implementation tách biệt. Interface nằm trong file header (.h), implementation trong file .m | Interface và implementation trong cùng một file |
Kiểm tra kiểu dữ liệu | Kết hợp static và dynamic typing, nhưng hầu hết là dynamic (kiểm tra kiểu tại thời điểm runtime) | Static typing (kiểm tra kiểu tại thời điểm compile time |
Tính bất biến (Mutability) | Theo mặc định, tất cả các đối tượng đều có thể thay đổi được. Khả năng biến đổi trong các lớp cơ sở như String được kiểm soát bởi tên lớp bạn sử dụng - tức là NSString luôn bất biến - không thay đổi, trong khi NSMutableString luôn có thể thay đổi. | Sử dụng var cho biến và let cho hằng số |
Boolean | Sử dụng true/false, YES/NO, kiểu BOOL/bool | Kiểu Bool, giá trị true/false |
Ký tự kết thúc câu lệnh | Dấu chấm phẩy ; |
Không cần ký tự kết thúc |
Quản lý bộ nhớ
Quản lý bộ nhớ thủ công là một thách thức tốn thời gian và nhàm chán mà các nhà phát triển sử dụng Objective-C phải đối mặt. Ngược lại, Swift sử dụng Automatic Reference Counting (ARC) để quản lý bộ nhớ hiệu quả hơn, giúp các nhà phát triển không phải lo lắng về việc quản lý bộ nhớ thủ công.
ARC sẽ tự động quản lý việc khởi tạo và giải phóng các vùng nhớ không còn dùng, tuy nhiên developer cần phải áp dụng các practices khi khởi tạo và truy cập các vùng nhớ trong lập trình async để ứng dụng không bị memory leak. ARC cho phép các nhà phát triển tập trung vào các khía cạnh khác của việc phát triển ứng dụng, từ đó nâng cao chất lượng các ứng dụng. Đáng chú ý là ARC của Objective-C chỉ hỗ trợ API Cocoa, điều này có thể là một hạn chế đối với các nhà phát triển làm việc với Core Graphics.
Khi nào chọn Objective-C hoặc Swift
Swift là sự lựa chọn tốt hơn so với Objective-C khi xây dựng ứng dụng iOS. Hầu hết – nếu không muốn nói là gần như tất cả – các ứng dụng iOS mới đều được xây dựng bằng Swift. Thực tế, thành tựu của Swift đã được minh chứng bởi các ứng dụng nổi tiếng như LinkedIn, Lyft, Khan Academy, Airbnb, Eventbrite, Sky Guide, Wikipedia, Coursera, Slack, và VSCO.
Tuy nhiên, có ít nhất hai trường hợp mà việc sử dụng Objective-C vẫn có lợi:
- Nếu bạn có sẵn 1 source code lớn viết bằng Objective-C và cần maintaince hoặc thêm một vài tính năng mới, có thể tốt hơn là tiếp tục sử dụng Objective-C. Mặc dù Swift có khả năng tương tác với Objective-C, tức là bạn có thể sử dụng cả hai ngôn ngữ trong cùng một dự án, việc duy trì ứng dụng như vậy có thể gây ra vấn đề. Ví dụ, có thể có những trường hợp đặc biệt mà dự án cần một developer thành thạo cả hai ngôn ngữ. Hơn nữa, việc chuyển đổi giữa hai ngôn ngữ có thể ảnh hưởng đến năng suất của developer.
- Nếu bạn thường xuyên sử dụng các framework bên thứ ba viết bằng C hoặc C++, Objective-C là sự lựa chọn đáng cân nhắc, vì Swift cần phải tạo ra một lớp wrap lại lớp C/C++, điều này thường phức tạp hơn so với việc sử dụng Objective-C.
Mức độ phổ biến năm 2024
The PYPL PopularitY of Programming Language Index Chỉ số mức độ phổ biến của các ngôn ngữ lập trình theo PYPL được tạo bằng cách phân tích tần suất tìm kiếm các hướng dẫn về ngôn ngữ trên Google. Càng nhiều lượt tìm kiếm các khoá học tutorial thì ngôn ngữ đó được coi là càng phổ biến. Dữ liệu raw cung cấp bởi Google Trends.
Tính đến tháng 8/2024, Swift duy trì vị trí top 9, trong khi đó Objective-C bị tụt 1 rank xuống vị trí thứ 11. Phía bên kia chiến tuyến, ngôn ngữ lập trình phổ biến cho Android là Kotlin ở vị trí thứ 13.
Các khảo sát khác các bạn có thể tham khảo ở đây
- https://survey.stackoverflow.co/2023/#most-popular-technologies-language
- https://www.jetbrains.com/lp/devecosystem-2023/swift-objc/
- https://www.statista.com/statistics/793628/worldwide-developer-survey-most-used-languages/
Các khảo sát trên chỉ mang tính tham khảo, không phải thước đo cho mọi vùng, lĩnh vực, đối tượng lập trình viên với level kinh nghiệm khác nhau.
Tham khảo
All rights reserved