Aumentando a legibilidade do código no desenvolvimento do iOS

Imagine um livro no qual não haja divisão em capítulos, e tudo corra sem quebra lógica e semântica, um livro onde não há parágrafos, pontos e vírgulas, um livro em que a primeira linha fala de uma coisa, a segunda sobre outra, a terceira novamente sobre primeira coisa

Apresentado?

Você poderia entender sobre o que é o livro?

Quão rápido você conseguiu encontrar a passagem em que está interessado?

Seu código, assim como o conteúdo do livro, precisa ser estruturado para facilitar a leitura e transmitir o significado.

Neste artigo, mostrarei exemplos de código de organização em que as classes terão a mesma sequência de blocos principais e sua divisão.

Por conveniência, usarei a palavra classe (classe), mas implica qualquer tipo de tipo (classe, estrutura, enum).

Graças à aplicação dessas dicas, seu código ficará legível, o que no futuro fornecerá comodidade e rapidez no trabalho com ele.

Obviamente, as dicas descritas podem ser atualizadas ao seu gosto, observando os princípios básicos.

Primeiro, vamos comparar o mesmo código de duas maneiras.

Um exemplo de uma classe bagunçada:


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

Esse código é semelhante a um despejo de métodos, variáveis ​​e saídas, no qual tudo se funde, é difícil entender a que se refere e em que lugar o que procurar.

Um exemplo de uma classe pura:


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

Linha vazia 38 - recue uma linha do último método para que você possa ver onde termina o último colchete do método e onde a classe termina.

A mesma funcionalidade é mostrada nos dois exemplos, mas a diferença é que a segunda opção tem uma estrutura clara, devido à qual a lógica é mais óbvia, o código é fácil de ler, você pode encontrar rapidamente o que está procurando nele e, além disso, é bom olhar para ele.

Princípios básicos para a formação de uma estrutura de classe pura:


  1. Sempre use // MARK: -
  2. Dê os nomes dos rótulos e defina sua prioridade
  3. Colocando a lógica fora dos métodos do ciclo de vida em métodos separados
  4. Usamos extensão para implementar os protocolos
  5. Selecione elementos logicamente relacionados
  6. Removemos não utilizados
  7. Automatizar rotina

1. Sempre use // MARK: -


Para facilitar a leitura, o livro é dividido em capítulos e será mais confortável trabalharmos se criarmos um índice de classe usando // MARK: - .

Essa tag não apenas se destaca bem de todo o código, mas também cria automaticamente um sumário - destaca as seções do código em negrito na lista de elementos desse arquivo.


Você pode visualizar o índice de um arquivo clicando no botão após a seta direita (>) na parte superior do arquivo, após o nome desse arquivo ou ctr + 6 (menu de itens do documento).

2. Damos nomes aos rótulos e estabelecemos sua sequência


Abaixo estão os principais rótulos para dividir o código em blocos conectados logicamente e sua sequência:

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

Ao usar esse método de agrupamento, é possível navegar facilmente no código de qualquer classe.

3. Retire os métodos lógicos do ciclo de vida para métodos separados


A lógica dentro dos métodos do ciclo de vida do ViewController deve ser colocada em métodos separados, mesmo se você precisar criar um método com uma linha de código. Hoje é um, e amanhã é dez.

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

Devido ao fato de os detalhes da implementação serem terceirizados para métodos de terceiros, a lógica do ciclo de vida fica mais clara.

4. Use a extensão para implementar protocolos


Retire a implementação do protocolo na extensão marcada // 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

Esse rótulo conterá tudo relacionado a este protocolo - tudo o que está apenas aqui e não há necessidade de ir para outro lugar; caso contrário, os métodos e propriedades do protocolo estarão espalhados por toda a classe.

5. Selecione os elementos logicamente relacionados


Para aumentar a visibilidade, é necessário selecionar elementos relacionados logicamente usando uma linha vazia:

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. Nós removemos não utilizados


Não deixe comentários desnecessários (padrão), métodos vazios ou funcionalidade inoperante - isso obstrui o código. Preste atenção à classe AppDelegate, provavelmente você encontrará métodos vazios lá com comentários dentro.

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. Automatize a rotina


Para evitar escrever manualmente em cada classe // MARK: - SomeMark , use Code Snippet .


Escrevemos um rótulo, selecionamos e, em seguida, Editor -> Criar trecho de código, atribuímos um nome a ele e chamamos de atalho.

// MARCA: - Bônus


  1. Marque a classe com a palavra-chave final se essa classe não tiver filhos - o projeto é compilado mais rapidamente e o código é executado mais rapidamente.
  2. Marque propriedades, pontos de venda e métodos com a palavra-chave privada - eles estarão disponíveis apenas dentro da classe e não estarão na lista pública de propriedades e métodos se não forem necessários lá.


Desejo todo o sucesso no desenvolvimento de aplicativos e deixe sua classe mais limpa!

// MARK: - Ajuda na redação de um artigo
Sergey Pchelyakov
Alexey Pleshkov AlekseyPleshkov

// MARK: - Links
Ray wenderlich código estilo

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


All Articles