Meningkatkan keterbacaan kode dalam pengembangan iOS

Bayangkan sebuah buku di mana tidak ada pembagian menjadi beberapa bab, dan semuanya berjalan tanpa gangguan logis dan semantik, sebuah buku di mana tidak ada paragraf, tidak ada titik dan koma, sebuah buku di mana baris pertama menceritakan tentang satu hal, yang kedua tentang yang lain, yang ketiga lagi tentang hal pertama.

Disajikan?

Bisakah Anda mengerti tentang apa buku itu?

Seberapa cepat Anda dapat menemukan bagian yang Anda minati?

Kode Anda, serta isi buku itu, perlu disusun agar kode itu mudah dibaca dan menyampaikan makna di dalamnya.

Pada artikel ini saya akan menunjukkan contoh kode pengorganisasian di mana kelas akan memiliki urutan blok utama yang sama dan rinciannya.

Untuk kenyamanan, saya akan menggunakan kelas kata (kelas), tetapi menyiratkan jenis apa pun (kelas, struct, enum).

Berkat penerapan tip-tip ini, kode Anda akan dapat dibaca, yang di masa depan akan memberikan kemudahan dan kecepatan bekerja dengannya.

Tentu saja, tips yang dijelaskan dapat ditingkatkan sesuai dengan keinginan Anda, dengan memperhatikan prinsip-prinsip dasar.

Pertama, mari kita bandingkan kode yang sama dalam dua cara.

Contoh kelas yang berantakan:


final class MessyViewController: UIViewController {
private let userService = UserService()
var userID: String?
private var userList: [User]?
@IBOutlet private weak var searchBar: UISearchBar!
weak var delegate: SomeDelegate?
@IBAction private func cancelButtonPressed(_ sender: UIBarButtonItem) {
dismiss(animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
navigationController?.navigationBar.backgroundColor = .red
navigationItem.title = "Some"
}
@IBOutlet private weak var tableView: UITableView!
}

Kode ini mirip dengan kumpulan metode, variabel, dan outlet, di mana semuanya bergabung bersama, sulit untuk memahami apa yang dimaksud dan di tempat apa yang harus dicari.

Contoh kelas murni:


final class CleanViewController: UIViewController {
// MARK: - IBOutlets
@IBOutlet private weak var searchBar: UISearchBar!
@IBOutlet private weak var tableView: UITableView!
// MARK: - Public Properties
var userID: String?
weak var delegate: SomeDelegate?
// MARK: - Private Properties
private let userService = UserService()
private var userList: [User]?
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
setupNavigationBar()
}
// MARK: - Private Methods
private func setupNavigationBar() {
navigationController?.navigationBar.backgroundColor = .red
navigationItem.title = "Some"
}
// MARK: - IBActions
@IBAction private func cancelButtonPressed(_ sender: UIBarButtonItem) {
dismiss(animated: true, completion: nil)
}
}

Baris kosong 38 - indentasi satu baris dari metode terakhir sehingga Anda dapat melihat di mana braket penutupan terakhir dari metode berakhir dan di mana kelas berakhir.

Fungsionalitas yang sama ditunjukkan pada kedua contoh, tetapi perbedaannya adalah bahwa opsi kedua memiliki struktur yang jelas, karena logikanya lebih jelas, kodenya mudah dibaca, Anda dapat dengan cepat menemukan apa yang Anda cari di dalamnya, dan di samping itu, hanya bagus untuk dilihat.

Prinsip dasar untuk pembentukan struktur kelas murni:


  1. Selalu gunakan // MARK: -
  2. Berikan nama label dan tetapkan prioritasnya
  3. Menempatkan logika dari metode siklus hidup ke dalam metode terpisah
  4. Kami menggunakan ekstensi untuk mengimplementasikan protokol
  5. Pilih Elemen Terkait Secara Logika
  6. Kami menghapus yang tidak digunakan
  7. Otomatiskan rutin

1. Selalu gunakan // MARK: -


Untuk memudahkan membaca, buku ini dibagi menjadi beberapa bab, dan akan lebih nyaman bagi kita untuk bekerja jika kita membuat daftar isi kelas menggunakan // MARK: - .

Label ini tidak hanya menonjol dari seluruh kode, tetapi juga secara otomatis membuat daftar isi - label ini menyoroti bagian-bagian dalam kode yang dicetak tebal dalam daftar elemen file ini.


Anda dapat melihat daftar isi file dengan mengklik tombol setelah panah kanan (>) di bagian paling atas file setelah nama file ini atau ctr + 6 (menu item dokumen).

2. Kami memberi nama label dan kami menetapkan urutannya


Di bawah ini adalah label utama untuk memecah kode menjadi blok yang terhubung secara logis dan urutannya:

