Pull to refresh

Comments 346

UFO just landed and posted this here

Что если я скажу вам, что код ревью делать необязательно?

Со многим согласен, особенно х-строк кода в классе, или скрамомания, но code review не соглашусь.
Я столько раз допускал ляпы, чтоб без дружеского просмотра мог легко выкатить трудно-отлавливаемые баги.
Да, и полезно во время review услышать иное мнение, или прийти к выводу что твое решение вполне себе надежное ...
Вобщем, говнокодом давно не страдаю, но обычные ляпы - легко. И code review мне в помощь.

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

[Возможно] разработчик сам может принять решение о важности код ревью в его задаче. В любом случае, это предмет для обсуждения, не истина

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

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

код ревью относится только к новым правкам

Как будто при рефакторинге накосячить нельзя)

относится уже к рефакторингу, решение о проведении которого принимается обычно +- архитектором

Тоже сильно спорное утверждение. Не стоит расширять свой субъективный опыт на всех.

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

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

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

Если вы спрашиваете мое личное мнение - то я бы ИЛИ попросил разбить на меньшие МРы, ИЛИ, как я писал выше:
можно поставить ревью самому себе, если изменение небольшое и ты берешь на себя всю ответственность за фикс.
Ответственность за правки имён разработчик может взять на себя)
Но первый вариант предпочтительнее. Ну и пара вопросов в догонку - Зачем менять эти имена? На что это повлияет? Если эта работа не принесет никакой пользы - ты вопросы уже будут на этапе обсуждения этого рефакторинга.

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

Да, и я не говорил про пользу именно для клиента. Это вы сами додумали)

И счета по системе Тайм + Материал (к которой в итоге все и сводится в заказной разработке) перестанут расти. Отличная польза.


Для массовых сервисов/коробок конечно другой подсчет цены.

Для меня самый страшный коммит имеет комментарий "bla-bla-bla minor refactoring". Наблюдал не один раз серъёзные проблемы в проде, связанные с такими "рефакторингами". Сейчас особенно внимательно отношусь к review таких задач.

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

им всем далеко до простого "Up"!

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

Да. Аппрув ПР обязателен. Причем, даже "для своих". Т.е. вот несколько человек, все на одной горизонтали, уровень лидов (тим и тех). Все в списке ревьюверов по умолчанию. И все равно друг друга контролируют.

В нашем случае так - оформил поставку - она уходит в компонентное ( IT) тестирование. Одновременно создается PR feature->develop. Если IT-тест прошел и нужно отправлять дальше, на бизнес-тест, тут уже нужен аппрув ПР, мерж в девелоп и отметка в задаче "Review Done" от ревьювера.

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

Но ревью нужно даже для рефакторинга. Ибо были случаи когда вылавливали весьма потенциально опасные артефакты в mission critical модулях. Именно после рефакторинга.

Ага-ага, лайкнул я так коммит где "только настройки". Потом все кольцо Кассандры пришлось переподнимать. Больше я по таким граблям не хожу)

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

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

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

пайплайн посткоммитного ревью

скользкая дорожка… у нас так очень существенный онлайн уронили часа на три


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


ну типа этож неважно всё

Ну, фигня случается. Это ж все меряется деньгами.

Если у вас благодаря посткоммитному ревью time-to-market вырос на неделю, а раз в пол года на 15 минут кладете прод - это ок

Если прод из-за такого падает регулярно - заслуженно надают по шапке

Но у нас получилось выстроить процесс так, что сервис целиком не ложился даже если ну совсем плохо все сделать (canary-deployment, вот это все). В итоге ни единого разрыва за пару лет (из-за посткоммитного ревью. В целом разрывы случались)

а раз в пол года на 15 минут кладете прод — это ок

ну там все за полгода дошло до того что прод начали класть раз в неделю стабильно… и собирать совещания "а как так вышлото?? а ктоэтосделал?" причем вернуть тесты перед деплоем после мерджа даже в теории не рассматривались… потомуштамедленно


прод — это не интернет магазин рыболовных крючков, это аналог гуглдокса (ну конечно не такого масштаба но с парой миллионов посетителей в сутки точно, причем платных)… класть его даже на 5 минут это залет

Если у вас благодаря посткоммитному ревью time-to-market вырос на неделю, а раз в пол года на 15 минут кладете прод - это ок

Это если у вас нет норматива от регулятора "максимальное время недоступности системы на более 5-ти минут".

А за 15 выкатят штраф с очень многими нулями. Практически гарантировано. Ну или сопровождение в мыле будет все откатывать и поднимать прод.

Но в любом раскладе потом будет "комиссия по инцидентам" на которой "А подать сюда Ляпкина-Тяпкина! " И чем все это для вас лично закончится... Да бог его знает...

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

Оффтоп, но всегда было интересно, как большие ребята замеряют время недоступности системы, основанной на запросах-ответах. Допустим, в промежуток с 21:42 до 21:47 система на 95% запросов отвечала кодом 200, а на 5% кодом 500. Сколько минут система была недоступна?

Зависит от. Самое правильное глянуть в формулировки SLA, например, на BigQuery: https://cloud.google.com/bigquery/sla

  • "Downtime" means more than a ten percent Error Rate. Downtime is measured based on server side Error Rate.

  • "Error Rate" means the number of Valid Requests that result in a response with an HTTP Status in the 500 range divided by the total number of Valid Requests during that period, subject to a minimum of 20 Valid Requests in the measurement period. Repeated identical requests do not count towards the Error Rate unless they conform to the Back-off Requirements.

  • "Monthly Uptime Percentage" means total number of minutes in a month, minus the number of minutes of Downtime suffered from all Downtime Periods in a month, divided by the total number of minutes in a month.

  • "Valid Requests" are requests that conform to the Documentation, and that would normally result in a non-error response.

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

Или клиент на может зайти в мобильное приложение - оно же само ничего не делает, там просто UI которому дали некое REST API, которое, в свою очередь, опирается на набор вебсервисов, а там каждый имеет соответствующий сервис-модуль на центральных серверах. Т.е. чтобы отрисовать картинку на экране телефона с остатками по счетам и прочим приложение дергает API, то дергает вебсервис, тот дергает сервис-модуль и вот в сервис-модуле на центральном сервере и "возникает синекдоха отвечания" (с) результат которой пробрасывается обратно.

Вообще разные запросы в банк идут постоянно "стремительным домкратом" (с)

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

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

На мой взгляд ревью полезен в любом проекте. Но есть нюансы:

  • Упомянутое Вами блокирование. Нет такой проблемы, если правильно поставлен процесс ревью: у него должен быть достаточно высокий приоритет, чтобы долго ждать ревью никому не приходилось, плюс количество ревьюверов необходимо свести к минимуму (в идеале - к одному человеку).

  • Если это срочный хотфикс - можно мержить без ревью, но ревью этому PR стоит сделать всё-равно, уже после мержа.

  • Если адекватное ревью объективно делать некому - напр. разработчик один на проекте или он один владеет этой технологией или предметной областью - точно придётся обойтись без ревью.

  • Ревью надо уметь делать. В частности, избегая при этом крайностей вроде механической реакции LGTM "чтобы не обижать", отчаянных споров из-за вкусовщины или перехода с кода на личности. Если ревью команда делать не умеет - это самая веская причина отказа от ревью, но даже в этом случае правильнее поступить иначе: обучить команду как делать ревью вместо отказа от него.

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

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

А мне интересно — без скрама это водопад или "как бог на душу положит".


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

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

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

У меня есть контраргумент и я им буду кидаться) Как-то работал сисадмином и одной из рабочих обязанностей было - наполнение нашего раздела на сайте, основанном на самописном движке, застывшем во времени с вечной "0.1" версией. Очередное задание: разместить срочное важное объявление в установленные сроки (это было важно). Проверять результат как-то даже не стал: а какой смысл? С веб-технологиями знаком, а тут всего лишь несильно форматированный блок текста, тем более через админку движка добавленный. Увидел что-то вроде "сохранено" и успокоился.

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

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

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

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

А у меня столько раз code reviewer требовал изменить какую-нибудь запятую, не влияющую на работу программ, но ему, видите ли, не нравится внешний вид кода (при том, что я с примерами в руках могу доказать, что мой внешний вид кода менее подвержен опечаткам).

Это особенности внедрения code review.
При правильной организации процедура может быть полезной - найти слабые места, обсудить решение, обменяться мнениями.
Думаю, атмосфера в команде играет роль, чтоб review воспринимался конструктивно.

Для таких вещей придумали линтеры.
Достаточно один раз договориться в команде и настроить правило линтера — с этого момента вопросы о запятых/переносах/etc возникать не будут.

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

А в некоторых средах ещё и есть автоформаттеры, чтобы тратить на скучные дела минимум времени.

UFO just landed and posted this here

у вас в команде/проекте не было принято и утверждено единого code style

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

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

им нужно следовать.

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

Не цените вы своё время и нервы, ой не цените.

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

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

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

Из ваших уст звучит так, будто принятое правило откровенно плохое, а ваше решение несомненно лучше.
Напомню контекст, мы сейчас говорим о правилах code style (вроде расстановки запятых или отступов). Так вот в этом контексте унифицированное правило однозначно лучше — хотя бы потому что не позволяет появиться мусорным изменениям в гите и не создаёт предпосылок для отклонения PR по этим причинам на ревью.


Для продуктивности команды такое решение лучше и если члены команды не могут прийти к консенсусу, то вариант с волевым решением считаю приемлемым.


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


Ну и кстати, "всегда иметь основание сказать "а я ведь предупреждал!" — не самое главное.

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

Конкретный use case, имевший место быть: через месяц после выкатки нового продукта в прибегает бизнес — "у нас происходит какая-то фигня: прибыли резко упали". Проблем несколько: во-первых, продукт уже выкачен и используется, поэтому тупо откатить на прошлую версию нельзя: в системе уже есть сотни клиентов, использующих выкаченный продукт, если откатить на предыдущую версию кода — клиенты, использующие этот продукт, попадут. Во-вторых, продукт — долговременный; если что-то сделать сейчас, то доходность станет известна только через пару недель. Все тесты (а покрытие, как известно, никогда не 100%) проходят. Вся (не то чтобы совсем уж маленькая) команда три дня лазает по коду — всё с виду нормально, никто не замечает ничего подозрительного, тем более, что там от силы сотня строчек кода добавилась, а на прибыль даже теоретически может влиять всего десяток из них. НО — ерунда происходит!

