Pull to refresh

Comments 95

Согласен с автором. Pimpl часто бывает нужен, а закомментированных кусков кода и т. п. быть не должно. Нужно уметь применять абстракцию. Хотелось бы добавить, что часто полезным будет внедрить систему автоматических текстов. Хорошо составленные тесты могут дополнять или даже заменять документацию публичной части класса.
Главное, что они заставляют абстрагироваться.
> автоматических текстов
WAT
Статья не претендует на полное сравнение кодовых баз проектов, я просто подметил интересные (плохие и хорошие) места в коде. И поверьте мне, аналогичный треш в Notepad++ ещё в сотнях мест, ровно как и отличные находки в Qt — тоже не.только в указанном моменте.
Там половина кода это doxygen дока, не так уж все и страшно. В Qt5 этот код еще и отрефакторили.
Спасибо, есть чему поучиться
Вы и вправду считаете, что снижение интереса к notepad++ вызван качеством исходного кода, а не удобством аналогов типа сублайма?
Это косвенное последствие. Notepad++ не успевает наращивать удобство с должной скоростью из-за ужасной кодовой базы. Спелчеккер прикручивали годами (вот только недавно закончили), карту кода передёрли с Сублима плохо и глючно и т.д. Я писал в статье о куче патч реквестов, висящих на рассмотрении по полгода просто потому, что интегрировать их слишком трудно и долго.
Или просто все скачали Notepad++, который занял свою целевую нишу (открытие всех непрофильных файлов) и который полностью устраивает и успокоились.
Я бы немного переформулировал основное послание: «Умейте видеть абстракции вовремя». Как старательно не проектируй, посреди реализации оказывается, что вот этот наследник использует только отрытый интерфейс родителя, а тот класс только какое-то время соответствовал этому интерфейсу, да и то только потому, что брал на себя не свои функции. К сожалению, многие абстракции кристаллизуются только после определенного времени разработки или даже использования системы. Угадать их заранее, по-моему, сроди ясновидению.
Но это не значит, что не надо стараться :)
Вы сами признаете, что вовремя увидеть можно далеко не всегда. Предлагаю вариант «Не бойтесь рефакторинга». Ну и тут привет всем любителям сдельного фриланса, конечно :)
В Qt есть еще одна прекрасная вещь — документация. Только после двух лет работы с библиотекой мне однажды понадобилось посмотреть в код
Первый абзац какой-то странный. Обычно, чтобы объяснить что-то неочевидное, подбирают простой и понятный пример. Вы же наоборот: объясняете азбучные истины хорошего программирования на нетривиальном примере, который даёт чуть ли не больше поводов для размышления, чем предмет статьи. Что, впрочем, нисколько не умаляет её ценности.
Вы приводите пример смертных грехов программистов, код Notepad++ как иллюстрацию, получается слишком категоричные суждения в отношении автора Notepad++

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

Macro m = _macro;

Было бы совсем не плохо, если бы вся оставшееся логика функции крутилась вокруг этой переменной. Например i,j допустимо употреблять в циклах.

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

Ну зачем это писать? Все мы знаем что метод разросся не из-за попытки сэкономить наносекунды.

Непонимания абстракций 'флаг', 'константа', 'магическое число'.

Странно, в том же коде есть CURRENTWORD_MAXLENGTH MAX_PATH, значит автор понимал что такое константа? Просто маленький технический долг в этом месте.

Отсутствие абстракции над кодировками

Отсутствие слоя абстракции над UI-примитивами операционной системы

Это, согласен, плохо.
А теперь сделаем шаг ещё выше по абстракциям и признаем, что главным является то, как называются компоненты (точнее, в каких терминах описывается их взаимодействие). Ошибка в этом месте тянет ложные абстракции и неудобные механизмы.

Я говорю про уровень выработки терминологии.

Например, пусть у нас задача собирать видеонаблюдение с географически разнесённой системы с перерывами в связи.

Мы можем сказать, что у нас есть мастер и слейвы. Можем сказать, что у нас есть сеть пиров с разным уровнем авторитетности (и задачей сети пиров является донесение данных до точек максимальной авторитетности), можем сказать, что у нас архивариус и генераторы.

