Top Banner
УК 03.002.01-2011 Учебный курс. Обучение. Контрактное программирование.
20

ук 03.002.01 2011

Dec 26, 2014

Download

Documents

etyumentcev

 
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: ук 03.002.01 2011

УК 03.002.01-2011 Учебный курс. Обучение.

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

Page 2: ук 03.002.01 2011

Базовые понятия

Page 3: ук 03.002.01 2011

Контрактная модель программирования

Б. Мейер Eiffel

Объект, предоставляющий ресурсы, называется сервером.

Объект, использующий ресурсы другого объекта, называется клиентом.

(КН 02.002-1999)

• Метафора условий и ответственности бизнес-контрактов.

• Контракт определяет ответственность объекта – поведение за которое он отвечает.

Page 4: ук 03.002.01 2011

Инвариант – логическое условие, значение которого не меняется.

• Asserts (жесткое падение)

• Тройка Хоара {pred} Action {post}

• Логика программирования

• Корректность программы

• Автоматическое тестирование

Предусловия – логическое условие, истинное до выполнения операции.

Постусловия – логическое условие, истинное после выполнения операции.

Page 5: ук 03.002.01 2011

• Нарушение инварианта – нарушает контракт абстракции

• Нарушено предусловие – клиент не соблюдает свои обязательства, и сервер не может выполнить операцию правильно

• Нарушено постусловие – свои обязательства нарушил сервер

• При нарушении какого-либо условия возбуждается исключительная ситуация (ПР 01.003)

• Конструктор используется для установки инвариантов класса (ПР 02.009)!!!

Page 6: ук 03.002.01 2011

Пример 1: Выделение класса

private FtpWebResponse _MakeRequest(string relativePath, string method, byte[] data)

{

FtpWebRequest ftpWebRequest = (FtpWebRequest)WebRequest.Create(GetPath(relativePath));

ftpWebRequest.Credentials = _credentials;

ftpWebRequest.Method = method;

ftpWebRequest.UsePassive = usePassive;

ftpWebRequest.ServicePoint.ConnectionLimit = 10;

if (data != null && data.Length > 0)

{

ftpWebRequest.ContentLength = data.Length;

using (Stream requestStream = ftpWebRequest.GetRequestStream())

{

requestStream.Write(data, 0, data.Length);

requestStream.Close();

}

}

return (FtpWebResponse)ftpWebRequest.GetResponse();

}

Page 7: ук 03.002.01 2011

• Требуется время на то, чтобы понять суть метода

• Нельзя повторно использовать для других типов запросов

• Название запутывает (MakeRequest, а надо MakeResponse)

• Смешение разных уровней абстракции

• Как следствие, несколько разных отвественностей, а значит потенциальные проблемы с замкнутостью

• Непонятно – что делать с ситуацией, когда тип запроса подразумевает данные в ответе, а их нет

Page 8: ук 03.002.01 2011

class Path

{

string normailizePath;

public Path(string relativePath)

{

normalizePath = GetPath(relativePath);

}

private void GetPath(string unnormalizedString)

{

}

public override string ToString()

{

return normalizePath;

}

}

private FtpWebResponse _MakeRequest(Path path, string method, byte[] data)

{

FtpWebRequest ftpWebRequest = (FtpWebRequest)WebRequest.Create(path.ToString());

ftpWebRequest.Credentials = _credentials;

ftpWebRequest.Method = method;

ftpWebRequest.UsePassive = usePassive;

ftpWebRequest.ServicePoint.ConnectionLimit = 10;

if (data != null && data.Length > 0)

{

ftpWebRequest.ContentLength = data.Length;

using (Stream requestStream = ftpWebRequest.GetRequestStream())

{

requestStream.Write(data, 0, data.Length);

requestStream.Close();

}

}

return (FtpWebResponse)ftpWebRequest.GetResponse();

}

Page 9: ук 03.002.01 2011

class Data

{ byte[] data;

public Data(byte[] exData)

{

if (null == exData)

throw ArgumentNullException();

if(0 == exData.Length)

throw new SomeException();

data = exData;

}

public byte[] Body

{

get

{

return data;

}

}

public int Length

{

get

{

return data.Length;

}

}

}

private FtpWebResponse _MakeRequest(Path path, string method , Data data)

{

FtpWebRequest ftpWebRequest = (FtpWebRequest)WebRequest.Create(path.ToString());

ftpWebRequest.Credentials = _credentials;

ftpWebRequest.Method = method;

ftpWebRequest.UsePassive = usePassive;

ftpWebRequest.ServicePoint.ConnectionLimit = 10;

if (data != null)

{

ftpWebRequest.ContentLength = data.Length;

using (Stream requestStream = ftpWebRequest.GetRequestStream())

{

requestStream.Write(data, 0, data.Length);

requestStream.Close();

}

}

return (FtpWebResponse)ftpWebRequest.GetResponse();

}

