Контрактное программирование (design by contract (DbC), programming by contract, contract-based programming) — это метод проектирования программного обеспечения. Он предполагает, что проектировщик должен определить формальные, точные и верифицируемые спецификации интерфейсов для компонентов системы. При этом, кроме обычного определения абстрактных типов данных, также используются предусловия, постусловия и инварианты. Данные спецификации называются «контрактами» в соответствии с концептуальной метафорой условий и ответственности в гражданско-правовых договорах.
pycontracts — способ проверять данные на входе/выходе функции в runtime.
Такой подход позволяет:
- проще писать тесты – проблемы с валидацией не возникают, и покрывается только бизнес-логика.
- гарантировать формат и качество ответа в API – появляются жесткие рамки того, что мы готовы принять и что мы можем отдать.
- проще понимать/рефакторить формат ответа, если это сложная структура с разными уровнями вложенности.
Использование @contract декоратор:
@contract(a='int,>0', b='list[N],N>0', returns='list[N]')
def my_function(a, b):
...
Использование аннотаций (for Python 3):
@contract
def my_function(a : 'int,>0', b : 'list[N],N>0') -> 'list[N]':
# Requires b to be a nonempty list, and the return
# value to have the same length.
...
Использование строк документации, вместе с :type: и :rtype: tags:
@contract
def my_function(a, b):
""" Function description.
:type a: int,>0
:type b: list[N],N>0
:rtype: list[N]
"""
Подробнее о pycontracts(список литературы 2 строчка)
from contracts import contract
# решение функции x^2/y*2
@contract
def foo(x, y):
"""
:type x: int|float,!= 0
:type y: int|float, != 0
:rtype: int|float
"""
if x != 0 & y != 0:
return (x**2)/(y*2)
else:
return -1
# возведение x в степень a(где a>=0)
@contract
def exponentiationFoo(x, a):
"""
:type x: int|float, > 0
:type a: int|float, >= 0
:rtype: int|float
"""
if a >= 0:
return x**a
else:
return -1
Начало
ввод(x, y, z);
если p1(x,y,z) то на L3
если p2(x,y) и p2(x,z) то на L1;
если p2(y,z) то на L2;
z=g1(x,y);
на L3;
L1: x= g1(y,z);
на L3;
L2: y= g1(x,z);
L3: вывод(x,y,z);
Конец