Các công cụ và thực tiễn tốt nhất cho dự án iOS

Với mẫu dự án Xcode mã nguồn mở

Khi làm việc trên các dự án iOS của Greenfield, tôi thường phải bắt đầu một dự án mới từ đầu. Trong khi làm như vậy, tôi và nhóm của mình luôn dành nhiều thời gian cho việc thiết lập dự án cơ bản như tích hợp các công cụ, thiết lập cấu trúc dự án, viết các lớp cơ sở, tích hợp các thư viện bên ngoài, v.v.

Tôi quyết định rằng thời gian dành cho khởi động dự án có thể được lưu lại và quá trình này có thể được tự động hóa. Tôi đã viết ra tất cả các thực tiễn và công cụ tốt nhất thông thường mà chúng tôi đã sử dụng và chuẩn bị một mẫu dự án mà tôi và nhóm của tôi có thể sử dụng khi bắt đầu các dự án mới. Mẫu này sẽ tiết kiệm thời gian thiết lập dự án và cũng cung cấp một nền tảng chung mà mỗi thành viên trong nhóm sẽ quen với việc bạn không cần phải suy nghĩ và khám phá cấu trúc và nền tảng dự án. Họ sẽ luôn như vậy.

Mỗi và mọi công cụ hoặc thực tiễn tốt nhất có trong mẫu đều xứng đáng có một bài viết riêng nhưng tôi muốn thử tổng hợp từng điểm và đưa ra lời giải thích ngắn gọn tại sao tôi đưa chúng vào.

Cocoapods

Tôi không nghĩ rằng cái này cần một lời giới thiệu. Đây là thư viện để quản lý các phụ thuộc bên ngoài cho các dự án iOS. Nó đã tồn tại trong một thời gian dài và rất mạnh mẽ và trận chiến đã được thử nghiệm trong hàng ngàn (nếu không phải hàng triệu) dự án. Có những người quản lý phụ thuộc thay thế ngoài kia như Carthage nhưng tôi đã quyết định đồng hành cùng Cocoapods vì nó có phạm vi dự án nguồn mở rộng nhất mà nó hỗ trợ. Sử dụng Cocoapods rất dễ dàng và nó đi kèm với một chỉ mục tìm kiếm cho phép bạn dễ dàng khám phá các gói mà bạn có thể cần.

Dự án mẫu đi kèm với một Podfile đơn giản bao gồm Swiftlint và R.swift. Mẫu cũng bao gồm một Gemfile để quản lý phiên bản Cocoapods được sử dụng để giải quyết các phụ thuộc. Đây là một cải tiến thường bị bỏ qua nhằm ngăn chặn các vấn đề phát sinh khi các nhà phát triển trong nhóm của bạn cài đặt các phụ thuộc bằng chính các phiên bản khác nhau của Cocoapods. Gemfile thi hành bằng cách sử dụng cùng một phiên bản Cocoapods trên toàn đội.

Swiftlint

Swiftlint là một công cụ rất hữu ích để thực thi các quy tắc và phong cách mã hóa nhất định cho mọi lập trình viên trong nhóm. Bạn có thể nghĩ về nó như một hệ thống đánh giá mã tự động cảnh báo người lập trình về những điều nguy hiểm như ép buộc, ép buộc, ép buộc, v.v. nhưng cũng thực thi một kiểu mã hóa thông thường bằng cách đảm bảo tất cả các lập trình viên tuân theo các quy tắc liên quan đến mã kiểu giống nhau. như quy tắc thụt lề hoặc khoảng cách. Điều này có lợi ích to lớn không chỉ tiết kiệm thời gian xem xét mã bằng cách thực hiện các kiểm tra cơ bản đó mà còn làm cho tất cả các tệp trong dự án trông quen thuộc, giúp tăng khả năng đọc và kết quả là sự hiểu biết của tất cả các nhà phát triển. Bạn có thể tìm thấy một danh sách tất cả các quy tắc ở đây. Trong mẫu, Swiftlint được cài đặt thông qua Cocoapods và được bao gồm trong bước Xây dựng giai đoạn để nó gợi ý và cảnh báo cho nhà phát triển ở mỗi bản dựng dự án.

R.swift

R.swift là một công cụ để nhận các tài nguyên được gõ mạnh, tự động hoàn thành như hình ảnh, phân biệt phông chữ và bản địa hóa. Nó thực hiện điều này bằng cách quét dự án của bạn và tạo các lớp nhanh chóng cần thiết để có được tài nguyên. Điểm bán hàng lớn nhất của thư viện này là trong khi sử dụng tài nguyên, nó tạo ra mã của bạn:

  • Gõ đầy đủ - ít truyền và đoán xem phương thức nào sẽ trả về
  • Biên dịch thời gian đã kiểm tra - không còn các chuỗi không chính xác khiến ứng dụng của bạn gặp sự cố khi chạy
  • Tự động hoàn tất - không bao giờ phải đoán tên hình ảnh / nib / bảng phân cảnh đó nữa