А разгадка была простая: был один code path, который тестами покрыт не был, потому что ситуация — "исключение из исключения из исключения", то есть теоретически вроде бы происходит настолько нечасто, что когда писали тест — его проглядели. Но на практике новый продукт проходил по коду десятки раз, вместо просто пары раз, как это было со старыми продуктами — и рано или поздно, ситуация "исключения из исключения из исключения" возникала. И вот в этом коде использовалась бесскобочная запись. Никто не удивлялся и не возбуждался — всё ж правильно написано! — но на деле интерпретатор видел приоритеты операций не такими, какими их видела команда — имела место старая хохма про 2 + 2 × 2, что и приводило к неверному срабатыванию ветвления с соответствующими результатами.

А если б тот, кто писал этот код, не надеялся на интерпретатор, а презрел бы "да со скобками некрасиво, убери их" и записал бы выражение в скобках, то три дня работы команды (а также денежные потери на тех продуктах, которые произошли ДО того, как на наличие проблему обратили внимание) не были бы про...трачены впусту.

Всё ещё не понимаю, как это относится к бизнесу. Вместо условного "2 + 2 × 2" с таким же успехом мог быть не менее трудно отлавливаемый NPE или ещё какая дичь.


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

Ну вот я и провёл: добавление скобок даже в очевидных случаях значимых недостатков не имеет (кроме чьего-то уязвлённого чувства прекрасного), зато в неочевидных случаях предотвращает аЦЦкие потери следовательно, скобки надо использовать всегда (это всяко проще, чем пытаться понять "а тот ли здесь случай или не тот"). Доказательство — выщеприведённый случай.

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


В первом случае нужно починить/заменить инструмент, во втором — следовать заветам дедушки Ленина.
А обмазывание скобками это заметание проблемы под ковёр.


UPD: Ну и кстати, для некоторых ЯП есть статические анализаторы, которые умеют отлавливать всякие неочевидные вещи. Очень рекомендую.

А обмазывание скобками это заметание проблемы под ковёр.

Для визуально мыслящих я говорю так: скобки — это перила на лестнице. Могу ли я построить лестницу без перил? Да нема базара. Могу ли я подняться по такой лестнице на третий этаж? Да тоже вполне. А вот буду ли я себя чувствовать себя в безопасности в процессе этого подъёма? Чёрта с два.

для некоторых ЯП есть статические анализаторы, которые умеют отлавливать всякие неочевидные вещи.

Хе, и как этот ваш анализатор поможет в данном случае? Откуда он знает, что человек имел в голове, когда писал код (то есть что бизнес-логика тиребует) — (a * b) + c или a * (b + c) ?

Откуда он знает, что человек имел в голове

Никак не узнает. Но и скобочки тут тоже не помогут.

скобочки тут тоже не помогут.

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

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

Сейчас, только машину времени заведу, вернусь на 15 лет назад и уговорю всех срочно написать фреймворки для такстов.

UFO just landed and posted this here

Умильно) Что называется, заставь дурака богу молиться — придётся все религии запретить, чтобы лбы не разбивали!

Код-ревью - это очень странная вещь.

Я лично встречался с ревьюиром, который считал, что он бог, и поэтому на ревью предлагал мне полностью переделать всё решение ( == архитектуру).

Да, там в MR было 200 строчек кода, да, я, возможно, не идеальный программист. Но сам факт того, что на ревью может найтись умник со своим очень личным и очень непоколебимым мнением - гарантия того, что вместо полировки кода будет -срач- жёсткие споры в команде. Как результат - готовый код попадёт в продукт/на рынок ещё не скоро. Нужно ли такое код-ревью - я не знаю.

Нужно ли такое код-ревью — я не знаю.

именно такое не нужно, но в целом само по себе дело полезное


p.s. я так разок с работы ушел из-за того что начальник постоянно за всех задачи переписывал, потому что "вы делаете не так как я думаю"

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


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

Сложный вопрос. Допустим, альтернатива действительно хорошая. И? Есть некий бизнес, бизнесу нужен на выходе какой-то продукт. Продукт делает несколько человек. Именно тех человек, которых удалось найти. "умник" предлагает лучшее решение. Лично мне не особо понятно, хорошо ли это вообще, или плохо. Ну ок, вот его решение внедрили. Код стал лучше. Но: в результате ушло время на повторную реализацию той же самой фичи, на это потрачены деньги компании, а с точки зрения конечного пользователя ничего не изменилось (есть фича, и она работает). Я не знаю правильного ответа. С одной стороны - очень здорово, когда код становится лучше. С другой стороны, мы всё же обычно работаем не для красоты, а для того, чтобы периодически выпускать релизы (которые позволяют продукту окупаться).

Оба решения отличались только косметикой, или так же алгоритмически и композиционно?

Плохой код в репозитории = плохой пример для подражания. Последующий код пойдёт деградировать её дальше.

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

Я не помню, это было несколько лет назад. Там точно не было кейсов пузырьковая Vs быстрая сортировка ;) Просто объекты, которые что-то обрабатывают, отдают результат и самоудаляются. На мой вкус, разница была незначительной.

На мой вкус, разница была незначительной.

А не допускаете, что умник знал, как оно устроено под капотом, и используемые им методы были более эффективными (вроде O(n) вместо O(n^2))? На паре-тройке объектов, конечно, разница была незначительной — однако под рабочей нагрузкой она бы крайне быстро подняла свою уродливую голову.

Про меня. Все четко сделал - комит. Сомнения - прошу PR апрувить. Хотя лучше вообще всегда, но время не резиновое.

Я бы пересмотрел вообще всё

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

Мне вернуться в прошлое и переписать статью, как вам нравится?

Да и есть вещи, которые я не могу рассказать.

Про программирование без код ревью - погуглите, есть много таких компаний. Без скрама тоже полно. Что именно, какие факты нужны?

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

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

Php для описания бизнес логики прекрасно подходит и прекрасно чувствует себя в highload. Есть ряд низкоуровневых задач, где выгоднее использовать многопоточность go и получить выигрыш, но это не значит, что надо его пихать везде и говорить, что другие подходы неправильные)

Бизнес-логика понятие очень растяжимое. Это может быть, например, плотная и быстрая работа с БД напрямую. Т.е. чтобы проверить наличие записи в БД с заданным значением ключа или дернуть из таблицы одну запись по ключу совершенно не обязательно использовать SQL движок. Можно напрямую обратиться к индексу (для проверки наличия записи просто ищем ключ в индексе и смотрим - есть он там или нет, саму запись читать не нужно).

Или некие коммерческие вычисления с фиксированной точкой где могут присутствовать различные операции типа "присвоение с округлением". В специализированных языках все это есть на уровне языка.

Или мощный механизм описания структур данных - перекрывающиеся поля, например. То что с том же C/C++ придется делать сложными наборfvb union'ов, а частично установкой указателей в рантайме, в том же RPG делается очень просто на уровне описания структур данных и выполняется в compile time

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

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

  1. Так DRY это не про то что в коде символы не должны совпадать. Если у вас "есть два разных по бизнес-смыслу раздела", то очевидно что здесь нет DRY

  2. Принцип про то к чему стоит стремиться. Не нужно усложнять без необходимости

  3. Потому что если можно Х + 1, то можно и Х + 2 не сильно ведь отличаются. А если можно Х + 2 то и Х + 3 можно. Чуете к чему идёт?

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

DRY расшифровывается как don't repeat yourself, остальное уже трактовки, в том-то и дело.

Речь о идёт о принципе или об аббревиатуре? Если о принципе, то даже книжка есть где рассказано, что он означает, от создателей так сказать.

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

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

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

Вы с кем из них спорите?

Идиот, аутист, миллениал и представитель Gen-Z заходят в бар.
Идиот говорит:
- Мне пол литра пива, пожалуйста.
Аутист: "А мне четверть литра".
Миллениал: "А мне одну восьмую".
Представитель Gen-Z: "А мне одну шестнадцатую".
Бармен:
- Эй, эй, эй, стоп! Мальчик, мы несовершеннолетним не наливаем!

Ничего не понял, но очень интересно))

Я бы еще добавил: зачем нужно расставлять типы в не типизированных языках? Только гемора добавлять.

Тайпскрипт вполне себе типизированный язык, компилятор проверяет типы при компиляции.

а потом компилирует и выбрасывает все типы

я так понял ts нужен только в процессе разработки, в продакшене он ничем не отличается от нативного js

Я вам даже больше скажу. Какой ЯП не возьми, а в итоге всё равно одни "нолики" и "единички" получаются :)

UFO just landed and posted this here

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

Задам дурацкий вопрос. Это про type erasure?

UFO just landed and posted this here

Смотря что вы имеете в виду. Если вы о type erasure в смысле C++

Нет, я про type erasure в смысле дженериков в Java

Если я нигде не пользуюсь конкретным n в типе Vect n Nat, то таскать с собой n в рантайме совершенно не обязательно.

В смысле если мы у нас есть объект с полем, которое называется pole и мы этот объект передаём по значению и путём статического анализа кода мы поняли, что pole не используется внутри функции, то мы можем не делать копию pole при передаче?

UFO just landed and posted this here

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

UFO just landed and posted this here
UFO just landed and posted this here

Любопытный язык с мутабельностью.

UFO just landed and posted this here
UFO just landed and posted this here

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

Только в плюсах нет зависимых типов

Да ладно, на минималках всё-таки есть.

Берём прям первый пример с википедии. "Тип, описывающий n-кортежи действительных чисел" это ... тадам ... float[n] Причём компилятор следит за совпадением n и за тем, чтобы n было вычислимо на этапе компиляции, т.е. не даст подсунуть float[3] туда, где ожидается float[2].

Зависимые типы не про вычислимые на этапе компиляции значения, а про их множества. Конкретное значение известно только в рантайме. А то, чём вы написали - это просто обобщённые типы.

UFO just landed and posted this here

Я обычно пишу на Java, но сейчас нужно было на TypeScript и возникла проблема как раз с типами.
Есть набор DTO описывающих структуру тела запроса, условно так:

export class FieldX {
  @ApiProperty()
  field1: string;
}

export class Request {
  @ApiProperty({ type: FieldX })
  fieldX: FieldX;
}

Только вот при обработке этого запроса NestJS создаёт инстанс класса Request в котором поле fieldX имеет тип сырого Object, вместо моего конкретного класса FieldX, из-за чего я не могу вызывать на нём методы описанные в классе FieldX.

Ничего хорошего в таком выбрасывании типов я не вижу.

UFO just landed and posted this here

Именно поэтому рантайм языка JS пытается заново типы угадать, да, заботливо вырезанные TS компилятором.

UFO just landed and posted this here

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

Да не сказал бы про проще рефакторить. Одно дело когда функция возвращает any, другое - было T, стало T | array<T> , но массив только для какого-то нового юз кейса. Тут пахнет тем, что рефакторинг вообще лучше не затевать, а сделать новую функцию с новым возвращаемым типом и потом поддерживать обе (привет DRY)

