Software Engineering I - kspt.icc.spbstu.rukspt.icc.spbstu.ru/media/files/people/pyshkin/... ·...

Preview:

Citation preview

Software Engineering IОбъектно-ориентированный

анализ и проектирование

Раздел 4. Механизмы

повторного использования и

паттерны проектирования

План раздела

• Повторное использование компонентов при

проектировании программного обеспечения

▫ Преимущества и проблемы

▫ Основные методы

▫ Объектные структуры

• Механизмы повторного использования кода

▫ Наследование и композиция

▫ Делегирование

▫ Параметризованные типы

План раздела

• Что такое «шаблон

проектирования» (паттерн)

▫ Неформальное определение

▫ Описание паттерна

▫ Примеры

План раздела

• Описание паттернов

▫ Вариант классификации

Основные паттерны

Порождающие паттерны

Разделяющие (структурные) паттерны

Другие структурные паттерны

Паттерны поведения

Паттерны для конкурирующих операций

• Послесловие

Преимущества и проблемы

Основные методы

Объектные структуры

Пример (объектная структура «Модель-представление-

контроллер»)

• Большая надежность программного обеспечения• Уменьшение проектных рисков• Стандартизация программного обеспечения• Быстрая разработка

Преимущества

• Дороже в сопровождении• Нет CASE-средств, ориентированных на компонентное

проектирование• Есть разработчики, предпочитающие написание собственных

компонентов• Трудности сопровождения каталогов библиотек компонентов• Трудности с поиском подходящих компонентов и их адаптацией

к проектным нуждам

Проблемы

Повторное использование

компонентов

Большая надежность ПО

Компоненты уже протестированы в

других приложениях

Уже выявлены и исправлены многие

ошибки

Меньше ошибок при интеграции системы

Преимущества

Большая надежность ПО

Уменьшение проектных

рисков

Стандартизация ПО

Быстрая разработка

Повторное использование

компонентов

Уменьшение проектных рисковЛегче оценить

затраты на повторное использование, чем

на разработку

Проще администрировать

Более точная оценка общих затрат

Управление персоналом

Преимущества

Большая надежность ПО

Уменьшение проектных рисков

Стандартизация ПО Быстрая разработка

Повторное использование

компонентов

Стандартизация ПО

Компоненты соответствуют стандартам (например,

GUI)

Меньше ошибок при программировании

Меньше пользовательских ошибок

Преимущества

Большая надежность ПО

Уменьшение проектных рисков

Стандартизация ПО Быстрая разработка

Повторное использование

компонентов

Быстрая разработка

Уменьшение времени разработки

Уменьшение времени на интеграцию

Уменьшение времени тестирования

Преимущества

Большая надежность ПО

Уменьшение проектных

рисков

Стандартизация ПО

Быстрая разработка

Повторное использование

компонентов

Дороже в сопровождении

Исходный код может быть недоступен или защищен лицензиями

Изменения, вносимые в компонент его разработчиком, могут привести к несовместимости с клиентской

системой

Проблемы

Дороже в сопровождении

Отсутствие CASE-средств

Есть разработчики, предпочитающие

написание собственных компонентов

Трудности сопровождения

каталогов компонентов

Трудности поиска и адаптации

Повторное использование

компонентов

Отсутствие CASE-средств

CASE-средства в больше степени ориентированы на проектирование «с нуля»

Непросто интегрировать CASE-средства с библиотеками компонентов

Проблемы

Дороже в сопровождении

Отсутствие CASE-средств

Есть разработчики, предпочитающие

написание собственных компонентов

Трудности сопровождения

каталогов компонентов

Трудности поиска и адаптации

Повторное использование

компонентов

Есть разработчики, предпочитающие написание собственных компонентов,

… потому что они лучше… потому что они лучше

соответствуют конкретным требованиям

… потому что это благородно и честно – писать свои программы!

Проблемы

Дороже в сопровождении

Отсутствие CASE-средств

Есть разработчики, предпочитающие

написание собственных компонентов

Трудности сопровождения

каталогов компонентов

Трудности поиска и адаптации

Повторное использование

компонентов

Трудности сопровождения каталогов компонентов

Создание и сопровождение библиотек – трудоемкий и дорогостоящий процесс

Методы классификации и информационного обмена недостаточно проработаны применительно к

компонентам

Проблемы

Дороже в сопровождении

Отсутствие CASE-средств