Как определим терминологию — так писать и будем. И это находится сильно выше, чем классы в приложении или конкретная модель пуш/поп/полл.

Идеология и терминология определяют формат решения задач.
Модель предметной области?
До определённго предела — да. Предметная область даёт россыпь терминов, понятий и отношений, на которые удобно опираться. Но программа большую часть времени не занимается предметной областью, а занимается «чем-то своим» (я это очень не люблю — но такова реальность — большую часть кода, если считать строками, программы занимаются сами собой, а на работу выделяют лишь малую часть). Вот это «что-то своё» и требует своей терминологии и понятий, и оно же определяет насколько хорошо программа будет делать полезную часть себя.
Золотые слова. А если сделать шаг ещё выше, то окажется, что главная проблема — каша в голове. Человек просто или инженер, или нет. Или он понимает, как устроен мир, или нет. Или он настоящий инженер, или ремесленник от программирования.
Ох, я бы вот тут не делал таких резких заявлений. «Понимать как устроен мир» это очень круто. На каждое уверенное знание человека приходится дофига слоёв, которые знаешь плохо и неизвестное (но заведомо большое) количество слоёв, о которых не знаешь.

Вот для меня было откровением существование SMM режима у процессоров. То есть маленькая революция в сознании того, как всё в компьютере работает. Хотя, вроде, системным уровнем интересуюсь и более-менее (думал что) знаю что делает процессор под управлением ОС.

У любого программиста копнуть — будут дыры. Либо сверху, либо снизу.
Вы упомянули про терминологические проблемы (мастер-слейв vs. P2P vs. архивариус). А есть ещё целый класс проблем, когда разработчик придумывает сложные решения для простых задач, просто потому что не может отличить реальную проблему от выдуманной им самим. Например, программист борется с тормозами программы, управляющей станком, оптимизируя тяжёлые вычисления распознавания изображений с камеры (запускает несколько потоков, в каждом потоке обрабатывает часть изображения, потом синхронизирует их, собирая результаты), при том, что можно запустить распознавание одновременно с перемещением механических деталей станка, и внезапно окажется, что существующей производительности распознавания достаточно. Это не дыра в том понимании, как вы узнали про SMM. Это вообще неумение подумать чуть шире, понять суть проблемы, которую надо решить.

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

Дыры есть у всех, это понятно. Проблема в том, на сколько порядков они отличаются в размерах. Вы узнали про любопытную фишку процессора, и у вас это знание легло на нужную полочку в «картине мира». Потому что у вас эта картина мира есть, и вы её пополняете по ходу развития. Дыры же в представлении о мире у большинства программистов настолько огромные, что даже мостик от исполнения JavaScript в браузере до аппаратуры компьютера они построить не в состоянии. Я уж не говорю про понимание работы стораджа или сети.
Стало интересно, а что вы имеете в виду под стораджем?
Те сложные штуки, которыми занимается камрад amarao.
Жаль, что не могу поставить больше одного плюса. Как я этого наелся, будучи тимлидом…
UFO just landed and posted this here
Да, причем этот расплавленный припой — китайский, как и Ferrari California в данном примере.

Автор попутал объем мотора этого автомобиля (260 cu in — 260 cubic inches) и его мощность в лошадиных силах (которая, как можно догадаться, у современной Ferrari никак не может быть 260 л.с.)
Автор признает, что в двигателях Ferrari действительно разбирается, как еноты в астрофизике.
Спасибо, автор. :-) Признание, достойное уважения.

Но я б поправил всё же количество лошадей, для будущих поколений. 454.
Выводы не в тему, даже если я прекрасно вижу абстракции — ограничения в виде языка никуда не денутся, а абстракцию можно будет реализовать любым из «советов»: глобальной переменной, большими функциями, преждевременной оптимизацией и т.д.

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

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