UFO just landed and posted this here

В тайпскрипте (это же ветка про тайпскрипт?) единственный типовый предикат — это A extends B. Не знаю, какую функциональность имел в виду товарищ @vanxant, но что-то мне подсказывает, что "какой-то новый юз-кейс" такими простыми предикатами может и не описываться.

Я некоторое время провёл, внося изменения в питоновский код, где в половину функций передавались аргументы params или opts, или сразу оба вместе. Каждый из них был словарём с переменным набором параметров/опций, причём они не формировались в одном месте, а прокидывались через много уровней, и их содержимое могло обогащаться/изменяться по ходу этого прокидывания.
То есть не было никакого спосбоа узнать, а какие ключи в принципе там могут лежать, и в каком формате их значения. Эту информацию приходилось собирать по крупицам, ползая по всему коду.


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

кстати к этому в каждом питоновском проекте приходят рано или поздно


причем забавно, сначала разрабы хейтят типизацию — типа бред, писанина, комунадо… а потом начинают и интерфейсы изобретать и типизацию тянуть и сериалайзеры разные прикручивать… и думаю иногда… а чё сразу на нормальном языке с типизацией не писать было?


я на каждом проекте с 15 года где работал в питоне на это попадал… (я стараюсь искать работу в крупных конторах с большими проектами)

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


Впрочем, в последние годы всё больше вижу, что народ распробовал аннотирование типов.

UFO just landed and posted this here

Вот про "язык не мешается" очень верное замечание. Большинство используемых в проде языков до сих пор не имеют не то что хотя бы тип-сумм, но даже и стандартного для этого языка типа result<T>. Ну или же завезли его слишком поздно, и встроенная в язык библиотека например швыряется исключениями.

сначала разрабы хейтят типизацию — типа бред, писанина, комунадо…

Это разрабы, которые вообще никогда не писали на других языках? Ибо я нелюбовь к строгой типизации видел только у убеждённых JS-фанатов.

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


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

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

Странные ребята. Во времена py2 было хорошим тоном всё равно было принято писать типы. Только в документации. Тайпхинты, очевидно, делают этот процесс проще, очевиднее и ещё с автоматической валиадацией.

хотя поварившись в какойнить джаве очень сложно пиасть код "по питонячи"…

Но python-код написанный джавистами действительно выглядит... странно.

Только в документации.

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

отсутствие строгой типизации в питоне

В питоне строгая типизация и без хинтов и всегда таой была. Нестрогая - в JS.

а чё сразу на нормальном языке с типизацией не писать было?

Ну блин, статическая/динамическая типизации — далеко не единственный критерий выбора языка.

UFO just landed and posted this here

Чтобы писать правильно: "в нетипизированных".

Желаю Вам никогда не сталкиваться с багами "cannot read prop of undefined", вернувшегося из трёхкратных замыканий типа any.

UPD: кажется, я не распознал сарказм. В этих ваших интернетах не поймёшь...

Очень помогает в поиски ошибок прям на лету без JIT, например в PHP array_search возвращает строку (значение) если значение найдено, и false если нет, поэтому если аргумент будет жестко string, то мы получим ошибку если значение не найдено, ибо а почему пришло false, может быть это следствие какой-то серьезной ошибки на сервере, который выдает ответ (а может и нет, в любом случае нужно разбираться), страшно даже представить что он пойдет дальше со значением false, а там и еще что-то ждет строку, а проверок-то у нас нет. С SQL то же самое, сколько было когда она ругалась когда кто-то пытался сунуть число вместо строки (ибо а почему он ждет строку, а приходит число), а не как раньше по недосмотру записывалось что не нужно. Поэтому после Java я понял что динамическая типизация порождает только говнокод и неотлавливаемые ошибки, которые в будущем могут проявиться так, что даже представить страшно, особенно когда на проде.

например в PHP array_search возвращает строку (значение) если значение найдено, и false если нет

О боже мой. Я, конечно, слыхал в инторнетах, что PHP супер кривой, но вот чтоб прям так. Как до такого вообще можно было додуматься? oO

Да норм решение так-то. В более других языках тех же лет выпуска в данной ситуации возвращается -1. Которое, мать его, является валидным индексом для substr и прочих операций со строками (означает "последний символ"). И вот это НАМНОГО хуже.

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

  • Стиль Си: в подобных случаях функция возвращает "0, NULL или -1" (это дословная цитата). А потом сервера не просто дидосят, а отправляют в состояние клинической смерти, выйти из которой помогает только Ctrl+Alt+Reset. Потому что fork при нехватке ресурсов возвращает -1 вместо pid, а парная ей kill понимает pid = -1 как "убить вообще все процессы, к которым есть доступ". Для рута это вообще все процессы в ОС кроме init, а базовый процесс сетевых демонов и всяких там служб как правило под рутом и запущен.

  • Вместо 0 и -1 ввести какие-то спецзначения в области NaN-ов (т.е. очень большие числа порядка INT_MAX). Это реализовали аппаратно в FPU, а вот в языки почему-то почти не завезли. Слышал, вроде js в старой опере так работал. Внутри PHP по факту сделано именно это, TRUE и FALSE это объекты - статические константы. Просто нужно было ввести дополнительные общеязыковые константы типа EMPTY или NOTFOUND.

  • Ввести тип-сумму result<T>. Но это в любом случае уже очень медленно аппаратно по сравнению с возвратом обычного инта в аккумуляторе, плюс нужно ломать сишное соглашение о вызовах.

  • Ввести свой тип int с блэкджеком и отсутствием переполнения, как в python. Оч. круто, но оч. медленно.

UFO just landed and posted this here

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

UFO just landed and posted this here

Да норм решение так-то. В более других языках тех же лет выпуска в данной ситуации возвращается -1. Которое, мать его, является валидным индексом для substr и прочих операций со строками (означает "последний символ"). И вот это НАМНОГО хуже.

Ну тут сами себе на хвост наступили...

Сначала в С сделали индексацию массивов с 0 (логически объяснив это тем, что индекс есть смещение от начала массива - ок, в целом нормально). Потом сделали -1 как "не валидный индекс массива". Потом кому-то пришло в голову сделать в каких-то местах -1 как "последний элемент". Ну и приплыли ваши чемоданы...

В том языке с которым в основном работаю сейчас, массивы индексируются с 1 (да, это вызывает некоторый дискомфорт когда работаешь то с С, то в другим языком, но привыкаемо). А "не нашли" (функции типа %lookup, %check...) обозначается как 0.

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

Как вариант - выкидывается системное исключение которое может быть перехвачено и обработано.

По крайней мере тут намного меньше ситуаций и потенциальными UB.

выкидывается системное исключение которое может быть перехвачено и обработано.

Ага, а ещё можно вызывать abort() . Ваши пользователи же не знают, где вы живёте, ведь правда?

Библиотечные функции в общем случае не знают тяжесть ошибки с точки зрения вызывающего кода, и вообще ошибка ли это. Ну со strpos / indexOf понятно, но вот например системная ошибка чтения ( io read error ). Где-то это прям паника , диск посыпался и всё такое. Тот же самый код, с теми же самыми системными вызовами, но для сети - это норма жизни и всего-лишь повод сделать if. А в каких-то случаях эта ошибка может вообще быть ожидаемым "успешным" поведением (сброс кэшей после удаления / снятия прав / etc). Кидаться исключениями на каждый чих - ну, такое.

Библиотечные функции в общем случае не знают тяжесть ошибки с точки зрения вызывающего кода, и вообще ошибка ли это.

На нашей платформе системное исключение - это ошибка с некоторым кодом.

например, перехватили ошибку MCH1202 - в соответвующем файле сообщений всегда можем посмотреть

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

Другой пример. Пишем на С API для работы с пользовательской очередью ( *USRQ). Чтение сообщений с таймаутом там идет через MI (машинная инструкция) DEQWAIT которая выкидывает исключение если таймаут истек, но в очереди ничего не появилось.

Пишем

  #pragma exception_handler(UsrQExeptHandler, 0, _C1_ALL, _C2_ALL, _CTLA_HANDLE_NO_MSG)        
    _DEQWAIT(pMessage, (_SPCPTR)pBuffer, &(pQueItem->spQueue));
  #pragma disable_handler

и простейший обработчик, который фиксирует ошибку

static void UsrQExeptHandler(_INTRPT_Hndlr_Parms_T* __ptr128 pexcp_data)
{
  // Запомним ошибку
  memset(usrqExeptionId, 0, 8);
  memcpy(usrqExeptionId, pexcp_data->Msg_Id, 7);
  wasError = true;
}

А дальше смотрим - если выставился флаг ошибки ее код MCH5801

То все нормально - просто таймаут истек, а читать нечего (очередь пустая).

Т.е. это не ошибка, идем дальше. Если код иной - там уже смотреть что случилось.

UFO just landed and posted this here

У вас моноидальная структура индексов отвалилась, а это неприятно.

Я бы скала что это непривычно после С, но ничего непряитного тут нет.

При этом интервал [1..n] - валидные индексы, 0 - не нашли, -1 - ошибка.

Если у вас есть два смещения ij от начала массива, индексируемого с нуля, то для того, чтобы получить суммарное смещение, достаточно просто написать i + j. Если у вас массив индексируется с единицы, то i + j уже не работает, надо не забыть вычесть единичку.

Опять же, дело привычки...

Какие свежие, современные и приятные подходы!

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

Способ, аналогичный исключениям тут тоже есть, причем, не языковый, а системный - отправка прерывающего значения в *PGMQ (очередь сообщений программы). И это более универсально. Просто потому что программа на RPG вызвала программу на С++, та выкинула языковое исключение, которое, если его не перехватить внутри программы С++, там и останется. А вот прерывающее сообщение уйдет выше по стеку и может быть перехвачено и обработано в вызывающей программе.

UFO just landed and posted this here

Ошибка чего?

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

Суть в том, что мы рассматриваем случай поиска чего-то где-то. Который имеет три возможных сценария:

  • Нашли что искали

  • Не нашли что искали потому что его там нет

  • Не нашли потому что в процессе поиска "что-то пошло не так".

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

  • Не нашли потому что нет или потому что что-то помешало (ошибка)

  • Если ошибка, то что за ошибка.

Или надо вводить сразу код возврата (что тоже хороший вариант) - >= 0 - индекс найденного, < 0 - код ошибки (при этом -1 - отсутствие искомого в области поиска, < -1 - какая-то ошибка, помешавшая поиску т.е. результат "если или нет" не определен).

В случае когда индексация начинается с 1 (в мире достаточно много языков где это так), > 0 - нашли, =0 - не нашли (эти два случая дают нам строго определенный результат есть/нет) и <0 - результат не определен т.к. что-то помешало (и только в этом случае уже требуется уточнение что именно).

