Я тут недавно научился программировать.
Вам, может, смешно, но у меня из трёх типов скилзов - projecteuler, тяп-ляп-прототип, Солидный Тест-Дривен, общая картинка ни хрена не складывалась. Более того, я годами пытался понять, как это люди делают тяп-ляп прототип и выдают это за готовое изделие. Фанерную конуру за уютный жилой дом.
А, в дополнение к трём типам ещё где-то сверху витал Дух Функционального Программирования, который иной раз снисходил на код в стиле projecteuler, но остальных гнушался.
Так вот, странным образом, после того, как перепёр МакБрайда с Патерсоном на скалу, картинка сложилась.
Картинка примерно такая.
Есть какая-то объективная реальность, данная нам в ощущениях, а не в теоремах и задачах. Мы эту реальность начинаем тыкать палкой, потом скриптуем это дело, усложняя, пока не получится прототип, который в целом как-бы делает дело, но смотреть на эту лапшу не хочется. Но работает, в простейших случаях; все случаи методом тыка не покроешь.
Ну и хорошо. Останавливаемся здесь.
И начинаем писать юниттесты, не трогая (по возможности) имеющийся код, а только изолируя всю объективную реальность, чтобы всё работало внутри матрицы. Прежде всего, покрываем те случаи, которые у нас уже работали в объективной реальности.
Теперь наша программа изолирована, и можно на ней ставить опыты. Пишем дикое количество юниттестов - конфигфайлы с отсутствующими полями, с отрицательными номерами портов, со всяким бредом; файловые системы, которые говорят, что файл есть, но читать его не дают; репозитории, бросающие исключение если их спросить про какой-нибудь фолдер; и т.п. Не забудем замокать время, так что наш wait будет просто тикать - и в конце теста проверять, что натикало.
По дороге если приходится сильно чинить код, то его, конечно, надо бы опять на объективной реальности прокатать.
Ну вот, и когда матрица готова, то можно работать над кодом.
Можно убирать мутабельность и заменять всё на фолды, редьюсы, мапы и фильтры; можно выделять классы, всё перефигачивать - гоняя при этом юниттесты; т.к. это настоящие юниттесты, а не тяп-ляп, то они все пробегают за секунду.
Ну и когда код почищен и блестит, можно наращивать функциональность - статистику, логгинг, репортинг, всякие такие финтифлюшки, опциональные конфиг-параметры, и т.д. Вы его гладите, он мурлычет.
Скорость офигенная.
P.S. Я тут ну не вполне для прикола, но вставил в свою последнюю апликашку что-то вроде варзей:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | val webServer = new Thread("Web Server") {
def response(text: String, code: String = "200 OK") =
"""HTTP/1.0 """ + code + """
Content-Type: text/html
Content-Length: """ + text.length + """
""" + text
override def run {
for(port <- env.webPort) {
val ss = new ServerSocket(port)
while (true) try {
val s = ss.accept
try { s.getOutputStream.write(response(stats.toString).getBytes)
} finally { s.close }
} catch { case ie: InterruptedException => return }
}
}
}
|
Это веб-сервер, который (если, конечно, в конфиге задан порт) возвращает статистику пока программа работает. 19 строчек. И не надо никакого asp.net api изучать.