Как я писал в своей предыдущей статье, я искренне верю, что обзоры одных вещей - очень ценная практика ». Я начал изучать работы код-ревью у очень талантливого и строгого разработчика. Поначалу это было тяжело, но это действительно помогло мне стать лучше, чем я считал возможным.

С тех пор я вкладываю много усилий и времени в правильные обзоры. Мои коллеги знают, что я один из самых увлеченных людей, когда дело доходит до обзоров, и что я выявляю все проблемы, которые можно было бы улучшить, независимо от того, насколько они незначительны.

Во время моего опыта одни и те же вещи, кажется, всплывают снова и снова, поэтому я составил список потенциальных улучшений или проблем, о которых нужно постоянно помнить и держать в голове.

В качестве заявления об отказе от ответственности я разработчик iOS и большинство вещей, которые я могу придумать, так или иначе связаны со спецификой платформы.

Но я также думаю, что есть некоторые аспекты, которые можно принять во внимание независимо от языка разработки (Мне бы очень хотелось услышать ваше мнение по этому поводу, особенно если вы не работаете разработчиком iOS)

Примеры кода будут на Swift или Objective-C, но я надеюсь, что они достаточно ясны, чтобы их можно было рассматривать как языковые агностики. Итак, давайте рассмотрим код :)

Красные флажки, не зависящие от языка

1. Не повторяйся - СУХОЙ

Возьмем в качестве примера следующий код

// Let's assume the array is not empty
if array.count == 1 {
   submitFormWithValues("Only one value selected", array)
} else {
   submitFormWithValues("\(array.count) values selected", array)
}

Сначала это должно показаться нормальным, но если вы внимательно посмотрите, этот метод вызывается 2 раза, хотя разница между двумя вызовами - это всего лишь один параметр.

Если, например, метод будет переименован или будет добавлен третий параметр, вам придется изменить код в двух местах, потому что в вашем коде есть дублирование.

Этого можно было избежать, используя следующее:

let string = array.count == 1 ? "Only one value selected" : "\(array.count) values selected"
// Now we can call the method only once
submitFormWithValues(string, array)

В приведенном выше примере в случае изменения метода нам просто нужно адаптировать код только в одном месте - больше никаких дублирований.

Для этого было бы много примеров, но в основном, когда вы видите одни и те же вещи более одного раза в методе или файле, просто спросите себя, как вы могли бы удалить дублированный код, вытащив переменную часть, уменьшив ее до возможно.

2. Возврат логических значений

func isEmpty(array: [String]) -> Bool {
   if array.count == 0 {
       return true
   } else {
       return false
   }
}

Когда вы возвращаете логические значения, внимательно изучите свой код, потому что в большинстве случаев его можно написать более простым способом.

func isEmpty(array: [String]) -> Bool {
   return array.count == 0
}

То же самое применяется при вычислении логических свойств для объектов. Например:

func hideHeaderIfEmptyTableView() {
   if datasource.count == 0 {
       header.hidden = true
   } else {
       header.hidden = false
   }
}

Это точно такой же случай, у вас есть случай if, когда внутри вы устанавливаете (или возвращаете) логические значения. Вы можете просто использовать эти значения напрямую.

func hideHeaderIfEmptyTableView() {
   header.hidden = (datasource.count == 0)
}

3. Уменьшите уровень отступов и используйте ранние выходы.

Чем больше уровней отступов в вашем коде, тем сложнее его читать и понимать.

Наш мозг способен одновременно удерживать только ограниченное количество условий, поэтому чем больше у вас петель, тем больше усилий требуется вашему мозгу, чтобы разобраться в них.

Этот вид идет рука об руку с правилом раннего выхода. Вместо того, чтобы весь ваш код был заключен в цикл if (весь код с отступом), вы можете просто добавить условие, для которого цикл не выполняется первым, и просто return, если это так.

Итак, это довольно просто. Вместо того, чтобы иметь:

func myMethod(elements: [String]) {
   if elements.count > 0 {
      for element in elements {
        // do some processing
      }
   }
}

Вы можете использовать:

func myMethod(elements: [String]) {
   if elements.isEmpty {
      return
   }
   for element in elements {
      // do some processing
   }
}

Я понимаю, что это тоже вопрос вкуса и стиля, но я считаю, что следовать этому намного проще, а поток управления немного более линейен.

4. «Застенчивый» код.

Как упоминалось в разделе Прагматичный программист, ваш код всегда должен быть «застенчивым».

Пишите все с наименьшей возможной областью действия и увеличивайте ее только в том случае, если вам действительно нужно - например, начните со всего private, как ваших свойств, так и ваших методов.

Другой способ применения этого правила - на уровне раскрытия свойств, которыми владеют ваши объекты. Допустим, у вас есть настраиваемый компонент пользовательского интерфейса, который содержит изображение внутри, которое также должно быть установлено извне вашего компонента.

