All streams
Search
Write a publication
Pull to refresh
25
0.1
Масляев Александр @maslyaev

Пользователь

Send message
Само существование GetStoppedFlagForItemID, который лезет в базу за одним флагом — это уже ошибка. Которую очень просто недопустить!
Не поверите, но бывает так, что такие фокусы бывают частью базового фреймворка. Добавляем в таблицу Item флажок Stopped, и сразу в коде можем писать if (MyItem.Stopped).... Обалденно удобно, если не злоупортеблять.

Как сделать правильно, я знаю. И вы знаете. И все знают. И как не нужно делать, тоже все знают, и все готовы поклясться страшной клятвой, что отныне никогда и ни за что. Но когда дело доходит до дела, открываем код, многократно насилованный поколениями сопровожденцев, и рука тянется к пулемёту. Все хорошие мальчики и девочки, но если ошибочность доделываемого явно не бросается в глаза, никто дополнительно напрягаться проводить раскопки не будет. Допилили, прогнали тесты, вроде работает, ну и ладно. В релиз.
По-правильному (предположим, изначально так и было сделано) все исходные данные для проверок извлекаются из базы заранее, вне циклов, и передаются вызываемым методам по цепочке вызовов. В конечном счёте выглядит всё вполне невинно: например, в метод прилетают параметры типа ItemID, Quantity, Summ, QExist. Метод сравнивает Quantity c QExist, и если нет превышения, то пускает выполнение по одной ветке, а если есть, то по другой. Предположим, в базу добавили флажок «Запретить отгрузку». Соответственно, если он для ItemID выставлен, то выполнение пускается по «обломной» ветке. Для добычи значения флажка уже есть метод GetStoppedFlagForItemID(), и вызов этого метода мы, не подумав, вписываем в условие. Здравствуй, тормоз.

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

К сожалению, это всё рядовые ситуации. Наверно, в любой системе, имеющей богатую историю, есть куча кусков, которые на первый взгляд выглядят как конфетки, а на самом деле самое настоящее дерьмо. В монолите хотя бы сразу бывает видно, что на диск или в сеть полезли совсем не там, где следовало.
Монолит:
function big_func() { // CC = 5
  for ... {
    for ... {
      ...
    }
  }
  if ... {
    for ... {
      ...
    }
  } else {
    ...
  }
}

Порезали:
function big_func() { // CC = 1
  small_func1();
  small_func2();
}

function small_func1() { // CC = 3
  for ... {
    for ... {
      ...
    }
  }
}

function small_func2() { // CC = 3
  if ... {
    for ... {
      ...
    }
  } else {
    ...
  }
}

Максимальная цикломатическая сложность была 5, а стала 3. Типа профит.
Пока какому-нибудь разработчику не понадобится подправить функционал в этом методе.
По-разному бывает. По опыту скажу, что докручивать «дополнительные вводные» в монолите проще и быстрее. И более предсказуемый результат. И меньше риска поймать побочку. Хотя, конечно, по-разному бывает.

Простой пример. Допустим, нужно на каком-то шаге сделать доп. проверку. А для этого нужно слазить в базу. Если дизайн мелкогранулированный, то находим нужную процедуру и ничтоже сумняшеся вписываем запрос к базе. Включаем — адские тормоза. А почему? А потому, что это только с виду у нас запрос на верхнем уровне кода, а реально он в трёх вложенных циклах. Если же мы работаем с монолитом, то сразу видим внешнее окружение и в мозгу автоматически срабатывает триггер «запрос в цикле снег голова попадёт».

