Советы, которые помогут вам писать более чистый код
В этой статье задокументировано то, что я прочитал, комментарии по связям с общественностью, которые я получил, и некоторые вещи, которые я узнал от своих коллег. Если вы можете добавить больше к этому, пожалуйста, не стесняйтесь комментировать.
Вал или Вар
Изменчивость против неизменности. Если бы у вас был выбор, что бы вы выбрали? Я всегда предпочту неизменность (val
вместо var
). Делая переменную изменяемой, вы открываете дверь неопределенности. Никто не может предсказать значение этой переменной в какой-то момент в этом классе, и эта переменная может оказать отрицательное или положительное влияние на весь класс из-за ее постоянно развивающегося характера. Попробуйте использовать var
только в том случае, если вы уверены, что val
не сработает в вашем сценарии. Не позволяйте роскоши var
. Ограничьте эту переменную некоторыми границами, используя val
.
Модификаторы видимости
В Kotlin есть четыре типа модификаторов видимости:
private
protected
internal
public
Большинство этих модификаторов будут ограничены частными или общедоступными, если ваш код плохо спроектирован. Они вступят в игру, когда ваши классы начнут делиться вещами, не слишком завися друг от друга. Возможно, если вы пишете чистый код.
Давайте посмотрим на следующий код:
abstract class Car { protected var name: String? = null protected var year: Int = 0 private val welcomeMessage = "Hi, Welcome to your new car" abstract fun modelName() abstract fun manufacturedYear() fun printWelcomeMessage() { println(welcomeMessage) } } class Chevrolet : Car() { override fun modelName() { name = "Beat" printWelcomeMessage() } override fun manufacturedYear() { year = 2012 } } class Hyundai : Car() { override fun modelName() { name = "Jazz" printWelcomeMessage() } override fun manufacturedYear() { year = 2015 } }
У нас есть базовый класс под названием Car
. Chevrolet и Hyundai расширяют его. Они могут получить доступ к имени и году, которые являются частью Car
, только потому, что это protected
. Таким образом, protected
имеет ту же видимость, что и private
. Но это также видно в подклассах.
Что, если вы сделаете имя или год внутренней переменной? Затем вы можете получить к нему доступ в любом месте из того же модуля. Нам не нужно расширять сам класс. А как насчет переменной welcomeMessage
в классе Car
? Он приватный и будет доступен только в классе Car
. Понимание различий между модификаторами видимости помогает при написании кода на основе принципов SOLID.
Уменьшить объекты Android в параметрах
Немного невнимательности, и вот у вас есть непроверяемые методы. Или вам придется потрудиться вдвойне, чтобы сделать его пригодным для тестирования.
fun importantMethod(size: Size) { // some logic using Size }
Мы передали объект Android Size
в качестве параметра для этого метода. Проблема возникает, когда вы пытаетесь создать макет для того же самого. Сложно создавать фиктивные объекты для вещей, связанных с Android. Вместо этого вы могли бы передать width
и height
int в качестве параметра. Найдите альтернативу в объектах Java/Kotlin. Всегда старайтесь ограничить использование объектов Android в параметрах метода.
Не злоупотребляйте функциями расширения
Функции расширения являются инновационными. Теперь мы можем расширять класс, фактически не наследуя его. Кроме того, мы можем добавить к нему новые свойства и сделать так, чтобы он выглядел так, как будто он был частью исходной реализации.
fun Activity.showToast(message: String) { Toast.makeText(this, message, Toast.LENGTH_SHORT) .show() }
Это хорошая функция расширения. Почему? Потому что он общий. Вы расширяете контекст активности и создаете что-то удобное. Многие действия могут использовать эту функцию расширения.
fun Activity.solvingAnIssueForActivityA() { // some logic }
Как насчет этого? Мы создали функцию расширения, не думая о хорошем дизайне. Как это повлияет на код.? Эта функция будет отображаться как автозаполнение, когда кто-то использует точку с действием. И разработчик будет удивляться, как моя активность знает о чем-то внутри ActivityA. Создавайте функцию расширения только в том случае, если вы считаете, что этот код можно воспроизвести, кто-то другой может его использовать, не задействована бизнес-логика и т. д. Используйте функции расширения с умом. Старайтесь не злоупотреблять ими.
Объекты Kotlin не являются потокобезопасными
object someCalculations { var value1 = 0 var value2 = 0 fun doingSomethingWithValue1() { // some logic } fun doingSomethingWithValue2() { // some logic } }
Как вы, возможно, уже знаете, мы используем объекты Kotlin в основном для создания синглетонов. Основное преимущество использования объекта в Kotlin заключается в том, что нам не нужно создавать его новый экземпляр. Проблема в том, что есть вероятность, что мы используем objects
для обмена данными между другими объектами/классами.
Давайте рассмотрим приведенную выше реализацию. Мы разработали его таким образом, чтобы value1
и value2
могли изменяться где угодно, и методы, использующие эти свойства, также могут быть доступны из любого места. Если вам не повезет, они будут доступны одновременно, и вы можете не получить ожидаемого обновленного результата. Итак, если возникает такой сценарий, лучше реорганизуйте свой код, чтобы иметь какой-то промежуточный класс, который может помочь в обмене данными. Или, если вы планируете двигаться дальше с объектом, убедитесь, что вы используете какой-либо механизм синхронизации, чтобы обеспечить обновление ваших полей.
Я узнал, что когда вы пишете код, основанный на принципах дизайна, ваше полотно расширяется. Не ограничивайте себя мышлением только с точки зрения Android. Это поможет всем причастным. Напишу больше, когда найду что-то новое. Хорошего дня. 😇
Не стесняйтесь взглянуть на мои последние статьи:
JNI на Android: как работают обратные вызовы
Планирование задач с помощью WorkManager
Эта статья была первоначально опубликована на clintpauldev.com