Я топлю совсем не за исключения. Монадическая обработка ошибок — наше всё.

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

  • Это внутризязыковая конструкция и работает только внутри языка

  • Требует дополнительных ресурсов

  • Зачастую замедляет процесс (особенно если ими пользоваться бездумно, раскидывай их направо и налево просто как способ выхода из объекта с каким-то результатом - такое доже встречал.

Возврат кода ошибки намного "легче". Но вот когда стогкнылся с платформой IBM i, увидел что там используется "структурированная ошибка". В общем случае это структура содержащая 7-значный код ошибки + ее данные. Полная текстовая расшифровка содержится в т.н. "message file" - нечто типа таблицы с кодами:

В этот файл можно добавлять свои сообщения, указывая код, серьезность и текстовую расшифровку. При этом &1, &2, &3 - параметры сообщения которые подставляются из данных.

Т.е. мы возвращаем структуру где содержится код + то, что будет подставлено в параметры. А дальше уже есть системные API, которые позволяют с этим сообщением делать что угодно - получить полный текст с подставленными параметрами, записать ошибку в очередь сообщений или joblog, вывести ее блокирующим сообщением (ожидающим ответа оператора) и получить ответ что делать дальше, вывести в очередь программы как блокирующее сообщение (тут есть полный аналог try/trow/catch, но на уровне системы в целом)...

Ну или просто посмотреть код ошибки и решить что с ней делать дальше...

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

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

Ну например - пишем программу на С где тупо делим на 0 не одумляясь последствиями. Потом вызываем ее из другой программы, на совсем другом языке. Если сделать это просто так - все упадет. Если сделать вызов с подавлением и перехватом исключения, то падения не будет - мы просто увидим что возникло исключение и сможет его обработать выше по стеку. Этакий try/catch, но на системном уровне.

Выглядит примерно так:

        monitor;
          Pgm(Parm1: Parm2: Error);
        on-error;
          Error = 'KSM2053Pgm';
        endmon;

Error - та самая структурированная ошибка.

Pgm - некая вызываемая программа. Которая может выполнится нормально. Или завершиться нормально, но заполнить структуру Error какой-то своей внутренней ошибкой. Или просто упасть с треском. И в последнем случае влетаем в блок on-error и в простейшем случае просто заполняем структуру Error ошибкой с кодом KSM2053 и именем упавшей программы в качестве параметра

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

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

И все это на уровне системы, а не какого-то одного языка.

И ошибки можем формировать сами какие нам надо.

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

Просто замечу, что вот здесь:

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

Это внутризязыковая конструкция и работает только внутри языка

... вы немного отстали от времени.

В частности, в винде, начиная с вин95, механизм исключений стандартизован на уровне ОС, в т.ч. туда же завёрнуты аппаратные исключения. Т.е., например, аппаратное исключение целочисленного деления на 0 нормальный компилятор С++ превратит в исключение С++ и наоборот, исключения написанных на С++ библиотеках можно перехватывать в каком-нибудь PHP или Java.

В линуксе и родственных ему по ABI ОС, в частности *BSD и MacOS, всё устроено намного, простите, черезжопнее, однако ж таки да, технически виртуальная машина Java может ловить как аппаратные исключения типа деления на ноль, так и - в теории - программные от библиотек на С++.

В частности, в винде, начиная с вин95, механизм исключений стандартизован на уровне ОС, в т.ч. туда же завёрнуты аппаратные исключения.

Я знаю что это работает. Все-таки на С/С++ с 91-го года (начинал еще с Turbo C 1.0, застал Tubo C++ и т.п.). Под винду писал начиная с 3.11 и потом 98, 2000, 7...
Вопрос в том - как это реализовано внутри. У нас я тоже могу в начале программы повесить exeption handler и внутри него генерировать плюсовые исключения.

И такие эксперименты у нас были. Но отказались т.к. это очень неэффективно. Работает, но медленно и ресурсы процессора (для нас это очень актуально) отъедает ощутимо.

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

Хотя можно делать и наоборот - закидывать пользовательскую структурированную ошибку при помощи системного API как *ESCAPE сообщение в программную очередь сообщений и ловить ее при помощи monitor - on-error выше по стеку. Будет полный аналог try - catch.

Но вообще большая часть системных API с высокой степенью интеграции возвращают именно структурированную ошибку вот в таком вот формате:

 typedef struct Qus_EC
    {
       int  Bytes_Provided;
       int  Bytes_Available;
       char Exception_Id[7];
       char Reserved;
     /*char Exception_Data[];*/           /* Varying length        */
    } Qus_EC_t;

Т.е. минимум - это код ошибки, но по желанию можете еще и под данные место зарезервировать (и указать это в Bytes_Provided) и тогда оно заполнит еще и данные (те самые параметры для подстановки в текстовую расшифровку).

Да норм решение так-то

Да не очень то норм. Ищем, скажем, объект типа User в массиве, а получаем false. Вот вам пример нормального api find на Scala. find ищет в листе и возвращает тип Option[T], который может быть Some[T] если что то нашли или None если ничего не нашли.

    val list = 1 :: 2 :: 3 :: 4 :: 5 :: Nil
    val result: Option[Int] = list.find(_ > 0)
    result.map { v =>
      // do something
    }
    result.flatMap { v =>
      // do something
    }
    result match {
      case Some(v) =>
      // do something
      case None =>
      // do something
    }

пример нормального api find на Scala

Да тоже не очень, если find может возвращать ошибки кроме "не найдено".

И ещё пара моментов, я просто не знаю Scala.

1. Гарантирует ли компилятор корректную распаковку Option? Т.е. что будет, если в вашем примере забыть написать ветку match, которая case None?

2.Что будет в случае Option[unsigned]? Т.е. сколько бит занимает Option в памяти или регистрах?

Про Option: Да, если не обработать одну из веток в закрытой иерархии - получишь по рукам.

Если может быть что-то кроме "не найдено" можно взять Either[Result, Error] тогда можно разные типы ошибок возвращать, и если они будут из закрытой иерархии то компилятор проконтролирует чтобы все типы ошибок были обработаны.

Про оверхед - он минимальный так проверки типов, если правильно делать, проходят на этапе компиляции и не остаются в рантайм (упрощено говоря)

Гарантирует ли компилятор корректную распаковку Option? Т.е. что будет, если в вашем примере забыть написать ветку match, которая case None?

Да, причем не только для именно Option, но и для любой закрытой иерархии как вам здесь уже написали. More abt pattern matching

Что будет в случае Option[unsigned]

Не совсем понял. Option[T] это дженерик, ему все равно что внутри.

Т.е. сколько бит занимает Option в памяти или регистрах

Думаю как и класс в Java. 12 байт на object header + 4 байта на reference + выравнивание на 8 байт по дефолту. Но тут все сильно зависит от jvm и параметров для нее.

Т.е. для 32-битного беззнакового целого option[unsigned] займёт 24 байта. Ясно, спасибо.

Мне один товарищ из бека на php присылал JSON следующего вида, если массив пустой был:

{
  "property": "[]"
}

И следующего, если там что-то лежало:

{
  "property":
  {
    1: "first element",
    2: "second element"
  }
}

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

По вашей же ссылке, кавычек вокруг квадратных скобок нет:

Empty property

The JSON empty concept applies for arrays and objects as shown below.

41	{
42	    "address":{}
43	     "homeAddresses":[]
44	      "phoneNumbers":[]
45	}

Ну и непустые массивы обычно выглядят как в примере ниже, а не как в моем предыдущем комментарии

{
  "property": [
    "first element",
    "second element"
  ]
}

Подумалось что Вы в принципе ожидали false/null что-то такое.
А так да, Вы правы, вдвойне странно учитывая что в php еще с 5 версии есть функция конверта в json ведущая себя адекватно.
Непустой ассоциативный имеет право иметь ключи, но тут тоже странно - они должны быть как "1":"first"

  1. Между { "property": "[]" } и { "property": [] }
    различие в том, что в первом случае -- это строка со скобками, а во втором (по вашей же ссылке) -- пустой массив

  2. Пример выше с объектом так же очень кривой, если это массив строк, должно быть просто { "property": ["first element", "second element" ] }

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

Чтобы было проще ревьювить. А, погодите, ревью уже отменили, отбой.

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

Преимущество нетипизированых ЯП не в том, что можно не писать типы, а в том, что можно самому решать, когда они нужны, а когда нет.

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

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

Стат. анализ - ну да, ну да, пошёл как я...

Весь мир насилья мы разрушим       
До основанья , а затем             
Мы наш мы новый мир построим,      
Кто был ничем тот станет всем!

Я бы так сказал - не надо к "правилам" относиться как к догме и возводить их в абсолют.

Многие из них есть просто результат внутренней договоренности (тот же codestyle).

Нормализация БД хорошо, но порой от нее приходится отступать ради повышения быстродействия.

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

И так далее и тому подобное.

Весь мир насилья мы разрушим 
До основанья , а затем
=== вы находитесь здесь ===
Мы наш мы новый мир построим,
Кто был ничем тот станет всем!

Нормализация БД хорошо, но порой от нее приходится отступать ради повышения быстродействия.

Либо менять СУБД на ту, что не требует выбирать между нормализацией и быстродействием.

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

И эта структура называется "поисковой индекс". Денормализация хранения для этого не нужна.

Нет, она не называется так. Конечно подразумевается, что индексы правильные в обоих случаях.

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

Лучше представьте субд, где нет ни таблиц, ни join.

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

А денормализация запись не замедляет, да?

Скорее нет, чем да. Но тут, конечно, надо каждый конкретный случай рассматривать.

Нормализация - это вообще редко про скорость.

Иногда лучше пару десятков лишних миллисекунд при записи и выиграть десятки минут при чтении. Зависит от профиля нагрузки.

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

Дайте угадаю, на сцену выходит $$$mol_query?

В каких случаях смена СУБД может помочь не выбирать между нормализацией и быстродействием?

Дело не в СУБД. Она достаточно мощная и достаточно быстрая. Дело в объемах обрабатываемых данных и требованиями к скорости обработки.

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

И часто речь не идет о задачах, которые можно решить одним запросом. Например, писк совпадений по нескольким параметрам в двух БД - одна ~50млн записей, вторая ~300-500тыс записей. Тут уже без распаралллеливания не обойтись. Головное задание делает отбор по одной БД и выкладывает отобранное на конвейер. Откуда данные разбираются 10-ю обработчиками и каждый из них ищет что по какому параметру где совпало (там важна классивкация совпадений - тут совпадение по параметрам 1 и 3, там по параметрам 2 и 5, здесь по параметру 4 и т.п.). Причем, совпадение может быть не прямым - две строки по 250 символов. Но одна на кириллице, вторая на латинице в транслитерации... Или паспорта - 66 09 345876, 6609 345876 и 6609345876 - это одно и то же. Или даты рождения - 12.08.1970, 12 авг 1970, 12-08-1970, 12081970... Т.е. просто сравнить А=Б нельзя, требуется предварительная "нормализация".

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

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

Нет... Десятки тысяч таблиц - от обилия бизнесовых сущностей.

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

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

Куча настроечных таблиц всяких для разных систем... Куча "витрин" - какие-то срезы по актуальным данным чтобы не собирать это все когда надо...

У нас сейчас по очень грубым оценкам

27 тыс. программных объектов
15 тыс. таблиц и индексов базы данных
Более 150 программных комплексов
Занимает более 30 Терабайт дискового пространства
В день изменяется более 1,5 Терабайт информации в БД
За день выполняется более 100 млн. бизнес операций
Одновременно обслуживается более 10 тыс. процессов

Только в процедуре закрытия опердня производится более 500 миллионов изменений в БД, при этом eё длительность составляет около 4 часов.

И не уверен что это актуальные данные. На текущий момент может быть еще больше.

И это только то, что работает на центральных серверах в рамках АБС (т.н. "Централизированные банковские системы", они же "мастер-системы"). А есть еще порядка 60-ти внешних систем - там свои сервера, свои данные.

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

Вы уверены что там реально 14к таблиц связей? Откуда вы это взяли?

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

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

А еще есть риски клиентов (репутационные, страновые...)

А еще у клиента могут быть субъекты (доверенные лица, бенефициары и т.п.).

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

И, кстати, таблиц только для связей один-ко-многим тут практически нет (я вот вообще не знаю). Скажем, основная таблица клиентов. Основной ключ там - ПИН клиента. + еще паровоз всякой информации. Но у клиента еще есть адреса (из порядка 6-ти, если память не изменяет, типов). Это таблица (точнее, две - адрес неструктурированный и адрес структурированный) где опять же ПИН, тип адреса, адрес.

Дальше ДУЛы (документы удостоверяющие личность). Тоже много типов и несколько записей на клиента. И опять - ПИН + тип ДУЛ + данные.

Если брать то, что относится к комплаенсу - там "субъекты списков росфина" (террористы, экстремисты и т.п.). А там уже персонажи

Она же Анна Федоренко… Она же Элла Кацнельбоген… Она же Людмила Огуренкова… Она же… Она же Изольда Меньшова... Она же Валентина Понеяд.

Т.е. у каждого субъекта несколько имен, адресов, ИНН, ДУЛов... И все это по нескольким таблицам разложено - таблица субъектов, таблица адресов, таблица ДУЛ... Плюс еще надо хранить историчность - в рамках какой версии списка когда данный субъект последний раз изменялся. Т.е. еще таблица заголовков списков (когда какой загружался)...

Когда делал эту самую БД - там 25 таблиц (включая архивы и журналы) и порядка 80-ти индексов.

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

А еще всякие рабочие таблицы, логи работы различных комплексов, настроечные таблицы...

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

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

Норм нативная реклама телеграм канала на 5к символов.
А по контенту: согласен, но банально. Всю статью можно выразить одним предложением: "не используйте технологии/процессы бездумно, а спрашивайте себя и команду зачем и почему"

В этом парадокс: мысль банальна, но догмы есть в каждой первой команде

"не используйте технологии/процессы бездумно, а спрашивайте себя и команду зачем и почему"

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

А дальше работает - не трогай. Первая заповедь связиста

В программировании нет вообще никаких непреложных истин.

Вышесказанное - непреложная истина или как?

Ахаха
Врет ли человек, который говорит, что он врёт?

Каждое категоричное утверждение - ложно, включая и это.

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

Ну, рисковать (добавлять категоричность) всё же придётся, а то останемся у "всё может быть так, или иначе, но это не точно, потому что оно это всё может вообще быть или не быть. Ничего не было ясно, не ясно сейчас, и никога не будет ясным!" :))))

