Программирование
3 совета для улучшения читабельности кода
В этой статье вы узнаете 3 простых совета, которые помогут сделать вашу кодовую базу более качественной и читабельной.
В этой статье вы узнаете 3 простых совета, которые помогут сделать вашу кодовую базу более качественной и читабельной.
Используйте ранние возвраты
У людей есть проблемы с пониманием длинного и глубоко вложенного кода. Это не в нашей природе. Мы гораздо лучше понимаем более короткий контекст и легче читаем его.
Один из способов добиться этого — использовать ранние возвраты. Вместо вложенных операторов if-else
пишите в них return
.
Трудно читать:
fun isPasswordValid(password: String): Result<Unit> = if (password.length > 8) { if (password.any { it.isUpperCase() }) { if (password.any { it.isLowerCase() }) { if (password.any { it.isDigit() }) { Result.success(Unit) } else { Result.failure(IllegalArgumentException("Password must have a number")) } } else { Result.failure(IllegalArgumentException("Password must have an lower case letter")) } } else { Result.failure(IllegalArgumentException("Password must have an upper case letter")) } } else { Result.failure(IllegalArgumentException("Password is too short")) }
Легко читать:
fun isPasswordValid(password: String): Result<Unit> { if (password.length < 8) { return Result.failure(IllegalArgumentException("Password is too short")) } if (password.none { it.isUpperCase() }) { return Result.failure(IllegalArgumentException("Password must have an upper case letter")) } if (password.none { it.isLowerCase() }) { return Result.failure(IllegalArgumentException("Password must have an lower case letter")) } if (password.none { it.isDigit() }) { return Result.failure(IllegalArgumentException("Password must have a number")) } return Result.success(Unit) }
Обе функции логически делают одно и то же, но второй пример гораздо проще для чтения и понимания!
Избегайте отрицаний в условных выражениях
При любом использовании if-else
следует избегать отрицаний в условиях. Единственным исключением является правило выше, когда это может уменьшить вложенность кода.
Когда вы используете отрицание в операторе if-else
, на самом деле вы создаете двойное отрицание для себя, что гораздо сложнее для понимания.
Трудно читать:
fun updateName(name: String?) { if (!name.isNullOrEmpty()) { _name.update { name } } else { _name.update { "" } } } // Double negation - even worse private fun notifyUnknownUsers(users: List<User>) { users.forEach { user -> if (!user.name.isNotEmpty()) { sendNoNameNotification(user) } } }
Легко читать:
fun updateName(name: String?) { if (name.isNullOrEmpty()) { _name.update { "" } } else { _name.update { name } } } private fun notifyUnknownUsers(users: List<User>) { users.forEach { user -> if (user.name.isEmpty()) { sendNoNameNotification(user) } } }
Создавайте значения и переменные как можно позже
Это одна из самых распространенных и самых коварных ошибок, которые загрязняют и увеличивают сложность вашей кодовой базы.
Когда мы ищем проблему в коде, мы стараемся как можно быстрее добраться до места ошибки. Каждое вычисление и значение, которое вам нужно прочитать, и которое бесполезно в данный момент, работает как тормоз. Также нужно больше запоминать, а не делегировать эту работу коду.
Трудно читать:
fun processPayment(payment: Payment) { val paymentRequest = if (payment.amount == null) { PaymentRequest.Error } else { PaymentRequest.Data(payment.amount) } val formattedAmount = AmountFormatter.formatAmount(payment.amount) val standard = AmountToStandardMapper.map(payment.amount) sendRequest(paymentRequest) displayAmountScreen(formattedAmount) displayAmountNotification(formattedAmount) displayStandardView(standard) displayStandardMessage(standard) }
Легко читать:
fun processPayment(payment: Payment) { val paymentRequest = if (payment.amount == null) { PaymentRequest.Error } else { PaymentRequest.Data(payment.amount) } sendRequest(paymentRequest) val formattedAmount = AmountFormatter.formatAmount(payment.amount) displayAmountScreen(formattedAmount) displayAmountNotification(formattedAmount) val standard = AmountToStandardMapper.map(payment.amount) displayStandardView(standard) displayStandardMessage(standard) }
Спасибо за чтение!