Вывод: идеальная абстракция должна быть (и может быть только!) на низких уровнях — как раз драйвера, ОС. При этом абсолютно неважно какой длины функция — она пишется «навсегда». А пользовательские интерфейсы, динамические страницы, отчеты и т.д. нужно реализовывать с худшей абстракцией, но с лучшим пониманием программистом. И тут уже нужны паттерны, советы от Гуру и т.д., отсутствие преждевременной (или вообще железо дешевле) оптимизации. Именно здесь успех Java и C#.
Собственно, самые простые и понятные абстракции уже давно написаны (операционные системы, драйвера, основные фреймворки). И гораздо больше задач горизонтальных на высоком уровне абстракции — именно поэтому в почете советы по чистому отформатированному коду и горизонтальных связях.
Все что я пишу, это чистое ИМХО, но как правило, нужно это выделять, иначе не поймут.

Паттерны — это способ быстро передать видение решения проблемы другому программисту. Они не могут быть хорошими или плохими. А вот решение на их основе может быть хорошим или плохим. Не знание паттернов ни в коем мере не помешает программисту решить задачу. Другое дело, сколько ему потребуется времени, что объяснить другому программисту, как он решил эту задачу.

Ни одна из книжек по паттернам не говорит когда и какой использовать. И на мой скромный взгляд, не сможет, т.к. не существует методик по решению задачи написание программных продуктов.
Немного не так. Паттерны — это стандартный способ решить часто встречающуюся техническую задачу. В одних ситуациях стандартное решение будет хорошим, в других плохим, в третьих всё равно каким. Главное чтобы такая задача действительно стояла, а не пригрезилась разработчику :)
Что вы подразумеваете под технической задачей?
Не может перед человеком стоять задачи создание существование объекта в единственном экземпляре, задача в любом случае звучит по другому.
И опять же, стандартное решение какой то задачи не может быть плохим. Оно может не подходить(плохо подходить) к данной проблеме, но плохим быть не может
Задача, выраженная в терминах языка — переменные, классы, объекты, ссылки, интерфейсы и т.п., без всякой привязки к семантике общей задачи. Такие задачи возникают в процессе декомпозиции.
На самом деле наши определения паттерна не являются противоречивыми.
Только мы с вами пытаемся по разному выделить главную функцию паттерна.
Вы, так как сейчас пытаются преподносить паттерны, а я так как по сути они используются среди программистов.

p.s.
опять же уточняю, что тут всё моё субъективное ИМХО, т.к. я не видел ни 1 человека, который бы мыслил паттернами. Паттерны вторичны, они появляются не в голове, а при попытке перенести свою мысль в речь(или на письмо)
Как мне кажется, во фразе «я использовал синглтон» содержится и описание проблемы, и выбранное решение, а, если я вас правильно понял, по-вашему, только решение.
С интересной стороны вы это рассмотрели. Согласен, на мой взгляд тут мы видим только решение.
Мне кажется, что такие фразы все-таки опасны. Тут на, мой взгляд, и о проблеме и о конкретном решении (даже синглтон тот же можно слегка по-разному сделать, не говоря о трудностях перевода и разного background-а) приходится догадываться и есть риск ошибиться. У меня лично как-то обычно не было нужды в паттернах, как «промежуточном» слое терминологии между идеей и кодом. Быстрее и нагляднее получалось примеры кода накидать в 1-2 строки и сравнить подходы.

Один мой бывший коллега так вообще только паттернами и разговаривал (часто, похоже, и мыслил тоже) и в переписке при просьбе руководителя расшифровать какой-то из не самых распространенных в С++ паттернов, дал ссылку на книгу на амазоне (не на википедию или еще какой-нить доступный текст). Причем, похоже, абсолютно без задней мысли.
У меня тоже не было, пока не прочитал GoF и PoEAA и не понял, что многие свои решения можно объяснить одним-двумя словами.

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

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

Часто надо было обсуждать код с точностью до символа: когда мы сочинали либы и хотелось, чтобы лишнего мусора программистам писать не приходилось. Но тут уже не паттерны важнее были, а удобство, лаконичность и интуитивность.