// MARK: - IBOutlets
// MARK: - Public Properties
// MARK: - Private Properties
// MARK: - Initializers
// MARK: - Lifecycle
// MARK: - Public Methods
// MARK: - Private Methods
// MARK: - IBActions
view raw MarkList.swift hosted with ❤ by GitHub

Saat menggunakan metode pengelompokan ini, seseorang dapat dengan mudah menavigasi dalam kode kelas apa pun.

3. Tarik logika dari metode siklus hidup ke metode terpisah


Logika di dalam metode siklus hidup ViewController harus dimasukkan ke dalam metode terpisah, bahkan jika Anda harus membuat metode dengan satu baris kode. Hari ini adalah satu, dan besok adalah sepuluh.

NOT Preferred
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.backgroundColor = .red
someButton.layer.cornerRadius = 10
someButton.layer.masksToBounds = true
navigationItem.title = "Some"
print("Some")
}
Preferred
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
setupNavigationBar()
setupSomeButton()
printSome()
}
// MARK: - Private Methods
private func setupNavigationBar() {
navigationController?.navigationBar.backgroundColor = .red
navigationItem.title = "Some"
}
private func setupSomeButton() {
someButton.layer.cornerRadius = 10
someButton.layer.masksToBounds = true
}
private func printSome() {
print("Some")
}

Karena kenyataan bahwa detail implementasi di-outsourcing-kan ke metode pihak ketiga, logika siklus hidup menjadi lebih jelas.

4. Gunakan ekstensi untuk mengimplementasikan protokol


Keluarkan implementasi protokol dalam ekstensi bertanda // MARK: - SomeProtocol :

NOT Preferred
final class CleanViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
// all methods
}
Preferred
final class CleanViewController: UIViewController {
// class stuff here
}
// MARK: - Table View Data Source
extension CleanViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return userList?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
return cell
}
}
view raw extension.swift hosted with ❤ by GitHub

Label ini akan berisi semua yang terkait dengan protokol ini - semua yang ada di sini dan tidak perlu pergi ke tempat lain, jika tidak, metode dan properti protokol akan tersebar di seluruh kelas.

5. Pilih elemen yang berhubungan secara logis


Untuk meningkatkan visibilitas, perlu untuk memilih elemen yang berhubungan secara logis menggunakan garis kosong:

NOT Preferred
private func showActivityIndicator(on viewController: UIViewController) {
activityIndicator.center = viewController.view.center
loadingView.backgroundColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
loadingView.alpha = 0.5
activityIndicator.hidesWhenStopped = true
activityIndicator.style = .whiteLarge
loadingView.center = viewController.view.center
loadingView.clipsToBounds = true
loadingView.layer.cornerRadius = 15
viewController.view.addSubview(loadingView)
viewController.view.addSubview(activityIndicator)
activityIndicator.startAnimating()
}
Preferred
private func showActivityIndicator(on viewController: UIViewController) {
activityIndicator.center = viewController.view.center
activityIndicator.hidesWhenStopped = true
activityIndicator.style = .whiteLarge
loadingView.center = viewController.view.center
loadingView.backgroundColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
loadingView.alpha = 0.5
loadingView.clipsToBounds = true
loadingView.layer.cornerRadius = 15
viewController.view.addSubview(loadingView)
viewController.view.addSubview(activityIndicator)
activityIndicator.startAnimating()
}


6. Kami menghapus yang tidak digunakan


Jangan meninggalkan komentar yang tidak perlu (default), metode kosong atau fungsionalitas mati - ini menyumbat kode. Perhatikan kelas AppDelegate, kemungkinan besar Anda akan menemukan metode kosong di sana dengan komentar di dalamnya.

NOT Preferred
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
//
// func someFunc() {
// print("Some")
// }
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain
//types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits
//the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
Preferred
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
return true
}
}
view raw AppDelegate.swift hosted with ❤ by GitHub


7. Otomatisasi rutin


Untuk menghindari penulisan secara manual di setiap kelas // MARK: - SomeMark , gunakan Cuplikan Kode .


Kami menulis label, pilih labelnya, lalu Editor -> Buat Cuplikan Kode, beri nama, lalu panggil pintasan.

// MARK: - Bonus


  1. Tandai kelas dengan kata kunci terakhir jika kelas ini tidak memiliki anak - proyek mengkompilasi lebih cepat dan kode berjalan lebih cepat.
  2. Tandai properti, outlet, dan metode dengan kata kunci pribadi - mereka hanya akan tersedia di dalam kelas dan tidak akan ada di daftar properti dan metode publik jika tidak diperlukan di sana.


Saya berharap Anda setiap keberhasilan dalam pengembangan aplikasi dan biarkan kelas Anda menjadi lebih bersih!

// MARK: - Bantuan dalam menulis artikel
Sergey Pchelyakov
Alexey Pleshkov AlekseyPleshkov

// MARK: - Tautan
Ray gaya kode wenderlich

Source: https://habr.com/ru/post/id453428/


All Articles