Pull to refresh

Comments 42

Мне недавно встретился код вывода количества FPS на экран, написанный начинающим программистом, и в этом коде был базовый класс, класс-потомок, виртуальные функции, конструктор с множеством параметров, variant. 

На лицо нарушение принципа KISS - Keep it simple, s@ka! :)

KISS это круто, а вот отсутствие пользовательского интерфейса и обработки ошибок - не круто. А вместе с ними начинаются классы и variant'ы. А так-то да, код всей полезной работы программы это обычно меньшая часть программы.

Согласен во всем, кроме одного: ананасы - добавлять! :)

Умение создать простое, понятное решение сложной проблемы — это высшее мастерство в программировании.

Прямая аллюзия на:

There is always an evident solution to every human problem—neat, plausible, and wrong.
H. L. Mencken

Мне кажется, что задачи бывают разные, и грести их все в одну кучу — упрощение.

Например, в коде библиотек общего назначения следование принципам YAGNI и KISS — самоубийство (вашим пользователям потребуется всё то, о чем вы подумали, и еще примерно три раза по столько того, о чем вам даже в страшном сне не приснится).

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

Если ваша сущность зависит от внешней сущности, dependency injection лучше организовать прямо сейчас, а не когда «потребуется».

А вот определять всякие свойства и методы с заглушками на вырост — это нет.

О, прямо мои мысли. Всё хотел их на бумаге изложить, да руки не доходили, а теперь вроде как и не нужно :)

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

Дополню. За счёт грамотных абстракций и названий можно добиться понимания "как это работает", но часто никак не объяснить "зачем".

Я код делю на Работающий, Правильный и Эффективный : ) Причем это три разных вида кода.

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

Правильный код - это код, который следует элементарным правилам: тому же SOLID, паттернам, где они собственно и возникают и т.д. - в целом я не согласен с хитропопыми заявлениями про "понимание, где надо следовать, а где не надо следовать правилам" - это банальный самообман самоуверенности - мол, я-то уж знаю че-почем : ) Это-то и приводит к тому, что пишут все кто в лес, кто по дрова и потом тратится время на разбирательства и проблемы на ровном месте из-за того, что кто-то внезапно решил, что он умнее. Не дано умничать, где без этого можно обойтись : ) KISS в частности и об этом : ) А вот Правильный код - он стандартный, особенно, если в компании есть четкие гайды, и - да, в некоторых местах можно было бы и "срезать путь" - но это будет вносить каждый раз новые неожиданные особенности в код и каждый раз в каждом проекте можно будет встретить что угодно, и разбираться с этим, и воротить дальше еще более непредсказуемые решения. Зачем? Ради чего?

Но, опять же, из-за своей природы, Правильный код хорош в понятности, но не оптимален из-за этого в плане производительности. А иногда производительность - это требование необходимое. И вот тогда и пишут уже Эффективный код - с хаками, с ручным управлением всего и вся, с экономией памяти и многая прочая, что может понадобиться, чтобы уложиться в требования. Тут ПРИДЕТСЯ отступить от правил, потому что по-правильному код работает медленно или в другом смысле недостаточно производительно. В любом случае важно, что Эффективный код пишут не от хорошей жизни, а вынужденно! И вот тут важно этот код постараться максимально изолировать от всего прочего, чтобы сложность не пустила метастазы по всему проекту, а второе - это тщательно задокументировать - что вы тут и для чего были вынуждены наворотить, а так же - как этим пользоваться : )

Make it work, then make it beautiful, then if you really, really have to, make it fast. 90 percent of the time, if you make it beautiful, it will already be fast. So really, just make it beautiful!

— Joe Armstrong, создатель языка Эрланг

Ну, насчет "красиво" - это тоже субъективно сильно. Я под Правильным кодом подразумеваю больше шаблонный код - когда от проекта к проекту везде одни и те же структура проекта, архитектура, компоненты, библиотеки, одинаковый DI и т.д. Понятно, что такое, во-первых, даже при примерно одинаковой сфере проекта не совпадает на 100%, но тем не менее - всё же процент шаблонности достигает 70-80%, а во-вторых - можно иметь разные шаблоны на разные классы задач.

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

Для реально же "особых" случаев - да, придется нестандартные решения вкручивать, но во многих сферах разработки такое встречается очень нечасто, и большую часть проектов выгоднее писать просто правильно, стандартно - и не выеживаться : )

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

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

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

У вашей собаки нестандартное количество лап.

Это из-за облучения от нестандартного компьютера.

У вашей собаки нестандартное количество лап.

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

Жаль, что ваша программа настолько не готова к реалиям внешнего мира. В моем питомнике, для которого я собирался внедрить вашу программу, у двух третей собак есть жабры. До свидания.

7 пункт как-то не согласуется с 1/2.

С одной стороны мы говорим пиши просто, а с другой - пиши с качественной архитектурой, и мол это одно и тоже на длиной дистанции, но это вообще далеко не всегда так.

У меня есть pet проект где код пишется за 2 часа вечером, очень быстро, и архитектуры там вообще 0, а подход называется проще выбросить и написать по новой - но для этого проекта это лучше решение, а есть рабочий проект - и там все чинно и архитектурно.

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

А что такое "развертывание архитектуры"?

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

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

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

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

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

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

С ИИ будет проще, у него нет своих интересов. Но пока не могет.

>> Вам должно быть стыдно, что вас все еще интересуют такие вопросы. Не важно, кто хочет вам что-то рассказать, важно лишь, что именно он рассказывает.

1) Галимая манипуляция на стыд. Тебе должно быть стыдно за это.

2) Всегда придерживался обратного. Каждого дурака слушать?

Не важно, кто хочет вам что-то рассказать, важно лишь, что именно он рассказывает.