(Если что, то я в основном на C/C++ писал, немного JS. Для Java тема, наверное, может быть чуть-чуть более актуальной)
В основном «паттерны» крутятся вокруг одного: использовать объект класса-наследника (предполагается что синглетон или что-то типа того) как эмуляцию объекта типа «функция» и потом применить стандартный приём из книжки пр функциональному программированию. Т.е. эмулировать функциональное программирование с помощью объектно-ориентированного (оно для этого подходит практически идеально). Дальше, если оверхед получился слишком большой, при возможности, как-то упростить. Т.е. всё вертится вокруг паттерна «Стратегия» (который встроен во многие современные ООП-языки в виде понятия «интерфейс»), который, собственно, и призван изображать из себя место для «первоклассного объекта типа 'функция'».

Про паттерны у меня в голове всегда вертится вопрос: почему именно «паттерны», а не «библиотечные функции», что было бы, по идее, проще? А потому, что кусок кода нельзя просто так взять и впихнуть в вызов библиотечной функции в качестве параметра.
Во всех этих ваших шарпах спокойно существуют все эти функции первого класса. Так что если бы это было возможно, это было бы реализовано. Умение фукнциональщиков видеть функциональщину везде неудивительно, равно как и умение ООПщиков видеть одни только объекты.
1) Я не «шарпист», а в Java это только планируется только частично в 1.8. В связи с невключённостью в мир .NET не знаю, насколько тема «паттернов» педалируется в нём.
2)
Так что если бы это было возможно, это было бы реализовано.
Есть немалая инерция. Насколько я знаю, «паттерны» (1994) старше чем Java (1995-1996) и старше чем С# (2000-2001) и вообще изначально относились только к C++, т.к. книга написана про C++. Кроме того, там скорее нужны не «функции» с заголовком и прочим оверхедом, а «блоки кода» как первоклассные объекты (такое к 1994 году уже было, например, в Clipper).
3) «Критика» «паттернов» на тему, что в функциональных языках они вырождаются в тривиальные вещи, опубликована ещё в 1996 — norvig.com/design-patterns/ppframe.htm
4) Вы так пишете, как будто ФП и ООП — это что-то плохое;-)
5) «Паттерны» — это сегодня исключительно про ООП (пример из Норвига из тех времён, когда вызов подпрограммы тоже был «паттерном», не в счёт). Потому, что ООП позволяет делать их больше, проще и лучше;-)
Я помню, у меня был несложный, но монструозный проект, построенный по всем паттернам ООП (ага, пек хлеб), в функциональном языке он получался намного короче. Но когда мне попозже понадобилось сделать что-то более приближенное к практике, то иммутабельность переменных и пр. заставляли меня писать такие костыли, что все эти фортраны с отутствием поддержки IEEE754 и записями а-ля «X=(X-X)+X» нервно курят в сторонке. А вот на шарпе с анонимками это было легко и приятно.

Я сам с математикой на «ты» и функциональные языки нравятся мне своей элегантнностю и лаконичностью, но в терминах ООП мне мыслить все же проще. А тот же шарп имеет практически те же функциональные возможности, что и какой-нибудь хаскель. Даже монады прикрутили :)
>Ни одна из книжек по паттернам не говорит когда и какой использовать. И на мой скромный взгляд, не сможет, т.к. не существует методик по решению задачи написание программных продуктов.
Вообще-то большая часть канонической "… Паттерны проектирования" банды четырех состоит из обоснования когда, зачем и почему может понадобиться данный прием, а когда и почему не стоит им пользоваться.
Пижама сладкий прыгать Луна вопреки быстро люк?

Что же тут непонятного? Когда от пижамы идёт сладковатый запах, даже на Луне, вопреки пониженной гравитации, быстро будешь прыгать ты, Люк. Более того, тут даже прямо само предложение содержит объяснение своих грамматических странностей. :)
У меня другие ассоциации. Люк настоящий, от марсохода.
> Пижама сладкий прыгать Луна вопреки быстро люк?

translate.google.com —>
русский —> китайский — >… (двадцать языков спустя)… —> болгарский —> английский

«Despite rapid pajamas and cute way to jump?»

Кажется, я понял, что автор пытался сказать…