Hãy xem xét mã sau bằng API chuỗi chính thức:

let icon = UIImage (có tên là: Tùy chỉnh-icon biểu tượng)

Nếu bạn viết sai tên hình ảnh, bạn sẽ nhận được một con số không ở đây. Nếu bất kỳ thành viên nào trong nhóm của bạn thay đổi tên của tài nguyên hình ảnh, mã này sẽ trở về con số không hoặc sẽ bị sập nếu bạn buộc gỡ bỏ hình ảnh. Khi sử dụng R.swift, điều này trở thành:

hãy để biểu tượng = R.image.customIcon ()

Bây giờ bạn có thể chắc chắn rằng biểu tượng thực sự tồn tại (trình biên dịch sẽ cảnh báo bạn nếu nó không nhờ kiểm tra thời gian biên dịch) và bạn sẽ không đánh máy trong tên biểu tượng vì bạn sẽ sử dụng tự động hoàn tất.

R.swift được cài đặt thông qua Cocoapods và được tích hợp trong mẫu dưới dạng Giai đoạn xây dựng và sẽ tạo các lớp trình bao bọc Swift trên mỗi bản dựng. Điều đó có nghĩa là nếu bạn thêm một tệp / hình ảnh / bản địa hóa / phông chữ / màu / nib, v.v. nó sẽ có sẵn cho bạn bằng cách sử dụng R.swift sau khi bạn biên dịch dự án.

AppDelegate riêng cho các bài kiểm tra

Một thực hành tốt thường bị bỏ qua là có một lớp TestAppDelegate riêng khi chạy thử nghiệm. Tại sao nó là một ý tưởng tốt? Chà, thường thì lớp AppDelegate thực hiện rất nhiều công việc khi khởi động ứng dụng. Nó có thể thiết lập một cửa sổ, xây dựng cấu trúc UI cơ bản của ứng dụng, đăng ký thông báo, thiết lập cơ sở dữ liệu và thậm chí đôi khi thực hiện các cuộc gọi API đến một số dịch vụ phụ trợ. Các xét nghiệm đơn vị không nên có bất kỳ tác dụng phụ. Bạn có thực sự muốn thực hiện các cuộc gọi api ngẫu nhiên và thiết lập tất cả cấu trúc UI của ứng dụng của bạn chỉ để chạy một số bài kiểm tra đơn vị không?

TestAppDelegate cũng là một nơi tuyệt vời để có mã mà bạn chỉ muốn chạy một lần trong khi thực hiện bộ thử nghiệm. Nó có thể chứa mã tạo ra giả, yêu cầu mạng, v.v.

Mẫu chứa tệp main.swift là điểm vào chính của ứng dụng. Tệp này có các phương thức kiểm tra môi trường mà ứng dụng hiện đang chạy là gì và nếu nó là môi trường thử nghiệm, hãy gọi TestAppDelegate.

Trình biên dịch hiệu suất cờ

Swift là một ngôn ngữ tuyệt vời, dễ sử dụng và an toàn hơn nhiều so với Objective-C (IMO). Nhưng khi được giới thiệu lần đầu tiên, nó có một nhược điểm lớn - thời gian biên dịch. Quay trở lại Swift 2 ngày, tôi đã làm việc với một dự án có 40k dòng mã Swift (một dự án cỡ trung bình). Mã này rất nặng với khái quát và kiểu suy luận và phải mất gần 5 phút để biên dịch một bản dựng sạch. Khi bạn thực hiện ngay cả một thay đổi nhỏ, dự án sẽ biên dịch lại và mất khoảng 2 phút để xem thay đổi. Đó là một trong những trải nghiệm tồi tệ nhất dành cho nhà phát triển tôi từng có và tôi gần như ngừng sử dụng Swift vì nó.

Giải pháp duy nhất trước đó, là thử và lập hồ sơ thời gian biên dịch của dự án và cố gắng thay đổi mã của bạn theo cách như vậy, điều đó sẽ làm cho trình biên dịch nhanh hơn. Để giải quyết vấn đề này, Apple giới thiệu một số cờ trình biên dịch không chính thức sẽ cảnh báo bạn khi biên dịch phần thân phương thức hoặc giải quyết loại biểu thức mất quá nhiều thời gian. Tôi đã thêm các cờ đó vào dự án mẫu để bạn sẽ được cảnh báo từ đầu về thời gian biên dịch dài cho ứng dụng của bạn.

