| 11. Не решайте чужие проблемы | |
| Поговорим о самом главном правиле, от которого происходят все остальные правила программирования. Идея заключается в следующем: «Человек должен решать только те проблемы, которые кроме него никто решить не может». | |
| Компьютеры создавались имено с той целью, чтобы решать задачи вместо человека. Время идет, прогресс не стоит на месте, спектр задач, которые в состоянии решить компьютер, расширяется каждый день. | |
| Однако, существуют очень много программистов, которые не доверяют задачи компьютеру, которые он мог бы решить гораздо лучше чем человек. К сожалению, к сожалению… Поговорим о конкретных примерах. | |
| | |
| Счетчики ссылок | |
| Программисты отказываются от смарт-поинтеров со счетчиком ссылок, мотивируя свои действия излишним оверхедом на подсчет этих самых ссылок. Взамен им приходится самостоятельно контролировать точки освобождения используемой памяти. Если программист допускает ошибку, то происходит утечка памяти и, возможно, какого-либо ресурса. |  |
| Помимо утечки памяти и ресурсов, в случае ошибки со стороны программиста в программе произойдут непредсказуемые изменения, поскольку на время жизни объекта может быть завязана определенная логика. | |
| | |
| Мутексы | |
| Программисты отказываются от «замыкателей» мутекса, привязанного к некоторой области видимости (например, boost::scoped_lock), мотивируя это вообще неизвестно чем — некоторым до сих пор мерещится оверхед на создание на стеке пустых объектов. Взамен программисту приходится самостоятельно контролировать точки освобождения мутексов. Если программист допускает ошибку, то через некоторое время происходит deadlock. | |
| | |
| printf-стиль и ellipsis-функции | |
| Программисты отказываются от статической типизации. Взамен им приходится контролировать соответствия типов вручную. Если программист ошибается, то об этом он узнает только на этапе выполнения, а не компиляции, как это могло бы быть. Да и то, только в тот момент, когда управление доберется до места ошибки. Да и то, с первого раза ошибка может остаться и незамеченной… | |
| | |
| Ассемблерные вставки | |
| Программисты используют ассемблерные вставки потому, что считают себя умнее компилятора. Программисты уверены, что они знают лучше компилятора как сделать паддинг границ цикла, как минимизировать число инструкций, сбрасывающих кеши процессора, как сбаллансировать распараллеленные вычисления, и так далее. Взамен им приходится самостоятельно складывать код из элементарных инструкций, учитывая все тонкости и особенности архитектуры процессора и прилегающих устройств. При этом, если архитектура «железной» составляющей меняется, то программисту приходится пересматривать все ассемблерные вставки. | |
| | |
| Таких примеров можно привести очень и очень много. И после каждого — если, если, если… И ничего удивительного в этом нет. | |
| Дело в том, что человек справляется со своими задачами гораздо хуже, чем машина. Человеку свойственно ошибаться. Человек обладает ленью, невнимательностью, нуждается в отдыхе, чтении фишек, медленно работает, при этом качество его работы всегда оставляет желать лучшего. | |
| Машина же, в отличие от человека, хоть пока что и не способна на творческую деятельность, прекрасно, быстро и безошибочно справляется с любыми нетворческими задачами, не нуждаясь при этом в сне, отдыхе, пище, или каких-либо других ресурсах, кроме электроэнергии. | |
| Все, что возможно автоматизировать, должно быть автоматизированно. Возлагайте на машину всю работу, которую она только способна выполнить. Сталкиваясь с очередной проблемой, не спешите решать ее самостоятельно — прежде всего задумайтель о том, как научить машину решать эту проблему. | |
| | |
| Рекомендации | |
| Пользуйтесь идиомой владения. Не думайте о том, когда следует освободить тот или иной ресурс. Пусть об этом думает компилятор. Поверьте, он сделает это вместо вас именно там, где это следует, и, в отличие от вас, никогда не ошибется. | |
| Не жертвуйте лаконичностью и изяществом архитектурных решений ради экономии памяти или производительности. Лучше пусть у вас будут десять книжных шкафов, на каждом из которых аккуратно расставлены по десять книг, чем один шкаф, беспорядочно забитый до отказа сотней книг. Помните, что недостаток ресурсов можно моментально восполнить новым железом, а вот недостаток в архитектуре восполнить моментально невозможно ни за какие деньги. За устранение последнего недостатка придется заплатить самым ценным ресурсом — временем. На современном рынке такая плата для компании может оказаться фатальной. | |
| Не отказывайтесь от уже существующей автоматизации, в том числе — статическая проверка типов, идиома владения, высокоуровневые конструкции вместо ассемблера, и так далее. Не отказывайтесь от всего этого ради сиюминутного удобства. За сэкономленные «сегодня» несколько часов придется заплатить неделями «завтра». | |
| Унифицируйте compile-time-овые, а не run-time-овые свойства сущностей. Многогранность поведения без четкого контроля со стороны машины еще никого не приводила ни к чему хорошему. | |
| Столкнувшись с любой проблемой, не думайте о том, как ее решить самостоятельно. Думайте о том, как научить машину решать эту проблему. | |
| Пишите unit-тесты! | |
| | |
| Примечание | |
| И в этот раз не стоит забывать о здравом смысле. Я не призываю вас менять quick sort на пузырьковый алгоритм, а если будет тормозить, покупать новое железо. Конечно же, если у вас имеется несколько алгоритмов, дающих одинаковый результат, использовать следует лишь тот, который обладает наименьшей сложностью. | |
| | |
| Резюме | |
| Чем больше решение задачи связано с творческой деятельностью, тем сложнее поручить это решение машине. Верно и обратное — чем легче решение задачи укладывается в некоторый математический алгоритм, тем проще будет машине справиться с этим решением. Занимайтесь только творческими вопросами, пусть все остальное делает за вас компьютер. При этом не так страшно, если вы сразу же не сможете научить машину решать вопросы, которые она решать в состоянии. Главное — видеть и понимать эту разницу. Умение придет с опытом. | |