«Пижама сладкий вопреки, люк быстро прыгать Луна»… Сурово…
Всё так, но ваше желание скрыть внутренности класса от программиста — чудовищно. Положите поля и методы в private, уберите private-секцию в конец файла, сгенерируйте документацию по public-части и расслабьтесь. Программист, который будет искать, почему абстракция работает не так, как ему кажется логичным, проклянет вас, если ему придется опускаться всё глубже и глубже в ад код. А те, кого всё устраивает, и так дальше документации не полезут.
И потом получить сложности при изменении этого private добра, пусть лежит в другом файле лучше.
Pimpl — точно такой же паттерн, как и все остальные. Он не хороший и не плохой. Просто нужно принять во внимание, зачем это нужно было в Qt и почему это не нужно вам, или boost.

Qt — это большая библиотека, которая поставляется в основном в бианрном виде. И ее использует куча проприетарного софта, который просто так не пересоберешь. Поэтому им действительно нужно было обеспечить бинарную совместимость между версиями. В добавок, pimpl отлично совмещается с их COW. Но зачем такое может понадобиться не библиотеке — не понятно.
Скажем, что в случае плюсов COW часто бонусом дает PIMPL.
Вот график его загрузок.


Ну это означает, что все скачали его, кому надо :)
А значит больше уже не надо, а почему?
Успех какого-нибудь популярного сегодня продукта (подставьте сюда свою любимую ОС, браузер, игру — да что угодно) определён именно тем, насколько хорошо спроектирована его архитектура, насколько хорошо высокоуровневые части отделены от низкоуровневых и друг от друга.


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

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

Почему бы не использовать тогда просто не использовать inline функции?
И немного сэкономить время, и читаемо.
минусующие, объясните и мне
Я не минусовал, но могу предположить, что про «пытался сэкономить» это был сарказм для усиления эффекта, а не попытка понять автора. Суть — в последнем предложении.
Так какой же редактор использовать вместо Notepad++?! Скажите скорее, а то я завтра на работе не смогу толком работать…
Холиварчик желаете? Сейчас сюда набегут любители всего — от вима до ворда.
Ну насчёт ворда — это, конечно, совсем уж жестоко как-то…
Я, например, пользуюсь стандартным редактором, встроенным в Far Manager 3.
>Ну насчёт ворда — это, конечно, совсем уж жестоко как-то
Вам «бип-бип» от vim'а
Отличная статья! Подобраны, довольно часто встречающиеся, и жизненые примеры «плохого кода». Сам давно стараюсь пользоваться принципами «программирования от абстракции», а не «от реализации».
Кстати, очень развеселая подсветка синтаксиса. Хотел заставить подсвечивать его файлы определенного расширения (например, файлы *.config как XML). Пробовал в Опции -> Определение стилей (и кто же их туда запихнул), сработало. После этого пытаюсь добавить еще одно расширение, уже не работает (причем и config тоже). В общем, ужас один. А он мне очень нравился…
Зато, я знаю проекты которые загнулись на стадии проектирования, хотя могли бы развиваться (со временем рефакториться) если бы не усиленное желание некоторых программистов потратить кучу времени на архитектуру, вместо того, чтобы тупа сесть и написать Нотепад++. Кстати последним пользуемся всей фирмой до сих пор. Скорость и стабильность его работы одна из причин.
Я пойду против системы, но огромный свитч-кейс — это не самое страшное зло, особенно учитывая, что все ветки помечены константами либо известными из WINAPI, либо собственными, но тоже более-менее понятными. Я бы, конечно, всю ветку WM_COMMAND вынес в отдельный метод, а окромя этого с остальным вполне можно жить. По сути каждая ветка кейс — вещь в себе, как отдельная функция, и может исправляться независимо.
О, не подумайте что это один-единственный метод, который вышел большим из-за свича. Там в других файлах методы в сотни строк без всяких свичей.
Я бы каждую ветку вынес в отдельный метод. Тогда вся конструкция switch имела бы единственное назначение/ответственность — выбор нужного метода.
Это скорее стратегия.
Мое наблюдение: терпимость к такому switch-еванию еще очень сильно зависит от IDE/редактора. Но мешанина из табов и пробелов в 6-м(!) уровне вложенности должна намекать на то, что и автору кода написание все-таки дается не совсем легко.

