Да, я просто Ваш тезис подкрепил реальным примером из того с чем вот прямо сейчас работают (что свежо в памяти).
Тут про то, что в БТ (бизнес-требования) в одном месте про отбор клиентов с активной записью не NI, в другом (хоть и по той же задаче) про получение даты из последней (но не обязательно активной) не NI записи, а про то что активная запись всегда будет последней по дате - это вообще БТ на совершенно другую задачу - организация и ведение этой самой таблицы.
И только сведение всех трех условия воедино дает вот такой неочевидный на первый непросвещённый взгляд результат в реализации.
И вот такие вещи - "почему тут сделано именно так" - и стоит писать в комментариях
Комментарии в коде нужны для прояснения неочевидных вещей. Попробую привести пример (не знаю, насколько удачно получится)
Есть задача обработки клиентов по определенной логике. Количество клиентов велико (пара-тройка десятков миллионов), каждый обрабатывается независимо от остальных, поэтому реализована параллельная обработка - одно (головное) задание занимается отбором клиентов по заданным критериям, формированием "пакетов" из нескольких клиентов и выкладкой их на "конвейер", другие (обработчики) в количестве 10 штук забирают пакеты с конвейера и обрабатывают содержавшихся в пакете клиентов.
В обработчике есть функция получения некой связанной с клиентом даты - даты смены типа идентификации клиента. Даты эти хранятся в исторической таблице. Там есть "активная" запись (текущий тип идентификации) которая является последней по дате и неактивные, исторические записи.
В ТЗ указано что надо выбрать последнюю по дате (не обязательно активную) запись, у которой тип идентификации не NI ("не идентифицирован") - так указано в бизнес-требованиях. А в коде, вместо поиска последней по дате записи с типом отличным от NI просто берется активная запись по уникальному (она может быть только одна для клиента) ключу.
И вот тут для понимания и избежания лишних вопросов уже нужен комментарий - в головном задании (а это другая программа и в ТЗ она описана отдельно) в условиях отбора клиентов стоит "отбор тех, у кого текущий уровень индентификации не NI" - это тоже бизнес-требования. Иными словами, когда обработчик получает клиента и приходит с ним в эту функцию, уже гарантировано что активная (последняя по дате) точно не NI - те, кто NI не пройдут отбор в головном задании и не попадут в обработчик.
Такие вот особенности логики нужно комментировать т.к. они могут быть неочевидны и реализация может вызывать вопросы.
Там еще есть один нюанс - документация связывает код с предметной областью.
Т.е. в документации может быть написано "получить выборку клиентов-ФЛ у которых отсутствует дата актуализации" и уровнем идентификации больше 0. Для аналитика это сразу понятно. Для разработчика тоже (если это не вася, которого вчера с вокзала позвали). Они оба сразу понимают как выбрать всех ФЛ из таблицы клиентов, ка проверить наличие у него даты актуализации и уровень идентификации...
А для ИИ придется загружать огромный объем информации (потому что на деле критериев может быть куда как больше - там и наличие счетов определенного типа и размеры остатков по счетам в рублевом эквиваленте и еще бог знает что) - фактически всю структуру БД из нескольких десятков тысяч таблиц с подробным описание какое поле в какой таблице что значит и в каких случаях для чего используется.
Прадедушка и через 35 лет работы от эффективного решения сложной задачи удовольствие получает :-) И, что характерно, ему платят именно за такие вот решения.
Ведь языки программирования намного лаконичней, чем естественные языки.
На самом деле нет.
Одну и ту же операцию "получить некую выборку из БД" в используемом сейчас инструменте я могут 3-5-ю разными способами. Не разными запросами, а именно разными способами - прямой доступ к БД по индексу, встроенный в код статический SQL запрос, встроенный в код динамический SQL запрос... И в каждом из способов еще могут быть вариации реализации...
Какой именно выбрать в каждом конкретном случае зависит от многих факторов. Размеры выборки, сценарии использования и т.п. И для каждой конкретной задачи оптимальное решение будет разным.
Чтобы ИИ выдал оптимальное решение, в него придется загружать огромный объем "сопутствующей" информации. На это тоже уйдет какое-то время.
И нужна соответствующее квалификация чтобы потом можно было адекватно оценить результат (не просто работает/не работает, а работает эффективно/не эффективно).
И возможно, придется делать несколько заходов - "этот код не будет эффективным потому что..." И это тоже время...
А так и получается примерно. Вся команда никогда не уходит. Уходит один человек, на его место приходит другой который быстро входит в курс дела (усилиями остальных членов команды).
Достаточно просто вести адекватные ТЗ, которые одновременно являются и документацией к коду. Ну а в коде в сложных местах вставлять комментарии связывающее блок кода с конкретными пунктами ТЗ.
А если вы уволитесь, чем будет отличаться ситуация, когда код написал ИИ или код написал другой программист, которого уже нет в проекте?
Примерно тем же, чем отличается совет ИИ пойти на автомойку пешком от реального решения поехать туда на машине.
На самом деле, когда аналитики берется за ТЗ, он всегда старается актуализировать его, приведя в соответствие с тем, что написано в коде.
ИИ может наставить поясняющих комментариев как в старом так и новом коде
Комментарии должны не код комментировать, а указывать на какую часть бизнес-логики он релаизует. Т.е. ИИ должен очень хорошо знать конкретную предметную область, архитектуру системы, структуру БД (а у нас это несколько десятков тысяч таблиц) и т.д. и т.п. прежде чем он сможет сказать хоть что-то внятное.
И да, все это никоим образом нельзя светить наружу, вся эта информация не должна выходить за пределы внутреннего контура.
У меня жена профессиональный переводчик. Причем, не бытовое бла-бла-бла, а научные статьи и технические тексты. Судя по тому, что переведенные ей статьи еще из серьезных журналов "по языку" не возвращали ни разу, переводчик неплохой.
Так, пользуется ИИ при переводе. Но только с целью уменьшения количества рутинной работы. Говорит что в целом справляется, но требуется тщательная проверка особенно в терминологии - может легко подцепить термины из смежной области.
Т.е. как помощник - да. Но под тщательным контролем. Полностью никак не заменит.
Вот прям пример из сегодняшнего. Есть некая задача, раскидана она по трем модулям (основным) + рабочая таблица. Эта задача отрабатывает раз в год. Периодически (фактически - каждый год) дорабатывается - бизнес приходит с новыми требованиями, нужно где-то что-то добавить, где-то что-то поменять. Я ей занимаюсь с, дай бог памяти, 19-го года. Последний раз лазил туда в прошлом году.
Но аналитики каждый год разные. И вот сейчас новый аналитик с вопросом - а как оно вообще работает (ТЗ там, конечно, есть, оно ведется и дорабатывается, но...)
Так вот, можно натравить на код ИИ и он объяснит. Но аналитик замучается все это разгребать т.к. там будет очень много лишней информации (там еще распараллеливание обработки имеет место быть - ему это нафиг не надо все.
А я посмотрел, вспомнил быстро и выкатил примерно на полстраницы то, что нужно именно аналитику для понимания как оно работает в целом. Основные важные моменты общей логики, без глубоких подробностей реализации.
Может. Но по времени, если логика сложная, а требования по производительности высокие, это может для хорошего разработчика занять больше времени чем написать самому
На то, чтобы объяснить ИИ все тонкости сложной бизнес-логики порой времени уходит больше, чем написать эту логику самому. Особенно, если знаешь предметную область и хорошо владеешь инструментом реализации.
А после ИИ все равно надо весь код досконально проверить и, скорее всего, поправить.
Он хорошо справляется с типовыми рутинными задачами условного "перекладывания джейсонов", но когда надо добиться максимальной эффективности в реализации чего-то сложного, тут времени уходит кратно больше.
Еще ИИ хорош как помощник в изучении чего-то нового. Когда задача ставится "а как вот тут вот это реализовать". А потом по каждой строке "а почему так, а можно иначе?".
Ну в целом таки да... Основная сложность в понимании тут заключается в тонкостях работы MOVE и его многочисленных модификациях - MOVE, MOVEL, MOVE(P), MOVEL(P), MOVEA...
Первая строка - заполнение переменной #OVSTR пробелами.
Далее - объявление #OVIDX типом с фиксированной точкой, 2 знака, 0 после запятой с одновременным занесением туда 1
Потом склейка строкового литерала 'USM2002' со значением переменной ZLINN и занесение результата в #OVSTR. А вот дальше магия...
MOVE '142' #OVSTR помещает строковый литерал '142' в конец #OVSTR (последние три позиции)
Дальше ищем строку #OVSTR в массиве строк APW. Поиск начинается с текущего значения #OVIDX (которое установлено в 1). Если строку нашли, то 50-й индикатор (*IN50) будет установлен в *ON (индикатор - логический тип принимающий значения *ON или *OFF, на самом деле тождественен CHAR(1) со значениями '1' или '0').
Если нашли и *IN50 = *ON, в #OVIDX будет содержаться индекс найденного элемента массива.
Ну а дальше MOVEL(P) которая уже нормально заносит найденный элемент массива (слева, (P) указывает на необходимость заполнить остаток результата пробелами) в переменную DSEPMS (если размер DSEPMS меньше чем APW(#OVIDX), ошибки не будет, просто обрежется то, что не влезло).
Современный RPGLE (free RPG) уже без всего этого. Там нормальный процедурный язык, без позиционности. И тот же lookup там выглядит абсолютно нормально
#OVRIDX = %LOOKUP(#OWRSTR: ARW);
Вернет индекс найденного элемента или 0 если не нашло.
Но вот аналогов MOVE сейчас нет. Есть обычное присвоение (слева, с обрезкой если не влезло или заполнением пробелами остатка), присвоение начиная справа или замена подстроки нужным значением. Т.е. вместо
MOVE '142' #OVSTR
Надо
%SUBSTR(#OVRSTR: %LEN(#OVRSTR) - 2) = '142';
Т.е. замена последних трех символов #OVRSTR значением '142'.
%substr, кстати, может использоваться как lvalue, так и rvalue - или заменить подстроку в строке или извлечь подстроку из строки.
А вот вместо
MOVEL(P) APW(#OVIDX) DSEPMS
будет просто
DSEPMS = APW(#OVIDX);
и вместо
'USM2002' CAT(P) ZLINN #OVSTR
тоже просто
#OVSTR = 'USM2002' + ZLINN;
Основная проблема fixed в его позиционности. Вложенные if или циклы читать невозможно - отступов нет. Поэтому первые 4 позиции - отведены под "метки". Скажем для внешнего if там ставят B001, для вложенного B002 и т.д. Соотвественно, для endif ставится E002, E001... Ну чтобы хоть как-то всю эту кашу развидеть можно было.
В общем, я со всем этим уже более 9-ти лет работаю, но fixed (хотя его немало попадается в старых модулях что на доработку приходят) все еще "по слогам" читаю, а свободно писать на нем так и не могу, только free... Благо компилятор понимает в том числе и мешанину из fixed и free кода - все новые вставки уже на free делаем
Ага. Особенно когда в доме животные - задолбаетесь настраивать датчики чтобы они срабатывали на человека (в т.ч. ребенка), но не срабатывали на собаку (особенно если это средняя или крупная порода).
Там где надо (например, на крыльце) - да, стоят. Внутри дома - больше проблем.
SAX хорош для больших XML и в тех случаях когда вам нужно только прочитать документ и извлечь из него какие-то данные (причем, вам может интересовать далеко не все что есть в документе).
DOM хорош для небольших документов, особенно в ситуациях когда вам надо прочитать, внести изменения и сохранить обратно.
И тут как всегда - сначала вникаем в задачу, а потом подбираем под нее оптимальный инструмент. А не всегда используем только то, что когда-то уже использовали просто потому что оно знакомое.
При работе с SAX еще надо "в голове" держать контекст. Вот пример
Тут мы видим что теги <Идентификатор> и <Наименование> могут быть как внутри тега <ТипСубъекта>, так и внутри тега <ТипДокумента>
В такой ситуации вам необходимо Устанавливать внутри какого внешнего тега вы находитесь чтобы правильно обработать тег внутренний. И это тоже ложится на вас.
Если у вас плохо расположены выключатели, то где гарантия, что все остальное сделано нормально? Если электрик делал абы как, то скорее всего там все так сделано.
Да, я просто Ваш тезис подкрепил реальным примером из того с чем вот прямо сейчас работают (что свежо в памяти).
Тут про то, что в БТ (бизнес-требования) в одном месте про отбор клиентов с активной записью не NI, в другом (хоть и по той же задаче) про получение даты из последней (но не обязательно активной) не NI записи, а про то что активная запись всегда будет последней по дате - это вообще БТ на совершенно другую задачу - организация и ведение этой самой таблицы.
И только сведение всех трех условия воедино дает вот такой неочевидный на первый непросвещённый взгляд результат в реализации.
И вот такие вещи - "почему тут сделано именно так" - и стоит писать в комментариях
Комментарии в коде нужны для прояснения неочевидных вещей. Попробую привести пример (не знаю, насколько удачно получится)
Есть задача обработки клиентов по определенной логике. Количество клиентов велико (пара-тройка десятков миллионов), каждый обрабатывается независимо от остальных, поэтому реализована параллельная обработка - одно (головное) задание занимается отбором клиентов по заданным критериям, формированием "пакетов" из нескольких клиентов и выкладкой их на "конвейер", другие (обработчики) в количестве 10 штук забирают пакеты с конвейера и обрабатывают содержавшихся в пакете клиентов.
В обработчике есть функция получения некой связанной с клиентом даты - даты смены типа идентификации клиента. Даты эти хранятся в исторической таблице. Там есть "активная" запись (текущий тип идентификации) которая является последней по дате и неактивные, исторические записи.
В ТЗ указано что надо выбрать последнюю по дате (не обязательно активную) запись, у которой тип идентификации не NI ("не идентифицирован") - так указано в бизнес-требованиях. А в коде, вместо поиска последней по дате записи с типом отличным от NI просто берется активная запись по уникальному (она может быть только одна для клиента) ключу.
И вот тут для понимания и избежания лишних вопросов уже нужен комментарий - в головном задании (а это другая программа и в ТЗ она описана отдельно) в условиях отбора клиентов стоит "отбор тех, у кого текущий уровень индентификации не NI" - это тоже бизнес-требования. Иными словами, когда обработчик получает клиента и приходит с ним в эту функцию, уже гарантировано что активная (последняя по дате) точно не NI - те, кто NI не пройдут отбор в головном задании и не попадут в обработчик.
Такие вот особенности логики нужно комментировать т.к. они могут быть неочевидны и реализация может вызывать вопросы.
Там еще есть один нюанс - документация связывает код с предметной областью.
Т.е. в документации может быть написано "получить выборку клиентов-ФЛ у которых отсутствует дата актуализации" и уровнем идентификации больше 0. Для аналитика это сразу понятно. Для разработчика тоже (если это не вася, которого вчера с вокзала позвали). Они оба сразу понимают как выбрать всех ФЛ из таблицы клиентов, ка проверить наличие у него даты актуализации и уровень идентификации...
А для ИИ придется загружать огромный объем информации (потому что на деле критериев может быть куда как больше - там и наличие счетов определенного типа и размеры остатков по счетам в рублевом эквиваленте и еще бог знает что) - фактически всю структуру БД из нескольких десятков тысяч таблиц с подробным описание какое поле в какой таблице что значит и в каких случаях для чего используется.
Прадедушка и через 35 лет работы от эффективного решения сложной задачи удовольствие получает :-) И, что характерно, ему платят именно за такие вот решения.
Именно так. Особенно это заметно по переводам всяких фильмов...
А вот когда идет статья в приличный рейтинговый журнал, то там ее могут запросто не принять по причине плохого качества перевода.
На самом деле нет.
Одну и ту же операцию "получить некую выборку из БД" в используемом сейчас инструменте я могут 3-5-ю разными способами. Не разными запросами, а именно разными способами - прямой доступ к БД по индексу, встроенный в код статический SQL запрос, встроенный в код динамический SQL запрос... И в каждом из способов еще могут быть вариации реализации...
Какой именно выбрать в каждом конкретном случае зависит от многих факторов. Размеры выборки, сценарии использования и т.п. И для каждой конкретной задачи оптимальное решение будет разным.
Чтобы ИИ выдал оптимальное решение, в него придется загружать огромный объем "сопутствующей" информации. На это тоже уйдет какое-то время.
И нужна соответствующее квалификация чтобы потом можно было адекватно оценить результат (не просто работает/не работает, а работает эффективно/не эффективно).
И возможно, придется делать несколько заходов - "этот код не будет эффективным потому что..." И это тоже время...
А так и получается примерно. Вся команда никогда не уходит. Уходит один человек, на его место приходит другой который быстро входит в курс дела (усилиями остальных членов команды).
Достаточно просто вести адекватные ТЗ, которые одновременно являются и документацией к коду. Ну а в коде в сложных местах вставлять комментарии связывающее блок кода с конкретными пунктами ТЗ.
Примерно тем же, чем отличается совет ИИ пойти на автомойку пешком от реального решения поехать туда на машине.
На самом деле, когда аналитики берется за ТЗ, он всегда старается актуализировать его, приведя в соответствие с тем, что написано в коде.
Комментарии должны не код комментировать, а указывать на какую часть бизнес-логики он релаизует. Т.е. ИИ должен очень хорошо знать конкретную предметную область, архитектуру системы, структуру БД (а у нас это несколько десятков тысяч таблиц) и т.д. и т.п. прежде чем он сможет сказать хоть что-то внятное.
И да, все это никоим образом нельзя светить наружу, вся эта информация не должна выходить за пределы внутреннего контура.
У меня жена профессиональный переводчик. Причем, не бытовое бла-бла-бла, а научные статьи и технические тексты. Судя по тому, что переведенные ей статьи еще из серьезных журналов "по языку" не возвращали ни разу, переводчик неплохой.
Так, пользуется ИИ при переводе. Но только с целью уменьшения количества рутинной работы. Говорит что в целом справляется, но требуется тщательная проверка особенно в терминологии - может легко подцепить термины из смежной области.
Т.е. как помощник - да. Но под тщательным контролем. Полностью никак не заменит.
Есть большие, долгоживущие (и развивающиеся) системы где отдельные модули не то что годами, десятилетиями работают.
Вот прям пример из сегодняшнего. Есть некая задача, раскидана она по трем модулям (основным) + рабочая таблица. Эта задача отрабатывает раз в год. Периодически (фактически - каждый год) дорабатывается - бизнес приходит с новыми требованиями, нужно где-то что-то добавить, где-то что-то поменять. Я ей занимаюсь с, дай бог памяти, 19-го года. Последний раз лазил туда в прошлом году.
Но аналитики каждый год разные. И вот сейчас новый аналитик с вопросом - а как оно вообще работает (ТЗ там, конечно, есть, оно ведется и дорабатывается, но...)
Так вот, можно натравить на код ИИ и он объяснит. Но аналитик замучается все это разгребать т.к. там будет очень много лишней информации (там еще распараллеливание обработки имеет место быть - ему это нафиг не надо все.
А я посмотрел, вспомнил быстро и выкатил примерно на полстраницы то, что нужно именно аналитику для понимания как оно работает в целом. Основные важные моменты общей логики, без глубоких подробностей реализации.
И это быстрее чем мучать ИИ.
Может. Но по времени, если логика сложная, а требования по производительности высокие, это может для хорошего разработчика занять больше времени чем написать самому
Ну вообще тимлид не занимается ревью как правило. У него другие задачи. Ревью делают сеньоры и техлиды.
И на ревью большей частью проверяются паттерны разработки и соответствие нефункциональным требованиям.
На то, чтобы объяснить ИИ все тонкости сложной бизнес-логики порой времени уходит больше, чем написать эту логику самому. Особенно, если знаешь предметную область и хорошо владеешь инструментом реализации.
А после ИИ все равно надо весь код досконально проверить и, скорее всего, поправить.
Он хорошо справляется с типовыми рутинными задачами условного "перекладывания джейсонов", но когда надо добиться максимальной эффективности в реализации чего-то сложного, тут времени уходит кратно больше.
Еще ИИ хорош как помощник в изучении чего-то нового. Когда задача ставится "а как вот тут вот это реализовать". А потом по каждой строке "а почему так, а можно иначе?".
Ну в целом таки да... Основная сложность в понимании тут заключается в тонкостях работы MOVE и его многочисленных модификациях - MOVE, MOVEL, MOVE(P), MOVEL(P), MOVEA...
Первая строка - заполнение переменной
#OVSTRпробелами.Далее - объявление
#OVIDXтипом с фиксированной точкой, 2 знака, 0 после запятой с одновременным занесением туда 1Потом склейка строкового литерала
'USM2002'со значением переменнойZLINNи занесение результата в#OVSTR. А вот дальше магия...MOVE '142' #OVSTRпомещает строковый литерал'142'в конец#OVSTR(последние три позиции)Дальше ищем строку
#OVSTRв массиве строкAPW. Поиск начинается с текущего значения#OVIDX(которое установлено в 1). Если строку нашли, то 50-й индикатор (*IN50) будет установлен в*ON(индикатор - логический тип принимающий значения*ONили*OFF, на самом деле тождественен CHAR(1) со значениями '1' или '0').Если нашли и
*IN50 = *ON, в#OVIDXбудет содержаться индекс найденного элемента массива.Ну а дальше
MOVEL(P)которая уже нормально заносит найденный элемент массива (слева,(P)указывает на необходимость заполнить остаток результата пробелами) в переменнуюDSEPMS(если размерDSEPMSменьше чемAPW(#OVIDX), ошибки не будет, просто обрежется то, что не влезло).Современный RPGLE (free RPG) уже без всего этого. Там нормальный процедурный язык, без позиционности. И тот же lookup там выглядит абсолютно нормально
#OVRIDX = %LOOKUP(#OWRSTR: ARW);Вернет индекс найденного элемента или 0 если не нашло.
Но вот аналогов MOVE сейчас нет. Есть обычное присвоение (слева, с обрезкой если не влезло или заполнением пробелами остатка), присвоение начиная справа или замена подстроки нужным значением. Т.е. вместо
MOVE '142' #OVSTRНадо
%SUBSTR(#OVRSTR: %LEN(#OVRSTR) - 2) = '142';Т.е. замена последних трех символов
#OVRSTRзначением'142'.%substr, кстати, может использоваться как lvalue, так и rvalue - или заменить подстроку в строке или извлечь подстроку из строки.
А вот вместо
MOVEL(P) APW(#OVIDX) DSEPMSбудет просто
DSEPMS = APW(#OVIDX);и вместо
'USM2002' CAT(P) ZLINN #OVSTRтоже просто
#OVSTR = 'USM2002' + ZLINN;Основная проблема fixed в его позиционности. Вложенные if или циклы читать невозможно - отступов нет. Поэтому первые 4 позиции - отведены под "метки". Скажем для внешнего if там ставят B001, для вложенного B002 и т.д. Соотвественно, для endif ставится E002, E001... Ну чтобы хоть как-то всю эту кашу развидеть можно было.
В общем, я со всем этим уже более 9-ти лет работаю, но fixed (хотя его немало попадается в старых модулях что на доработку приходят) все еще "по слогам" читаю, а свободно писать на нем так и не могу, только free... Благо компилятор понимает в том числе и мешанину из fixed и free кода - все новые вставки уже на free делаем
Это старый RPG FIXED И вы мне будете рассказывать про нечитаемость :-)
Ага. Особенно когда в доме животные - задолбаетесь настраивать датчики чтобы они срабатывали на человека (в т.ч. ребенка), но не срабатывали на собаку (особенно если это средняя или крупная порода).
Там где надо (например, на крыльце) - да, стоят. Внутри дома - больше проблем.
SAX хорош для больших XML и в тех случаях когда вам нужно только прочитать документ и извлечь из него какие-то данные (причем, вам может интересовать далеко не все что есть в документе).
DOM хорош для небольших документов, особенно в ситуациях когда вам надо прочитать, внести изменения и сохранить обратно.
И тут как всегда - сначала вникаем в задачу, а потом подбираем под нее оптимальный инструмент. А не всегда используем только то, что когда-то уже использовали просто потому что оно знакомое.
При работе с SAX еще надо "в голове" держать контекст. Вот пример
и в том же XML
Тут мы видим что теги <Идентификатор> и <Наименование> могут быть как внутри тега <ТипСубъекта>, так и внутри тега <ТипДокумента>
В такой ситуации вам необходимо Устанавливать внутри какого внешнего тега вы находитесь чтобы правильно обработать тег внутренний. И это тоже ложится на вас.
Если у вас плохо расположены выключатели, то где гарантия, что все остальное сделано нормально? Если электрик делал абы как, то скорее всего там все так сделано.