Pull to refresh

Портрет Нуба

Reading time 17 min
Views 6.4K
Original author: Steve Yegge
Чем старше я становлюсь, тем менее важной становится запятая. Пусть читатель сам решает, где ему ставить паузы. — Elizabeth Clarkson Zwart


Примерно так я комментировал свой код двадцать лет назад (внимание, чуток драмы):

/*
 * Когда мы дойдем сюда, наша структура уже будет готова. 
 * К тому же, мы создали достаточно большой буфер, в который 
 * можно засунуть все входные данные, плюс есть немного места
 * про запас. Я не уверен, понадобится ли оно, но хуже не будет. 
 * Теперь нам надо обновить счетчик, предполагая, что клиент 
 * уже прочитал значение, но еще не использовал его. Сначала 
 * я хотел переложить обязанность инкремента на плечи вызывающего
 * кода. С другой стороны, это означает, что инкремент нужно делать всем, 
 * поэтому я решил, что будет лучше перенести его сюда. Но мы можем 
 * пересмотреть это решение позже, если вдруг кому-то из внешних функций 
 * захочется делать инкремент самому.
*/
counter++; // инкрементировать счетчик для потребляемого значения

/*
 * Теперь нужно просмотреть весь буфер с данными. Для этой 
 * операции нам понадобится еще один индекс, иначе перед 
 * выходом из функции мы потеряем начальное значение. 
 * Я хотел назвать эту переменную ‘ref’, потому что в некотором
 * смысле мы будем обращаться с ней как со ссылкой на данные. 
 * В конце концов я пришел к выводу, что самым лучшим  
 * названием для нее будет ‘pos’. Если что, я не против обсудить
 * это решение.
*/
char* pos = buffer; // начинаем наш обход данных

/*
Теперь, мы...
*/


Ну что, узнаете? А должны! Если быть предельно невежливым, весь код выше написал нуб. (Между прочим, если вы не знаете, кто такой нуб, значит вы — нуб).



Вот так пишут junior-программисты. В третьей главе замечательной книги Малькома Глэдвела “The Tipping Point”, рассказывается о рассуждениях 2-х летней девочки, которые поразительно похожи на то, что вы прочитали выше. Девочку зовут Эмили и она рассказывает себе истории, когда ее родители уходят из комнаты и оставляют ее одну. Вот, прочитайте выдержку:

Завтра, когда мы проснемся, сначала я, потом папа, потом мама, мы пойдем на кухню и будем завтракать, а потом мы пойдем играть, а потом придет папа и Карл тоже придет и мы еще немного поиграем. А потом Карл пойдет сядет в машинку и Эмили тоже сядет и еще кто-нибудь сядет, а потом мы поедем в ясли, а когда мы туда доедем, мы все выйдем из...


Описание жизни глазами двухлетней Эмили завораживает. Она абсолютно нормальный ребенок. Все дети говорят что-нибудь подобное, когда мамы и папы нет рядом.

Автор книги поясняет:

Лингвисты называют эти истории временными повествованиями. Девочка создает историю, в которой связываются в одно целое события, действия и чувства. Это очень важный процесс в умственном развитии ребенка.


Ну а если вы еще раз поглядите на тот код двадцатилетней давности, то можно смело утверждать, что я делал то же самое, что делала Эмили — я создавал временное повествование для того, чтобы выстроить умственную картинку расчетов для себя. Эти истории в коментах, которые я сам себе рассказывал, были очень важным процессом в развитии меня как разработчика. Я был ребенком, ищущим смысл в большом, страшном новом мире.

Почти все программисты проходят такой путь. Это абсолютно нормально.