В таком случае если тормоза адские, то можно считать, что повезло, потому что сразу заметили и сразу исправили. Но часто бывает, что из-за такой же или подобной пакости снижение скорострельности получается маленькое и на глаз не заметное. Процентов на 10. Потом в схожей ситуации добавится ещё 10, потом ещё и ещё. В результате имеем, что программка, которая раньше летала на Pentium-3 теперь тормозит на Core i7. Хотя функциональности добавлено с гулькин нос. Начинаем смотреть что плохо, и понимаем, что перепахивать нужно всё. А на это уже ни ресурсов, ни желания :(
Цикломатическая сложность последовательно идущих кусочков складывается методом суммирования из сложностей каждого из этих кусочков.
Чаще всего, ошибка не в 20 строчках и не в 2000, а в одной. Иногда её проще отладить в длинной портянке, иногда целесообразно вытащить в отдельно отлаживаемый кусок. Если второе, то вынести. Почему бы и нет? Главное — подходить с умом к процессу и не делать фетиш ни из мелкокусочечной нарезки, ни из монолитостроения.
А вот для 2000 строк кода — нужно держать в голове всю ветку условий и набор параметров.
А их всё равно держать придётся. Кусок в 20 строк всё равно обретает смысл только в контексте всей задачи. Если задача сама по себе сложна, то нет никакого способа уменьшить сложность её реализации. Да, каждый отдельный маленький метод прост, но выполнение задачи даёт не каждый отдельный метод, а их полный комплекс. Нарезка монолита на 100 кусочков очень не способствует пониманию единого целого во всей полноте.
Метод внутри метода в случае его заведомо однократного использования не сокращает длину кода внешнего метода. Даже немножко увеличивает. То есть количество страниц останется примерно тем же.
Но как способ сделать так, чтобы враги не догадались, как оно работает, это определённо можно рекомендовать :))
Понятно. Сначала собрать монолит из кусочков, а потом опять его разобрать. После третьей итерации шаг «разобрать» делать уже не захочется.
Во многих случаях достаточно покрыть публичные методы.
А публичный-то метод у нас один. Собственно, сам монолит.

Конечно, ко всему нужно подходить с умом. Если есть смысл обвесить кусок отдельным юнит-тестом, то конечно его нужно вынести. Я же ни в коем случае не выступаю против обоснованной фрагментации. Я против фрагментации, мотивированной абстрактным формальным критерием снижения цикломатической сложности.
особенно если им давать семантически значимые названия
Вот с этим обычно вообще беда. Варианты в стиле «Посушить_клиенту_голову_после_стрижки_ежиком_если_он_пришел_по_рекомендации_васи» — форменный кошмар.
Монолит — один предмет тестирования, а сотня его ошмётков — соответственно сотня предметов. Не забываем о рефакторинге. В какой-то момент может оказаться, что ключевую логику (допустим, это 50% объёма кода) можно ускорить на порядок, если сделать не вдоль, а поперёк. Что будем с тестами делать?

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

Да, понять метод в 2000 строк не просто. Но понять 100 методов по 20 строк — вообще катастрофа. Может быть, отчасти из-за этого и получается, что "разработчик 95% времени читает свой или чужой код и только 5% пишет"?
Заминусуйте меня до смерти, но я, бывает, предпочитаю не длинные, а очень длинные методы.

Банальный пример. Допустим, вытаскиваем мы что-то из какой-то внешней системы. Обычная ETL-задачка. Для начала нужно проверить параметры, потом установить соединение, сформировать запрос, получить ответ, распарсить ответ, сопоставить сущности, выполнить кучу разных трансформов, записать данные, запротоколировать. Если вытянуть всё в одну колбасу, получается, например, 5 тыс. кода. Выносим повторяющиеся куски, получаем 2 тыс. строк основного метода плюс 1 тысяча строк вспомогательных. Есть ли смысл в погоне за снижением цикломатической сложности нарезать оставшиеся 2 тыс. на мелкие кусочки, если заведомо известно, что они в качестве самостоятельных единиц точно больше нигде и ни для чего не понадобятся? От слова «никогда»?

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

Когда мне надо написать «роман в коде», я просто в его начало вписываю описание сюжета, а потом размечаю повествование. Как-то так:
// 1. Делаем раз
// 2. Делаем два
// 3.…

