Писать код легко. Как только у вас есть решение и вы освоили синтаксис любимого языка программирования, писать код легко. А если LLM пишет для вас целые функции? Ещё проще. Но самое сложное — не само написание. А чтение. Время, необходимое для загрузки ментальной модели системы в вашу голову. Вот в чём, собственно, и заключается вся стоимость.
Ментальная модель — это то, что вы создаёте, читая код. Это ваша внутренняя карта того, как работает система, где находятся сложные части, что от чего зависит. Без неё вы просто смотрите на строки текста.
Когда я работал подрядчиком, большинство моих работ начиналось одинаково. Мне поручали исправить ошибку или добавить новую функцию в приложение, которое я никогда раньше не видел. Поначалу моя ментальная модель была чистой и пустой. Чтобы начать её наполнять, я проверял главную страницу, чтобы понять, как она выглядит. Я смотрел на исходный код страницы: это React? jQuery? Сторонний плагин? Я сканировал кодовую базу, чтобы проверить, используется ли где-то ещё карусель, которую они запрашивают на главной странице. Я проверял процесс сборки, настройки тестирования, инструменты, которые они использовали. Каждая обнаруженная мной мелочь добавлялась в модель в моей голове.
Это было похоже на переезд в новый город. Вы начинаете с подъезда своей квартиры, проходите несколько улиц, замечаете, какие дороги ведут к автостраде, где находится продуктовый магазин, и постепенно начинаете ориентироваться. Именно так ощущается чтение кода: вы создаёте мысленную карту, чтобы не теряться при каждом движении.
Скажем, вам нужно понять простую функцию, например, getUserPreferences(userId). Чтобы построить мысленную модель, вам нужно отследить:
- Где определена эта функция?
- Что она возвращает? Это Promise? Какова структура данных?
- Обращается ли она напрямую к базе данных или через API?
- Используются ли уровни кэширования?
- Что произойдёт, если пользователя не существует? Кто ещё вызывает эту функцию и в каких контекстах?
- Есть ли побочные эффекты?
Понимание того, что делает всего одна функция означает переходы между схемами базы данных, определениями API, промежуточным ПО обработки ошибок и несколькими точками вызова. Только после построения этой сети взаимосвязей у вас появляется достаточный контекст для безопасного изменения чего-либо.
И это медленно. Читать код сложнее, чем писать его. Гораздо сложнее. Написание кода — это движение вперёд: вы прокладываете новый путь. Чтение кода означает повторение чьих-то шагов, что обычно означает переходы между файлами, отслеживание вызовов функций, понимание побочных эффектов и расшифровку намерений, которые не были прописаны. Понимание одной функции часто означает просмотр пяти других файлов. Только после всего этого у вас появляется достаточная карта, чтобы начать.
По той же причине отладка сложнее, чем кодирование. На Stack Overflow один из самых частых комментариев под плохим вопросом: «Можете показать нам, что вы сделали?» Не видя шагов, никто не сможет загрузить в свою голову нужную модель, чтобы помочь. Именно поэтому постоянно возникает проблема XY. Люди спрашивают о симптоме, не предоставляя контекста, который позволил бы другим восстановить всю картину.
Меня до сих пор восхищает адвокат, использовавший ChatGPT в суде. Он подал заявление, в котором ссылался на шесть дел, которые, как оказалось, не существовали. Все спрашивали: почему он их не прочитал? Ответ тот же: построение модели требует времени и усилий. Ему пришлось бы разбирать каждое дело, читать их и вписывать в более широкое понимание правовых прецедентов. Чтение — это сложная часть. Генерация — это легко.
Чтение — это не просто просмотр кода и его построчное изучение. Это также изучение документации, ревью кода и совместное программирование. По сути, это решения для ускорения процесса построения нашей ментальной модели. Но, помня об этом, вам всё равно нужно читать и понимать. Вы заметите, что программисты часто хотят переписывать всё с нуля, потому что «старый код — отстой». Что ужасно, так это тратить время на чтение и понимание.
Именно это делает LLM одновременно мощными и опасными в программировании. Генерирует ли ИИ идеальный код или полный бред, вам всё равно придётся его читать. Вам всё равно придётся отслеживать, что он должен делать, как он взаимодействует с остальной частью системы и каковы побочные эффекты. Чем длиннее сгенерированный код, тем больше времени требуется для построения вашей ментальной модели. И только после этого вы сможете обнаружить проблемы, места, где сгенерированный код не совсем подходит или незаметно что-то ломает.
Когда LLM может генерировать бесконечное количество кода или текста, это соблазняет нас пропустить чтение. Но пропустить создание модели невозможно. Вы же не хотите загрузить чужое сохранение и оказаться посреди битвы с боссом. Вот что ощущается, когда наследуешь или генерируешь код, который не понимаешь.
Вот почему настоящее узкое место в разработке программного обеспечения — это не написание, а понимание.
На данный момент у нас нет эквивалента LLM для понимания. Что-то, что могло бы мгновенно перенести полную ментальную модель из системы в вашу голову. Пока мы этого не сделаем, узкое место не сдвинется с места. Мы решили проблему «скорости печати». Мы можем генерировать больше кода, чем когда-либо сможем прочитать. Но пока мы не решим проблему «понимания», стоимость разработки программного обеспечения останется прежней: время, необходимое человеку, чтобы всё это осмыслить.
Это имеет реальные последствия для того, как мы используем ИИ-инструменты. Вместо того, чтобы просить ИИ генерировать большие блоки кода, нам, возможно, лучше попросить его помочь нам понять существующий код. Вместо того, чтобы измерять производительность по количеству написанных строк кода, нам следует измерять её по тому, насколько быстро команды могут создавать точные ментальные модели своих систем.
Будущее программирования может заключаться не в более быстрой генерации большего количества кода, а в более быстром формировании понимания. И это гораздо более сложная задача.

