Fabien Potencier — Founder of Symfony framework at PHP fwdays conf! Kyiv, June 1
×Закрыть

Программист разумный

[Об авторе: Руслан Дмитракович — разработчик ПО и предприниматель, в ИТ-индустрии с 1994 года. Пионер интернет-рекламы в Украине: основатель Украинской баннерной сети, рекламного агенства «Интернет-эксперт». Создатель проекта Code X-ray — повышение эффективности работы команд разработчиков на основании статического анализа кода]

Папа посылает сынка в магазин:
— Иди купи хлеб и молоко! Слышишь? Купи две вещи, две вещи! Хлеб и молоко! Две вещи! Понял? Понял?
Сынок покивал и пошёл. Приносит шайбу. Папаша орёт:
— Я тебе, что сказал? «Купи две вещи»! Две вещи! Где клюшка?!

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

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

«Программные проекты редко терпят крах по техническим причинам. Чаще всего провал объясняется неадекватной выработкой требований, неудачным планированием или неэффективным управлением. Если же провал обусловлен всё-таки преимущественно технической причиной, очень часто ею оказывается неконтролируемая сложность. Иначе говоря, приложение стало таким сложным, что разработчики перестали по-настоящему понимать, что же оно делает». Стив Макконнелл, «Совершенный код»
«Существенная черта промышленной программы — уровень сложности: один разработчик практически не в состоянии охватить все аспекты такой системы. Грубо говоря, сложность промышленных программ превышает возможности человеческого интеллекта». Гради Буч, «Объектно-ориентированный анализ и проектирование»
«Управление сложностью — квинтэссенция программирования». Брайан Керниган

Понятие «сложность» встречается часто, но, к сожалению, понимание этого термина дается на откуп читателю. Давайте разбираться!

«Фак ю, Спилберг, непонятно!»

Мой интерес к тому, как работает человеческий мозг, возник на обсуждении проекта. В ходе доклада человек, презентующий проект, показал вот такое:

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

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

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

Человеческий мозг как вычислительная машина

Давайте рассмотрим когнитивные способности человека — его возможности воспринимать, запоминать и обрабатывать информацию. Вот несколько фактов:

  • максимальный объем внимания, количество объектов, которые человек может воспринять одномоментно, колеблется от четырех до шести (оперативная память);
  • мыслит нормальный человек однопоточно и переключение от одной деятельности к другой часто приводит к ошибкам, а также снижает темп работы (одноядерный процессор);
  • количество логических операций в секунду сильно ограничено (тактовая частота) (для примера скажите, чему равно ( (true && !false) && (!true || false) ). Надеюсь, в пару секунд уложились. Нет? ;) );
  • объем информации, воспринимаемый за единицу времени, также сильно ограничен (скорость коммуникационного интерфейса).

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

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

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

Но самое главное, не всякий алгоритм человек выполнит с легкостью. Читая код программы, программист выполняет его в уме. И, например, параллельные вычисления, асинхронность, рекурсия («Я оглянулся посмотреть, не оглянулась ли она, чтоб посмотреть, не оглянулся ли я») обычно вызывают проблемы.

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

Уровни абстракции или сильная сторона мозга

В отличие от компьютера, человеческий мозг может перескакивать на объекты разных уровней сложности, скрывая детали. Например, с точки зрения мозга, запомнить набор букв «П, Н, А, Т, Г» также сложно, как и набор слов «ПОЛ, НОГА, АНАНАС, ТИГР, ГАЗ».

Вернемся к истории c презентацией. Почему возникли разные мнения по поводу одного и того же изображения? Для того чтобы справляться со сложными (состоящими из многих частей) объектами, человек использует чанкинг: группировку информации таким образом, который позволяет лучше ее воспринимать и запоминать.

Диктуя или запоминая номер телефона, вы, скорее всего, будете использовать группу цифр, таким образом уменьшая количество объектов, которыми оперирует ваш мозг. Такие операции мы делаем подсознательно.

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

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

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

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

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

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

«Любой дурак может написать код, понятный компьютеру. Хороший программист пишет код, понятный человеку». Мартин Фаулер

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

О сложности кода можно судить на основе метрик сложности. Хорошая идея включить автоматический анализ кода в процесс разработки. Но это тема для отдельной статьи.

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

Отношения в команде и коммуникация

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

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

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

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

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

Культура компании влияет на коммуникацию и знания коллектива, а те, в свою очередь, влияют на реализацию проекта.

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