UFO just landed and posted this here

Вы не прошли через линтер тов Тарского: использование метаязыка первого уровня (для описания мира) в качестве метаязыка второго уровня (описание языков первого) . Вот вам таск - закройте до вечера.

А так как язык и мета язык являются частью мира, то достаточно и одного достаточно мощного для описания мира языка.

UFO just landed and posted this here

код-ревью, который прям вредит time-to-market это нездоровый код ревью.

сколько он у вас занимает, что это прям становится проблемой?
и что, бизнес страдает прям от этого лага?

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

UFO just landed and posted this here

не путайте time-to-market с time-to-garbage

UFO just landed and posted this here

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

не поможет, как сотрудник галеры я плачу от такого, но всеравно так делаю, а все очень просто


Мне прилетает задача, я ставлю на неё время, учитывающее это вот всё по правилам… а через неделю приходит разъяренный РП от заказчика с криками что он платит за реализацию ф-ции, а не рефакторинг и что мы (галера) охренели что простые задачи типа поменять текст в виджете ставим срок по 20 часов (а там архитектурно никак не сделать иначе) ведь явно явно для того чтобы бабла побольше содрать… потом начинают часы резать насильно и выкидывать из оплат такие доработки
в итоге приходится делать так как получается чтобы не бил заказчик и собственное руководство


Это кошмарно, но есть причины почему такую работу приходится делать и в таких местах работать

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

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

Так и речь не про то, чтобы в галерах это использовать. Речь о том, когда галерщик приходит в нормальную компанию работать с этим всем "багажом" в голове

Cоветую хотя бы иногда пересматривать вообще всё.

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

Это как запах кода, только для правил и процессов разработки.

Это называется "критическое мышление".

Ладно правила линтера на размер функции, один очень деятельный человек на моей памяти протолкнул ограничение на количество return в функции, тогда-то и началась веселуха.

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

По-моему, это правильно: в начале метода проверить краевые условия и корректность входных данных и сделать return (или бросить исключение) если что-то не так. А потом писать основную логику. Это лучше чем оборачивать её в дополнительный if. Как правило, основная логика на экран не помещается и мотать её туда-сюда замучаешься при отладке/улучшайзинге. Поэтому хочется разбить метод на более мелкие "блочки" кода.

Но 15 return это перебор, согласен :)

внутри третьего вложенного цикла

Это (вложенные циклы) уже само по себе не очень читаемо :) Иногда помогает переход на более декларативный стиль с лямбдами и Stream API.

Целая MISRA C (индустриальный стандарт для разработки прошивок в автопроме) запрещает больше одного return.

В C без этого неверное тяжело в контексте очистки ресурсов. В идиоматичном C++/python/Java/C# это скорее всего не нужно - там есть деструкторы/context managers/using/...

А в чем проблема ;)
ret= ....
goto exit;
exit:
return ret ;

и все дела

Ну тут уже от языка зависит.

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

В том, с которым работаю я, есть во-первых, subroutines - подпрограммы в рамках процедуры (как в древнем бейсике было - gosub). Без нового уровня стека, без собственных локальных переменных, без своих параметров. Но хорошее средство для структурирования кода. И точку выхода можно организовать через такую вот сабрутину:

где надо ставим

exsr srExit;

и пишем

begsr srExit;
  // делаем что нам надо на выходе
  return;
endsr;

А еще есть блок on-exit куда попадаем после выполнения return (и можем заменить возвращаемый результат если нужно). Тут return уже не так страшен т.к. у нас есть одна контролируемая точка выхода.

Но это все языковая специфика.

Иногда одна точка выхода из функции может усложнять ее логику, но по моему мнению влияет скорее положительно. Те же PMD и Checkstyle для Java включают соответствующие правила.

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

Однако, на мой взгляд, эти проблемы перевешиваются такими плюсами как:

  1. Удобство отладки. Можно гарантировано поставить точку останова на единственный return и ждать.

  2. Упрощение потока управления и затрат на понимание кода: чтобы понять, что будет возвращено функцией не требуется анализировать весь код, в котором return могут вызываться в произвольных местах: внутри условий, циклов, условий в циклах и т.д.

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

Это реальность? Не передергивание? Многие линтеры настолько не доросли до возможности задавать исключения, что вынуждают творить дичь?

UFO just landed and posted this here

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

UFO just landed and posted this here

Эти 80% - новостные порталы, бложики, форумы, интернет-магазы и лэндинги. Там хайлоадом не пахнет и их всё-равно на чём писать.

UFO just landed and posted this here

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

...эээ Фейсбук (ладно, уже не совсем на php). Как будто хайлоад когда-то был про язык.

Может автор что-то свое под хайлоадом понимает? Если приложение не скейлится, то хайлоад не вывезет, на чем его ни пиши. А если на пыхе и норм скейлится, то почему бы и не хайлоад.

UFO just landed and posted this here

<ловите-пхпшника-мем.жпг>

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

Насчет линтеров и ограничений на количество строк, то мне кажется это имеет смысл.
Когда читал Мартина с его Чистым кодом меня прямо до глубины поразил пример переписанный с принципом максимального сокращения размеров функции. Получилось прямо что ты ЧИТАЕШЬ код как обычный текст, а не как в фильме Матрица среди зеленых цифр видишь блондинку в красном. Так что вынести в отдельную функцию с названием даже обычное использование stream api в яве мне кажется хорошей идеей. Это проще читать. Если из функции можно выделить отдельную функцию - то обычно лучше сделать.

Есть противоположный взгляд на труды Мартина. https://qntm.org/clean

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

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

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

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

UFO just landed and posted this here

Даже если и умеют, то делают далеко не всегда. И это поведение может меняться между версиями компилятора.

ТЛДР: для любого инструмента своя сфера применения, а возводить всё в абсолют глупо.

Зачастую это просто ошибочные выводы, перепутаны причина и следствие. В хорошем продукте был Code Review? Значит Code Review обязателен для хорошего продукта. А правда состоит в том, что инструменты и подходы в хороших продуктах выбираются понимающими людьми, и именно они создают хороший продукт, а не инструмент. Когда методологии спускаются "сверху" ⬆ "вниз" проект манагерами и т.п. то получается такое описанное буквоедство. И не стоит забывать, что основная цель этих подходов не помогать разработке, а сделать роль разработчика "несущественной". Чтобы можно было менять команды как перчатки, без ущерба для скорости и качества. И кстати эта цель весьма достижима, ведь при тупом следовании концепции можно достичь результата, что все команды будут вносить изменения одинаково медленно и некачественно.

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

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

это важно кстати использовать типовые и стандартные вещи
потому что когда приходишь в контору, а там 90% инструментов или самописные или из какихто мудреных проектов которые гений сеньор который 5 лет назад тут работал притащил… хочется взяться за голову и убежать


