Jul. 28th, 2016

birdwatcher: (Dore: Ogre)
Младенец сделал тесто и позвал сестру жарить из этого теста вафли. Вскоре приходит, растерянный:
- Наташа нашла очень маленький bug в тесте, которое я сделал...
Я, нервно:
- Какой там еще может быть баг?
- Ну не знаю, мы не можем определить его вид...
birdwatcher: (Leif Gram: Mr. Fix)
Осознал интересную вещь.

У программистов общим местом является положение о том, что чем короче функции, тем лучше. По крайней мере, каждая функция должна помещаться на один экран. Но это очень слабое требование, скорее, отправная точка. Конечно, надо делать короче. Чтобы было сразу видно, что каждая функция делает, и какая она безошибочная. Есть даже специальная характеристика кода: loc per method. У кого меньше, тот и молодец.

Я к этому всегда относился, как к безобидному чудачеству, вроде обсуждений, сколько пробелов должно быть в одном табе и на какой строчке должна быть открывающая фигурная скобка: на той же, что if, или на следующей. Здоровые люди этим не занимаются, а больным их болезнь как раз помогает быть более ценными сотрудниками, так что тем более не надо спорить. Мозг - странная штука.

Но вот пришлось разобраться в куске одной системы, который, как оказалось, делает следующее: проходит в цикле по массиву, и для каждого элемента вызывает функцию двух аргументов. Первый аргумент - это просто текущий элемент массива, а второй - сумма всех элементов от нулевого до данного. Вроде, трудно грубо ошибиться.

Конечно, никакого цикла в явном виде там нет, не лохи писали, а есть однострочный вызов stl::for_each, плюс двадцать вложенных однострочных функций. Каждая из этих функций тривиально оптимальна. В конце концов, она занимает одну строчку. Попробуй-ка, оптимизируй!

Но если немного подумать, что происходит, то можно убедиться, что частичные суммы не накапливаются по ходу дела, а вычисляются для каждого элемента заново. Вместо линейной сложности достигнута квадратичная. Каждая конкретная функция невероятно хороша, а всё вместе никуда не годится. И заметить это при таком способе записи решительно невозможно: control flow не постулирован в явном виде, а подразумевается. Исправить сможешь, только если будешь по каким-то посторонним причинам переписывать всё заново.

Так что дело не такое уж безобидное.