Для контраста, вот код, который я пишу сегодня:
(defun js2-parse-variables (in-for decl-type)
"Распарсить 'var', 'const' или 'let' утверждение или for-loop инициализатор.
IN-FOR истинно, если мы находимся в середине init-конструкции for-а.
DECL-TYPE это токен: или VAR или CONST или LET, в зависимости от контекста.
Возвращает распарсенное значение"
(let ((result (make-js2-var-decl-node))
      destructuring-init
      destructuring
      s start tt init name node
      (continue t))
  ;; Примеры:
  ;; var foo = {a: 1, b: 2}, bar = [3, 4];
  ;; var {b: s2, a: s1} = foo, x = 6, y, [s3, s4] = bar;
  (while continue
    (setq destructuring nil
          s nil
          tt (js2-peek-token)
          start js2-token-start
          init nil)
    (if (or (= tt js2-LB) (= tt js2-LC))
        ;; Деструктор, например, var [a, b] = ...
        (setq destructuring (js2-parse-primary-expr))
      ;; Название простой переменной
      (js2-must-match js2-NAME "msg.bad.var")
      (setq name (make-js2-name-node))
      (js2-define-symbol decl-type js2-ts-string))
    (when (js2-match-token js2-ASSIGN)
      (setq init (js2-parse-assign-expr in-for)))
    (if destructuring
        (progn
          (if (null init)
              ;; если (var [k, v] in foo) проинициализированны по-разному
              (unless in-for
                (js2-report-error "msg.destruct.assign.no.init")))
          (setq node (make-js2-destructuring-init-node :start start
                                                       :end js2-ts-cursor
                                                       :lhs destructuring
                                                       :initializer init))
          (js2-node-add-children node destructuring init))
      ;; простая переменная, возможно с инициализатором
      (setq node (make-js2-var-init-node :start start
                                         :end js2-ts-cursor
                                         :name name
                                         :initializer init))
      (js2-node-add-children node name init))
    (js2-block-node-push result node)
    (js2-node-add-children result node)
    (unless (js2-match-token js2-COMMA)
      (setq continue nil)))
  result))

В каком бы ужасе я находился, если бы я увидел этот код 20 лет назад. Боже, линии не отделены друг от друга! Некоторые из этих линий даже не прокомментированы! Какая ужасная функция! Я бы вопил “переписать все!!!”, если бы вдруг мне надо было с этим кодом работать.

Несмотря на то, что сегодня я пишу больше на Java или Javascript, я специально выбрал пример Emacs-Lisp функции, чтобы показать, каким отвратительно чуждым показался для меня двадцать лет назад ее код.

Если быть честным, то я согласен, это некрасивая функция. Это порт какого-то Java кода из парсера Javascript в Mozilla Rhino, который является портом какого-то C-ишного кода из парсера SpiderMonkey, который, скорее всего, взят из кода какого-то другого компилятора. У компиляторов есть т.н. родословная, и если ее отследить, то можно дойти до ассемблерного кода полувековой давности. Это я к тому, что все что связано с компиляторами скорее всего будет выглядеть некрасиво, если сравнить с “обычным” кодом.

Но даже если бы я писал на Java, мой код выглядел бы больше похожим на Emacs-Lisp, нежели на нубский код двадцатилетней давности. Он был бы плотнее: в нем было бы меньше пустого пространства и гораздо меньше коментов. И эти коменты скорее всего были бы предназначены для автоматического генератора API-документации. В общем, мой код сегодня гораздо более компактен.

В те старые дни, откровенно говоря, слишком много кода на экране сразу бы переполнило мой буфер сложности. И если мне пришлось с ним работать, то вероятнее всего я бы привычно переписал его с нуля или откомментировал бы каждую строчку. Однако сегодня я без особых возражений пробьюсь через все его сложные конструкции и даже не буду жаловаться (ну, разве что чуть-чуть). Если у меня есть цель и сложный код, который нужно написать для ее достижения, то скорее всего я буду заниматься написанием этого кода, а не рассказывать самому себе про него истории.

Десять лет опыта превращают вас в подростка

В конце концов, после некоторого пребывания в стадии двухлетнего ребенка, программист переходит на уровень тупого подростка. Я думаю, все слышали про печальные новости о том, как малолетки застревают в скалах, падают с утесов, гибнут в лесу? Даже не смотря на все предупреждения, подростки считают себя неуязвимыми и поэтому попадают в неприятные ситуации.

