Имплементация: превратить контракт в работающий код
Имплементация — конкретная реализация поведения: тело функции, класс, выполняющий интерфейс, или модуль, соответствующий протоколу. Требование отвечает на вопрос «что должно происходить», а реализация определяет «как». Написанный код ещё нужно проверить на согласованных примерах и границах.
Сначала сформулируйте проверяемый контракт
Допустим, нужна функция нормализации подписи. Принимается строка; пробелы по краям удаляются, серии пробельных символов внутри заменяются одним пробелом. Пустой результат запрещён. Число или другой объект не преобразуется в строку молча. Регистр и пунктуацию функция менять не должна.
Реализация и примеры
def normalize_label(value: str) -> str:
if not isinstance(value, str):
raise TypeError("Expected a string")
result = " ".join(value.split())
if not result:
raise ValueError("Label cannot be empty")
return result
assert normalize_label(" Red\tFox ") == "Red Fox"
assert normalize_label("Red-Fox") == "Red-Fox"
for invalid in ("", " "):
try:
normalize_label(invalid)
except ValueError:
pass
else:
raise AssertionError("Expected ValueError")Здесь алгоритм короткий, но решения явно видны: какая нормализация допустима и какие ошибки возвращать. Аннотация str помогает инструментам анализа, но сама по себе не обеспечивает runtime-проверку типа — для неё нужен явный isinstance или другой согласованный механизм.
Какие шаги полезны в большой задаче
- Запишите входы, выходы, ошибки и ограничения, включая побочные эффекты: сеть, файлы, изменения базы.
- Определите границу модуля и зависимости. Не обязательно вводить сложную архитектуру ради небольшой чистой функции.
- Проверьте обычный случай, пустые и ошибочные входы, а также свойства, которые должны сохраняться. Конечный список тестов не означает проверку всех возможных исполнений.
- После корректности измеряйте реальную производительность и меняйте только то, что объясняет наблюдаемую проблему.
Инструменты не заменяют контракт
IDE, компилятор, интерпретатор и библиотеки помогают находить ошибки и выполнять программу, но не знают все ваши продуктовые требования. Интерпретатор не обязан просто «читать исходник построчно»: возможны промежуточное представление и другие этапы исполнения. Для интерфейсов и Protocol отдельно проверяйте не только имена методов, но и фактическую семантику результата.