Есть разработчики, предпочитающие

написание собственных компонентов

Трудности сопровождения

каталогов компонентов

Трудности поиска и адаптации

Повторное использование

компонентов

Трудности с поиском подходящих компонентов и их адаптацией к проектным нуждам

Трудно найти в точности подходящие компоненты

Компоненты могут быть сложными для изучения

Разрабатываемая система может существенно отличаться от

системы, в который был использован компонент

Проблемы

Дороже в сопровождении

Отсутствие CASE-средств

Есть разработчики, предпочитающие

написание собственных компонентов

Трудности сопровождения

каталогов компонентов

Трудности поиска и адаптации

Повторное использование

компонентов

Уровни абстрагирования [Meyer B.]

• Компоненты реализуют некоторые функции• Интерфейс: сами функцииФункциональность

• Набор слабо связанных программных объектов• Интерфейс определяется именами объектов компонентов

Несистематическое группирование

• Компонент – это класс в ООП• Интерфейс: методы и операцииАбстракции данных

• Группа тесно связанных классов (объектная структура)• Интерфейс образуют интерфейсы объектов, входящих в структуруКластеры классов

• Компоненты как полностью автономные структуры• Интерфейс: APIСистемный уровень

Объектный структуры

We structure our software to make change easier; after all, software is meant to be soft

(Martin FOWLER)

Инфраструктуры систем

• Коммуникационные системы• Пользовательские интерфейсы• Компиляторы

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

• Стандарты + Классы для взаимодействия компонентов• Примеры: CORBA, COM, DCOM, EJB,…

Инфраструктуры приложений (Application Frameworks)

• Применительно к конкретным прикладным областям• MFC, VCL, GTK+, AWT, Swing,…

Пример: объектная структура

«Модель-представление-контроллер»

ModelStores system stateReplies to the requestsExpresses system functionsNotify about its changes

ViewShows model viewReads model statePerforms controller’s commandsSends user action messages

ControllerManages system behaviorUpdates modelUpdates views

1

User interactswith application

through Views 2

View transfersuser inputto the Controller

3

ControllerChangesModel’s state

4

Model sendsupdate messages

to its Views 5

View reads Model’s state and update itself

Пример: объектная структура

«Модель-представление-контроллер»• «Летающий шарик»

Наследование и композиция

Делегирование

Параметризованные типы

Дизайн с учетом будущих изменений

Наследование и композиция

Различные модели наследование реализуют

различную семантику

Открытые или скрытые члены базового класса

Наследование интерфейса не следует путать с наследованием

реализации

Наследование

Открытое

is-like-a kind-of

Закрытое

implemented-by

Наследование и композиция

Композиция тоже может выражать

семантикуimplemented-by

Что мы моделируем?

Иногда композиция может быть

альтернативой наследованию

Композиция

Предметная область

contains is-part-of

Особенности реализации

implemented-by

Делегирование

Методологии и практики

программирования

Сопровождаемость и изменяемость кода

Существуют различные стратегии органиазции

потока управления программы

Управляющая логика программы

Линейная модель(Calls and Answers)

Процедурное программирование

(иерархии процессов)

Голливудский принцип (Don’t call

us, we’ll call you)

Паттерн делегирования

Событийная модель

Параметризованные типы

Реализация в языках программирования

В зависимости от диапазона поддерживаемых типов…

Полиморфизм – это возможность работать с объектами различных

типов в рамках унифицированного интерфейса. Эта концепция

применима как к типам данных, так и к функциям

Полиморфизм

Ad-hoc polymorphism

Наследование и иерархии типов

Перегрузка методов и операций

Параметрический полиморфизм

Обобщенные (параметризуемые,

настраиваемые ) типы

Проектирование с учетом будущих

изменений

Области

Пределы ответственности

Предусмотрениеизменений –

существенный аспект

Как обеспечить изменчивость

ПО

Управление проектом

Управление требованиями

Bug-Tracking

Управление изменениями и

сопровождением ПО

Уровень исходного кода

Механизмы и практики

повторного использования

Шаблоны проектирования (Design Patterns)

Design Pattern. Идея и концепция

Неформальное определение

Описание паттерна

Примеры

Вариант классификации

Паттерны это способ выразить и

зафиксировать опыт проектировщиков• Хороший паттерн…

▫ описывает успешное решение

▫ предполагает ясный и хорошо читаемый код

▫ предоставляет конкретное решение конкретной проблемы

