В рамках задания мы напишем на Python игрушечный бэкенд для интернет-магазина с локальным хранилищем данных в памяти: научимся создавать, читать, изменять и удалять товары, работать с корзиной и управлять всем этим через простую консоль администратора. Задание выполняется поэтапно, и каждый следующий шаг опирается на предыдущий.
- Запуск локальных проверок — как установить uv на macOS и Windows и запустить скрипты, которые локально выполняют те же проверки кода, что и CI на GitHub.
- Сдача домашнего задания — как загрузить решение в свой форк, оформить Pull Request в исходный репозиторий и что нужно для того, чтобы работа была принята на проверку.
- Часть 1. Генератор идентификаторов Twitter Snowflake — нужно написать генератор 64-битных числовых идентификаторов, в которые упакованы метка времени, номер узла и счётчик последовательности. Такие идентификаторы уникальны и примерно упорядочены по времени, а из самого идентификатора можно узнать, когда и на каком узле он был создан.
Максимальный балл за каждое задание — 10. Правильность решения проверяется закрытыми тестами.
Работа принимается к оцениванию, только если выполнены все условия:
Если хотя бы одно условие не выполнено, работа не принимается и оценивается в 0 баллов.
Тесты разбиты на функциональные блоки: каждый блок соответствует функции или классу из задания и имеет свой вес (более сложные блоки весят больше). Внутри блока тесты делятся на две группы:
| Группа тестов | Доля веса блока | Что проверяет |
|---|---|---|
| Базовые (типичные входные данные) | 70% | Основная логика реализована верно |
| Граничные (пустой ввод, нулевые и предельные значения, повторы и т. п.) | 30% | Обработка особых случаев |
Формулы:
балл_блока = 0.7 · доля_пройденных_базовых + 0.3 · доля_пройденных_граничных
балл_за_правильность = 10 · Σ(вес_блока · балл_блока) / Σ(вес_блока)
Дополнительные правила:
- Нереализованный функционал. Блок, в котором функционал не реализован (заглушка,
pass,NotImplementedError), получает 0 баллов. Остальные блоки оцениваются как обычно, дополнительного штрафа за нереализованное нет. - Ошибки выполнения. Тест, в котором возникло необработанное исключение, считается проваленным.
- Зависание. У каждого теста есть ограничение по времени выполнения. Если решение не укладывается в него (например, из-за бесконечного цикла), тест считается проваленным.
Кроме правильности, оценивается качество кода. За нарушения ниже из балла за правильность вычитаются штрафы. Каждое нарушение штрафуется один раз, сколько бы раз оно ни встретилось в работе.
У каждого нарушения есть уникальный код: S — серьёзные, M — средние, T — типовые. При проверке преподаватель указывает в комментарии к работе только коды (например, S1, M2, T1), а расшифровку и штраф можно найти в таблицах ниже.
| Код | Нарушение | Что имеется в виду |
|---|---|---|
S1 |
Копипаста | Вместо вынесения повторяющейся логики в функцию, метод или цикл один и тот же (или почти тот же) код скопирован несколько раз. Мешает расширяемости: любое изменение приходится вносить во все копии |
S2 |
Слишком длинные функции | Функция делает много разных вещей одновременно (вычисления, проверки, преобразования, форматирование в одном месте) и не читается целиком. Ориентир: более 30–40 строк или несколько несвязанных обязанностей. Такой код тяжело читать и поддерживать |
S3 |
Магические значения | Числа и строки с неочевидным смыслом прописаны прямо в коде, а не вынесены в именованные константы. Как и копипаста, мешает расширяемости: значение приходится искать и менять по всему коду |
S4 |
Слишком широкий перехват исключений | Голый except: или except Exception: без необходимости; молча проглоченные ошибки (except ...: pass). Так можно пропустить что-то важное |
S5 |
Изменение входных данных | Функция неожиданно изменяет переданные ей аргументы, хотя из названия и описания это не следует. Неожиданное поведение, источник серьёзных ошибок |
| Код | Нарушение | Что имеется в виду |
|---|---|---|
M1 |
Большая вложенность | Более трёх уровней вложенности (if, for, while, try, with) внутри одной функции. Лечится ранним возвратом (return, continue) и выносом логики в отдельные функции |
M2 |
Неинформативные имена | Имена вроде a, tmp, data2, x1, а также имена, не отражающие суть, или не соответствующие PEP 8 (например, camelCase для функций и переменных) |
M3 |
Избыточные глобальные переменные | Изменяемое глобальное состояние там, где достаточно параметров, возвращаемых значений или атрибутов класса |
M4 |
Мёртвый код | Код, который нигде не используется: неиспользуемые функции, классы, переменные, константы, импорты, недостижимые ветки. Сюда же относятся крупные куски закомментированного кода «на будущее» и оставленный отладочный print. Затрудняет чтение, но на работу программы не влияет |
| Код | Нарушение |
|---|---|
T1 |
else или elif после return, raise, continue или break |
T2 |
Явное приведение к bool в условиях (if bool(x):) и сравнение с True / False (if x == True:) |
T3 |
Сравнение с синглтонами и членами enum'ов через == / != вместо is / is not |
T4 |
Проверка пустоты коллекции через len(x) == 0 вместо if not x |
T5 |
Обход через for i in range(len(items)), когда индекс не нужен (вместо for item in items или enumerate) |
T6 |
if cond: return True else: return False вместо return cond |
T7 |
Изменяемое значение по умолчанию у аргумента (def f(x=[])) |
T8 |
Ручная конкатенация строк вместо f-строк |
T9 |
Избыточные комментарии, пересказывающие очевидный код |
Если работа подозревается в списывании, студент получает −5 баллов. Эти баллы не вычитаются из оценки за правильность, а заменяют итоговую оценку: итоговой оценкой становится −5, независимо от результата тестов.
Студент может оспорить этот балл на занятии, доказав, что не списывал, а написал код самостоятельно (например, объяснив решение и ответив на вопросы по нему). Если подозрение снимается, работа оценивается по обычным критериям.
если есть подозрение в списывании:
итоговая_оценка = −5
иначе:
итоговая_оценка = max(0, балл_за_правильность − штрафы_за_оформление)
Итоговая оценка за домашнее задание округляется до ближайшего целого по правилам математики: дробная часть от 0.5 и выше округляется вверх, меньше 0.5 — вниз (например, 7.5 → 8, 7.4 → 7).
Если вы не согласны с оценкой, напишите преподавателю. Укажите, с каким блоком или с какой частью критериев вы не согласны, и приведите аргументы. Оценка пересматривается по тем же критериям, которые описаны выше.