КОНТРАКТНОЕ
ПРОГРАММИРОВАНИЕ
Самунь Виктор
Имеющиеся проблемы в Perl
• Perl слабо типизирован
• Тип данных определяется динамически
• Слабые возможности прототипов функций
Проблемы при программировании
• Изменение API
• Изменение типов данных
• Проверка данных
• Контекст
Решение проблем (возможное)
• Документация
• Тестирование
Контрактное программирование
• Метод проектирования ПО


• Предложено Бертраном Мейером при разработке Eiffel
• 1986 год


• Возникло из:
   • Формальной спецификации
   • Формальной верификации
   • Логики Хоара


• По контракту можно сгенерировать документацию
Что задаёт контракт?
• Типы данных
• Предусловие   (precondition)
• Инвариант     (invariant)
• Постусловие   (postcondition)
Последовательность проверки
1.   Предусловие
2.   Инвариант
3.   Вызов функции
4.   Инвариант
5.   Постусловие
Какие языки имеют нужные средства?
• Eiffel          • C (DBC for C)
•D                • C++ (Contract++)
• Spec#           • C# (Code Contracts)
• SeC             • Java (jContractor)
•…                • Perl (Class::Contract)
                  •…
Class::Contract
Определение классов
package ClassName;
contract {
  # Спецификация атрибутов и методов
  # класса ClassName
};
Конструктор и деструктор
contract {
  ctor ‘new’;
    impl { ... };

  dtor;
    impl { ... };
};

$x = new MyClass;
Инварианты класса
contract {
  invar { ... };
    failmsg ‘Contract failed on %s’;
};
Определение атрибутов
contract {
  attr ‘scalar_attr’;
  attr ‘yet_scalar’ => SCALAR;
  attr ‘array_attr’ => ARRAY;
  attr ‘hash_attr’ => HASH;
  attr ‘obj_attr’ => SomeClass;
};
Определение методов
contract {
  method ‘my_method’;
    impl { ... };
};

&self
Пред- и пост- условия (атрибуты)
contract {
  attr ‘my_attr’;
    pre { ... };
      failmsg ‘Fail Message’;
    post { ... };
      failmsg ‘Fail Message’;
};

&value
&old
Пред- и пост- условия (методы)
contract {
  method ‘my_meth’;
    pre { ... };
      failmsg ‘Fail Message’;
    post { ... };
      failmsg ‘Fail Message’;
    impl { ... };
};

&self
&old
Пример
package MyClass;
use Class::Contract;

contract {
  ctor 'new';

 attr 'val' => SCALAR;
   pre { $_[0] =~ /^d*$/; };

 method 'm1';
   pre { $_ [0] =~ /^d+0$/ };
   impl { ${self->val} += $_ [0]; };

  method 'm2';
    impl { ${self->val} ++; };
    post { ${self->val} < 100; };
};
Пример

use MyClass;        use MyClass;

$x = new MyClass;   $x = new MyClass;
$x->m1 (40);        $x->m1 (400);
print ${$x->val};   print ${$x->val};
$x->m2;             $x->m2;
print ${$x->val};   print ${$x->val};

> perl 1.pl         > perl 1.pl
40                  400
41                  Post-condition at
                    MyClass.pm line 16 failed
                     at 1.pl line 6
Что есть ещё?
• Sub::Contract
• Class::Agreement
Спасибо за внимание!
     Вопросы?

Контрактное программирование