Ngày nay, thời gian xây dựng đã được cải thiện đáng kể và bạn rất hiếm khi cần điều chỉnh mã của mình chỉ để cải thiện thời gian xây dựng. Nhưng tốt hơn hết là bạn nên biết trước để cố gắng khắc phục sự cố khi dự án trở nên quá lớn.

Cấu hình Dev / Staging / Sản xuất

Một thực tiễn tốt khác (hoặc tôi có thể nói là cần thiết) là có các cấu hình và biến môi trường riêng biệt cho môi trường phát triển, dàn dựng và sản xuất. Hầu như mọi ứng dụng hiện nay đều phải kết nối với một số loại dịch vụ phụ trợ và thông thường, các dịch vụ đó được triển khai trên nhiều môi trường. Môi trường phát triển được sử dụng cho các triển khai hàng ngày và cho các nhà phát triển để kiểm tra mã của họ. Môi trường dàn dựng được sử dụng để phát hành ổn định cho người kiểm tra và khách hàng để kiểm tra. Chúng ta đều biết môi trường sản xuất để làm gì.

Một cách để hỗ trợ nhiều môi trường trong dự án iOS là thêm cấu hình cấp dự án.

Cấu hình cấp dự án

Khi bạn đã xác định các cấu hình, bạn có thể tạo tệp Cấu hình.plist chứa các biến cho từng môi trường.

Cấu hình.plist

Khi chạy dự án, bạn có thể chỉ định cấu hình nào sẽ được sử dụng. Bạn có thể làm điều này trong sơ đồ xây dựng.

Sau đó, bạn cần thêm một thuộc tính bổ sung trong tệp Info.plist của dự án. Giá trị của thuộc tính này sẽ được giải quyết một cách linh hoạt trong thời gian chạy với tên của cấu hình hiện tại.

Đây là tất cả cấu hình sẵn cho bạn trong mẫu.

Điều duy nhất còn lại là viết một lớp có thể truy xuất các biến đó trong thời gian chạy tùy thuộc vào cấu hình được chọn trong sơ đồ xây dựng. Mẫu có chứa một lớp Trình quản lý cấu hình có thể truy xuất các biến cho môi trường hiện tại. Bạn có thể kiểm tra việc triển khai lớp đó trên Github để xem nó hoạt động như thế nào.

Đọc

Mỗi dự án nên có một Readme cơ bản ít nhất có hướng dẫn cách cài đặt các phụ thuộc và chạy dự án. Nó cũng nên chứa một mô tả về kiến ​​trúc và mô-đun dự án. Thật không may, các nhà phát triển không muốn viết tài liệu (một readme là một phần trong đó) và tôi đã thấy dự án đang được phát triển trong nhiều tháng và họ thậm chí còn có một Readme cơ bản. Để giảm bớt gánh nặng của việc viết readme cơ bản này, mẫu chứa một readme tiêu chuẩn bao gồm cài đặt và cấu trúc dự án. Khi bạn thiết lập một dự án mới bằng cách sử dụng mẫu, bạn sẽ có Readme tự động đi kèm.

Gitignore

Ngày nay, hầu hết các dự án sử dụng GIT làm hệ thống kiểm soát phiên bản của họ. Khi sử dụng GIT, bạn thường wan để bỏ qua một số tệp hoặc thư mục trong dự án như thư mục bản dựng hoặc thư mục dữ liệu dẫn xuất. Để tiết kiệm cho bạn những rắc rối khi tìm kiếm tệp gitignore phù hợp với dự án iOS của bạn, mẫu bao gồm một gitignore tiêu chuẩn được cung cấp bởi những người đóng góp Github.

Các lớp cơ sở để xử lý các liên kết và thông báo sâu

Hầu như mọi ứng dụng hiện nay đều phải xử lý các liên kết và thông báo sâu. Để làm điều này, một nhà phát triển phải viết một số lượng mã soạn sẵn trong lớp AppDelegate. Mẫu có bao phủ và cũng cung cấp các lớp cơ sở giúp làm việc với các liên kết sâu và thông báo dễ dàng hơn.

Tóm lược

Để tổng hợp, mẫu cố gắng bao gồm các thực tiễn tốt nhất và tích hợp các công cụ hữu ích của bên thứ ba. Điều này sẽ giúp bạn và nhóm của chúng tôi dành thời gian cho việc thiết lập dự án mới và cũng cung cấp một nền tảng chung và mạnh mẽ cho phần còn lại của dự án. Có thể nó phục vụ bạn tốt!

PS: Nếu bạn có bất kỳ vấn đề hoặc yêu cầu tính năng nào cho mẫu, hãy để lại cho tôi một vấn đề trên Github. Tôi sẽ cố gắng giải quyết nó trong thời gian rảnh.