Хорошая статья, спасибо. Однако, как мне показалось, люди начали совершенно необоснованно ругаться на пункт 7. Видимо, просто не прочли про то, что следует использовать встроенный в язык механизм свойств, а не выпячивать наружу публичные поля класса. Кстати, это возможно делать и в PHP :-) Я считаю, что в данном вопросе нужно всё-таки не мыслить догмами. Скорее, свойства стоит использовать, если и геттер и сеттер производят небольшие действия. Если же это что-то, что работает очень долго и включает нетривиальную логику, то следует использовать методы. Кстати, ещё один случай, когда стоит предпочесть метод — это отсутствие самоочевидной семантики свойств. Например, если такой код:
if (foo.bar == 1)
foo.bar = 1;
что-то делает (ну, разве что кроме, например, ленивой загрузки, кэширования и т.п.), то bar — никакое не свойство.
И, кстати, раз уж статья рассказывает о несовершенстве языков, приводящем к «некрасивому коду», то могу напомнить ещё один недостаток. Касается он отсутствия возможности писать расширения к существующим классам. Выливается это в то, что приходится писать всевозможные helper-классы и напрямую писать что-то вроде:
Helper.ext(obj, foo, bar)
вместо
obj.ext(foo, bar)
В качестве «реальной» задачи для иллюстрации данного замечания могу предложить следующий пример. Дана последовательность целых чисел. Требуется найти квадраты нечётных чисел. Сравните пример на Haskell:
foo = map (**2) $ filter odd
и на C# 3.0
public static IEnumerable<int> Foo(IEnumerable<int> sequence)
{
return sequence.Where(x => x % 2 == 1).Select(x => x * x);
}
с примером на Python
def foo(sequence):
return map(lambda x: x * x, filter(lambda x: x % 2 == 1, sequence))
Как видите, без нагромождения скобок программа выглядит гораздо изящнее
Эх, хороши исключения, да вот в PHP они реализованы с изъяном — библиотечные функции, а так же различные исключительные ситуации вроде 1 / 0 или null->foo() реализованы не с помощью исключений. Конечно, есть способ с set_error_handler и выкидыванием, но опять же, он почему-то не всегда работает. Например, в том же случае с null->foo обработчик, установленный с помощью set_error_handler почему-то не срабатывает. А это значит, что вместо исчерпывающего стектрейса я получаю невнятное сообщение всего лишь с одним номером строки.
Хм, думаю встраивание логики вычисления выражения в классы, описывающие AST, не есть хорошо. Вообще, для таких случаев в языках без алгебраических типов и сопоставления с образцом используют паттерн «посетитель». Да и использовать строки для хранения типа операторов, как-то не очень… Собственно, то же касается bool'а для того, чтобы определять, унарный ли это минус или not. Кстати, не стоит делать поля элементов AST private'ами.
Не совсем правильно называть приведённую штуку «компилятором выражений». Скорее всего, это лексический + синтаксический анализаторы + вычислитель (evaluator). Всё-таки компилятор должен порождать код или байт-код, а тут интерпретируется сразу AST.
Наконец, скажу одно слово: ANTLR (в дополнение к упомянутому yacc'у).
Странная какая-то статья. Ведь, если я не ошибаюсь, все браузеры, кроме Safari, рендерят текст не своими силами, а системными функциями, и всё сильно зависит от того, что за система и как она настроена. Вот тут взяли Windows XP, где отключили ClearType. Opera, Crhome и Firefox так или иначе сводят создание шрифтов (через прослойки, возможно) к Windows API фукнции CreateFont, передавая в параметре fdwQuality значение DEFAULT_QUALITY. IE7 при этом имеет настройку, в зависимости от которой он передаёт либо DEFAULT_QUALITY, либо CLEARTYPE_QUALITY. Так что (не считая Safari) тест лишь показывает преимущества ClearType. Теперь о Safari. Туда Apple включили свой, очень хороший движок рендеринга шрифтов. Он субъективно мне больше нравится. Попробуйте на бумаге распечатать, там будет как раз ближе к тому, как Safari рендерит. Насчёт того, что «тяжёлый». Как раз наоборот, благодаря этому буквы лучше видны. А если объективно — об этом очень подробно на RDSN писал пользователь McSeem2. К сожалению, сейчас не могу найти статью. Замечу тем, кто захочет найти, что это статья не про рендаринг в Safari, а про рендеринг шрифтов вообще. Там было про всё — и про ClearType, и про Linux и про Mac.
Ну вот, в DTD так и написано - ELEMENT. Везде, когда говорят о HTML и XML (особенно, это касается документации w3c) говорят об элементах, а теги - это лишь способ записи этих элементов в линейной форме. Например, можно воспользоваться DOM и создать элемент p без использования каких-либо тегов.
Может, кто-то меня сочтёт занудой. Но теги p, hr и style вообще ничего не могут содержать, а тем более, о них ничего не говорится в DTD. Другое дело, что, к примеру, между открывающим и необязательным закрывающим тегами <p> и </p> находится содержимое элемента p, про который и говорится в DTD. Часто встречаюсь с подобной неточностью, в т.ч. и на Хабре.
if (foo.bar == 1) foo.bar = 1;что-то делает (ну, разве что кроме, например, ленивой загрузки, кэширования и т.п.), то bar — никакое не свойство.
И, кстати, раз уж статья рассказывает о несовершенстве языков, приводящем к «некрасивому коду», то могу напомнить ещё один недостаток. Касается он отсутствия возможности писать расширения к существующим классам. Выливается это в то, что приходится писать всевозможные helper-классы и напрямую писать что-то вроде:
вместо
В качестве «реальной» задачи для иллюстрации данного замечания могу предложить следующий пример. Дана последовательность целых чисел. Требуется найти квадраты нечётных чисел. Сравните пример на Haskell:
и на C# 3.0
public static IEnumerable<int> Foo(IEnumerable<int> sequence) { return sequence.Where(x => x % 2 == 1).Select(x => x * x); }с примером на Python
def foo(sequence): return map(lambda x: x * x, filter(lambda x: x % 2 == 1, sequence))Как видите, без нагромождения скобок программа выглядит гораздо изящнее
Не совсем правильно называть приведённую штуку «компилятором выражений». Скорее всего, это лексический + синтаксический анализаторы + вычислитель (evaluator). Всё-таки компилятор должен порождать код или байт-код, а тут интерпретируется сразу AST.
Наконец, скажу одно слово: ANTLR (в дополнение к упомянутому yacc'у).