Verbesserung der Lesbarkeit von Code in der iOS-Entwicklung

Stellen Sie sich ein Buch vor, in dem es keine Unterteilung in Kapitel gibt und alles ohne logische und semantische Aufteilung verläuft, ein Buch, in dem es keine Absätze, keine Punkte und Kommas gibt, ein Buch, in dem die erste Zeile über eine Sache erzählt, die zweite über eine andere, die dritte noch einmal als erstes.

Präsentiert?

Könnten Sie verstehen, worum es in dem Buch geht?

Wie schnell könnten Sie die Stelle finden, an der Sie interessiert sind?

Ihr Code sowie der Inhalt des Buches müssen so strukturiert sein, dass der Code leicht zu lesen ist und die Bedeutung darin vermittelt.

In diesem Artikel werde ich Beispiele für das Organisieren von Code zeigen, in denen Klassen dieselbe Reihenfolge von Hauptblöcken und deren Aufteilung haben.

Der Einfachheit halber werde ich das Wort Klasse (Klasse) verwenden, aber jede Art von Typ (Klasse, Struktur, Aufzählung) implizieren.

Dank der Anwendung dieser Tipps wird Ihr Code lesbar, was in Zukunft Komfort und Schnelligkeit bei der Arbeit bietet.

Natürlich können die beschriebenen Tipps unter Beachtung der Grundprinzipien nach Ihren Wünschen aktualisiert werden.

Vergleichen wir zunächst denselben Code auf zwei Arten.

Ein Beispiel für eine unordentliche Klasse:


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!
}

Dieser Code ähnelt einem Speicherauszug von Methoden, Variablen und Outlets, in dem alles zusammengeführt wird. Es ist schwierig zu verstehen, worauf er sich bezieht und an welcher Stelle gesucht werden muss.

Ein Beispiel für eine reine Klasse:


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)
}
}

Leere Zeile 38 - Einrückung einer Zeile von der letzten Methode, damit Sie sehen können, wo die letzte schließende Klammer der Methode endet und wo die Klasse endet.

In beiden Beispielen wird die gleiche Funktionalität gezeigt, aber der Unterschied besteht darin, dass die zweite Option eine klare Struktur aufweist, aufgrund derer die Logik offensichtlicher ist, der Code leicht zu lesen ist, Sie schnell finden können, wonach Sie suchen, und außerdem ist es einfach schön, ihn anzusehen.

Grundprinzipien für die Bildung einer reinen Klassenstruktur:


  1. Verwenden Sie immer // MARK: -
  2. Geben Sie die Namen der Etiketten an und legen Sie deren Priorität fest
  3. Logik aus Lebenszyklusmethoden in separate Methoden umwandeln
  4. Wir verwenden die Erweiterung , um die Protokolle zu implementieren
  5. Wählen Sie Logisch verwandte Elemente
  6. Wir entfernen unbenutzte
  7. Routine automatisieren

1. Verwenden Sie immer // MARK: -


Um das Lesen zu vereinfachen, ist das Buch in Kapitel unterteilt, und es ist für uns angenehmer zu arbeiten, wenn wir mit // MARK: - ein Klasseninhaltsverzeichnis erstellen.

Diese Bezeichnung hebt sich nicht nur gut vom gesamten Code ab, sondern erstellt auch automatisch ein Inhaltsverzeichnis. Sie hebt Abschnitte im Code in der Liste der Elemente dieser Datei fett hervor.


Sie können das Inhaltsverzeichnis einer Datei anzeigen, indem Sie auf die Schaltfläche nach dem Rechtspfeil (>) ganz oben in der Datei nach dem Namen dieser Datei oder Strg + 6 (Menü Dokumentelemente) klicken.

2. Wir geben Namen von Labels an und legen deren Reihenfolge fest


Nachfolgend finden Sie die wichtigsten Bezeichnungen zum Aufteilen des Codes in logisch verbundene Blöcke und deren Reihenfolge:

// 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

Wenn Sie diese Gruppierungsmethode verwenden, können Sie problemlos im Code einer beliebigen Klasse navigieren.

3. Ziehen Sie die Logik aus den Lebenszyklusmethoden in separate Methoden


Die Logik in den Lebenszyklusmethoden des ViewControllers muss in separate Methoden unterteilt werden, auch wenn Sie eine Methode mit einer Codezeile erstellen müssen. Heute ist eins und morgen ist zehn.

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")
}

Aufgrund der Tatsache, dass Implementierungsdetails an Methoden von Drittanbietern ausgelagert werden, wird die Logik des Lebenszyklus klarer.

4. Verwenden Sie die Erweiterung, um Protokolle zu implementieren


Nehmen Sie die Protokollimplementierung in der mit // MARK gekennzeichneten Erweiterung heraus : - 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

Dieses Etikett enthält alles, was mit diesem Protokoll zu tun hat - alles, was nur hier ist und nirgendwo anders hingehen muss, da sonst die Methoden und Eigenschaften des Protokolls über die Klasse verteilt sind.

5. Wählen Sie die logisch verwandten Elemente aus


Um die Sichtbarkeit zu erhöhen, müssen logisch verwandte Elemente mit einer leeren Zeile ausgewählt werden:

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. Wir entfernen unbenutzte


Hinterlassen Sie keine unnötigen Kommentare (Standard), leeren Methoden oder toten Funktionen - dies verstopft den Code. Achten Sie auf die AppDelegate-Klasse. Höchstwahrscheinlich finden Sie dort leere Methoden mit Kommentaren.

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. Routine automatisieren


Verwenden Sie Code Snippet, um ein manuelles Schreiben in jeder Klasse zu vermeiden. // MARK: - SomeMark .


Wir schreiben ein Etikett, wählen es aus, dann Editor -> Code-Snippet erstellen, geben ihm einen Namen und nennen es Verknüpfung.

// MARK: - Bonus


  1. Markieren Sie die Klasse mit dem Schlüsselwort final, wenn diese Klasse keine untergeordneten Elemente hat. Das Projekt wird schneller kompiliert und der Code wird schneller ausgeführt.
  2. Markieren Sie Eigenschaften, Outlets und Methoden mit dem privaten Schlüsselwort. Sie sind nur innerhalb der Klasse verfügbar und nicht in der öffentlichen Liste der Eigenschaften und Methoden enthalten, wenn sie dort nicht benötigt werden.


Ich wünsche Ihnen viel Erfolg bei der Anwendungsentwicklung und lasse Ihre Klasse sauberer werden!

// MARK: - Hilfe beim Schreiben eines Artikels
Sergey Pchelyakov
Alexey Pleshkov AlekseyPleshkov

// MARK: - Links
Ray wenderlich Code-Stil

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


All Articles