Есть очень много подобных вещей в языках программирования, но мы выбрали для вас самые известные из них.
Пустые строки в Oracle SQL
Image courtesy Nic Hughes CC BY 2.0
Oracle считает строки нулевой длины эквивалентными NULL. Это существенное отличие от других БД и ANSI/ISO стандарта SQL, который подразумевает, что пустая строка — ранее известное значение, а NULL — неизвестное, и они не могут быть эквивалентны. Это может принести головную боль при написании кода для нескольких RDBMS или переписывании кода.
Возникла путаница в далёком 1979 году, когда вышла первая версия SQL, а соответствующий стандарт ещё не был разработан. Впрочем, в Oracle предупреждают, что в ближайшем будущем подобное явление пустой строки может исчезнуть.
Цитаты:
«Да, это одна из „прекрасных“ фич Oracle DB» — Lukas Eder
«Пустая строка эквивалентна NULL не больше, чем числу 0» — Ben Blank
«ЧТО!? Я так рад, что мы не используем Oracle. Это пугает» — Jeff Davis
+ как универсальный оператор конкатенации в JavaScript
Image courtesy MicroAssist CC BY-SA 2.0
Оператор + перегружен в JavaScript, и выполняет роль как математического сложения чисел, так и конкатенации строк. То есть если один из операндов строчный, а другой числовой, то условно вместо 1+1=2 вы получите ‘1’+1=’11’: JavaScript без предупреждения приведет число к строке.
Причина тому — недостаточный контроль за совместимостью типов. Например, в Python + используется ровно для тех же целей, но у вас ни за что не получится сложить число и символ.
Цитаты:
«Проблема в том, что скрытое приведение типов в выражениях непредсказуемо» — Anonymous
«JavaScript должен выбрасывать исключение в таком случае» — crgwbr
«+ для конкатенации строк — кошмар» — Matteo Riva
Модули Perl должны возвращать true
Image courtesy anthony kelly CC BY 2.0
Каждый модуль в языке Perl должен возвращать true. Если же этого не происходит, то разработчик рискует сильно подпортить себе карму и столкнуться с ошибкой компиляции.
Причина этого ясна и понятна, если понимать, что такое модуль в Perl. Программа компиляции, рассматривая подключённые к коду модули, в первую очередь проверяет их выполняемость. Даже если в модуле нет кода инициализации, Perl все еще ожидает получить на выходе True.
Цитаты:
«Эта штука всегда оставляет у меня тошнотворное чувство» — Drew Hall
«Это не имеет практического применения, учитывая непрерывно возникающее раздражение» — Schwern
Триграфы в C и C++
Image courtesy REUTERS/Gary Hershorn
Языки C и C++ поддерживают триграфы — трёхсимвольные обозначения, которые автоматически конвертируются в односимвольные. Так, например, комбинация ??! выдаст вам |. Если вы хотите максимально запутать необразованного врага, решившего прочитать ваш код, используйте вместо квадратных скобок комбинацию ??( и ??).
Смысл триграфов вовсе не в желании разработчиков языка обфусцировать код, а в том, что когда-то давно многие клавиатуры просто не содержали распространённых ныне символов, например фигурных скобок.
Цитаты:
«Google не поможет, если вы ищете что-то по запросу ??!??!» — Isaac
«Все так ненавидят триграфы, что C99 принес диграфы как альтернативу… еще больше обфускации» — dododge
«Радость триграфов — делает C нечитаемым с 1977 года» — Martin Beckett
Чувствительность к регистрам PHP
Image courtesy Gregg O'Connell CC BY 2.0
В то время как большинство языков программирования чувствительны к регистру, в PHP названия функций, классов и методов к нему нечувствительны. Но что наиболее сильно поражает разработчиков — то, что имена переменных, констант и свойства классов всё же регистрозависимы.
Доподлинно неизвестно, откуда повелось такое расхождение, но наиболее вероятный вариант — изначальное желание создателей PHP выделить интерфейс CGI в отдельный полноценный язык программирования.
Цитаты:
«Ну, это PHP. Не удивляйтесь» — Grzechooo
«Вот почему PHP-программисты используют подчеркивания вместо CamelCase, называя свои функции» — paperstreet7
«Я не имею ни малейшего представления о том, как создавать языки программирования...» — создатель PHP Rasmus Lerdorf
«Есть ли в PHP что-то, не вызывающее недоумения?» — Lambda Fairy
Истинный ноль в Ruby
Image courtesy DaveBleasdale CC BY 2.0
В Ruby 0 == TRUE. Это неожиданно, расходится с большинством других языков, включая Python и C, где 0 всё-таки FALSE, и часто сбивает с толку новичков в Ruby.
Причина в том, что в Ruby только boolean false и нулевое значение (nil) вычисляются в FALSE; все остальное имеет значение TRUE. 0 рассматривается как любое другое число.
Цитаты:
«Это может быть странным, если бы я не считал это неплохим» — Chris Lutz
«Вот почему я люблю Ruby. Мне не приходится иметь дело с таким zero-false злом» — Edditoria
«0==true // аргх, компилятор C в моей голове взорвался!!» — kenny
Пробелы в Python
Image courtesy Paul Kitchener CC BY 2.0
Вместо пунктуации или ключевых слов Python использует отступ для обозначения блока, к которому принадлежит строка кода. Неправильное количество пробелов или смешивание пробелов и табуляции может привести к ошибкам.
Создатели языка стремились сделать код более читабельным и уменьшить количество нажимаемых клавиш за счет того, что многие редакторы и IDE расставляют отступы автоматически.
Цитаты:
«Нет, правда: это то, что мешает мне когда-либо полюбить Python» — wazoox
«Я обожаю отступы в Python, но есть ньюанс: при копировании и вставке кода из Интернета это часто приводит к необходимости дополнительной очистки» — Greg
«Если вам нужны навязанные отступы, вы слишком ленивы» — Joris Meys
Массивы в C подчиняются арифметике указателей
Image courtesy BlueGum CC BY-ND 2.0
Кроме того, что можно получить ссылку на элемент массива как a[i], можно получить ее как i[a].
Причина в том, что массивы в C — указатели на блоки памяти, поэтому a[i]=*(a+i)=*(i+a)=i[a].
Цитаты:
«… это бесценно, когда вы участвуете в конкурсе обфускации C...» — Confusion
«Я не расцениваю это как особенность, это просто взгляд на ядро C. Все для указателей и максимально быстрого получения доступа к памяти. В некотором смысле это красиво» — Michael Neale
Предопределённые переменные Perl
Image courtesy Emily Mathews CC BY 2.0
Если внимательно ознакомиться с описанием языка Perl, можно найти достаточно большое количество предопределённых переменных с, мягко говоря, странными названиями (правда, имеющими достаточно длинный английский эквивалент).
Они служат для выдачи информации или обеспечения доступа к различным аспектам программы. Так, например, $@ — сообщение об ошибке, $$ — идентификатор процесса, $^V — используемая версия Perl. Новичкам приходится часто заглядывать в документацию.
Цитаты:
«Очень раздражает» — MatrixFrog
«Классная штука для однострочников, кстати» — niXar
«Я думаю, что худшие из них — $@ и @$. Работают оба, но я до сих пор не знаю, что делает второй...» — Artem Russakovskii
«Между прочим, есть еще серьезная проблема с этими переменными: они не гуглятся!» — malvim
Автоматическая вставка точки с запятой в JavaScript
Image courtesy Nate Angell CC BY 2.0
JavaScript требует установку точки с запятой в конце каждого законченного выражения. В случае, если этого сделано не было, а после идёт, скажем, пустая строка, JavaScript расценивает это как невнимательность разработчика и самостоятельно вставляет точку с запятой, что иногда помогает, но нередко приводит к ошибкам и неожиданному поведению программы.
Изначально вставка точки с запятой предназначалась для удобства, чтобы сделать C-подобный синтаксис JavaScript проще для новых разработчиков.
Цитаты:
«У вас точно будут проблемы, если вы разрабатываете язык с расчетом на то, что ваши пользователи идиоты» — Rob Van Dam
«Совет: выясните нужное место для точки с запятой и поставьте ее. Это лучше всего» — Doug Crockford
«Вставка точки с запятой — одна из злейших частей JavaScript» — fennec
Автоупаковка в Java и кеширование Integer
Image courtesy Erich Ferdinand CC BY 2.0
Java автоматически упаковывает примитивы в объекты, например, int в Integer. В целом ничего страшного, но Integer кешируется, если его значение лежит между -128 и 127. Это может привести к непредвиденным результатам в случае сравнения автоупакованных объектов, так как программа будет присваивать значение TRUE, если оба объекта имеют значение от -128 до 127, и FALSE во всех остальных случаях.
Autoboxing уменьшает количество кода, а кеширование Integer повышает производительность. Но нужно помнить о подводных камнях.
Цитаты:
«Вот результат преждевременной оптимизации» — Joschua
«Это не распространенная ошибка, но хороший повод использовать нативные типы Java для чисел, логических переменных и так далее» — Ravi Wallau
«Я так рад, что пишу на C#» — Will
Автор перевода: Илья Бубнов
___
P. S. Выбрать направление и начать обучаться по одной из технологий, о которых рассказывалось выше, можно на сайте GeekBrains.
Комментарии (170)
ivorobioff
28.03.2016 09:07+1Но что наиболее сильно поражает разработчиков — то, что имена переменных, констант и свойства классов всё же регистрозависимы.
Вот тут не соглашусь, так как за все время программирования на пхп не сталкивался с этой проблемой решил специально проверить данное утверждение в PHP 7. Все работает в независимости он регистра.
Как обычно, на пхп гонят завистники :)
Myth Busted!alexkunin
28.03.2016 13:05+2Проблемка будет, если на регистро-зависимой файловой системе у вас класс называется не так, как файл. А еще константы таки зависимы:
define('ABC', 1);
echo ABC;
echo abc; // Notice: Use of undefined constant abc — assumed 'abc' in [...][...] on line 3
Или вы про const в классах? Так тоже ж зависят от регистра:
class a { const b=1; }
echo a::b;
echo a::B; // Fatal error: Uncaught Error: Undefined class constant 'B' in [...][...]:3
И свойства классов тоже:
class a { var $b=1; }
$i = new a();
echo $i->b;
echo $i->B; // Notice: Undefined property: a::$B in [...][...] on line 4
Проверял тут — http://sandbox.onlinephpfunctions.com/, версия 7.0.3.
d_fomenok
28.03.2016 09:07+1Про С++ даже не интересно. Все знают, что в нём много устаревших вещей, которые никак не выпилят для обратной совместимости. И на практике никто не использует триграфы.
Lence
30.03.2016 10:30К особенностям Oracle можно отнести механизм sequence, довольно отличительная черта от остальных RDBMS строящие таблицы с автоинкрементном. А вот строки нулевой длины эквивалентны NULL удобно. Не хотелось бы, чтоб это правило в дальнейшем поменялось.
alexkunin
30.03.2016 16:13Так Postgres то же самое делает, вроде. Просто дает удобный «макрос» SERIAL, который делает все сам, но работает только во время создания таблиц. Если же нужно изменить существующую, то все придется руками делать — CREATE SEQUENCE и т.д.
Но это неплохо, на самом деле, потому что такой подход дает больше возможностей. А еще это часть стандарта, и встречается в других СУБД.
Lence
30.03.2016 16:24Конечно же от этого больше плюсов — сквозные "айдишки", кэширование, шаг инкримента, начальная/конечная позиция. Но реакция пользователей других СУБД примерно такая же как и когда узнают про is null, вместо = ''
FRiMN
02.04.2016 13:51В Perl есть два разных набора операторов сравнения — один для строк, другой для чисел: http://ru.perlmaven.com/sravnenie-skalarov-v-perl
Нужно следить за кавычками вprint
:
@i = ('a', 'b', 'c'); print "@i"; # a b c print @i; # abc
Списковый операторprint
. Для запятых слева от него он имеет наименьший приоритет, но повышает приоритет правой запятой.
@i = ('a', 'b', print 'c', 'd'); print "\n",@i; # cd # ab1
vladon
В C++17 триграфы убрали.
Athari
А до этого отключили по умолчанию во всех компиляторах, вроде.