Но имхо, опенсорсный код должен все-таки более-менее нейтральный код-стайл выбирать, если он, конечно, не для галочки опенсорсный. Лично у меня проблема была бы в чтении не столько в количестве кейсов, а в том, что там сильно разнородный код: там и макросы пишут, и пути склеивают и чисто UI-код. Собственно, там помимо вышеописанных еще как минимум абстракций бизнес-логики (макрос, открытый документ, типа того) не хватает, чтобы этот switch их только «склеивал воедино»
В этом большом свитче нет ддаже банального единообразия поведения кейс-ветвей. Вернее не поведения, единого контракта в плане даже илинообразного выхода. Где return TRUE, а где $result = ...; break;
Назвать javasript интерпретатор v8 engine было офигеннейшей идеей для американского рынка. V8 — это мощность, скорость. Классика американского моторостроения, живая легенда, сердце любого маслкара, ну и заодно болидов наскара, драг-рейсовых и вообще почти всего, что движется на колёсах и похоже на машину.
Я, как далекий от авто тематики, долго врубался в название. Даже была версия, что это закодированное слово «weight»
Абстракции — это очень хорошо и правильно, и мне обычно больше нравится код с правильными абстракциями и написанный по SOLID-принципам, и сам я стараюсь писать именно такой.

Но зачастую всё это не определяет успех проекта, даже опен-сорсного. Привожу пример из систем контроля версий. Для начала возьмём Bazaar, дела у которого, судя по всему, не очень:
Bazaar had a lot going for it. It is written in a popular and accessible programming language. The code is clean, with lots of comments and good test coverage…

We lost sight of what mattered for our users, focusing on features that were nice but perhaps not as necessary as we thought. We overengineered. We didn't get rid of the crufty unnecessary features. It's harder to comprehend, contribute to or fix performance issues in a large layered codebase. And the larger a codebase becomes, the larger the surface for bugs, the harder it is to refactor.
(с) Bazaar Retrospective


А вот известное мнение Линуса по поводу c++, абстракций и «объектных моделей» (которое вдохновляет и заставляет призадуматься, но до конца с ним согласиться сложно):
If you want a VCS that is written in C++, go play with Monotone. Really. They use a «real database». They use «nice object-oriented libraries». They use «nice C++ abstractions». And quite frankly, as a result of all these design decisions that sound so appealing to some CS people, the end result is a horrible and unmaintainable mess.


Всё же мой любимый принцип — KISS. :)
UFO just landed and posted this here
Ок, данный конкретный факт и вправду вышел лажей. Моя вина. Это однако не отменяет ни примеров плохого кода, ни того факта, что патчи годами висят на рассмотрении, ни того, что по скорости наращивания функционала Notepad++ давно уступил как минимум Сублиму, ни общей идеи статьи о важности абстракций.

Прочитать 20 фактов, придраться к одному слабому и на этой основе перечеркнуть все выводы — приём чёрной риторики, давайте не будем её применять.
UFO just landed and posted this here
Не думаю, что это хороший тест. Просто отобразить текст или отобразить его с подсветкой синтаксиса — это уже большая разница по времени. Тогда уж лучше сравнивать скорость работы с таким файлом — поиск в нём, переходы к строкам.
П.с.: не пользовался ни Notepad++, ни Sublime, поэтому комментарий чисто теоретический
UFO just landed and posted this here
Спасибо, душевно по Notepad++ прошлись. Со своей стороны могу добавить:

«Молодец, сэкономил. И получил код, в котором противно копаться и нужно тратить кучу времени на понимание и исправление. „