Page 10: ук 03.002.01 2011

private FtpWebResponse _MakeRequest(Path path, string method, Data data)

{

FtpWebRequest ftpWebRequest = (FtpWebRequest)WebRequest.Create(path.ToString());

ftpWebRequest.Credentials = _credentials;

ftpWebRequest.Method = method;

ftpWebRequest.UsePassive = usePassive;

ftpWebRequest.ServicePoint.ConnectionLimit = 10;

if (data != null)

{

ftpWebRequest.ContentLength = data.Length;

using (Stream requestStream = ftpWebRequest.GetRequestStream())

{

requestStream.Write(data, 0, data.Length);

requestStream.Close();

}

}

return (FtpWebResponse)ftpWebRequest.GetResponse();

}

private FtpWebResponse _MakeRequest(Path path, IResponseMethod method, Data data)

{

ResponseBuilder builder = new FTPResponseBuilder(this);

builder.Path = path;

method.Apply(builder);

if (data != null)

builder. Data = data;

return builder.GetResponse();

}

interface IResponseMethod

{

void Apply(IMethodHandler handler);

}

Interface IResponseHandler

{

void Handle(string method);

}

Page 11: ук 03.002.01 2011

• Фабрика билдеров

• ConnectionLimit из файла конфигурации

• Ограничить методы, соответствующим протоколом

Page 12: ук 03.002.01 2011

private WebResponse _MakeResponse(Path path,

IResponseMethod method)

{

ResponseBuilder builder = new FTPResponseBuilder(this);

builder.Path = path;

method.Apply(builder);

return builder.GetResponse();

}

interface IResponseMethod

{

void Apply(IMethodHandler handler);

}

Interface IResponseBuilder

{

void Handle(string method);

Data Data

{

set;

}

}

class ResposeWithBody: IResponseMethod

{

IResponseMethod method;

Data data;

public ResponseWithBody(IResponseMethod m, Data d)

{

if (null == d)

throw

ArgumentNullException();

method = m;

}

public override void Apply(ResponseBuilder builder)

{

method.Apply(builder);

builder.Data = data;

}

}

Page 13: ук 03.002.01 2011

Контракт метода в ООП

• возможные типы входных данных и их значение;

• типы возвращаемых данных и их значение;

• условия возникновения исключений, их типы и значения;

• присутствие побочного эффекта метода;

• предусловия, которые могут быть ослаблены (но не усилены) в подклассах (УК 02.001-2011, Принцип подстановки Лисков);

• постусловия, которые могут быть усилены (но не ослаблены) в подклассах (УК 02.001-2011, Принцип подстановки Лисков);

• инварианты, которые могут быть усилены (но не ослаблены) в подклассах;

• (иногда) качественные характеристики, такие как гарантии производительности, например, временная сложность или сложность по памяти

Page 14: ук 03.002.01 2011

RAII

RAII (Resource allocation is initialization) – выделение ресурса есть инициализация

• Адаптер для ресурса – класс, реализующий требуемое от ресурса поведение

• Конструктор используется для выделения ресурса

• Деструктор для освобождения

• Инвариант адаптера – ресурс выделен и находится в работоспособном состоянии

Page 15: ук 03.002.01 2011

RAII в .Net

• Неуправляемые ресурсы

• IDisposable

• Инструкция using

Page 16: ук 03.002.01 2011

using vs. try-finally

using (A a = new A())

{

}

try

{

A a = new A();

}

finally

{

a.Dispose();

}

Page 17: ук 03.002.01 2011

Пример 2: Курсор Песочные часы

void f()

{

Cursor previous = Cursor.Current;

Cursor.Set(Cursor.Wait);

try

{

throw …

}

finally

{

Cursor.Set(previous);

}

if (…)

{

Cursor.Set(previous);

return file2;

}

f (…)

{

Cursor.Set(previous);

return file;

}

}

class MyCursor: IDisposable

{

Cursor previous;

public MyCursor()

{

Cursor previous = Cursor.Current;

Cursor.Set(Cursor.Wait);

}

public void Dispose() { Dispose(true); }

void Dispose(bool disposed)

{

….

Cursor.Set(previous);

}

}

void f()

{

using (MyCursor cursor = new MyCursor)

{

throw …

if (…)

{ return file2; }

if (…)

{ return file; }

}

}

Page 18: ук 03.002.01 2011

delegate D(); class CursorExtender { public static void WaitingAction(D d) { Cursor previous = Cursor.Current; Cursor.Set(Cursor.Wait); try { d(); } finally { Cursor.Set(previous); } } } void f() { Cursor.WaitingAction( new delegate{ { throw … if (…) { return file2; } if (…) { return file; } } ); }

Page 19: ук 03.002.01 2011

Что дальше

• Юнит-тестирование

• Интеграционные тесты

• Приемочные тесты

Page 20: ук 03.002.01 2011

Вопросы?