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

Грубо говоря:

#! /usr/bin/env scala

def joinChat ( userId : Long, chatId : Long ) {
println ( s «userId = $userId, chatId = $chatId» )
}

val userId = 123L
val chatId = 456L

joinChat ( userId, chatId )
joinChat ( chatId, userId )

Код успешно выполняется и выводит:

userId = 123, chatId = 456
userId = 456, chatId = 123

Понятно, что все id-шники представляют собой Long, поэтому компилятор не может обнаружить ошибку. А теперь немного перепишем код:

#! /usr/bin/env scala

class User ( )
class Chat ( )
case class Id [ A ] ( value : Long )

def joinChat ( userId : Id [ User ] , chatId : Id [ Chat ] ) {
println ( s «userId = ${userId.value}, chatId = ${chatId.value}» )
}

val userId = Id [ User ] ( 123L )
val chatId = Id [ Chat ] ( 456L )

joinChat ( userId, chatId )
// joinChat(chatId, userId)

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

./script2.scala:15: error: type mismatch;
found   : this.Id[this.Chat]
required: this.Id[this.User]
joinChat(chatId, userId)
^
./script2.scala:15: error: type mismatch;
found   : this.Id[this.User]
required: this.Id[this.Chat]
joinChat(chatId, userId)
^
two errors found

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

Перекрестная ссылка: Так ли плоха статическая типизация?

Дополнение: См также value classes .

admin

Share
Published by
admin

Recent Posts

Консоль удаленного рабочего стола(rdp console)

Клиент удаленного рабочего стола (rdp) предоставляет нам возможность войти на сервер терминалов через консоль. Что…

1 месяц ago

Настройка сети в VMware Workstation

В VMware Workstation есть несколько способов настройки сети гостевой машины: 1) Bridged networking 2) Network…

1 месяц ago

Логи брандмауэра Windows

Встроенный брандмауэр Windows может не только остановить нежелательный трафик на вашем пороге, но и может…

1 месяц ago

Правильный способ отключения IPv6

Вопреки распространенному мнению, отключить IPv6 в Windows Vista и Server 2008 это не просто снять…

1 месяц ago

Ключи реестра Windows, отвечающие за параметры экранной заставки

Параметры экранной заставки для текущего пользователя можно править из системного реестра, для чего: Запустите редактор…

1 месяц ago

Как управлять журналами событий из командной строки

В этой статье расскажу про возможность просмотра журналов событий из командной строки. Эти возможности можно…

1 месяц ago