То же самое происходит и в программировании. Младшие программисты, заработав пять-шесть лет опыта (и в чем-то до сих пор нубы), начинают городить управляторы миром, и через некоторое время вдруг оказываются в неустойчивом положении на вершине утеса, надеясь на то, что сейчас прилетит вертолет и спасет их. Они твердят себе “моя следующая система будет гораздо лучше” или даже падают с этого утеса — проект проваливается, людей увольняют или сама компания банкротится.

Я тоже проходил через это. Но тут надо сказать себе, что несмотря ни на что, даже
самому крутому программеру нужно иметь толику оптимизма и храбости, если он хочет добиться чего-то существенного. Следует всегда понимать и отдавать себе отчет в том, что каким бы вы не были опытным суперпрофессионалом, проект может завалится как без вас, так и с вами, стараетесь вы или нет.

Если вы, как менеджер по персоналу или владелец фирмы, вдруг читаете в чьем-то резюме слова о “5-6 лет опыта разработки”, то знайте — их нельзя перевести как “опытный”. Это переводится так: чувствующий свою неуязвимость малолетка, с вероятностью 50 на 50 напишет вам кучу дерьма, в которой потом не разберется ни его команда, ни он сам, и которую он вероятнее всего не один раз будет переделывать. Но все это в порядке вещей — любой разработчик бывает подростком в своей профессиональной жизни.

Восприятие компактного кода

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