Ревью, работа в паре и «шкаф». Или одна голова хорошо, а две лучше

Человеку свойственно ошибаться. Ошибки при создании програмного обеспечения — нормальное явление. Ошибки бывают самыми разными, и мы не будем углубляться в подробности. Но все они связаны с тем, что человеческий мозг работает не так идеально, как хотелось бы. В силу ограничений мозга, описанных выше, разработчик что-то упускает из виду и делает ошибку. И вот тут применима пословица «Одна голова хорошо, а две лучше». Вовлекая в процесс коллегу, мы тем самым включаем механизм контроля и обратной связи. Таким образом мы увеличиваем «вычислительные ресурсы», направленные на решение задачи. Конечно, мы начинаем терять часть времени на коммуникацию, но качество работы растет.

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

Есть несколько вариантов взаимодействия, когда вы можете управлять затратами на коммуникацию, но в тоже время использовать ресурсы коллеги:

  1. «Шкаф» — самый простой, быстрый, но в тоже время эффективный способ. Просто расскажите кому-то, что вы собираетесь делать. Очень вероятно, что вы сами заметите ошибку. Дело в том, что, проговаривая решение, вы включаете в работу еще одну часть своего мозга и таким образом полнее используете его возможности.
  2. Коллективное обсуждение решения, мозговой штурм.
  3. Ревью кода коллегами. По моим наблюдениям, качество анализа кода коллегами сильно зависит от объема просматриваемого кода. Поэтому в случае большого количества кода, который требует анализа, я предпочитаю просматривать код вместе и задавать вопросы.
  4. Парная разработка. Данный метод хорошо работает для задач средней сложности, не требующих высокой концентрации. Таким образом у вас получается процесс 3 в 1: создание продукта, обсуждение и анализ выполненной работы. Однако, по моим наблюдениям, если решение не очевидно, то задача может «забуксовать» и более эффективно использовать в наборе техники, описанные выше.

Выводы

«Сложность» — одно из самых важных понятий, которым должен владеть разработчик ПО и всегда помнить о нем в своей повседневной деятельности.

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

Вот несколько способов уменьшить сложность при разработке:

  • налаживайте коммуникации в команде, совершенствуйте язык общения, стандарты и соглашения. Учитесь слушать и понимать друг друга;
  • обращайте внимание на количественные параметры создаваемых объектов: количество файлов в каталоге, методов у класса, состояний объекта или переменной, связей между компонентами и т. д. При достижении установленного предела перерабатывайте проект;
  • используйте фреймворки, библиотеки и инструменты, позволяющие скрыть сложность в уже существующих компонентах;
  • используйте языки и нотации, наиболее подходящие для решения вашей задачи. Например, SQL может быть самым лаконичным и понятным средством для построения отчета, а для описания бизнес-процесса нотация BPMN.

Напоследок повторю избитую цитату:

«Управление сложностью — самый важный технический аспект разработки ПО. По-моему, управление сложностью настолько важно, что оно должно быть Главным Техническим Императивом Разработки ПО». Стив Макконнелл, «Совершенный код»

Не забывайте об этом!

LinkedIn

53 комментария

Подписаться на комментарииОтписаться от комментариев Комментарии могут оставлять только пользователи с подтвержденными аккаунтами.
«Шкаф» — самый простой, быстрый, но в тоже время эффективный способ. Просто расскажите кому-то, что вы собираетесь делать.

Непонятно, почему «шкаф». Это термин Друкера? А то в IT краях это обычно называется «метод утёнка».

Метод утенка — это «парное» программирование с неодушевленным предметом.
«Шкаф» — это разговор с человеком в перерыве например.

Метод утенка — это «парное» программирование с неодушевленным предметом.

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

«Шкаф» — это разговор с человеком в перерыве например.

Если вы знаете такой вариант термина, то, может, ответите и на вопрос про его происхождение?

Это олдскульное ;) Согласен, лучше было употребить более распространенный термин.

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

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

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

Т.е. по мнению Фаулера всеькто писал линукс полные дураки

Оригинальная фраза: Тот чей скилл >= полный дурак, может писать код понятный компу. ты пишешь Оригинальная фраза && ты не можешь понять сорсы линупса => писатели линупса дураки. На лицо явное нарушение логики.

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

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

elixir.bootlin.com/...​.5/source/kernel/cgroup.c

