Советы, которые помогут вам писать более чистый код

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

Вал или Вар

Изменчивость против неизменности. Если бы у вас был выбор, что бы вы выбрали? Я всегда предпочту неизменность (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