Камнем преткновения здесь является то, что я называю “восприятие компактного кода”. Оно возрастает с вашим опытом, особенно если вы пишете ПО для разных областей применения и используете разные языки. Этот процесс очень похож на улучшение восприятия все более и более сложных книг у ребенка, которой проходит весь путь от азбуки с большими буквами и картинками до больших книжек, с мелким-мелким шрифтом. (Прогресс в конце-концов приведет к книге Finnegan's Wake, если вам любопытно). Нубы здесь — дети с низким восприятием, а у профи разумеется оно выше.

Проблема возникает тогда, когда нужно расшарить код в группе программистов, где есть как одни, так и другие.

С одной стороны, я слышал про одну методику (и даже следовал ей), которая, проще говоря, предлагает писать код на уровне наименьшего общего знаменателя для всех программистов. Подразумевалось, что если вы будете писать сложно и новенькие разработчики не будут понимать ваш код, тогда вы ухудшите продуктивность всей команды, уменьшите шансы на успех и тому подобное. В общем, основание для применения этой методики есть.

С другой стороны, наконец-таки после стольких лет я могу критически посмотреть и оценить ситуацию с точки зрения профи. Программист с высоким восприятием сжатого кода будет в ужасе от кучи бессодержательных коментов на экране. Почему? Потому что для того, что бы как можно быстрее понять смысл написанного, ему нужно загрузить в голову как можно больше полезного контента. Например — сложный алгоритм. Предпочтительнее видеть его на одном экране, чем размазанным на многих. Это означает сжатие кода, то есть уменьшение числа отступов, пробелов и коментов. Особенно комментов, потому что они не несут в себе никакой практической пользы, а тупо повторяют то, что и так написано в коде. Как раз обратного хочет нуб — он хочет больше свободного пространства, больше коментов. Нуб хочет сфокусироваться на одном выражении и выбросить все другие из поля зрения, чтобы они не мешались. Потому что иначе ему сложно.

В общем да, это проблема.

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

Лично я предпочел бы разбираться в сжатом, сложном коде небольшого объема, чем в здоровой системе из тысяч файлов с коментами. Думаю, что после этого утвеждения большинство из вас скажут, что я капризный старый динозавр. Ну, может быть я и есть старый динозавр *р-р-р-р-р-р*.

Одержимость метаданными

Как всем известно, коменты — это метаданные. То есть информация о данных, в случае, если данными является ваш код. Люди очень часто думают, что коменты это всего лишь разновидность метаданных. Нет! Коменты и метаданные — это одно и то же.

Метаданные — это любая форма описаний или моделирования чего-либо. В нашем случае коменты выступают в роли естественного для языка программирования описания вычислений на этом языке. То, что делает метаданные мета-данными — отсутствие строгой необходимости в них. Если у меня есть собака и паспорт родословной на нее, и я вдруг потеряю паспорт, то у меня останется совершенно нормальная собака.

Возможно, вы уже знаете, что комментарии в коде никак не влияют на рантайм-исполнение. Компилятор тупо выбрасывает их. И только что мы с вами установили, что нубы склонны избыточно комментировать свой код, тщательнейшим образом описывая каждый шаг вычисления. Точно так же, как двухлетняя девочка Эмили моделировала свою идеальную пятницу, уверяя саму себя в том, что она взаправду знает, как устроен весь мир.

Мы с вами знаем, что статические типы — это тоже метаданные. Они как специализированные комментарии к коду, предназначены для двух разновидностей читателей: для программистов и для компиляторов. Статические типы — это истории о вычислениях, помогают и тем и другим понять действия программы. Их тоже можно выбросить в рантайме, потому что они всего лишь комментарии, и ничего больше. Они как паспорт родословной у собаки — радует владельцев и заставляет гордиться. Но собаке все равно, есть ли у нее паспорт, или нет.

Если статические типы являются коментами, тогда мне кажется, что люди, которые уж очень сильно полагаются на статическую типизацию, люди, которые обожают процесс статического моделирования — нубы.

Ха-ха.

Ну, если посерьезнее, то я ничего не имею против статической типизации. Я против ее чрезмерного использования. Младшие программисты злоупотребляют статической типизацией точно так же, как они злоупотребляют коментами.

Я проведу параллель с моделированием данных, которое является разновидностью статической типизации. Работали когда нибудь над проектом, где использовались большие объемы данных или серьезные БД? Наверняка вы замечали такой тип людей, которые считают себя гуру “моделирования данных” и гордятся своей карьерой моделистов. Как правило, они занимаются больше логическим моделированием, нежели физическим. Когда-то они начинали как обычные программисты, но вдруг на каком-то этапе своей карьеры они обнаружили, что их призвание — моделировать данные. Как будто бы они родились для этого.

Если вы знаете о ком я, то вы наверняка заметили и то, что такого рода люди всегда мешаются под ногами. Они сбиваются в банды, формируют всякие Комитеты Потоков Данных и Советы Схем Данных или еще какие-нибудь странные бюрократические структуры, предназначение которых одно — обеспечить их безопасность. Они тратят кучу времени на препинания с обычными программистами, которым завтра надо сдавать проект. Особенно сильно страдают от них субподрядчики. Вроде как они не связаны с основной доходной деятельностью компании, но по несчастливой случайности им оказалось нужно что-то поправить в БД.

Я видел очень много компаний, в которых моделисты затрудняли работу разработчиков, обосновывая свои претензии “сохранением целостности данных”. При этом, все что требовалось таким компаниям — это гибкость и подвижность, что по своей сути противоположно “моделированию данных”. Вы не представляете, какое гибкое и подвижное хранилище можно сделать на банальных парах “ключ-значение”. (Я напишу много, много постов на эту тему, уж не сомневайтесь).

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

Хардкорщики-моделисты часто страдают одной из форм наркомании, называемой “одержимость метаданными”. О, это соблазнительный процесс. Он не заставляет вас никуда торопиться. Вам не нужно делать ничего сложного. Для каждой новой вещицы будет своя коробочка. С другой стороны, использовать немного метаданных имеет смысл (будь это коменты, статические типы или модели данных). Люди могут общаться, используя термины из модели, или машины могут использовать эти метаданные, чтобы потюнить производительность программ. Тем не менее, удивительно большое число разработчиков в отрасли слишком сильно перегибают палку, вместо реальных дел предпочитая эти дела описывать.

Одержимость метаданными применима и к обычным программистам. Код — это данные, и данные — это код. Эти понятия связаны неразрывно. Данные в ваших генах — это код. Чертежи здания — это код. Понятия, повторюсь, на самом деле неразличимые, они связаны между собой фундаментально через восприятие Интерпретатором, который в свою очередь является сердцем Computer Science. Метаданные — это больше почки Computer Science. Можете продать одну и жить спокойно дальше.

Ползучая бюрократия

Как мне кажется, самая главная причина, почему такие языки как C++/Java (в противоположность всяким динамическим Perl/Python/Ruby или уж совсем гиковых Modula-3/SML/Haskell) стали повсеместно использоваться в индустрии, заключается в том, что они оба одинаково угождают всем разработчикам — как уверенным в своих силах, так и неуверенным.

Предположим, есть две группы программистов. Одна пишет на плюсах, используя стиль языка С с буферами и указателями, но при этом ограничивает введение новых пользовательских классов. И другая группа, которая тратит недели, вымучивая основанную на шаблонах и прочем метапрограммировании систему типов, пытаясь смоделировать на ней что-то, что сложно моделируется или не моделируется этими шаблонами вообще. Как вы думаете, какая группа сделает полезной работы больше? Мне кажется, что первая. Все что делают люди из первой группы — перемещают данные туда сюда и запускают алгоритмы, а плюсы помогают им сгладить всякие неровности и шероховатости — накрутить структур данных для публичного API, например. Это гораздо полезнее, чем трата времени на то, чтобы научить самописную систему обработки ошибок правильно ловить всевозможные программные исключения. Конечно, очень здорово и весело писать подобную всемогущую модель, но на практике достичь более менее приличного результата потребует гораздо больше усилий, чем оно того стоит.

Точно так же, в стиле C, можно писать код и на Java. Многие опытные разработчики так и делают. Java более привлекательна, чем C, за счет ООП из коробки. Прошу не путать — ООП все же слегка ортогонально системе статических типов. Вам не нужны статические типы, чтобы пользоваться OOП. Более того, концепт ООП был рожден и обкатан много-много лет назад как раз в динамических языках, таких как SmallTalk и Lisp, задолго до изобретения всякой статической шелухи. Важными элементами ООП являются синтаксис (да даже он не так важен) и объектная модель, представляемая в рантайме.

И вот, вы можете взять Java, заюзать ее плюшки — массивы, связные списки, хэш-таблицы, добавить туда совсем чуть-чуть своих классов и написать со всем этим добром нужный вам код. Или вы можете потратить годы на построение тысяч иерархий классов и UML-документов, рассказывая всем истории о своей замечательной системе, которую вы когда-нибудь доделаете.

Почему Perl, Python и Ruby и т.п. так непривлекательны для большинства разработчиков? Потому что они заставляют разработчиков проделывать работу до конца. Что еще хорошо в этих языках — в них достаточно сложно накрутить моделей и вселенских управляторов (хотя некоторые люди пытаются). В общем и целом, они (как и обычный C) заставляют вас проделать все что нужно, чтобы добиться конечного результата. Разумеется, такие языки очень непопулярны у одержимых метаданными нубов. Смешно, я помню, как я бесился, когда давным-давно Larry Wall обозвал всех java-разработчиков школотой. Как показал опыт, это немного не так… но только совсем немного.

А Haskell, OCaml и его производные? Они тоже исповедуют путь 45-летней давности, предлагаемый Академией Статического Типизирования, то бишь заставляют разработчиков моделировать все и вся. Разработчики это ненавидят. Эти языки никогда-никогда-никогда не добьются никакого коммерческого успеха, точно так же как его не добился концепт “семантического веба”. Вы не можете заставить людей создавать метаданные для всего, с чем они хотят работать. Они будут ненавидеть вас за это.

С моделированием связана еще одна очень актуальная проблема. Модели, которые получаются в результате этого процесса, часто оказываются “неправильными”. Наверное, это сложно понять с самого начала — как может модель быть неправильной? Код (или данные), живут в этой модели и подгоняются под ее правила и ограничения, поэтому и код и данные корректны с точки зрения модели. Однако, модель “неправильная” тогда, когда с ее помощью нельзя отразить реальные вещи из какой-нибудь области, под которую эта модель создавалась. Взять ту же java — всегда, когда вы хотите использовать множественное наследование или примеси, вам нужно изменять представление вещей у себя в голове, чтобы они подошли под ограничения и правила мира java. Вы портите естественный дизайн, поэтому java — “неправильная”.

Важным теоретическим понятием в мире моделирования для моделистов является “звучание” систем типов. То что звучит — это хорошее, годное, а что не звучит — стало быть, наоборот. О, как они любят рассуждать, что звучит, а что не звучит. Java и C++ — не звучат. Но что теоретики-моделисты не понимают, так это то, что пока они не придумают систему, которая была бы корректна в понятии “правильности” (я описал его чуть выше), они будут раз разом фрустрировать своих пользователей, которые наверняка предпочтут более гибкие языки. (И да, scala-исты, нельзя описать весь мир с помощью списков свойств — нужно быть еще проще).

На сегодняшний день, чем больше система звучит, тем больше она “неправильная”. Это первая причина, по которой C++ и Java являются такими успешными: вы можете перестать пользоваться моделью типов, если вдруг она начнет вам мешать.

Вторая причина непосредственно связана с возможностью этих языков создавать пользовательские типы данных. Но, обращаю внимание, далеко не потому, что от них можно получить практическую пользу при создании систем (а польза есть). Причина, по которым C++ и Java так популярны, заключается в том, что предлагаемая ими статическая типизация позволяет бросить заниматься по-настоящему полезными делами и начать бить в нубские баклуши. То есть, моделировать вселенную или писать для самого себя истории.

Java просто переполнена такими нубами. Нет ни одного книжного магазина или форума, где бы их не было. Их можно найти даже в туалетах в некоторых компаниях. Построить модель всего на свете нельзя: это формально невозможно и на практике приведет в тупик. Но они пытаются снова и снова, и, точно так же как и моделисты данных, убеждают своих коллег и вас заниматься этим. А если вы отказываетесь — вы Преступник.

Это приводит их на “утес” нубства снова и снова. И, раз они по своей сути малолетки, они не могут понять, что же они сделали не так. У систем типов есть свой вес и своя мера инертности. Такие системы нужно создавать, их нужно поддерживать, тратить время на изменение и на определение обходов всяких проблем, если таковые обнаруживаются. Эти системы — просто коменты и ничего больше. Такие метаданные эквивалентны вспомогательной документации. Ну а статические системы типов — это то, что становится на пути гибкости, быстрой разработки и расширяемости.

В качестве иллюстрирующего примера я взял Apache Struts и WebWork и написал кучу слов про эти фреймворки. Но все удалил. Вместо того, чтобы тратить кучу времени, лучше почитайте, что сами разработчики Struts пишут про свой фреймворк в статье “Эволюция Struts 2”:

…архитектура Struts 1 не позволяет вносить во фреймворк значительные улучшения и так же имеет значительные ограничения функциональности. В частности, в ней не хватает возможностей Ajax, быстрой разработки и расширяемости.


Struts 2 заменил собой Struts 1 по причинам, описанным в цитате. Через некоторое время по тем же причинам WebWorks заменил собой Struts 2.

Несколько слов стоит посветить JUnit 4. Разработчики этого фреймворка, являя собой пример эталонного нуба, решили, что представленные в Java 5 аннотации — решение всех проблем человечества. Не знаю, смеятся или плакать, но они перенесли весь свой код из нормальных методов в тела аннотаций — самое абсурдное применение метаданных, что я когда-либо видел. Но хватит об этом. Кому интересно — погуглите, в инете много информации по этому поводу.

Наверняка среди нас есть крепкие Java-орешки, которые сейчас скажут нам, что быстрая разработка невозможна без статической модели. Ведь умные IDE обладают возможностью парсить эту модель и как следствие быстро генерить валидный для этой модели код.

Объясните тогда мне, почему разработчики Struts посчитали свое детище неспособным к быстрой разработке? А ответ, мои маленькие любители Java, заключается в том, что любая достаточно сложная модель типов может разломать сколь угодно умную IDE. Никакая IDE не сделает вашу разработку быстрой, если ей надо парсить десятки тысяч классов. Наборот, разработка станет медленней, потому что вы погрязнете в куче метаданных. Конечно, IDE поможет вам ориентироваться в модели, но чем шире океан, тем больше времени нужно лодочнику, чтобы переправиться с одного берега на другой.

В мире есть тысячи opensource-ных проектов на Java, которые были задизайнены программистами-нубами. Эти проекты испытывают какие-то постоянные затруднения, и как я всегда думал, в основном из-за Java. Но сегодня можно с уверенностью сказать — даже несмотря на невзрачность Java как языка (который, по-моему, стал тревожно похож на Pascal), виной всему культура разработки. Как только одержимость метаданными и прочая бюрократия начинают вползать в ваш проект, команду или организацию, очень сложно найти в себе силы противостоять им.

Все эти одержимые метаданными люди закапывают нас землю своими “коментами” в виде моделей типов. Я тоже делал такие модели, когда был нубом. Самое плохое, что делают они это с самыми лучшими намерениями, а их молодости и энергии хватает даже на то, чтобы стоять на каждом углу или выходе и протягивать нам листовки о том, как здорово было бы смоделировать вселенную.

Как правило, опытные программисты игнорируют таких людей и занимаются делом.

Решения и соглашения

Разработка ПО — неоднозначный процесс. Маленькая моделька, которую сделал один программист, другому покажется проявлением одержимости метаданными.

При моделировании следует придерживаться тех же правил, что и при комментировании кода: не пытайтесь смоделировать все на свете! Оставьте код в покое — пусть он сам за себя говорит.

Например, предположим, что вам нужно вернуть два значения из функции в Java. Этот язык не поддерживает возвращение нескольких значений из функции напрямую. Так что же вам делать? Создать специальный класс MyFunctionCallResult с двумя полями ValueOne и ValueTwo (ну, может еще названия полей поменять соответствующим образом)? Или же просто вернуть вызывающему коду массив из двух элементов (может быть даже элементов разных типов) и пусть он сам разбирается, что с массивом делать?

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

Еще пример — публичный API. Тут нужны комментарии. Так сделайте их в форме, пригодной для автоматического генератора документации, которую потом будут читать клиенты и потребители. Только не переборщите — для того, чтобы вызвать ваш веб-сервис, клиенту не надо вчитываться в кучу страниц текста и диаграмм.

Ну и последний совет. Если в процессе инспекции или отладки вы вдруг обнаружили некрасивый или тормозящий код, то можно рассмотреть возможность введения дополнительных взаимодействующих типов. Но держите в голове то, что это компромисс — ценой внесения метаданных вы чуть-чуть ухудшаете поддерживаемость, стоимость, гибкость, тестируемость и расширяемость. Не заходите слишком далеко и все будет ОК.

Следуя этим советам, любой утес, на который вы заберетесь окажется не таким уж высоким, чтобы с него нельзя было спуститься на своих двоих.

Постскриптум

Оставляю коменты включенными. Ну, до тех пор, пока мне в почту не повалятся ссылки “нажми-на-мой-спам”. Мне очень любопытно, что из всей этой затеи получится. Это был очень трудный пост для меня. Мне сложно было его писать, я очень много раз его правил. Мне кажется, что я не очень ясно высказал свою точку зрения. Я так же не уверен, что смог достучаться до одержимых метаданными людей и показать им, что у них есть проблема. Хотя, раз уж теперь они знают, что где-то рядом ходят другие люди, которые имеют такие проблемы, то это уже хорошо.

Не стесняйтесь, высказывайте свое мнение!
Tags:
Hubs:
+91
Comments 171
Comments Comments 171

Articles