Вот к примеру что вы можете сказать глядя на этот код? Ах вам не понятно, ну значит те кто писал код «дураки»

А еще там есть файлы по 20000 строк с ассемблерными вставками и прочей магией. Почему вдруг он должен быть понятен человеку.

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

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

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

Система должна быть понятна тому, кто с ней работает. Приведеный Вами пример особо ничем не отличается от любой другой предметной области, которая требует специальных знаний. Но кроме этого есть другие моменты. Например прибейте форматирование или переназовите переменные в стиле a, b c . Компилятор все равно «поймет» написанное, а человеку прийдется уже очень сильно напрячься. Думаю Фаулер имел в виду именно такие моменты, а не наличие знаний предметной области.

Правильно. Но судя по статье это не так. Человек принес схему системы, но она сложная. Просто сложная и все тут.

а вы статью вообще читали?

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

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

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

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

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

Ничего нового в статье, но как напоминание для многих неплохо написано.

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

Занимательное чтиво. Но для определения сложности кода есть вполне себе сформулированные и осязаемые метрики — например цикломатическая сложность.
ru.m.wikipedia.org/...​Цикломатическая_сложность
Читабельность, и понятность и т.д. это просто отдельные штуки. И не стоит их путать с сложностью.

Не надо путать цикломатическую сложность со «сложностью».

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

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

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

Можно еще много чего считать или просто будку перекрашивать.
ТС ведет речь о «сложности» в человеческом понимании, а не о неких фиктивных метриках для частных случаев.
А вот тут со «сложностью» все очень и очень сложно. До сих пор даже приемлемых определений нет.

А с каких пор цикломатическая сложность стала фиктивной метрикой?
А ’сложность в человеческом понимании’ это про оценочные суждения. Они как правило субъективны. И естественно не консистентны от человека к человеку.
Если покопаться, то в каких ни будь paper по психологии найдется даже определение этой ’сложности’.
Так вот собственно, объективная сложность системы (измеренная какой-нибудь метрикой) != субъективная оценочная сложность.

А с каких пор цикломатическая сложность стала фиктивной метрикой?

Потому что она не имеет никакого отношения к тому, что люди понимают под словом «сложность».

А ’сложность в человеческом понимании’ это про оценочные суждения. Они как правило субъективны. И естественно не консистентны от человека к человеку.

Субъективны, но не совсем. Как пример, массово используется оценка экспертов и такой подход работает.

по психологии найдется даже определение этой ’сложности’

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

объективная сложность системы

и

измеренная какой-нибудь метрикой

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

Вот выше есть картинка с примером — таки там нарисована сложная система (но может вся сложность просто в выбранном отображении, а система простая).

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

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

Оценка экпертов на то и оценка, что это оценочные суждения. И в некоторых случаях оценка базируется на объективных показателях/метриках.

И нет, такой подход скорее не работает чем работает. (оценка сама по себе)
Более того, оценка експертом скорее всего нужна для достижение консенсуса по некоторому вопросу.

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

Не ’истинной ’ или ’правдивой’. А всего-лишь объективной

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

У программного кода может быть сложность, трудоёмкость и громоздкость. Цикломатическая сложность — это громоздкость. Трудоёмкость — это расписать 100500 важных частных случаев и отработать каждую странную хотелку клиента, а сложность — это уровень усилий на понимание собственно общих принципов и подхода (и тут проблемы типа «что такое моноид в категории эндофункторов и как он влияет на исполнение кода в этом месте?» или «а как это мы тут умудрились завернуть транзакцию в оператор сложения?»)
К сожалению, «сложность в чистом виде» не имеет отдельного слова в языке, и слишком часто под сложностью понимают все три вместе.

Т.е. есть как минимум 3 разных понятия, подразумеваемых под ’сложность’. Но нет, будем смешивать их в одно потому что есть 1 слово?
Теперь про пресловутую ’общественно полезность’ и ’трудоемкость’.
Трудоемкость можно выразить через количество логических операций необходимых для решения задачи. Оно очень даже осязаемое и измеряемое. Причем консистентно от человека к человека. Другой вопрос что для некоторых подзадач существуют уже готовые решения, и некоторые об этом знают, а некоторые нет.

Но нет, будем смешивать их в одно потому что есть 1 слово?