помню был проект, там половина ci/cd была написана на инструментах из гитхаба от какихто странных челов типа Vasya1995ef111111 c 5 звездами и 40 коммитами 2х летней давности — причем это форк какогото известного инструмента который уже настолько вперед ушел что вернуться нереально
и ты вместо того чтобы работу работать изучаешь костыли и мигрируешь задеприкейченные тулзы которые ктото сюда припер вместо общепринятых подходов...

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

GIT тоже самописная система. Просто не все самописные инфраструктуры хорошие :)

обычно люди работают на работе чтобы какойто продукт делать, а не эксперименты ставить в стиле "а давайте мы этот проект на object pascal напишем, я слышал что в какомто институте он популярен, значит люди опомнятся и вернуться к нему" (с)

Чем это отличается от "а давайте этот проект на X напишем, я слышал, что в Гугле он очень популярен"? А ведь сейчас решения именно так и принимаются.

А ведь сейчас решения именно так и принимаются

решения надо принимать по принципу
"сколько разрабов у нас знают язык X? готовы мы еще набирать людей на язык X? как быстро мы найдем людей если все уволятся, на язык X"
А не по принципу "в Гугле популярно"


Я уже даже Ruby немного выучил, поскольку у меня было несколько задач по переписыванию микросервисов с руби на питон, из-за того что в команде из 10 разработчиков, был один рубист и он все сподвиг в начале 10х годов перехдить на руби… а потом гдето в районе 15 годов уволился… и в 18 году питонисты отчаялись искать миддла на руби ради одного сервиса и решили тупо мигрировать на типовой для компании стек и не плодить больше таких экспериментов


сейчас вот у меня есть задача на C#… потому что ктото сделал сервис на нем, а из всей комманды разработки в 20 человек, шарп только я когдато трогал и на яве писал, все остальные чистые питонисты...

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

UFO just landed and posted this here

решения надо принимать по принципу

Эх... Какой смысл писать о том, как надо принимать решения? Из моей практики:

Нанимают CTO/нового менеджера и он говорит: будем использовать Domo, snowflake и Go. Притом, что весь проект написан на перле и работает уже 10 лет. Ах да, про микросервисы же забыл. И кому вы тут будете рассказывать, как надо принимать решения? Этому CTO/новому менеджеру? Так он во первых, никого не спрашивал. А во вторых, на первой же встрече публично сказал всем: мы будем уважать желание любого из вас покинуть нашу компанию.

Нанимают CTO/нового менеджера и он говорит: будем использовать Domo, snowflake и Go. Притом, что весь проект написан на перле и работает уже 10 лет.

а в данном случае означает что в этой компании ваше мнение не учитывается, но возникает вопрос, как вас программиста на перле заставляют переписывать проект на Go? вам доплатят? вам снизят грейд с сеньора-перла на джуна-го?


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


все эти звоночки плюс отсутствие участия в выборе инструментов отдела разработки означает то что вам пора менять работу

Очень правильный mindset ибо best practices иногда оказываются порочными.

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

поэтому и придумали Single responsibility principle

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

Бъешь по голове *тут должна быть ссылка на коан про то, что объекты это процедуры, но я не нашёл его*

Как-то однажды знаменитый учитель Кх Ан вышел на прогулку с учеником Антоном. Надеясь разговорить учителя, Антон спросил: "Учитель, слыхал я, что объекты — очень хорошая штука — правда ли это?" Кх Ан посмотрел на ученика с жалостью в глазах и ответил: "Глупый ученик! Объекты — всего лишь замыкания для бедных."

Пристыженный Антон простился с учителем и вернулся в свою комнату, горя желанием как можно скорее изучить замыкания. Он внимательно прочитал все статьи из серии "Lambda: The Ultimate", и родственные им статьи, и написал небольшой интерпретатор Scheme с объектно-ориентированной системой, основанной на замыканиях. Он многому научился, и с нетерпением ждал случая сообщить учителю о своих успехах.

Во время следующей прогулки с Кх Аном, Антон, пытаясь произвести хорошее впечатление, сказал: "Учитель, я прилежно изучил этот вопрос, и понимаю теперь, что объекты — воистину замыкания для бедных." Кх Ан в ответ ударил Антона палкой и воскликнул: "Когда же ты чему-то научишься? Замыкания — это объекты для бедных!" В эту секунду Антон обрел просветление.

Про код-ревью вас зацепило

Да, зацепило. Потому что time-to-market хоть и в минусе, но в общем и целом бизнес в плюсе почти всегда (почти - потому что испортить можно все и всегда).
1. Код-ревью как средство обучения сотрудников - когда бородатый сеньор объясняет джуну в чем он не прав, что качает одному софты, а второму харды;
2. Код-ревью как шаринг знаний по проекту - когда ты в один прекрасный момент получаешь задачку в той части кода, в которую лез один раз тысячу лет назад, но зато смотрел ревью коллеги, который там работает, и у тебя уже есть знания, иначе ты можешь порушить устойчивые костыли или просто надолго там задуматься;
3. Код-ревью как валидация ошибок - опять же, если у одного человека есть bus-фактор, то он как кодовнер может отвалидировать и исправить ошибки еще до влития куда-либо, их потом не нужно искать!
4. Код-ревью как "о офигеть, я не знал что так можно" - я вот не знал, что в JS стало можно обращаться к testString[0], вместо testString.charAt(0) , и пусть конкретно это - минорное и незначительное знание, но если это будет касаться чего-то крупнее? Человек с любым опытом может не знать/забыть какие-то вещи.

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

Пожалуйста приложите ссылку на эту статью к вашему CV, чтобы нанимающие вас люди не тратили на собеседование свои ресурсы.

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

Сказанному здесь есть математическая основа: https://habr.com/ru/articles/656773/

varanio говорит о том, что ничто не должно быть возведено в абсолют, т.е. золотая середина, гармония (смотрим формулу).

Отличная статья!

Ну это же три стадии профессионализма:

  1. Делать по правилам

  2. Придумывать правила

  3. Нарушать правила

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

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

А неофит может дойти до третьего этапа, главное не оставаться на первом вечно.

заповеди, правила

Если DRY, KISS и иже с ними доведено именно до непреложных правил и заповедей, то тут явно что-то не так. Если все еще и утрируется, как в примерах, то это уже надо звать людей в белых халатах. Можно же и SRP интерпретировать как необходимость создавать отдельное DTO для каждой операции над основным объектом...

Если это опытный программист, и в большинстве случаев поступает разумно, то может и не надо его ограничивать всякой фигнёй — это уменьшение эффективности, да еще и снижение мотивации

Ядро проекта пишем на Java, добавляем кусок на Python, пара кусков на Go, еще один прям микро-микросервис на PHP, обработку данных делаем на С++ и немного макросов в Excel.... Зато все очень эффективно и замотивировано было сделано. А потом разработчик, который был ответственен за вот эти все языковые "причуды", увольняется и вам приходится искать такого "многофункционального", эффективного и замотивированного разработчика на проект с непонятным стеком. Нормальная идея, да.

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

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

Ядро проекта пишем на Java, добавляем кусок на Python, пара кусков на Go, еще один прям микро-микросервис на PHP, обработку данных делаем на С++ и немного макросов в Excel.... Зато все очень эффективно и замотивировано было сделано.

Ну не надо в крайности.

У нас основная бизнес-логика пишется на RPG Но есть достаточное количество низкоуровневых вещей, которые удобнее и эффективнее писать на С/С++ (более того, платформа позволяет вообще линковать модули на разных языках в один программный объект). А в RPG код еще можно вставлять SQL выражения - выборка скулем, обработка на RPG, например.

А еще есть CL - командный язык системы (тоже компилируемый) - на нем тоже иногда всякие небольшие программки пишутся, те же инсталляторы поставок.

Естественно, что разработчиков так и готовят - RPG основной язык, CL должен знать основы, С/С++ - бонусом.

И вот как-то нет проблем, знаете-ли...

И вот как-то нет проблем, знаете-ли...

Допустим я устроился к вам на работу и решил начать писать на Java. Мне это разрешат или нет?

У вас это просто не получится :-) Тут нет джавы на центральных серверах.

Потому что жрет много ресурсов и все равно работает медленнее того же RPG или C/С++.

Ну и те задачи, которые нам приходится решать на джаве просто не напишете - ни взаимодействия с БД там не будет (то, что на RPG пишется), ни низкоуровнего взаимодействия с системными сервисами (теми же "машинными инструкциями").

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

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

У вас это просто не получится :-) Тут нет джавы на центральных серверах.

То есть меня ограничат? Это однозначно уменьшит мою эффективность и снизит мотивацию… :)

А вам на берегу обозначат стек с которым аридется работать. Не нравится - за шиворот никто тянуть не будет. Просто найдете себе другое место.

Тут речь идет о том, на чем получается наиболее эффективно, а не о том, на чем кому-то нравится писать.

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

Ну так там же вот выше написано что не надо всякой фигнёй ограничивать :)

Тут нет джавы на центральных серверах.

Потому что жрет много ресурсов и все равно работает медленнее того же RPG или C/С++.

Честно говоря, это звучит максимально странно. Нет, конечно, жава (плюс жава-машина) потребляет память. И конечно какая-нить математика на жава будет работать медленнее чем на Ц++. Но ведь обычно программа не работает, а ждёт :) пока отработает какой-нибудь ввод/вывод.

Поэтому жава давно умеет в параллельность/асинхроннось (правда, это приводит к ещё большему жору памяти). Это позволяет компенсировать "медленный" язык более плотной "упаковкой" потоков исполнения.

Ведь всякая Кафка/Кассандра/далее-везде написаны на жава и никто особо не страдает что они медленные.

Другое дело что спец-язык является предметно-ориентированным и его компилятор сразу знает какие места надо максимально оптимизировать. И набор выразительных средств тоже заточен под предмет, поэтому краток и ёмок. Не то что в ц++: куча крутых команд борются за включение в стандарт "своих" фишек, поэтому в стандарте есть всё! И даже жаву вон прогнули на var, непонятно зачем :)

Но ведь обычно программа не работает, а ждёт :) пока отработает какой-нибудь ввод/вывод.

Здесь это не так. Весь основной код, реализующий бизнес-логику, работает в фоновых заданиях. Он не ждет ничего (ну некоторые классы задач ждут события какого-то). Он должен максимально быстро и с минимальными затратами ресурсов процессора (в периоды пиковых нагрузок утилизация процессора может достигать 90%, а это, на минуточку, Power9 - 4 сборки по 4 проца, каждый 12 SMT8 ядер - итого 1536 параллельных потоков на сервере). С памятью попроще - там только оперативки (на считая виртуальной) 12Тб стоит (насколько знаю).

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