Вместо того, чтобы отображать изображение как свойство чтение / запись, вы можете предоставить метод для обновления соответствующего свойства внутри вашего класса. Изображение будет отображаться только как только для чтения, и вы также можете иметь больший контроль над значениями, которые устанавливаются в вашем свойстве.

5. Удалите пустые методы и неиспользуемый сгенерированный код.

Лучший код - тот, которого не существует

Возьмите за привычку удалять любой (даже созданный в IDE) код, который вы не используете. Не оставляйте вокруг вашего кода пустые методы, неиспользуемые переменные, импорт, устаревшие комментарии.

Если он вам не нужен, просто удалите его.

Удаление кода должно быть одним из ваших любимых занятий разработчика. Конечно, это для меня.

Совершенство достигается не тогда, когда больше нечего добавить, а когда нечего убирать - Антуан де Сент-Экзюпери

То же самое и с любым закомментированным кодом. Не оставляйте это просто так. В любом случае у вас есть вся история в вашем инструменте управления версиями, поэтому просто удалите ее. Если он вам когда-нибудь понадобится снова, вы можете просто вернуть свой файл - хотя по моему опыту, вы редко возвращаетесь к коду, в котором не уверены (что может быть причиной, по которой вы решили прокомментировать его в первую очередь).

Другие вещи, которые следует учитывать

Вы всегда должны помнить об этом при просмотре кода:

  • Жестко запрограммированные значения. Сначала спросите себя, нельзя ли каким-либо образом удалить статическое значение? Строки, числа с плавающей запятой, целые числа, что бы это ни было. Если ответ положительный, то продолжайте и улучшайте его :) Если вы не можете избавиться от него каким-либо образом, сохраните его в статической переменной (или в любом другом формате на языке, который вы используете. ).

Имя будет содержать значение в некотором контексте, например defaultImageWidth или controllerIdentifier, что упрощает понимание того, что это должно было означать всякий раз, когда вы вернетесь к коду через некоторое время. Еще одним преимуществом было бы то, что, по моему опыту, иногда эти ценности проявляются снова и снова, в большем количестве мест. Если они не хранятся в переменной, вам нужно будет изменить код во всех местах, когда ваше значение изменится с 3 на 4, что снова приведет к дублированию кода.

  • Стандарты и рекомендации команды - всегда следите за тем, чтобы стандарты соблюдаются всеми, и не упускайте ничего из виду при проверке кода. Это должно включать в себя согласованные способы именования переменных, форматирование кода, передовые методы для вашего языка, согласованные в вашей команде, с заботой о том, чтобы имена, методы и решения означали одно и то же для всех.
  • Регистрируйте свои ошибки - возможно, это очевидно, но я думаю, что об этом стоит упомянуть, тем более, что вы не видите значения этого, если ваш код уже не находится в производстве (в это время довольно сложно внести изменения, хотя бы в мобильные приложения). Убедитесь, что каждый раз, когда ваш код достигает недопустимого состояния или некоторые свойства настроены неправильно, даже если вы думаете, что некоторые вещи невозможны, просто регистрируйте ошибку и помещайте в сообщение как можно больше информации. Вы не поверите, сколько раз это пригодится.

Objetive-c / swift конкретные наблюдения

1. Не забудьте отменить регистрацию наблюдателей.

Каждый раз, когда вы просматриваете или пишете код, который регистрируется для получения какого-либо уведомления или подписывается в качестве наблюдателя на обновления, убедитесь, что вы проверяете, что они также отменяют регистрацию / отменяют подписку. Вы будете удивлены, сколько раз вы забываете об этом аспекте, и все мы знаем, насколько сложно отлаживать «Сообщение, отправленное в освобожденный экземпляр» :)

Я не могу этого достаточно подчеркнуть, чек чек чек.

2. Наиболее конкретные аргументы метода

Возьмем, к примеру, обратные вызовы кнопок. Всегда пишите метод с наиболее конкретным типом, который вы знаете для своего параметра, а также всегда добавляйте вызывающий объект.

Это может помочь в двух случаях: когда становится более ясно, что происходит, и что только кнопка может вызывать этот метод, и в случае, если вам нужно проверить свойства этого объекта, вам не нужно его приводить или что-то еще. Возможно, он вам сейчас и не понадобится, но всегда оставляйте место для дальнейшего развития.

@IBAction func didClickContinue(sender: id) { 
    // in an year maybe you wont remember what sort of object is calling this method
}

Вы можете использовать что-то более значимое, что потребует меньше времени, чтобы выяснить, что на самом деле делает код.

// How about using this? You'll ever know what this method is used for and what the calling object can be
@IBAction func didClickContinueButton(sender: UIButton) {
}

О селекторах:

// Always include the calling object in the callback
let tapGesture = UITapGestureRecognizer(target: self, action: “didTap:”)

3. Наиболее общие ссылки на объекты