Это к кому вопрос?
Я как раз предлагаю не смешивать, если есть возможность (а она всегда есть, можно сказать что-то в духе "сложность-1"/"сложность-2«, «бытовая сложность» / «собственно сложность» и т.п.)
Почему вы накинулись на меня, а не на кого-то другого?

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

Нет, нельзя, не осязаемое и не измеряемое. Потому что то, где один прозревает решение с помощью третьего глаза, второй просто отбросит все неудачные варианты согласно своему опыту и из оставшихся выберет один по эстетическим соображениям, а третий будет проводить полный R&D всех комбинаций по всем осям.
Хотя если вы рассматриваете только самые тривиальные задачи вроде написания формы ввода под заданные поля — да, там алгоритм задан на 100% и надо лишь ему следовать.

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

«Другой вопрос», что те решения могут не подойти в данном конкретном случае по массе причин, и применять решение только потому, что оно где-то подошло раньше — очень плохой подход.

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

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

Не работает.

Работает. Прямо с ходу могу назвать аж несколько вариантов. Знаю проекты где это применяется.
— все та же цикломатическая сложность
— тупо размер бинаря
— наличие и количество циклов переменной длинны (очень актуально для всех real time систем)
— все та же О(N)

И все это про ’сложность’

И всё это не работает, даже O(n), потому как там есть коэффициентик, о котором почему-то большинство местных пограммистов не в курсах.

У Виктора сильная специфика — embedded, обработка изображений и т.п.
Там высокий порог вхождения, сложные алгоритмы, которые невозможно или неэффективно упрощать до того, что влезает в функции сложности до 10-15, вылизывание единиц процентов, если не долей процентов, и часто hard realtime.
С другой стороны, я вообще не вижу смысла связывать области такой специфики с основной темой статьи — которая, по Спольски, в основном касается классического «внутреннего» софта, хоть он за последние 20 лет и поглотил весь веб. Поэтому в этой подветке обсуждения нет смысла.

Не совсем. В эмбедед я нос не сую в явном виде. А если что тормозит, то в 99% случаях надо переделывать весь алгоритм (в том числе и на теоретическом уровне). единицы процентов мне неинтресны.
А вот по O(n). Надо всего-лишь посмотреть на определение O и o нотаций, чтобы понять, когда O(n^2) быстрее O(n), например.
Например, переход с линейного поиска на деревья (knn в том числе) или кластеризацию не всегда нужен. Да мы можем c O(n) перейти на O(log(n)), но это часто может усложнить алгоритм и сильно и замедлить его и это O даст выйгрыш только при n>>1000.

Не совсем. В эмбедед я нос не сую в явном виде.

Но мышление у тебя всё равно «того» типа.

Надо всего-лишь посмотреть на определение O и o нотаций, чтобы понять, когда O(n^2) быстрее O(n), например.

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

Раньше (до Интернета) было в основном наоборот — медленные машины, мало памяти, но низкая скорость заваливания данными и люди могли вовремя отреагировать. Тогда, да, 1*n^3 было очень часто выгоднее 10000*n.

класичний приклад — комутація каналів/пакетів.

Щось не вловив звʼязок...
Комутація каналів — тому що надійно діє тільки при ручному виконанні?

В тому смислі, що складність комутації каналів росте експоненційно від кількості каналів, а складність комутації пакетів — логарифмічно. На початковому етапі КК була на порядки ефективнішою за КП, чому абстрактний телеком і обрав цей підхід. Із збільшенням абонентської бази експоненційний ріст складності/вартості обладнання та каналів призвів до того, що КП виявився ефективнішим, і телеком переїхав на КП, обкатану та доведену до ума злими енторнетчиками.

Вообще-то для embedded очень даже характерна задача добиться размера бинаря не больше чем Х. А размер бинаря это один из видов метрик для измерения сложности. Так что...

Вообще-то для embedded очень даже характерна задача добиться размера бинаря не больше чем Х.

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

Так что...

Нет, не связано.

Взагалі-то, складність системи пропорційна ступеню характеристичного рівняння, що цю систему описує. Простий і зрозумілий кількісний показник.

Шкода, що стільки розказано про складність, і цитати з класиків є, а про структурну та функціональну декомпозицію — ані слова.

Менi дуже цiкаво, скiльки людей з тих що прочитають Ваш коментар, зможуть оцiнити цей «простий i зрозумiлий» показник. :) Моя мета, звернути увагу на проблему неконтрольованоi складностi при розробцi. Дуже багато людей взагалi про це не думають i навiть не здогадуються, що вона є. А от що з цим робити, можна писати i писати...