Ну вот просто пример - Вася через мобильное приложение отправляет Пете по номеру телефона 5 000 рублей. Для этого мобильное приложение должно у Васи спросить с какого счета? А хватит там денег? А Петя это кто - на какой счет в какой банк?

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

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

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

Ну и такой момент. На нашей платформе программный объект содержи не только исполняемый, но и т.н. TIMI-код (машинные инструкции - что-то типа ассемблера, но уровнем повыше). И метку под какой именно проц собран исполняемый код.

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

А джава... Это в любом случае интерпретатор. Пусть байткода, но интерепретатор. Т.е. оно по определению более ресурсозатратно и менее эффективно чем машинный код предельно оптимизированный под конкретный проццессор.

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

Спасибо, интересно. А ещё интересно как это всё внедрялось исторически. Альфа же один из первых коммерческих банков, да и всякие цифровые услуги они внедряли в первых рядах. Там сразу влезли на технологии IBM или были какие-то промежуточные метания?

И вот как-то нет проблем, знаете-ли...

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

Вы определились с ядром системы (IBM RPG, как я понял). Применение С/С++ - обосновано удобством разработки и быстродействием, а значит у вас в команде все (или какая-то часть) понимают и умеют писать на этих языках. И т.д. У вас все равно установлены определенные рамки по разработке, по допустимым технологиям и т.д.

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

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

Если нет вообще никаких ограничений, то разработка очень быстро может скатиться в "Повелителя мух"

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

Специфика в том, что "будет работать быстрее" здесь является абсолютным приоритетом.

Если вы знаете Питон и умеете Питон и хотите Питон - вам не надо идти к нам, а надо искать место где будет Питон. И это сразу проговоаривается "на берегу".

Условия такие - вам будет дано три месяца (и персональный наставник) для изучения технологического стека (платформа + язык). Официально это называется "испытательный строк", но на самом деле просто обучение т.к. готовых разработчиков под этот стек очень мало. ТД подписывается с первого дня, полная оплата с первого дня, отпуск, регулярный бонус - все с первого дня (единственное - ДМС и НС .оформляются после трех месяцев).

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

Во главу угла в разработке здесь всегда ставится эффективность полученного кода (быстродействие, утилизация CPU) - все это проверяется на обязательном нагрузочном тестировании. Технологический стек жестко определен. Кроме того, есть достаточно объемные "нефункциональные требования" - что можно что нельзя. На самом деле правил очень много. Кому все это не нравится - уходит. Хотя особой текучки у нас нет.

Специфика в том, что "будет работать быстрее" здесь является абсолютным приоритетом.

Технологический стек жестко определен. Кроме того, есть достаточно объемные "нефункциональные требования" - что можно что нельзя. На самом деле правил очень много.

Так в этом и суть - у вас есть правила и ограничения на стек, которые необходимы именно вашей команде. Эти правила были обоснованы, а не придуманы с потолка. Они призваны решать множество вопросов связанных с разработкой продукта, его приоритетов, кодовой базой и т.д. И если кто-то решит написать кусок проекта на Python, даже если он будет работать быстрее аналогичного кода на IBM RPG и С/С++ - это будет порицаться, надо будет переделывать на имеющийся стек, потому что есть ограничения.

В статье же прямо говорится, что подобное ограничение - "неразумно" и нуждается в переосмыслении. Прочитайте пункт 4 ("Мы пишем только на таком-то языке") в статье.

Дальше идет не менее важный кусок:

Если это опытный программист, и в большинстве случаев поступает разумно, то может и не надо его ограничивать всякой фигнёй — это уменьшение эффективности, да еще и снижение мотивации

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

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

Ну... Не то чтобы придуманы. Есть чисто технически ограничения. Например, Питона у нас нет. На нашей платформе (IBM i). Т.е. оно может быть и есть в природе, но у нас не установлено. Чтобы установить, нужно очень аргументированно обосновывать что это даст реальный результат. Т.е. многочисленные тесты, доказывающие что это реально выгодно с точки зрения производительности, эффективности и т.п.

Конечный вопрос всегда один - "сколько на этом заработает банк?".

И если кто-то решит написать кусок проекта на Python, даже если он будет работать быстрее аналогичного кода на IBM RPG и С/С++ - это будет порицаться, надо будет переделывать на имеющийся стек, потому что есть ограничения.

Если удастся доказать что Питон эффективнее для решения задач чем RPG или С/С++ - будет внедряться Питон. Но это надо доказать.

Здесь все решения выбираются не потому что кому-то хочется или не хочется делать именно так, а исключительно исходя из соображений предельной эффективности. Количество клиентов растет постоянно (три года назад было порядка 36млн, сейчас уже почти 50млн), растет количество бизнес-операций (мне лично приходилось переделывать один модуль, который изначально писался исходя из нагрузки 50 000 операций в сутки, а потом вдруг этих операций стало 5 000 000 в сутки). А железо все то же (железо очень специфическое, так просто не купишь, тем более сейчас). Посему, сейчас огромное количество задач связано с оптимизацией строго кода. Как пример - то, что было написано в 2015-м году и всех устраивало по скорости, сейчас перестало устраивать т.к. ввиду возросшего кратно объема данных работает слишком долго и начинает тормозить остальные процессы в рамках отведенного временного окна. Приходится пересматривать алгоритмы, искать какие-то хитрые пути решения (обычно это кеширование и/или распараллеливание обработки больших объемов данных, если используется SQL, то его т.н. "линеаризация" - избавление от разных group by и агрегатных функций с последующей потоковой постобработкой избыточной выборки). Тут много опыта накоплено уже что и где работает эффективнее.

Если говорить конкретно про RPG - он выбран не просто так. Во-первых, более 80% кода на платформе IBM i написано на RPG. Это специализированная платформа для коммерческих серверов, а RPG язык для коммерческих расчетов (нативные типы с фиксированной точкой, очень гибкие возможности описания сложных структур данных, работа со строками, датой, временем - все это уже есть в языке).

