Как стать автором
Обновить

Комментарии 38

Сложность программирования не в написании кода.

«Сложность» понятие относительное. Если писать один и тот же алгоритм с помощью разных инструментов, то сложность его реализации будет зависеть от сложности/понятности используемого инструмента.

Сложность программирования не в реализации алгоритмов.

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

Теперь уже и я заинтригован :-)

Придумать алгоритм (и доказать его правильность, оценки производительности и т.д.) — это computer science. Двухколоночная вёрстка в рецензированном журнале, индекс цитирования потом, может быть, структура данных имени себя.


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


99% кода не реализует никаких специально выделенных алгоритмов, а использует готовые в составе библиотек.


99% кода — принимает решения в соотвествии с бизнес-логикой или выполняет требования (других кусков кода). Или борется с требованиями. Или подстаивается под них. Или пытается оные требования угадать.


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


… А потом оно всё гниёт, потому что документации нет и следующему человеку легче написать своё, чем разбираться "в этом".

… легче написать своё, чем разбираться «в этом»
Так вот «это» и есть сложность языка программирования. И если из написанного непонятно, что и как должно выполняться, то ни ТЗ, ни инфраструктура тут не помогут.

Если у вас есть покрытие тестами, актуальное ТЗ, инфраструктура сборки и деплоя (работающие), то на содержимое кода можно смотреть, можно не смотреть. Сопровождать такое будет если и не удовольствие, то "окей".


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

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

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

Вторая крайность, это есть сборка, деплой, тесты, ТЗ, но исходники написаны на каком нибудь Brainfuck`е

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

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


В коде на 10000 разобраться можно без документации (при должном энтузиазме). В коде на 10+ миллионов строк — нет.

Вот мы и подходим к главному.

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

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

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

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

В чем сложность сопровождения кода выполнения команды 'grep' в Linux'е?

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

Куча релизов на куче архитектур/платформ и ни одного слома говорит о том, что сопровождение grep простое или что сопровождение grep сложное?

Ну, я китайский тоже не понимаю, но я его и не изучал. Если начну изучать — начну понимать. Посмотрел историю изменений — не видно, что там люди упахиваются. Ни по комментам, ни по кол-ву изменений в коде — за прошлый год было меньше сотни коммитов от 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 — это не программирование, документирование — это не программирование. Даже отладка — не программирование. Сопровождение кода шире, чем программирование, поэтому сложнее. Но программирование — это и есть написание кода, программы.


"Сложность разработки ПО не в написании кода." — с этим я согласен.

SLOC? Серьезно?
По моему на эту тему уже давным давно все разжевали очень популярно. Метрик нет, не будет и быть не может.

Далее поводу порог входа и прочей мишуры: ну имели мы уже 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 нельзя сравнивать у разных проектов. Но в рамках одного проекта, который использует единые стандарты кодирования, вполне можно.

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

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

Про эпидемию индусского кода напомнить?

В принципе, получить сферическую относительную сложность ВСЕГО проекта — можно, конкретный модуль — уже врядли, конкретную задачу — точно нет. Могу даже пример привести: PG13 строит r-tree индексы на 1-2 порядка быстрее. Патч, реализующий сортировки через Z-нотацию довольно прост и элегантен, осталось вот только понять почему до этого никто раньше не додумался а если додумался почему не реализовал.

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

Но понятие «сложность» сродни термину «куча»

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

Кстати а какая практическая польза вашей «метрики»?
Про эпидемию индусского кода напомнить?
Попробуйте запостить индусский код в какой нибудь Open Source проект.

Начал я с того, что сложность разработки ПО растет, но почему — не понятно.

А польза от статьи в том, что сложность (и стоимость) разработки/поддержки программного проекта можно попробовать рассматривать не только как производную от кода самого проекта, но попробовать учитывать увеличение сложность используемых инструментов разработки.
Ну обычно сложность инструмента увеличивает сложность входа, но при активной разработке обычно наоборот уменьшает сложность разработки\поддержки.
Яркий пример С++, после стандарта 11, многие вещи стало писать намного проще.
Ну и да мерить по SLOC это совсем неправильно. В программировании самое сложное это продумывать архитектуру и придумывать новые алгоритмы. Самое интересное, что чем лучше продумана архитектура тем меньше SLOC получишь и тем проще разработка, ну и соответственно наоборот. По крайней мере обычно это так.
Если честно, то я не вижу связи между активной разработкой и уменьшением сложности работ. Скорее всего, тут как раз обратная зависимость, т.к. большее количество людей требует более мелкой декомпозиции задач и большего объема работ при взаимодействии в проекте. А если активность связана с изменчивостью требований (или наращиванием функционала), то от этого сложность конечного продукта тоже не уменьшится.

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

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

Вы возможно путаете сложность проекта как такового и сложность разработки\поддержки. Само собой чем дольше разрабатывается проект тем он становится сложнее, но как правило при этом уменьшается сложность поддержки и внедрения новых фич, потому что в основном они строятся по верх уже написанного кода, а потому более сложные вещи должны внедрятся проще. Простой пример, возьмём разработку UI, переиспользование готовых виджетов, чем больше виджетов становится тем проще писать код с их использованием, следовательно процесс разработки становится проще. Не будете же вы писать при каждом использовании виджета его по новой.
… потому что в основном они строятся по верх уже написанного кода, а потому более сложные вещи должны внедрятся проще.
Знаете, у нас с вами наверно разный опыт. То, что вы написали работает только для небольших или не очень старых проектов. Но если проект разрастается выше определенного предела, то его поддержка и добавление новых фич наоборот становится значительно сложнее, т.к. могут появляться совсем не очевидные зависимости в легаси коде, который уже все позабыли, но который все еще нужно поддерживать.

В противном случае, все бы так и делали, как вы говорите. Или даже можно было бы всем миром навалиться и сделать одну супер-пупер библиотеку, в которой будет все (или почти все). А потом легким движением руки «поверх написанного кода» можно будет создавать новые формы.

Не верю! (С)

Мне сразу вспомнились однострочники на перле, когда заговорили про кол-во строк в контексте сложности.
В го куча такого:
if err != nil {

}
Серьезно, такие проверки на ошибки в количестве строк могут занимать 10-20% кода. Неужели это можно считать сложностью?

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