Ну, системотехніка — взагалі непроста штука, а складність — це поняття саме з системотехніки. Я зовсім не очікую, що написане зрозуміють фахівці з профтехосвітою. Проблема з неконтрольованою складністю виникає тому, що системотехнічні рішення приймаються людьми, що не мають ані відповідної освіти, що дозволила б уникнути помилки, ані досвіду, який хай на власних синцях і емпірично, але дозволив би скласти власне уявлення про проблему.

Зі складністю людство вміє давати раду виключно декомпозицією. Спочатку розбиваємо систему на достатньо невелике число виокремлених складових, функції та зв’язки між якими можна проаналізувати в умі. Затим повторюємо розбиття рекурсивно, аж поки не дістанемося до рівня тривіальних функцій, які можна формалізувати у спеки і передати кодерам на реалізацію. Да, типовий ватерфол, в якому проблема складності передбачена від самого початку, і задає послідовність дій.

Успішно відхилятися від цієї схеми вдається або в нескладних випадках, або в типових, де структура та функціонал елементів системи заздалегідь відомі, і можна одразу починать з бантиків-рюшечок на радість замовнику.

Дякую за слушний коментар! Тому що Ви написали треба вчитися, крiм того, не кожен має достатнi аналiтичнi здiбностi. Ну i головне перед тим як вирiшувати проблему, треба ii усвiдомити. ;)

Навичка декомпозиції нескладна, якихось особливих здібностей для того непотрібно. Розгледіти в жаби фюзеляж і шасі може кожен. Правда, як завжди, виникає проблема, що одне й те саме ціле можно декомпонувати у різні способи. І, в залежності від обраної моделі декомпозиції, можуть бути різні вузькі/слабкі місця. І тут вже тільки досвід, практика, набиті синці та гулі. За битого двох небитих.

Простий і зрозумілий кількісний показник.

Жарт вдався, дякую :)

структурну та функціональну декомпозицію — ані слова.

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

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

Ну, от візьмемо автомобіль. Якщо дивитися на нього в цілому, це купа металів та полімерів помороченої форми, що забезпечує функціонал їзди. Без декомпозиції розібратися в ньому непросто. Але ми можемо виокремити в автомобілі кузов, двигун, трансмісію, ходову, електрику, і розбиратися з ними по окремості. Двигун ми можемо теж декомпонувати на поршневу, розподіл етц. І так продовжуємо до останнього гвинтика.

Тут важливо те, що від нашої декомпозиції автомобіль не змінюється і не ускладнюється. Змінюється лише наше уявлення про автомобіль. Наше розуміння автомобіля. Перехід від цілісної НЁХ до стрункої ієрархії модулів, що дозволяє зрозуміти сабж, мені важко назвати ускладненням.

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

Перехід від цілісної НЁХ до стрункої ієрархії модулів, що дозволяє зрозуміти сабж, мені важко назвати ускладненням.

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

Вы говорите про уже готовую и рабочую систему.

Дивним чином більшість ІТ-задач — це «комп’ютеризація» вже існуючих систем. Банкінг, документообіг етц — всі вони існували і до виникнення ІТ. Інколи системи існують актуально, інколи — тільки в голові у замовника, але спільне одне — вони вже існують. Задача ІТ — це реалізувати існуючу систему на ІТ-базі. Реалізації ж повинен передувати етап зрозуміння цієї системи — якраз шляхом декомпозиції. Інколи в процесі декомпозиції вдається знайти косяки в архітектурі прототипу або в уявленні замовника про те, як повинна виглядати система. А без декомпозиції ТЗ виглядатиме як «зробіть кнопку ЗБС».

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

Як же ж не стає простіше, коли окремі задачі в межах окремого модуля стає можливим вирішувати?

Саме завдяки виокремленню незалежних модулів об’єм окремих компетенцій зменшується до рівня, доступного окремому фахівцю. Вивчить та розібратися в абсолютно всіх нюансах навіть такого нескладного агрегата, як автомобіль, здатні одиниці. Засвоїти нюанси обслуговування ходової вже здатні тисячі майстрів. А крутить гайки (в правильному порядку і з правильним моментом) вже може навчитися кожен другий.

Саме декомпозиція дозволяє делегувати певні роботи розробникам самих різних рівнів компетенції. Одному можна доручити аналіз термодинамічних процесів, а для іншого межею здатностей є не використовувати болти М4 там, де потрібні М12.

Подписаться на комментарии