// (1) Делаем раз


// (2) Делаем два
...
И нормально. Никто не жаловался.

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

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

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

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

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

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

Вот представьте, что лично для вас убралась перспектива старости и смерти. Состояние организма пришло в биологическую норму (25-30 лет) и там навсегда стабилизировалось. У всех окружающих — то же самое. 90-летняя бабушка, еле доковыливавшая до лавочки и ненавидевшая весь свет за то, что жизнь не удалась, превратилась в бойкую красивую деваху с горящими глазёнками, потратила гробовые деньги на модные шмотки и айфон, и теперь хочет жить полной жизнью. И, конечно, секса.

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

И тут к вам подкатывают типа «Слышь, чувак, есть мазочка срубить по-быстрому миллиончик рубликов. Родина в опасности. Они нас земляными червяками назвали».

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

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

1. В результате обретения бессмертия средняя продолжительность жизни увеличится. Да? Нет? Капитан Очевидность настойчиво подсказывает, что да.

2. Сохранение существующих темпов прироста населения в сочетании с радикальным увеличением продолжительности — это лет через 100-200 превратить всю поверхность Земли в одну большую мумбайскую трущобу. Да? Нет? Калькулятор подсказывает, что да.

3. Встаёт задача снижения рождаемости пропорционально увеличению продолжительности жизни. Если оно само собой не образуется (по причине «незачем рожать»), то ничего не остаётся, как организовать это принудительно. Не считаясь со средствами и без оглядки на абстрактный гуманизм. Задача должна быть решена, и она будет решена.

4. Так или иначе, детей становится меньше. Возможно, раз в 10-20. В идеале — в 100-200 раз, потому что людей и так слишком много. Дети становятся экзотическими зверьками, про которых все слышали, но далеко не все видели в живую.

5. Тема «дети» уходит из круга задач, повседневно решаемых большим процентом людей. Следовательно, уходит из культуры.

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

Хобби — да, вариант. Всякие реконструкции — тоже. Но это всё маргинальщина, очень далёкая от мэйнстрима. Мэйнстрим постепенно возьмёт своё. Потихонику, полегоньку, за какие-то сто, двести, пятьсот лет, но возьмёт.
правительственного декрета предписывающего раз в 1000 лет завести одного ребенка
Боюсь, правительства не будет. За ненадобностью.
пока обман не вскрывается...
Я бы ожидаемый период вскрытия обмана исчислял в днях.
можно предложить вариант «повышающего коэффициента для смертного»
Для этого сначала надо на всей Земле устроить один большой СССР. В рыночной экономике схема с повышающим коэффициентом не сработает. Или мгновенно оставит смертных без работы.
Штрафбат, выпускаемый на противника без оружия — крайне неэффективное средство ведения войны.

Давайте прикинем, что нужно предложить бессмертному наёмнику, чтобы он рискнул шкуркой. На второй чаше весов (которую надо перевесить) у нас имеется:
1. Спокойно занимаясь мирным трудом и по субботам выпивая рюмочку вискарика, бессмертный за свою вечную жизнь употребит бесконечный объём вискаря.
2. Понемножку флиртуя с разными встречными девчонками, бессмертный в перспективе перетрахает всех, кого пожелает. Во всех мыслимых обстоятельствах и комбинациях.
3. Имея в перспективе вечность, можно развить в себе любые таланты и стать кем угодно. Ну и что, что сейчас клиент весь в долгах как в шелках, перебивается случайными заработками и вообще по жизни туп как дерево? Имея вечность впереди, он может стать хоть известным политологом, хоть станцевать в очень большом театре, хоть выучить эту… как её… кавантовую физику. А чё, хуже других, что ли?

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

Information

Rating
2,987-th
Location
Москва, Москва и Московская обл., Россия
Registered
Activity