▫ ориентирован на практику▫ ориентирован на

разработчиков, так как хорошие паттерны подчеркивают сильное влияние человеческого фактора в проектировании программ: отличные программы пишут отличные разработчики

Хороший паттерн

Успешное решение

Ясный и читаемый код

КонкретностьОриентирован

на практику

Для разработчика

• Что такое design pattern

▫ Решение проблемы в некотором контексте

MVC [since 1988]

GoF [since 1993]

Другие реализации

▫ Идеи

Обобщение частных решений на

распространенные случаи

Уровни абстрагирования

Отделение изменяющегося кода от

относительно стабильного

• Шаблон: определение

▫ Каждый шаблон является правилом из трех

частей, выражающих связь между

определенным контекстом, проблемой и

решением (Alexander)

при этом это решение должно быть

повторяемым

этому решению можно обучить

это решение имеет имя (Vlissides)

▫ Шаблон как средство структуризации

объектно-ориентированного кода

• Описание шаблона (1)

▫ Идентификация

имя

классификация

другие известные имена

▫ Проблема (контекст)

▫ Суть решения (синопсис)

▫ Мотивы

когда (почему) решение используется

когда (почему) следует отказаться от шаблона

• Описание шаблона (2)

▫ Структура решения (основная схема)

классы и объекты

их функции и отношения

▫ Реализация

▫ Следствия

положительные

нейтральные

отрицательные

▫ Примеры применения

прикладные решения

API & Frameworks

Пример: Singleton

• Задача о построении генератора уникальных

целочисленных ключей

▫ Генерируем положительные целые числа по

порядку

▫ В проекте должен быть только один такой

генератор

• Реализация на C++

• Реализация на Java

Singleton в приложении

• Задача о построении системы unit-тестов для

проектируемых классов

▫ Иерархия тестов

▫ Уникальная идентификация тестов c

использованием Singleton

▫ Реализация на Java

Пример 2: Матрицы

• Контекст▫ Математические вычисления с матрицами

▫ Эффективность и управление памятью

• Модели размещения▫ Contiguous (rectangular) arrays

▫ Jagged arrays

▫ Другие…

• Проблема▫ Абстрагироваться от модели размещения при

использовании матриц

Пример 2: Матрицы

• Матрица как математический объект

• Матрица как объект данных

20 14 -7 9

16 -2 99 1

4 0 -2 73

0

1

2

0 1 2 3

Number of rows (numStr)

Number of columns (numCol)

Elements (numStr*numCol)

Пример 2: Матрицы

• Модели размещения в памяти

20 14 -7 9 16 -2 99 1 4 0 -2 73

intint*

Row 0 Row 1 Row 2

(a) Rectangular array

20 14 -7 9

16 -2 99 1

4 0 -2 73

int*

int**

int

(b) Jagged array

Row 0

Row 1

Row 2

Пример 2: Матрицы

• Поддержка языками программирования

Contiguous Jagged Notes

FORTRAN + – Contiguous arrays are stored by columns

C +/– + Contiguous arrays may be implemented manually

C++ + + On the base of STL tools

Java – +

C# + + Different syntax for each model

Пример 2: Матрицы

