Привет, Хабр! Жизнь не стоит на месте, как и мое исследование, так что пришла пора пересмотреть то, как я оцениваю код.
Изначально я опиралась на анализ целых репозиториев — мы вычисляли семантическую плотность и классические метрики кода. Результаты были многообещающими, но на практике я столкнулась с «шумом», который невозможно игнорировать:
-
Проблема «Чужого кода»: в реальных проектах личный почерк автора размыт правками лидов, автогенерацией и legacy-кодом. Да и кто хранит корпоративный код на GitHub?
-
Отсутствие эталона: сравнивать код банковского API и шейдеров для Unity — это как сравнивать соленое с длинным. Модели нужна точка отсчета.
-
Нейрогенерация и «заброшки»: на GitHub часто лежат либо старые учебные проекты, либо быстрые эксперименты, которые не отражают реальный уровень инженера «здесь и сейчас».
Теперь я предлагаю пойти от большего к меньшему: вместо того чтобы изучать весь «организм» (репозиторий), мы возьмем его крошечный образец.
Честно подсмотренная идея
Я решила адаптировать метод, который используют коллеги на собеседованиях: мы даем респонденту заведомо неверный, но рабочий кусок кода. Там есть всё: нарушение SOLID, раздутое наследование, отсутствие DI и «лапша» из данных. Задача инженера — «полечить» его.
Чем больше «архитектурных правок» сделает человек, тем выше его насмотренность и больше опыт. Но как оценить результат объективно и быстро?
Код – это буквально литературное произведение, поэтому будет не зазорно обратить внимание на лингвистически термины. Для оцифровки качества рефакторинга адаптируем два лингвистических параметра, вычисляемых с помощью модели GraphCodeBERT:
-
Плотность решений: Отношение количества архитектурных маркеров (интерфейсы, инъекции, паттерны) к общему числу токенов. Такая метрика позволит оценить уровень «зашумленности» реализации.
-
Семантическая плотность: Концентрация информационной нагрузки в одном блоке кода. Высокий показатель будет свидетельствовать об эффективном использовании архитектурных приемов вместо «воды».
Теоретическая апробация: Зонд против Репозитория
Перейдем к эксперименту: проверим, может ли компактный архитектурный «зонд» объемом всего в 30 строк оказаться репрезентативнее целого репозитория. Этот фрагмент — результат моей совместной работы с нейросетью, синтезированный специально для данного эксперимента.
public interface INotifier{ string Target { get; } void Send(string msg);}public class EmailNotifier : INotifier{ public string Target { get; set; } public void Send(string msg) => Console.WriteLine($"To {Target}: {msg}");}public class OrderProcessor{ private readonly IEnumerable<INotifier> _admins; public OrderProcessor(IEnumerable<INotifier> admins) { _admins = admins; } public void ConfirmOrder(int id) { var validAdmins = _admins.Where(a => !string.IsNullOrWhiteSpace(a.Target)); foreach (var admin in validAdmins) { admin.Send($"Order {id} confirmed"); } }}
Теперь рассчитаем и сравним заявленные выше метрики для 9 репозиториев из выборки в статье о GrafCodeBert и для данного «идеального» кода.
Результаты в таблице говорят сами за себя.
|
Источник |
Плотность решений (DD, %) |
Семантическая плотность (SL) |
|
Репозиторий №0 |
1.94 |
0.029 |
|
Репозиторий №1 |
1.34 |
0.063 |
|
Репозиторий №2 |
2.85 |
0.040 |
|
Репозиторий №3 |
6.11 |
0.025 |
|
Репозиторий №4 |
2.40 |
0.034 |
|
Репозиторий №5 |
4.81 |
0.031 |
|
Репозиторий №6 |
3.79 |
0.034 |
|
Репозиторий №7 |
1.63 |
0.041 |
|
Репозиторий №8 |
0.74 |
0.034 |
|
Среднее по репозиториям |
2.84 |
0.037 |
|
Архитектурный зонд |
1.47 |
0.108 |
В среднем, при высокой плотности решений в репозиториях, видна низкая семантическая плотность, особенно в сравнении с зондом.
Что же, математически мы доказали, что зонд лучше. Пришло время понять, как его использовать для оценки грейда.
Путь до идеала и дальше
Чтобы оценить решение кандидата, нам нужно проверить, насколько близко он подошел к задуманному архитектурному эталону. В процессе исследования, пришлось отказаться от расчета линейного расстояния между векторами в пользу векторной проекции.
Таким образом мы измеряем «длину пути», пройденного от сломанного кода к «идеалу», выраженного в переменной K. Если K выше единицы — значит, человек предложил решение даже более эффективное, чем выбранный эталон.
Апробация на реальности
Апробировать методику было решено на реальных людях. Респонденты делились своим опытом, грейдом, навыками в теории и правили «сломанный» зонд. Опрос все еще активен, он занимает не больше 10 минут.
Полученные ответы я использовала для расчета TSI (подробнее вот в этой статье) и K-score – то, насколько близко к идеалу респондент поправил код в промежутке от сломанного до идеального.
Логика вычисления результирующего грейда была следующей:
Результаты и пояснения уже были разосланы тем, кто прошел опрос и захотел их узнать. (Очень надеюсь, что они никого не разочаровали ^_^) А теперь пришла пора посмотреть на общие обезличенные результаты.
Анализ реальных кейсов подтвердил применимость моих идей. Сводные данные подтверждают: даже на малой выборке предложенный семантический зонд позволяет идентифицировать грейд специалиста с точностью, сопоставимой с многочасовыми скринингами.
Выводы
Разрабатываемый подход — это не замена собеседованию, но мощный инструмент «доказательного грейдирования». Он более гибкий, чем стандартные системы, и позволяет за считанные минуты получить объективный инженерный паспорт, минимизируя человеческий фактор и предвзятость. И самое вдохновляющее здесь — это результаты K > 1, когда человек находит решение изящнее и эффективнее выбранного эталона.
Буду рада вашим комментариям и предложениям. Чем больше вы делитесь собственным опытом и указываете на «проблемные» места, тем значимее будет итоговый результат😉.
ссылка на оригинал статьи https://habr.com/ru/articles/1029692/