Когда вы используете объект, сохраните его в переменной, которая имеет наиболее общий тип, позволяя вам использовать нужную вам функциональность.

Например:

private var viewController: AlertViewController?
init() {
   viewController = AlertViewController()
   navigationController?.pushViewController(viewController,     animated: true)
}

Вы могли заметить, что методу push нужен только UIViewController, а не AlertViewController. Следовательно, мы можем сохранить его в свойстве самого общего типа UIViewController.

// We dont need any particular properties of the AlertViewController so we can save it as a UIViewController
private var viewController: UIViewController?
init() {
   viewController = AlertViewController()
   navigationController?.pushViewController(viewController, animated: true)
}

Идея здесь не в том, чтобы предоставлять информацию, когда она специально не запрашивается. Чем меньше объекты знают друг о друге, тем меньше у вас зависимостей в вашем коде.

4. Документация - знаки Pragma.

Когда класс становится слишком большим (иногда это случается, независимо от того, насколько мы велики разработчики: D), полезно добавить какое-то разграничение для общедоступных / частных методов, реализаций протокола, общедоступных / частных переменных, всего, что будет Помогите всем, кому придется разбираться в коде и работать с ним, легче ориентироваться в классе.

Другие вещи, за которыми нужно следить

  • Сохранять циклы - всегда проверяйте делегаты на слабые ссылки. Также рекомендуется фиксировать себя как слабые внутренние блоки, чтобы предотвратить циклы сохранения.
  • Быстрое принудительное развертывание. Когда вы видите принудительное развертывание, всегда спрашивайте себя, нет ли лучшего способа сделать это? Может быть, защита, необязательная цепочка. Убедитесь, что вы все продумали, прежде чем принимать это как часть кода.
  • Ненужный код. Как упоминалось ранее, не оставляйте рядом ненужный код. Например, неявный импорт, ссылка self (когда она не является обязательной, например, в замыканиях), фигурные скобки для аргументов в случаях if и switch, объявление типа для переменных или свойств, тип которых может быть определен автоматически, блоки параметров, которые вы не используете

Было бы, если учесть все вышеперечисленное:

Еще кое-что..

Очень важным аспектом является то, что здесь нет ничего лишнего, чтобы комментировать. Возможно, вы знакомы с теорией разбитого окна. Я полностью уверен, что это применимо к коду и в целом к ​​разработке программного обеспечения. Это прекрасно объясняется в Программист-прагматик.

Итак, если вы видите что-то, что не кажется вам полностью подходящим, просто поставьте под сомнение это. Вы видите лишний пробел или опечатку, укажите на это. В конечном итоге это будет иметь большое значение.

Это требует времени и реальных усилий, но всегда окупается способами, о которых вы даже не догадывались.

Подведение итогов

Это лишь некоторые базовые вещи, которые я учитываю при проверке кода, которые я узнал в последние годы, работая с очень талантливыми и увлеченными людьми. Конечно, всегда необходимо обсудить логические детали и детали реализации, которые нельзя абстрагировать в таком списке.

Я стараюсь держать свой список всегда открытым и постоянно добавлять что-то. Всегда ищите новые возможности.

По мере того, как команда привыкает к обзорам, качество кода будет улучшаться, и элементы из списка больше не будут появляться так часто. Вот тогда вам нужно посмотреть глубже, может быть, что-то стало ясно после того, как беспорядок был удален.

Во время проверки вы всегда должны спрашивать себя: есть ли другой способ улучшить этот код?

Мне бы хотелось услышать, что еще вы считаете нужным для отзывов в вашей команде. Что обязательно в вашем списке?

Если вы хотите получить персональный инструктаж по совершенствованию своих навыков разработки мобильных приложений и получить от меня информацию по вашим наиболее насущным проблемам с iOS или Android, в настоящее время я открыт для обучения других разработчиков. Если вам интересно, просто свяжитесь с нами. Подробнее здесь: https://mobiledev.consulting/1x1-expert-coaching/

Моя цель - постоянно учиться, и я считаю, что нет лучшего способа получить более глубокое понимание, чем обучать и делиться с другими тем, что вы знаете. Вот почему я хочу поделиться своим опытом с любым мобильным разработчиком, который хочет узнать больше и стать сильнее.

Если вас интересуют обзоры кода, вы можете также проверить это:



Я надеюсь, что вам понравилось это читать, и что он смог дать небольшое руководство в процессе проверки.

Пожалуйста, дайте мне знать, как вы его нашли, если вы думаете, что можете применить его и к языку программирования, с которым работаете :)

Вам нужна помощь в совершенствовании навыков разработки мобильных приложений? Я хочу поделиться своим опытом и знаниями с людьми, которые хотят узнать больше и стать лучше, а также узнать как можно больше от вас.

Итак, если вы заинтересованы в разработке плана сотрудничества для своего профессионального развития, просто напишите мне по адресу c [email protected]