• Поддержка на уровне языка (C#)

// Contiguous array (stored by rows)

int [,] matrix = new int[ 3, 4 ]; // Matrix definition

matrix[ 1, 2 ] = 99; // Access to the element

// Jagged array

int[][] matrix = new int[ 3 ][]; // Array of references

for( int ixStr=0; ixStr<3; isStr++ ) {

matrix[ 0 ] = new int[ 4 ]; // Row allocation

}

matrix[ 1 ][ 2 ] = 99; // Access to the element

Пример 2: Матрицы

• Набросок решения на C++ (структурный подход)

template <class T>

struct RectangularArray {

int numStr; // Number of rows

int numCol; // Number of columns

T *body; // Base address in the heap

};

template <class T>

struct JaggedArray {

int numStr; // Number of rows

int numCol; // Number of columns

T **body; // Base address for array of pointers to the rows

};

template <class T>

void Allocate2DArray( RectangularArray<T>& array, int n, int m ){

array.numStr = n;

array.numCol = m;

array.body = new T[ n*m ];

}

template <class T>

void Allocate2DArray( JaggedArray<T>& array, int n, int m ) {

array.numStr = n;

array.numCol = m;

array.body = new T*[ n ];

for( int i=0; i<n; i++ ) {

array.body[ i ] = new T[ m ];

}

}

• Резервирование памяти

template <class T>

inline T GetElem( const RectangularArray& array, int i, int j ) {

return array.body[ i*array.numCol + j ];

}

template <class T>

inline void SetElem( RectangularArray& array, int i, int j,

T& elem ) {

array.body[ i*array.numCol + j ] = elem;

}

template <class T>

inline T GetElem( const JaggedArray& array, int i, int j ) {

return array.body[ i ][ j ];

}

template <class T>

inline void SetElem( JaggedArray& array, int i, int j, T& elem ){

array.body[ i ][ j ] = elem;

}

• Методы для доступа (методы-аксессоры)

/*

template <class T, template <typename> class ArrayType>

void Allocate2DArray( ArrayType<T>& array, int n, int m );

template <class T, template <typename> class ArrayType>

inline T GetElem( const ArrayType<T>& array, int i, int j );

template <class T, template <typename> class ArrayType>

inline void SetElem( ArrayType<T>& array, int i, int j, T& elem );

//...

*/

• Виртуальный интерфейс ArrayType

▫ Определяет общие операции

▫ Формирует основу для разработки обобщенных

алгоритмов

template <class T, template <typename> class Array>

void PrintAllMax( const Array<T>& array ) {

for( int i=0; j<array.numStr; j++ ) {

T max = GetElem( array, i, 0 );

for( int j=1; i<array.numCol; i++ ) {

if( GetElem( array, i, j ) > max )

max = GetElem( array, i, j );

}

cout << "Max(" << i << ")=" << max << endl;

}

}

• Пример обобщенного алгоритма

Using objectPrintAllMax( array )

Access to the implementation

Implementation

GetItem( array, i, j )

array.body[ i*m + j ]

• Уровни абстрагирования

▫ Уровень работы с объектами

▫ Уровень доступа к реализации

На этом уровне конструируются алгоритмы

▫ Уровень реализации

Using objectPrintAllMax( array )

Access to the implementation

Implementation

GetItem( array, i, j )

array.body[ i*m + j ]

• Требования к объектно-ориентированному

решению

▫ Клиентский код (работающий с матрицами) не

должен зависеть от модели хранения в памяти

▫ Различные модели хранения должны

реализовать один и тот же интерфейс

▫ Необходимо предусмотреть возможность

изменения модели хранения без

необходимости переделки клиентского кода

▫ Необходимо предусмотреть возможность

встраивания новых моделей размещения

• Объектно-ориентированное решение

// Host class

template <class CStorage>

class CMatrix : public CStorage {

// CMatrix class realization

};

// Strategy classes

class CRectStorage {

// Implicitly implements CStorage interface

// for 2D Rectangular storage

};

сlass CJaggedStorage {

// implicitly implements CStorage interface

// for 2D Jagged storage

};

// Specializations

typedef CMatrix<CRectStorage> CRectMatrix;

typedef CMatrix<CJaggedStorage> CJaggedMatrix;

• “Виртуальный” интерфейс CStorage

▫ В этом решении также используется

параметрический полиморфизм

/*

template <class T>

class Cstorage {

public:

CStorage<T>();

CStorage<T>(const int, const int);

CStorage<T>& operator=(const CStorage<T>&);

T &getEl(const int, const int) const;

void setEl(int, int, T );

int getNRows()const;

int getNCols()const;

protected:

~CStorage<T>();

};

*/

• CRectStorage: класс стратегии №1

template <class T>

class CRectStorage /* implements CStorage */ {

public:

CRectStorage<T>(const int nRows = 2, const int nCols = 2);

CRectStorage<T>& operator=(const CRectStorage<T> &cont);

T &getEl(const int i, const int j) const;

void setEl(int i, int j, T val);

int getNRows() const;

int getNCols() const;

protected:

// Destructor is protected for safe usage in derived classes

~CRectStorage<T>();

private:

// Service method for copying data from newSource to source

void setSource(T* newSource);

T* source; // Pointer to memory (matrix rows)

int nRows; // Number of rows

int nCols; // Number of columns

};

• CRectStorage: реализация (1)

template <class T>

CRectStorage<T>::CRectStorage(const int nRows, const int nCols) {

assert( nRows > 0 && nCols > 0 );

this->nRows = nRows;

this->nCols = nCols;

source = new T[nRows*nCols];

}

template <class T>

CRectStorage<T>::~CRectStorage() {

if(source) delete[] source;

source = 0;

}

• CRectStorage: реализация (2)

// Only for internal usage in this class:

// newSource array size is expected to be equal to nRows*nCols

template <class T>

void CRectStorage<T>::setSource(T* newSource) {

for( T* pSource = source, *pNewSource = newSource;

pSource-source < nRows*nCols;

pSource++, pNewSource++ )

*pSource = *pNewSource;

return;

}

• CRectStorage: реализация (3)template <class T>

CRectStorage<T>& CRectStorage<T>::operator=(

const CRectStorage<T> &stor ) {

if(this != &stor)

{

if(nRows*nCols == stor.nRows*stor.nCols)

{

nRows = stor.nRows;

nCols = stor.nCols;

}

else

{

delete[] source;

nRows = stor.nRows;

nCols = stor.nCols;

source = new T[nRows*nCols];

}

setSource(stor.source);

}

return *this;

}

• CRectStorage: реализация (4)template <class T>

T &CRectStorage<T>::getEl(const int i, const int j) const {

assert((i < nRows)&&(i >= 0)&&(j < nCols)&&(j >= 0));

return source[i + nRows * j];

}

template <class T>

void CRectStorage<T>::setEl(int i, int j, T val) {

assert((i < nRows)&&(i >= 0)&&(j < nCols)&&(j >= 0));

source[i + nRows*j] = val;

}

template <class T>

int CRectStorage<T>::getNRows() const {

return nRows;

}

template <class T>

int CRectStorage<T>::getNCols() const {

return nCols;

}

• Cmatrix: Host Class

▫ Учитывает стратегию хранения

▫ Обеспечивает типичные операции

▫ Может содержать итераторы (для STL)

template <class T, class CStorage>

class CMatrix : public CStorage {

public:

CMatrix<T, CStorage>(const int nRows=2, const int nCols=2);

CMatrix<T, CStorage>(const CMatrix<T, CStorage> &matr);

// Operations on matrices

CMatrix<T, CStorage>& operator+= (

const CMatrix<T,CStorage>& );

CMatrix<T, CStorage> operator+ (

const CMatrix<T, CStorage>& matr) const;

// Other operations

// ...

};

• CMatrix: реализация (1)

// Constructor calls strategy class constructor

template <class T, class CStorage>

CMatrix<T, CStorage>::CMatrix( const int nRows,

const int nCols ) :

CStorage(nRows, nCols) {}

// Copy constructor calls strategy class constructor and

// then copies data

template <class T, class CStorage>

CMatrix<T, CStorage>::CMatrix(const CMatrix<T, CStorage>&matr):

CStorage(matr.getNRows(), matr.getNCols() ) {

for(int i = 0; i < matr.getNRows(); i++)

{

for(int j = 0; j < matr.getNCols(); j++)

{

setEl(i, j, matr.getEl(i, j));

}

}

}

• CMatrix: реализация (2)

template <class T, class CStorage>

CMatrix<T, CStorage>& CMatrix<T, CStorage>::operator+= (

const CMatrix<T, CStorage>& matr ) {

assert( getNRows() == matr.getNRows() &&

getNCols() == matr.getNCols() );

for(int i = 0; i < getNRows(); i++) {

for(int j = 0; j < getNCols(); j++) {

setEl(i, j, getEl(i, j) + matr.getEl(i, j));

}

}

return *this;

}

template <class T, class CStorage>

CMatrix<T, CStorage> CMatrix<T, CStorage>::operator+ (

const CMatrix<T, CStorage>& matr) const {

CMatrix<T, CStorage> res = *this;

res += matr;

return res;

}

• Матрицы: следствия▫ Абтракции хранения, реализованные в CJaggedStorage и CRectStorage ,обеспечивают управление элементами при разных способах размещения в памяти

▫ Класс CMatrix использует общий интерфейс двумерных массивов. Это позволяет разрабатывать код, работающий с матрицами, независимо от деталей внутреннего устройства конкретного контейнера и легко изменять требуемый тип контейнера

▫ Общий интерфейс, задаваемый CStorage и иерархия классов стратегий обеспечивает открытую инфраструктуру для добавления новых классов стратегий

Software Engineering IОбъектно-ориентированный

анализ и проектирование

Раздел 4. Механизмы

повторного использования и

паттерны проектирования

Q & A

Recommended