Pull to refresh

Comments 25

Я иногда не понимаю зачем в языки вводят все эти "упрощения" (которые по факту являются усложнениями).

Если для понимания какого-то фрагмента кода рядовому (подчеркиваю, не лиду, не сеньору, а рядовому миддлу или джуну) требуется потратить времени БОЛЬШЕ, чем для понимания аналогичного по функционалу кода, но написанного через базовые конструкции, общие для всех языков, то грош цена такому "упрощению".

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

Общая эффективность такого кода только падает, а не растёт. Поскольку эффективность кода заключается не только в количестве строк, но и во времени, затрачиваемом на его сопровождение НЕ АВТОРОМ данного кода (а это очень важно в больших командах, сопровождение НЕ АВТОРОМ).

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

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

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

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

UFO just landed and posted this here

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

UFO just landed and posted this here

Потому что иногда лидам и сеньорам нужно написать тонну кода, который джун вообще не напишет, а времени в обрез. Поэтому лид или сеньор берёт Scala / Haskell / нужное подчеркнуть и пишет софтину за сравнительно короткий промежуток времени, полагаясь на parametricity и прочие результаты CS последних 50 лет, чтобы в этой разработке не утонуть. Иногда даже бывает, что такой весь проект, и джунов на него просто не нанимают.

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

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

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

Я иногда не понимаю зачем в языки вводят все эти "упрощения" (которые по факту являются усложнениями).

Потому, что если ими правильно пользоваться, то они упрощают жизнь. А если неправильно, то усложняют. Примерно как бензопила, автомобиль, топор.

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

А вы что, истина в последней инстанции? Может вы вообще ничего не знаете и в лидах оказались за выслугу лет? Уж если код в тыщу раз компактнее, да ещё и оптимальнее, то именно его и надо использовать. И если лид режет такой код, то нафига такой лид нужен в проекте.

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

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

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

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

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

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

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

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

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

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

Согласен. В "Чистом коде" Мартина это называет принципом наименьшего удивления. То есть, при чтении кода не должно возникать вопроса "а это что?"

И есть еще один аспект. Простой код существенно проще для отладки. Особенно хорошо это начинаешь понимать после бессонной ночи с орущим клиентом на телефоне в попытках выяснить что там вообще у него происходит. Особенно если он с другого конца планеты.

: <value> ( -- value ) \ <value> counter ;

Кусочек кода на языке Factor. Определяет функцию <value>, которая при каждом запуске выдаёт новое натуральное число. В скобках что-то вроде типа (из ничего получается одно значение, в Factor функция может выдавать несколько значений, которые кладутся в стек, оттуда же берутся аргументы).

Пестов, кажется, обиделся (никто не оценил), на письма с вопросами не отвечает. А мне нравится!

Вложенный match можно же переписать (замечание справедливо, но подъязык match'ей обычно вывозит очень и очень сложные конструкции с guard'ами и т.д.):

def doSomething(res: Future[Either[Throwable, Option[A]]]) = res match {
   case Success(a) =>
      a match {
        case Left(ex) => 
        case Right(Some(c)) =>
        case Right(None) =>
        }
    
   case Failure(ex) =>
}

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

UFO just landed and posted this here

Можно было бы решить, кстати, и просто неймингом: вместо filter и filterNotkeepWhich и skipWhich.

UFO just landed and posted this here

def filter[A](p: A => Predicate): List[A]

Вот тут понятнее точно не стало. Предикат - это функция, возвращающая boolean. Например, имеющая тип A => Boolean. Именно отсюда название "p" в определении

def filter(p : A => Boolean): List[A]

Хотя и это определение понятно только тем, кто уже в курсе, что делает filter(). Но тогда уж надо назвать функцию не filter(), а например retainWhere().

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

Пойдёт в копилку заумных фраз.

Да простит меня автор, но Скала - просто жуткий язык. Один из неудачных примеров языков созданных из академического любопытства, а не по необходимости. Такого безумного количества конструкций ради попыток впихнуть все известные парадигмы программирования я в других современных языках не знаю.Не удивительно, что после появления Котлина и фейслифтинга Java, от Скала стали по возможности отказываться. В конце концов, если вам нужен ФП в какой-то части проекта можно задействовать Кложур. Уж с ним-то точно все ясно.

Sign up to leave a comment.