Краткое руководство по грамотному оформлению интерфейсов.
Предисловие
Это руководство я публикую для своих учеников, которые только начинают свой пусть в изучении языка Swift. В этой небольшой заметке я хочу расписать основные аспекты правильного структурирования классов, что бы навигация по ним была интуитивно понятной, как для создателя, так и для стороннего наблюдателя.
Введение
Читаемость кода является одним из самых важным аспектом в программировании и поэтому существуют определенные стандарты, как в написании кода, так и в оформлении интерфейсов. Особенно это касается вью контроллеров, которые сами по себе являются довольно массивными объектами и поэтому навигация по ним должна быть предсказуемой, в не зависимости от того работаете ли вы со своим проектом или же со сторонним.
Структура класса
Класс всегда начинается со свойств, к которым относятся аутлеты, вычисляемые свойства, а также публичные и приватные переменные и константы:
final class ViewController: UIViewController { // MARK: - IB Outlets @IBOutlet private var mainLabel: UILabel! @IBOutlet private var secondaryLabel: UILabel! @IBOutlet private var someLabel: UILabel! @IBOutlet private var mainTextField: UITextField! @IBOutlet private var secondaryTextField: UITextField! // MARK: - Public Properties var dataModel: DataModel! var someString = "" // MARK: - Private Properties private let dataManager = DataManager.shared private let networkManager = NetworkManager.shared private let imageManager = ImageManager.shared }
Обратите внимание в какой последовательности объявлены свойства: сначала объявляются аутлеты, затем публичные переменные и константы, после которых уже идут приватные свойства. Так же обратите внимание на то, что аутлеты для лейблов разделяет пустая строка от аутлетов для текстовых полей. Такие разделители в виде пустых строк визуально отделяют логические блоки кода друг от друга, что повышает его читаемость. Не пренебрегайте ими, но и не злоупотребляйте. Достаточно одной пустой строки, что бы отделить одно от другого.
При помощи комментария // MARK: класс можно поделить на разделы. Эти комментарии играют роль заголовков, по которым можно быстро перемещаться по разделам. У каждого файла в проекте есть содержание, открыть которое можно, кликнув на название класса в верхней строке, в которой прописан путь до класса:
В этом списке отображаются все свойства и методы класса, а заголовки позволяют легче ориентироваться по всему содержимому и перемещаться в нужное место в один клик.
После свойств класса объявляются инициализаторы, если в них есть необходимость:
// MARK: - Initializers init(name: String) { self.name = name }
После инициализаторов объявляются переопределенные методы родительского класса. Это те методы, которые помечены ключевым словом override:
// MARK: - View Life Cycles override func viewDidLoad() { super.viewDidLoad() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) } // MARK: - Navigation override func prepare(for segue: UIStoryboardSegue, sender: Any?) { }
После переопределенных методов объявляются IB Actions, т.е. методы связанные с элементами пользовательского интерфейса:
// MARK: - IB Actions @IBAction private func buttonDidTapped() { } @IBAction private func sliderValueOnChange(_ sender: UISlider) { }
После IB Actions определяются методы экземпляра:
// MARK: - Public Methods func fetchData(from url: URL) { } func doSomething() { }
И в самом конце класса объявляются приватные методы. Это те методы, которые создаются для реализации внутренней логики самого класса:
// MARK: - Private Methods private func setupUI() { } private func setupNavigationBar() { } private func showAler(witnTitle title: String, andMessage message: String) { }
Так же классы могу иметь расширения или extensions. Расширения позволяют группировать методы со связанным функционалом в одном месте, что делает код более организованным и читаемым. Так если класс необходимо подписать под протокол, то для этого лучше определить отдельное расширение с соответствующим заголовком:
// MARK: - UITabvleViewDataSource extension ViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { } func tableView(_ tableView: UITabvleView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { } }
Кроме того расширения полезно использовать для распределения обязанностей между командой. В этом случае для каждого расширения создается отдельный файл, что позволяет работать над одним классом сразу нескольким участникам проекта.
В итоге структура класса должна выглядеть следующим образом:
// MARK: - IB Outlets // MARK: - Public Properties // MARK: - Private Properties // MARK: - Initializers // MARK: - Overrides Methods // MARK: - IB Actions // MARK: - Public Methods // MARK: - Private Methods
Общие советы
-
Не храните в классе методы, которые ни как не используются. Т.е. если у вас есть метод
viewDidLoad(), но при этом он пустой, то смело его удаляйте. Ни чего лишнего в коде быть не должно. -
Удаляйте все шаблонные комментарии, которые достаются вам “из коробки” при добавлении новых классов.
-
Используйте в качестве разделителей логических блоков кода пустые строки, но не более одной.
-
Названия классов должны быть емкими и отражать их суть. В проекте не должно быть классов с именем
ViewController. Не сокращайте имена классов. В проекте не должно быть классов с именемMainVC.
ссылка на оригинал статьи https://habr.com/ru/articles/744470/
Добавить комментарий