Тут можно выделить более конкретную проблему, чем абстрактные “противно» и «куча времени». Проблема — кошелек Миллера. Функцию такого размера физически не получится прочесть ни у одного программиста по вполне себе физиологическим соображениям. Поэтому как только там появится что-то кроме мега-свича (а оно появится, поверьте старику) — эта функция станет генератором фееричных, трудно ремонтируемых багов.
Интересное мнение.
А думаете стоит вообще видеть эти абстракции и выносить все в модули на первом же этапе разработки? Например если разобрать абстракцию автомобиля до скелета, то, думаю, для многих, останется двигатель и шасси. А можно прикрутить спереди пропеллер и видоизменить кузов, и вот получается самолет. Или прикрепить снизу винт — получается лодка. Но это так себе самолет и фиговенькая лодка. Чтобы получить летающий аппарат помощнее нужно очень сильно отрефакторить и двигатель и шасси.
Только я где-то написал, что в текстовые исходники надо подмешивать образы (хотябы графические, хотябы стрелочки), так меня сразу отпинали. Зашел сюда — здесь болтают про текстовые абстракции и радуются… Поймите же: можно сколько угодно что угодно говорить, но пока программы пишутся буквами — мы все будем их писать со скоростью муравья или черепахи, и никакие абстракции не помогут, если нельзя их визуально задокументировать.
Scratch? Ну так что-то он не шагает по планете победоносной поступью сламливая на своем пути С/С++, делфи, сисиетку и прочих монстров продакшена.
Этот скратч не компилируется в бинарники. Только сам скратч умеет его исполнять. К тому же его возможности очень ограничены.
И в этом причина.
Я посмотрел скрин в википедии, это игрушка для детей, которые почти не умеют программировать. Какой еще на нём продакшен делать…
Я, наверно, напишу статью с концепцией многомерного программирования на какой-нибудь хабр в своё время, но вижу, что обосрут, заминусуют и сгнобят меня намертво, если это сейчас сделать. Я как-то ковырялся в моделировании, если кто-то слышал GPSS и Arena — делают одно и тоже. Но в первом случае текстовые проги писать надо, которые никто не понимает, а во втором просто рисуешь схемку, задаешь параметры и готово. Это как усилитель на транзисторах можно схематично начертить, а в первом случае (по принципу GPSS) это была бы текстовая программа, как исходник файла векторной графики:)
Абсолютно согласен с автором. Только тут есть и другая крайность.
Часто сталкиваюсь с кодом авторства миддлов-жуниоров, в котором они начинают накатывать абстракции на всё подряд, даже там где они не нужны, и нужно сделать просто уникальную реализацию какого-то микромодуля, и эта реализация уложится в 30 строк кода.

Даже если потом этот модуль придется абстрагировать, То рефакторить 30 строк до более абстрактной сущности — проблем не составит, а вот продуманная сложная абстрактная архитектура может так и не использоваться ни разу до завершения проекта. А время уже потрачено, и вместо 30 строк хардкода, получаем в проекте 5 классов в разных пакетах, которые хренпойми как взаимодействуют.

Я поддерживаю схему разработки:
Говнокод, выполняющий поставленную задачу -> рефактор и абстракция с архитектурой поверху -> релиз.

Часто рефактор и не требуется, а часто он требуется через полгода, когда реализованная сущность уже доросла до самодостаточного модуля, требующего неких оберток и абстрктного представления.

Хардкод тоже плохо, и если вещи требующие абстракции не были замечены изначально — потом исправить так же сложно. Но нужно таки с умом подходить. И хардкод и абстракции хороши каждый для своих задач.
Хорошо помогает выявить необходимость абстракции написание тестов до говнокода, выполняющего задачу.
Пока никак не перейду на ТДД… Планирую в следующем проекте попробовать. Но думаю что так и есть. По логике ТДД — тесты являются представлением ТЗ в виде кода, если я правильно понимаю. И такая идеалогия мне оч нравится, я люблю абстрагировать свой код до логических бизнес-сущностей, и стараюсь чтобы сущности в коде соответствовали описанию задачи словами.
Правильно понимаете, но даже до такого уровня абстракций необязательно подниматься (или опускаться?). Зачастую для построения хорошей абстракции достаточно понимания «что-то тест (прежде всего инициализирующая часть) слишком сложный становится». Утрируя — что за абстракция, если у неё 7 конкретных зависимостей, причем явно не задаваемых, а только через рефлексию?
Понял, спасибо)
Только кармы не хватит даже плюсик на месадж паставить) Так что просто спасибо)
Sign up to leave a comment.