Я с 91-го по 17-й год писал только на С/С++. С 17-го больше пишу на RPG. И когда приходится возвращаться к С/С++ очень часто возникает вопрос - "ну зачем так сложно все? можно же намного проще и удобнее сделать...". Например, почему я должен помнить все эти макросы _MIN_INT и т.п. (которые еще и в разных компиляторах могут быть по разному определены и помнить в каком хидере они определены? Почему я не могу использовать универсальные *loval/*hival которые компилятор сам понимает как минимальное/максимальное значение для данного типа?

Почему я не могу инициализировать поля структуры дефолтными значениями непосредственно при ее описании?

И таких вопросов много возникает.

Хотя с другой стороны некоторые другие вещи на С/С++ пишутся проще и естественнее.

Нет одного какого-то языка на все случаи жизни. Что-то удобнее делать на одном, что-то на другом. И упираться в "я пишу только на С/С++" непродуктивно. Разработчик - это прежде всего подходы к решению задач. А язык - инструмент. Знаешь несколько языков - можешь выбирать наиболее подходящий инструмент для решения конкретной задачи.

А рабочие станции у вас "обычные" или тоже на этой специальной ОС? А IDE и прочие средства разработки/ отладки - "привет из 80-х" или более-менее современно выглядят?

Я без прикола, просто правда интересно каково это, прогать на спецплатформе.

А рабочие станции у вас "обычные" или тоже на этой специальной ОС?

Ну, к счастью, время аппаратных терминалов IBM5250 уже прошло.

Сейчас используется эмулятор. Самое простое и доступное - бесплатный пакет от IBM - ACS (IBM i Access Client Solutions) под любой десктоп - Win, Mac, Linux. Там кроме терминала еще много чего есть (работа с БД - посмотреть структуру таблиц, индексы, хранимые процедуры и прочее и прочее, есть "интерактивный SQL" где можно не только запросы погонять, но и посмотреть их "демонстрацию" - план запроса как движок его будет выполнять - что там с покрытием индексами и прочее).

Ну а сам терминал как-то так выглядит

Там уже общение с системой через команды языка CL (отдельная тема)

Каждое окошко терминала - отдельное задание (JOB) на сервере. Открою два окошка - будет два задания. Туту тоже отдельная тема

Все это на обычном компе работает.

А IDE и прочие средства разработки/ отладки - "привет из 80-х" или более-менее современно выглядят?

Долгое время особых альтернатив не было - была только RDi (Rational Development for i) от IBM. Штука мощная, но жутко тяжелая - это Eclipce к набором специфических плагинов для работы с серверами.

К тому же еще и платная...

Сейчас большинство переходит на VSCode - во-первых, к нему есть хороший набор плагинов (тот же IBM i Development Pack и еще ряд полезного)

Ну и свои плагины, по конкретно наши сервера тоже есть у нас.

Самое заморочное - сборка. Когда пришел в банк (в 17-м году) все собирали руками. Это значит закинуть на сервер (через RDi, впрочем, она позволяет и прямо на сервере в объектами работать) все объекты поставки, потом написать программу-инсталлятор на CL, скомпилировать ее на сервере (CL компилируемый язык) и запустить. Оно уже само все соберет.

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

В целом сейчас работает весь цикл CD/CI - Тестовые сборки - с компа на сервер. Поставка для дальнейшего внедрения - git + jenkins + artifactory.

Несколько мешают требования УИБ - с локального компа через VPN невозможно достучаться даже до тестового сервера (и всего что с ним связано - тот же jenkins). Это можно только с виртуалки во внутреннем периметре через VDI. Кто-то постоянно там работает, мне некомфортно. Я предпочитаю на локалке все делать, потом с гит выкинуть, зайти на VDI (у меня под это дело от дельный старый ноут выделен - VDI терминал), там подтянуть из гита и собрать. Т.е. рабочее место дома примерно так:

Справа - VDI ноут (там как раз эмулятор 5250 запущен). Слева - локальный рабочий с допмонитором.

Отладка... Ну вроде как можно в RDi или VSC делать, но я привык к хардкорному встроенному системному STRDBG в терминале.

Там, в принципе, и редактор есть SEU, но он уж слишком хардкорен :-)

Так что в целом ничего такого уж страшного нет. Все достаточно комфортно, хотя и с особенностями.

Нет одного какого-то языка на все случаи жизни. Что-то удобнее делать на одном, что-то на другом. И упираться в "я пишу только на С/С++" непродуктивно. Разработчик - это прежде всего подходы к решению задач. А язык - инструмент. Знаешь несколько языков - можешь выбирать наиболее подходящий инструмент для решения конкретной задачи.

В целом, я согласен с этим утверждением.

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

95% статей на хабре что-то рекламируют, явно или неявно. Да и сам хабр создан ради денег с рекламы.

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

Ой, нет, это тоже атака без аргументов.

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

Согласен со многим. Любые технологии надо применять разумно, а не бездумно (ради моды, выпендрежа и т.д.).

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

Ну, простой пример: для интернет-магазина на джанго делал калькулятор... rest api, json, сериализаторы... Жалею. Не нужно было там этого. Сейчас кайфую от htmx и пары вьюх. Никакого JS, никакого JSON, никаких сериализаторов и прочей абстракции мне в данном случае не нужно.

Или... Здесь на хабре недавно кто-то выложил простенький проект на питоне (вроде на джанго) по сокращению ссылок, который его попросили сделать на проваленном собеседовании. В комментах сразу посыпались советы, что надо было всё сделать в докере, метод по сокращению ссылки вынести из модели в отдельный слой - в модуль services.py (или типа того - для бизнеслогики)... У меня сразу возникает вопрос: А нафига? Зачем для единственного метода (на несколько строк) создавать отдельную абстракцию? Вот одна единственная модель, вот в ней передо мной метод... зачем этот метод выносить в отдельную абстракцию? Потому что модно? И модуль с названием services - ну, так себе, ни о чем не говорящее общее название.

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

Вот смотрю код Wagtail - там много длинных файлов на тысячу и более строк и... весьма комфортно себя чувствую.

В общем мой вывод: не надо использовать технологии бездумно по шаблону или ради моды. Не надо вводить абстракции ради абстракций.

Так и на это есть общепринятаярекомендация - избегай преждевременной оптимизации.

Короче в программировании куда ни плюнь, всюду ограничения -)

Цифровой рубль. Это мода, выпендреж или старый добрый распил?

Хороший кодревью еще поискать сильно надо. Обычно все вырождается в одну из крайностей:

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

  2. парное колупание каждой буквы изменений с автором; от п.1 отличается только тем, что автор занимается пересказом кода, а ревьюер по-прежнему лениво скользит глазами и рандомно ставит вопросы "почему?" В итоге вместо полезных изменений с рефакторингом и погашением техдолга обычно выбирается то, где поменьше про код рассказывать нужно.

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

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

длина строки должна быть не более чем Y

Такие вещи начинаешь ценить, просматривая на двух панелях изменения в vcs

Два 4k ultra wide монитора и нет проблем

Два 4k ultra wide монитора и нет проблем

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

Два 4k ultra wide монитора на расстоянии 4х метров? И всё головой вертеть не надо.. 😂

И строка снова не влезает или не видны буквы.

Ручное тестирование замедляет процессы?

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

айтишники любят говорить (особенно в твиттере), какие они избранные интеллектуалы

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

"Работа програмиста заключается в том, чтобы заменить ваше рабочее место на небольшой скрипт" (c)

UFO just landed and posted this here
UFO just landed and posted this here

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

А зачем мержить нестабильный код?

Уже писал тут - у нас мерж (с необходимым апрувом ПР) происходит только после прохождения первого этапа тестирования и перед вторым (бизнес-тестом). К этому моменту код уже стабилен.

UFO just landed and posted this here

его публикация в репозитории позволит перейти к разработке зависящих от него модулей

У нас разработка зависящих модулей не требует мержа в девелоп. ДОстаточно раскать поставку на нужном тестовом юните.

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

Если без лишних подробностей, то есть BRD - хотелки бизнеса. Есть ОТАР - архитектурное решение. На основе всего этого составляется FSD - это уже ТЗ.

После разработки первый этап - компонентное тестирование в тестовых юнитах. Это тест на соответствие FSD. Этим занимается аналитик и тестировщик. На этом этапе в поставку еще могут вноситься изменения.

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

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

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

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

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

UFO just landed and posted this here

Ну просто процессы везде выстраиваются по разному. Нет каких-то единых правил (есть общие направления в рамках которых каждая команда свои правила вводит).

У нас только разработчиков, которые пишут под центральные сервера (те, что на IBM i) сотни две (наверное, точно не скажу - много команд по направлениям разным - лимиты, тарифы, ядро, комплаенс, пластиковые карты, система расчетов, кассовый модуль, депозиты...). У каждой команды свой круг задач, свой проект в гите. Пересечения незначительны (хотя они есть, конечно).

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

UFO just landed and posted this here

Ну я до банка с промавтоматизацией имел дело, так что в курсе что там и как :-)

А когда наступает это волшебное время для ревью и рефакторинга в вашей модели?
Есть все основания полагать, что после


быстрее выпустить MVP и получить обратную связь

стейкхолдеры попросят проделать то же самое с новой бизнес-хотелкой.

UFO just landed and posted this here

Ревью дает две важные вещи:

  1. Сам факт того, что код будет кто-то смотреть и оценивать, усиливает внимание разработчика к коду. Одно дело быстро сделать правочку для себя, и другое - показать свою работу коллегам.

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

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

Альтернатива есть — так называемое «бесточечное программирование» (tacit programing). Удачи в чтении этого кода (это APL):

((+.×⍨⊢~∘.×⍨)1↓⍳)17

Имеем код без повторений, больше напоминающий мусор.

Это банальная лень, экономия энергии. Пресловутые система 1 и система 2.

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

Во-вторых, систем не две, и деление на системы (large-scale brain networks) не имеет отношения к экономии. Следовать плану - это потребность, использовать шаблоны - это оптимизация, такие механизмы разума встроенные или естественные, но они не про деление на системы.

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

В фунции не должно быть более чем X строк В таких случаях хочется спросить, почему именно столько, а не на одну больше или на две меньше.

Сколько помещается в один экран без прокрутки.

Статью в целом можно описать одной фразой: "Думайте, прежде чем повторять за другими", вообще это не только разработки касается.

А так можно любой полезный совет/принцип довести до абсурда: SOLID, dependency inversion - возникает ситуация, когда разработчик вместо использования int - делает свой интерфейс и передает его управляющему коду для реализации.

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

Ещё не хватает пункта "а нафига этот ваш Git, а на jQuery раньше скрипты писал и сразу в прод катил".
Вы не тимлид, вы хайпожор

У каждого программиста между ушей есть нейросеть, которой он пользуется.

Мало того, у некоторых есть даже производные от неё — ум, разум, интеллект и т. д.

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

Хорошие советы для любительской разработки, но не для бизнеса. В бизнесе скорость будет поважнее

В бизнесе скорость будет поважнее

— С какой скоростью вы умеете печатаеть?
— 1000 знаков в минуту!
— ?!!???...
— Правда, такая фигня выходит....

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

когда на полном серьёзе рассуждают о скорости выкатывания изменений в продакшн.

потому что от этого на полном серьезе зависит финансирование и в случае стартапа еще и жизнь фирмы

Не нужно тиражировать этот менеджерский бред, тут, в большинстве своём, умные люди собрались.

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


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

Apple смотрит на Вас... ну или как минимум смотрело, пока Джобс не того.

За то, похоже, его менеджеры и не любили.

За то, похоже, его менеджеры и не любили

Эппл не смолгла бы существовать без менеджеров с одним только Джобсом (потому что надо в маркетинг еще, в продажи и головой думать, а Джобс там устроил непойми что когда молодым был)
Но тут и верно то что креативная фирма где только одни менеджеры тоже не может нормально работать (тому пример конкурент яндекса известный который ничего не может но постоянно чтото старается)


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

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

То есть человек либо умный, либо менеджер? Полностью поддерживаю мысль!

Интересная логика.

И что в соответствие с ней происходит, когда умный человек превращается в менеджера?

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

И что в соответствие с ней происходит, когда умный человек превращается в менеджера?

Рискну предположить, что старческая деменция?

когда умный человек превращается в менеджера?

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

Ну так я встречал и выражение "его айтишник укусил". Оно тоже не от хорошей жизни? :)

Наоборот от хорошей! =)

То есть человек либо умный, либо менеджер? Полностью поддерживаю мысль!

тут получается несколько парадоксальный вывод, умные бывают только рядовые работники, менеджеры уже не умные ;)


на самом деле это немного не так. некоторые вещи можно делать только будучи менеджером или "сочувствующим"


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


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

Что опять? Придумайте уже что то новое ибо каждые надцать лет подобные темы подымаются из праха. При чем во всех направлениях. В эмбеддед комьюнити 25-30 лет назад все говорили что никто С использовать не будет, он тяжелый, жрущий ресурсы не в себя, не дает полного контроля аппаратного уровня да и поддерживается лишь некоторыми компаниями. То ли дело вечный и богом данный АСМ. И что сегодня? Хоть кто-нибудь в здравом уме будет писать проект на чистом АСМ в продакшн?)) Лишь поддержка мамонтов той же 25-30 летной давности.

Но тут же стоит и отметить что в эмбеддед дополняющее развитие, а не вытесняющее. АСМ все так же широко используется для вставок и инициализации, С для периферийного уровня и РТОС, С++ все чаще появляется для компонентов бизнес логики и формирование аппаратно-программных фреймворков. Есть место и для JSON для IoT задач, protobuf для сериализации и многое другое. И даже, прости господи, Питон для скриптов и автоматизации. И как то нормально все используется в своих определенных местах))

PS: ревью кода - вещь в себе. Иногда полезная, а иногда губительная. Когда ты чувствуешь что тебе нужная помощь или свежий сторонний взгляд - то это прям выручает. А вот когда к тебе прикапываются из-за скобочек, переносов и прочего - это уже перебор. Особенно когда ты вносишь изменение в проект и стараешься соответствовать общему виду текущего кода, а не тому как это будет рассматривать ревьювер под микроскопом))

PPS: намного важнее учиться составлять техническое описание своего кода и тех документацию. А не ограничиваться названием методов в 100500 символов и 3 слов в коммите) Но в это могут не многие.

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

А как вы определите в каких случаях нужно принимать решение надо не по принципу, а по здравому смыслу?

Для этого естественно тоже существуют свои принципы :)

Вы серьёзно не знаете? Как же вы без этого живёте?..

В программировании нет вообще никаких непреложных истин

Их, непреложных истин, вообще нигде нет.

Ну вот вы самостоятельно в конце статьи и пришли к объяснению того, почему правила все-таки нужны и почему им следуют) Программирование - это не физика, тут все от начала и до конца придумано людьми для людей и потому из любого правила можно найти исключения. Однако гипотетическая компания, в которой правила не соблюдают (потому что DRY не всегда работает) будет крайне неэффективна. Каждое решение будут обсуждать.
Как по мне, лучше смириться с тем, что некоторая часть задач делается планово неоптимально, но зато работа ведется единообразно и предсказуемо. Да, разумеется, часть правил будут грубо нарушаться, когда возникает острая необходимость. Это можно сравнить с законами в государстве (кстати, внезапно, совершенно в любом, а не только в "недемократическом") - они постулируются как обязательные, но когда очень надо, само правительство их и нарушает. И так получается все равно лучше, чем тотальное беззаконие.

Articles