Забавно, а я вот ровно за эту фразу — не читая текст — плюсанул и тут, и карму.

Всегда придерживался обратного. Каждого дурака слушать?

А как вы пополняете список идолов авторитетов? Кого можно слушать?

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

Пополнение списка авторитетов идёт как раз после прочтения и премениня на себе или на практике того, что повествуется, сравнения с жизненным опытом. А для этого нужно понимать - в чём автор хотя бы поверхностно разбирается, потому что сейчас все пункты выглядят как гороскоп - и про всё и ни о чём;)

А про неважность экспертизы и опыта - вы когда приходите в клинику, хотели бы, чтобы вам диагноз ставил опытный врач, или в целом можно голосованием сидящих в очереди решать?:)

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

Во-вторых, членство в вашем «списке авторитетов» еще не гарантирует того, что человек не ошибается в смежном вопросе, а отсутствие в этом списке — не означает, что человек несет ересь нон-стоп.

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

Просто подумайте, что в общепризнанном списке авторитетов почетные места занимают Мартин и Фаулер, которые принесли больше зла в индустрию, чем все остальные авторы, вместе взятые. А долгое время казавшийся адекватным Пайк — вдруг расчехлился и выкатил язык, про который он сам же говорил: «Сделано так, потому что красоту никто не поймет, зато дебилы, которых понабрали по объявлению, ничего не попортят».

Мое мнение об этом посте: Очень полезные советы, я удивился когда услышал штуку MVP, на днях купил книгу и там часто употребляется суть MVP.

Для понимания, что может происходить, нужно найти определение функции some_function() и посмотреть, какого типа возвращаемый результат, и что возвращает функция Get() у этого типа.

Очевидно же, что проверяем само наличие возвращаемого значения и под else обработка ошибок; при правильном именовании some_function никуда лезть не надо. Лучше конечно воспользоваться готовым std::expected и писать просто if(result).

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

Есть 2 ситуации, когда молодой программист такое пишет.

Первое - когда его руководитель и техлид не дал толковых пояснений, нужно ли расширение в будущем и если нужно, то как. Система измерения пиписек в IT прямо гласит - если ты не пишешь сложный код, то, скорей всего, ты ничего не знаешь, и попадать под гнев начальства за то, что вместо иерархии классов тупо загоняешь в массив и обрабатываешь функцией, никто не хочет, потому пишет по-максимуму. Пригодится на развитие - хорошо. Нет - но код же работает. Здесь не ошибка программиста, а ошибка управления.
Второе - это когда сам себе и архитектор, и техлид. Вот тут да, бывают нюансы.
У меня был как-то маленький заказик, который ожидал вырасти в большой. Человеку надо было автоматизировать печать этикеток, но чисто по опыту работы в той же сфере я видел, что ему нужен достаточно большой инструмент с интерфейсом, обработкой событий и целой кучей проверок и сравнений. Можно было обойтись простым прогоном по столбцам таблицы, но сделал по-уму. И получил бонусом заказ на развитие в том же объеме, который выполнить было уже проще на порядок - просто добавил в класс свойство и дописал по строчке в каждом цикле +небольшая функция на обработку. Но бывает, что такие проекты никуда и не вырастают. А есть и наоборот. В прошлом месяце мне прислали поправить код, который писан тупо многократным прогоном массива в 2018 году - исправно работал, но недавно они обновили 1С, и тот добавил в отчет нечитаемые символы, и потекли условия. Было бы все написано по уму - я бы просто добавил в класс обработку с удалением лишнего. А так пришлось писать функцию и искать, куда втыкать, и руки чесались все переписать, потому что написано неоптимально, из расчета, что ресурсы всегда будут обгонять объем обрабатываемых этим данных. То же и универсализацией. У меня кочует из проекта в проект комплект функций и универсальных кусков кода, и мысль о создании универсальных решений на этапе создания была излишним решением в 80% случаев для текущей задачи. То есть, некоторые первые пользователи моих поделок оплатили облегчение мне жизни в дальнейшем (и, возможно, что я облегчил еще кому-то, кто залезал в этот код).

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

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

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

Спасибо ,это как оддушина ,именно это я искал

Пишите как попало, но главное - потом перепишите это с нуля, с учётом всего набранного опыта.

Опасный подход. По моему опыту, в продакшн уйдет написанное «как попало», а на переписывание с нуля никто не выделит ресурсы.

KISS, YAGNI, тесты, рефакторинг - все это скорее для pet-проектов.

Обычно достаточно всего одного-двух членов в команде, чтобы оставлять кучу всякого дерьма на проекте. Писать тесты - почти всегда стена сопротивления. Мол, торопимся. Или просто «не хочу». Хотя это самому разработчику сэкономит время на пинг-понге задачи с тестировщиком. Нужно прикладывать массу усилий, чтобы убедить человека выкинуть неиспользуемый функционал. «Ну ведь сделал уже, вот, работает». Очень сложно объяснять людям, что код нужно делать читаемым. Почему-то неочевидно людям, что в очевидном коде баги находятся очень быстро.

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

Правильно написанная программа прежде всего понятна.

Правильно написанная программа прежде всего работает. То есть, приносит бизнес-ценность. Всё остальное - не более, чем приятный бонус.

Правильно написанная программа - та, за которую мне заплатили.

Это только на первом этапе. В процессе сопровождения становятся важны и другие свойства.

Бизнес ценность приносит то, что потом не вызывает боли при поддержке ;) Это кстати очень больная и частая проблема.

Загляни́те в код докера, по этой логике — он приносит отрицательную бизнес-ценность.

Это другое, совсем другое, это не бизнес логика, это системные инструменты :)

Это наверное первая статья на Хабре, про которую я скажу ППКС.

Автор, так держать, мое почтение!

Sign up to leave a comment.

Articles