Слишком многие программисты пишут код в духе моего поведения в тот вечер.
Сообщить об ошибке в коде можно разными способами, например:
• Вернуть в результате работы функции код ошибки, который означает, что функция отработала неверно. Код ошибки очень легко игнорировать. В коде ничто не укажет на проблему. Вообще теперь стало принято игнорировать значения, возвращаемые некоторыми стандартными функциями С. Часто ли вы проверяете значение, возвращаемое функцией printf?
• errno — любопытный маразм языка С, специальная глобальная переменная, которая должна сигнализировать об ошибке. Ее легко игнорировать, ее неудобно применять и она служит источником всяческих неприятностей: что, например, делать, если в программе несколько потоков, вызывающих одну и ту же функцию? Одни платформы помогают избежать проблем в таких ситуациях, другие — нет.
• Исключения — это более организованный способ уведомлять об ошибках и обрабатывать их, причем способ, встроенный в язык. Игнорировать исключения невозможно. Или все же можно? Мне часто встречался код типа
try {
//…что-то выполнить…
}
catch (…) {} // игнорировать ошибки
Единственное достоинство этой ужасной конструкции — подчеркнуть, что в коде происходит нечто сомнительное с точки зрения морали.
Игнорируя ошибку, закрывая глаза и делая вид, что ничего не произошло, вы подвергаетесь большому риску. Как моя нога сильнее пострадала потому, что я не остановился немедленно, так и движение напролом через красные флажки может привести к очень серьезным проблемам. Проблемы нужно решать при первой же возможности. Не затягивайте выплату долгов.
Если не обрабатывать ошибки, вот что вы получите:
• Нестабильный код. Код со множеством восхитительных и трудных для обнаружения ошибок.
• Небезопасный код. Взломщики часто пользуются недостатками обработки ошибок для взлома программных систем.
• Плохая структура. Если в вашем коде постоянно проявляются ошибки, которые трудно обрабатывать, то, вероятно, у вас неудачный интерфейс. Формулируйте его таким образом, чтобы ошибки становились менее назойливыми, а их обработка не была столь обременительна.
Следует не только проверять все возможные ошибки в коде, но и обнажать все потенциально ошибочные состояния в интерфейсах. Не скрывайте их — нет смысла притворяться, что ваши службы всегда будут работоспособны.
Почему мы не выполняем проверку на ошибки? Вот некоторые стандартные оправдания:
• Обработка ошибок загромождает код, затрудняя его чтение и отслеживание «нормального» потока выполнения.
• Это лишняя работа, а на меня давят сроки сдачи.
• Я уверен, что эта функция никогда не вернет ошибку (printf всегда работает, malloc всегда выделяет память, а если нет, наши проблемы гораздо серьезнее…)
• Это прототип, нет смысла делать его пригодным для коммерческого применения.
С какими из них вы согласны? Что вы могли бы на них возразить?
Не просто учите язык, поймите его культуру
Андерс Норас
В средней школе мне пришлось изучать иностранный язык. В то время мне казалось, что достаточно хорошего знания английского языка, и потому я благополучно проспал три года уроков французского. Спустя несколько лет я поехал отдыхать в Тунис. Официальный язык этой страны — арабский, но так как это бывшая французская колония, в Тунисе широко распространен французский. По-английски говорят только в местах пребывания туристов. Из-за своего невежества в языках мне пришлось проводить время главным образом близ бассейна за чтением книги «Finnegans Wake» (Поминки по Финнегану), в которой Джеймс Джойс продемонстрировал свое владение как формой, так и языком. Джойс играючи соединил вместе более 40 языков, и чтение книги стало для меня удивительным, хотя и непростым опытом. Это переживание новых средств выражения, сотканных автором из иностранных слов и фраз, осталось со мной на протяжении всей моей карьеры программиста.