# Лекция 1. Программирование по контракту. Мы видим следующий код: ```java public class Magic { int magic(int a, int n) { int r = 1; while (n != 0) { if (n % 2 == 1) { r *= a; } n /= 2; a *= a; } return r; } } ``` Что это за код? Как понять: 1. Пристально посмотреть. 2. Написать тесты. * Это не поможет понять, работает ли код. Тесты могут только показать, что код **НЕ работает**. 3. Написать формальное доказательство. Для последнего пункта нам понадобится *теорема о структурной декомпозиции*. **Формулировка**: Любой код, который мы можем написать на каком-то языке, можно представить в виде замыкания следующих операций: 1. Ничего 2. Последовательное исполнение операций (последовательность действий) 3. Присваивание 4. Ветвление 5. Цикл `while` С точки зрения теоремы, этих действий достаточно, чтобы написать любую содержательную программу. Можно ли ввести такую конструкцию при помощи примитивов выше: ```java try { // some code here } catch (...) { // some code here } finally { // some code here } ``` Давайте введем переменную `exitCode` и для каждого действия, в зависимости от того, успешно оно выполнилось или нет, будем обновлять `exitCode`. ```java if (exitCode == 0) { // без ошибок // делаем дальше } else { // ничего не делаем } ``` Попытаемся этим воспользоваться. Мы хотим наложить какие-то условия на нашу функцию, так что если эти условия на вход выполняются, то мы получим гарантированно правильное значение. Чтобы это доказать, нам помогут *тройки Хоара*. Хоар придумал quick sort. Тройка состоит из `P`, `C` и `Q`, где * `P` - пред-условие * `C` - код, * `Q` - пост-условие Если у нас есть код `C`, и мы выполняем какое-то пред-условие, то после исполнения кода, у нас будет выполнено какое-то пост-условие. Для операции *ничего*: ```java /* Pred: Condition Code: ; Post: Condition */ ``` То условие, которое было до того, как мы сделали *ничего*, останется. Для *последовательности действий*: ```java /* Pred: P1 Code: ... Post: Q1 Pred: P2 Code: ... Post: Q2 */ ``` Таким образом из `Q1` должно следовать `P2`. ```java /* Pred: P1 Q1 -> P2 Post: Q2 */ ``` Для *присваивания*: ```java /* Pred: Q[x = expr] Code: x = expr Post: Q */ ``` Например ```java // Pred: (x = a + 2)[x = 6] -> a = 4 x = a + 2 // Post: x = 6 ``` То есть только при `a == 4`, выполнится пост-условие. Для операции `ветвление`: ```java /* // Pred: cond && P1 || ~cond && P2 if (cond) { // Pred: P1 ... // Post: Q1 } else { // Pred: P2 ... // Post: Q2 } // Q1 -> Q && Q2 -> Q // Post: Q */ ``` Для цикла `while`: ```java /* // Pred: P = I while (cond) { // Pred: I // Post: I (инвариант цикла) } // Post: Q = I */ ``` Посмотрим на примере: ```java // Pred: true // Post: r = A' ^ N' int magic(int a, int n) { // A' = a, N' = n -- начальные значения // Pred: A' == a && N' == n int r = 1; // Post: r == 1 && a ** n * r == A' ** N' // Pred: a ** n * r == A' ** N' // Inv: (a ** n) * r = A' ** N' while (n != 0) { // Pred: a ** n * r == A' ** N' if (n % 2 == 1) { // Pred: a ** n * r == A' ** N' r = r * a; // Post: a ** (n - 1) * r = A' ** N' // Pred: a ** (n - 1) * r = A' ** N' n = n - 1; // Post: a ** n * r = A' ** N' } // Post: a ** n * r = A' ** N' // Pred: a ** n * r = A' ** N' n /= 2; // Post: a ** (2 * n) * r = A' ** N' // Pred: a ** (2 * n) * r = A' ** N' a = a * a; // Post: a ** n * r = A' ** N' } // Post: a ** n * r = A' ** N' && n == 0 // Pred: r = A' ** N' return r; // Post: r = A' ** N' } ``` Мы формально доказали, что метод `magic()` возводит число `a` в степень `n`. Такая функция называется чистой, так как она не зависит от внешних переменных. То, что мы написали, называется контракт. Участниками контракта являются *пользователь* и *разработчик*. Мы, как разработчик, требуем пред-условие, и тогда можем гарантировать, что пост-условие будет выполняться. `interface` в java -- частный случай контракта. Это были случаи определения контракта для *чистых* функций. А как действовать в других случаях. Приведем пример ```java int x; // Pred: // Post: int add(int y) { x = x + y; return x; } ``` Определим *модель* как некоторое состояние нашего класса. ```java /* Model: x (целое число) */ ``` ```java int x; // Pred: true // Post: x = x' + y (x' -- старый x) int add(int y) { x = x + y; return x; } ``` Здесь контракт соблюдается. А здесь: ```java int x; // Pred: true // Post: x = x' + y (x' -- старый x) int add(int y) { x = x + y * 2; return x / 2; } ``` Контракт также соблюдается. То есть нам не важны детали реализации. Можно даже сделать вот так: ```java private int x = 10; // Post: x = 0 void init() { x = 1; } // Pred: true // Post: x = x' + y int add(int y) { x = x + y * 2; return (x - 1) / 2; } // Pred: true // Post: R := x int get() { return (x - 1) / 2; } ```