Comments 38
Сложность программирования не в написании кода.
Сложность программирования не в реализации алгоритмов.
Теперь уже и я заинтригован :-)
Придумать алгоритм (и доказать его правильность, оценки производительности и т.д.) — это computer science. Двухколоночная вёрстка в рецензированном журнале, индекс цитирования потом, может быть, структура данных имени себя.
Реализовать алгоритм (т.е. закодировать его по оной статье с двухколоночной вёрсткой) — ну, интересное упражнение на знание языка, не более.
99% кода не реализует никаких специально выделенных алгоритмов, а использует готовые в составе библиотек.
99% кода — принимает решения в соотвествии с бизнес-логикой или выполняет требования (других кусков кода). Или борется с требованиями. Или подстаивается под них. Или пытается оные требования угадать.
Основная сложность в программировании (как инжинерной дисциплины) — это сопровождение кода. Не написать программу, а написать программу так, чтобы она соответствовала ожиданиям. Не только ТЗ, но и ожиданиям идустрии, другого ПО. Написать так, чтобы в неё потом можно было вносить изменения за разумное время. Написать так, чтобы изменения с ошибками были отловлены на этапе тестирования. Иметь инфраструктуру этого тестирования.
… А потом оно всё гниёт, потому что документации нет и следующему человеку легче написать своё, чем разбираться "в этом".
… легче написать своё, чем разбираться «в этом»Так вот «это» и есть сложность языка программирования. И если из написанного непонятно, что и как должно выполняться, то ни ТЗ, ни инфраструктура тут не помогут.
Если у вас есть покрытие тестами, актуальное ТЗ, инфраструктура сборки и деплоя (работающие), то на содержимое кода можно смотреть, можно не смотреть. Сопровождать такое будет если и не удовольствие, то "окей".
А вот если тестов нет, кода сборки/деплоя нет, документации нет, тот тут, действительно, больно. Опять же, вне зависимости от того, как хорошо оно написано.
Мы обсуждаем две крайности.
Первая, это когда система не имеет документации, ТЗ и тестов и единственный способ в ней разобраться — это исходный код. Для такой системы, естественно, логичность кода и понятность языка будут иметь первостепенное знание.
Вторая крайность, это есть сборка, деплой, тесты, ТЗ, но исходники написаны на каком нибудь Brainfuck`е
Но если ни в первом, ни во втором случае разобраться не получается, то единственный выход, переписать все с нуля.
Реальный код (то, что обычно на продакшене крутится) не похож на учебные примеры, и ключевой его особенностью является сложность. Вне зависимости от изящества языка и конструкций в тексте, его будет много. Вопросов, которые код покрывает, будет много. Неконсистентностей и затычек для них будет много. Без инфраструктуры вокруг оно будет не разбирабельно.
В коде на 10000 разобраться можно без документации (при должном энтузиазме). В коде на 10+ миллионов строк — нет.
Не зависимо от того, как хорошо документирован код, через какое то время устаревают инструменты, необходимые для него работы, завершаются жизненные циклы внешних зависимостей, и самое главное, приходят новые люди взамен тех, кто уже смог разобраться в системе.
И у новых людей возникает необходимость разбираться в системе с самого начала, но в других начальных условиях (новые инструменты, новые версии языком программирования и т.д.)
Основная идея статьи заключается в том, что сложность изучения системы для новых людей растет даже в том случае,
Если у вас есть покрытие тестами, актуальное ТЗ, инфраструктура сборки и деплоя (работающие), то на содержимое кода можно смотреть, можно не смотреть.
Просто по факту того, что меняются (усложняются) рабочие инструменты, которые приходится использовать новым сотрудникам.
Основная сложность в программировании (как инжинерной дисциплины) — это сопровождение кода.
В чем сложность сопровождения кода выполнения команды 'grep' в Linux'е?
Ну если смотреть на историю, то у грепа вышла куча релизов, при этом вроде бы ни один не сломал обратную совместимость ни на одной из архитектур или платформ.
Вот это выглядит выше моего текущего paygrade: https://git.savannah.gnu.org/cgit/grep.git/tree/configure.ac
А вот пример активной жизни:
https://git.savannah.gnu.org/cgit/grep.git/commit/?id=192e59903c7d313bb47de3d5c15b3dc634e98c5f
https://git.savannah.gnu.org/cgit/grep.git/commit/?id=016e590a8198009bce0e1078f6d4c7e037e2df3c
Ну, я китайский тоже не понимаю, но я его и не изучал. Если начну изучать — начну понимать. Посмотрел историю изменений — не видно, что там люди упахиваются. Ни по комментам, ни по кол-ву изменений в коде — за прошлый год было меньше сотни коммитов от 5 человек в сумме.
Если у вас есть покрытие тестами, актуальное ТЗ, инфраструктура сборки и деплоя (работающие), то на содержимое кода можно смотреть, можно не смотреть.
В чём же тогда, по-вашему, выражается "сопровождение кода", если на "содержимое кода" можно даже не смотреть при определённых условиях? И в чём сложность такого "сопровождения"?
Внесение изменений и исправление ошибок, в т.ч. не покрытых тестами.
Внесение изменений в существующий код, по вашему, не является "написанием кода"? Согласно этой логики мы пишем код до первого сохранения, после чего — сопровождаем.
У меня слегка устаревшие взгляды, я считаю написанием кода любое его редактирование. Вне зависимости есть ли к этому коду тесты, является ли код выполняемой программой или библиотекой, будет ли он компилироваться в машкоды или транспилироваться в другой язык. Машинные коды — это тоже программа для определённого типа процессоров и её тоже можно написать ручками в шестнадцатеричном редакторе. Когда-то ценностью являлся сам код (программа), а не вот это вот всё вокруг неё.
Походу, в IT появилось слишком много специалистов, которые не могут создавать код, но могут его сопровождать, раз заявления "сложность программирования не в написании кода" встречает такое понимание. Вот только компьютеры остались прежними — они по прежнему выполняют двоичный код в массе своей. И мы по прежнему должны составлять программы, если хотим от них чего-то добиться.
И не нужно путать "программиста" и "разработчика ПО" — это очень разные специальности.
Я вижу много язвительности у вас. Все, кто могут сопровождать код, могут его писать (потому что нужно писать патчи и вообще, дорабатывать напильником). Обратное не всегда верно, потому что сопровождающий иногда видит кусок системы, которую не видит программист.
В целом, code is liability. Вы утверждаете, что у кода — положительная ценность (это asset), а я утверждаю, что отрицательная (это liability, т.е. обязательства). Потому что написать код легко. Взял и написал. Он даже здесь-и-сейчас проблему решил. А вот после того, как код (который решает проблему здесь-и-сейчас) попал в состав более крупного продукта, компания, которая это получила себе в хозяйство, будет вынуждена учитывать существование этого кода, и либо модифицировать его, либо адпатировать другой код (до/после) для учёта специфичных требований этого кода.
Так что первые вопросы, который я задаю людям, предлагающим "написать самим", это "какие существующие решения ты уже посмотрел? Почему каждое из них не подоходит?". Примерно в половине случаев оказывается, что либо уже есть решение, либо есть метод решеня в существующем ПО.
Обычно происходит создание кода чтобы решить проблему (удостовериться, что код выполняет свою задачу), и только после этого новый код необходимо провести в состояние, годное для публикации в составе более крупного проекта (оформление, комментарии, автодокументирование и т.д.).
Если сделать только первое (написал и оставит без оформления), то «просто код» будет решать поставленную перед ним задачу, но сопрвождать такой код в дальнейшем действительно будет очень тяжело.
И если мне не изменяет память, то Брукса писал про множитель х3 для трудозатрат, необходимых для превращения «просто кода» в «код, пригодный для поддержки».
Язвительность — черта моего характера. Сам я с этим смирился, а остальные ещё в процессе. Программирование — это написание кода, а не его сопровождение. Сопровождение же включает в себя также и программирование. Если вы утверждаете обратное (что программирование включает в себя сопровождение), то вы вывернули носок наизнанку.
Код, который решает проблемы "здесь-и-сейчас" не был написан для более крупного продукта, а был написан для "здесь" и "сейчас". Тот, кто воткнул этот код в состав более крупного продукта — вот он и есть злобный буратин, а не программист, который код написал.
Сейчас модно программировать из блоков — набрать набор инструментов (фреймворки/библиотеки), обмазать всё интеграционным кодом, воткнуть бизнес-функций, описать красиво и продать подороже. Это ваш же подход — взять решение, которое было сделано для другой предметной области, и перетянуть в свою. Скопом. Со всеми плюсами и минусами. Без учёта нюансов. Так быстрее и дешевле. Да, в короткой перспективе. А в долгой — программа из asset превращается в liability.
Я утверждаю, что код должен решать поставленную задачу и выкидываться, как только он из asset превратился в liability.
А в чём? Я заинтригован.
А его сопровождении. Написать код вам может почти кто угодно. С 99.999% написанное не будет решением поставленной задачи в полном объёме (будут баги).
И вот тут вот начинается любопытное. Если к этому добавить изменяющееся окружение и требования, ситуация становится менее любопытной и более привычной.
Само собой чем дольше разрабатывается проект тем он становится сложнее, но как правило при этом уменьшается сложность поддержки и внедрения новых фич, потому что в основном они строятся по верх уже написанного кода, а потому более сложные вещи должны внедрятся проще. Простой пример, возьмём разработку UI, переиспользование готовых виджетов, чем больше виджетов становится тем проще писать код с их использованием, следовательно процесс разработки становится проще. Не будете же вы писать при каждом использовании виджета его по новой.
… писать новый становится проще. Поменять старый — легче повеситься, потому что из 100 использованных виджетов только 10 актуальные, ещё 10 используются не по назначению, а оставшиеся переплетены в такой комок, что страшно даже думать.
Хотите простой пример? Возьмите любую программу образца 2002 года, поддерживающую юникод (unicode 3.2) и попытайтесь туда добавить современный юникод с поддержкой цвета кожи (13.0).
Так сказать, удачи.
IMHO, сопровождение кода, не являющееся написанием кода — это не программирование. Анализ требований — это не программирование, devops — это не программирование, документирование — это не программирование. Даже отладка — не программирование. Сопровождение кода шире, чем программирование, поэтому сложнее. Но программирование — это и есть написание кода, программы.
"Сложность разработки ПО не в написании кода." — с этим я согласен.
По моему на эту тему уже давным давно все разжевали очень популярно. Метрик нет, не будет и быть не может.
Далее поводу порог входа и прочей мишуры: ну имели мы уже php с низким порогом входа и что получили? Огромное количество кода который поддерживать невозможно, трейсить нереально, etc Теперь php почти «оджавился», после 8 версии я даже не знаю, почему бы людям сразу JSP не брать.
ЗЫ Ну и накину еще чуток, вот одна строка кода. Сложная она или простая? Сможете сходу сказать что тут происходит? А не сходу?
var result = document.evaluate("tbody/tr[not(contains(translate(., '"+search.toUpperCase()+"', '"+search+"'), '"+search+"'))]", tableObj, null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
ЗЫЗЫ чего все так к коду привязались? Непосредственно его написание не так уж много времени занимает в работе разработчика
А «сложность» строки кода как раз определяется возможностями синтаксиса языка. И если вам не понятно, что там написано и как это должно работать, то в этом есть и толика проблемы самого языка программирования.
И вопрос не в написании кода, а в его понимании.
SLOC нельзя сравнивать у разных проектов. Но в рамках одного проекта, который использует единые стандарты кодирования, вполне можно.
Про эпидемию индусского кода напомнить?
В принципе, получить сферическую относительную сложность ВСЕГО проекта — можно, конкретный модуль — уже врядли, конкретную задачу — точно нет. Могу даже пример привести: PG13 строит r-tree индексы на 1-2 порядка быстрее. Патч, реализующий сортировки через Z-нотацию довольно прост и элегантен, осталось вот только понять почему до этого никто раньше не додумался а если додумался почему не реализовал.
про сложное дело под названием «программирование». И то, что программирование действительно является делом не простым воспринимается как факт и обычно не требует какого либо подтверждения.
Но понятие «сложность» сродни термину «куча»
Напомню с чего вы начали, как вы так быстро спустились сразу к коду — для меня загадка.
Кстати а какая практическая польза вашей «метрики»?
Про эпидемию индусского кода напомнить?Попробуйте запостить индусский код в какой нибудь Open Source проект.
Начал я с того, что сложность разработки ПО растет, но почему — не понятно.
А польза от статьи в том, что сложность (и стоимость) разработки/поддержки программного проекта можно попробовать рассматривать не только как производную от кода самого проекта, но попробовать учитывать увеличение сложность используемых инструментов разработки.
Яркий пример С++, после стандарта 11, многие вещи стало писать намного проще.
Ну и да мерить по SLOC это совсем неправильно. В программировании самое сложное это продумывать архитектуру и придумывать новые алгоритмы. Самое интересное, что чем лучше продумана архитектура тем меньше SLOC получишь и тем проще разработка, ну и соответственно наоборот. По крайней мере обычно это так.
То, что писать с использованием С11 стало проще, полностью согласен. Особенно если пишется изолированный кусок кода. Но все становится печальнее, если разработчик вынужден писать с поддержкой старых версий (например, для обеспечения обратной совместимости). В этом случае тоже упрощения не получается, новый стандарт нужно выучить и одновременно помнить, где его нельзя использовать.
Про архитектуру полностью согласен! Но сейчас речь идет о сравнении кода в одном проекте, с единой архитектурой и стандартом кодирования, так что влияние архитектуры на SLOC в рамках одного проекта будет минимально.
Скорее всего, тут как раз обратная зависимость, т.к. большее количество людей требует более мелкой декомпозиции задач и большего объема работ при взаимодействии в проекте. А если активность связана с изменчивостью требований (или наращиванием функционала), то от этого сложность конечного продукта тоже не уменьшится.
Вы возможно путаете сложность проекта как такового и сложность разработки\поддержки. Само собой чем дольше разрабатывается проект тем он становится сложнее, но как правило при этом уменьшается сложность поддержки и внедрения новых фич, потому что в основном они строятся по верх уже написанного кода, а потому более сложные вещи должны внедрятся проще. Простой пример, возьмём разработку UI, переиспользование готовых виджетов, чем больше виджетов становится тем проще писать код с их использованием, следовательно процесс разработки становится проще. Не будете же вы писать при каждом использовании виджета его по новой.
… потому что в основном они строятся по верх уже написанного кода, а потому более сложные вещи должны внедрятся проще.Знаете, у нас с вами наверно разный опыт. То, что вы написали работает только для небольших или не очень старых проектов. Но если проект разрастается выше определенного предела, то его поддержка и добавление новых фич наоборот становится значительно сложнее, т.к. могут появляться совсем не очевидные зависимости в легаси коде, который уже все позабыли, но который все еще нужно поддерживать.
В противном случае, все бы так и делали, как вы говорите. Или даже можно было бы всем миром навалиться и сделать одну супер-пупер библиотеку, в которой будет все (или почти все). А потом легким движением руки «поверх написанного кода» можно будет создавать новые формы.
Не верю! (С)
Мне сразу вспомнились однострочники на перле, когда заговорили про кол-во строк в контексте сложности.
В го куча такого:
if err != nil {
…
}
Серьезно, такие проверки на ошибки в количестве строк могут занимать 10-20% кода. Неужели это можно считать сложностью?
И когда вы будете сравнивать SLOC одного и того же проекта в разные моменты времени, то они не будут влиять на разницу в оценке сложности (если они составляют постоянный процент от общего кода).
Простое сложное программирование