Файл: Методы и средства проектирования информационных систем и технологий (Основные понятия проектирования).pdf
Добавлен: 24.04.2023
Просмотров: 1741
Скачиваний: 31
СОДЕРЖАНИЕ
Глава 1. Основные понятия проектирования информационных систем
1.1 Понятие информационной системы
1.2 Методологические подходы к проектированию информационных систем
Глава 2. Объектно-ориентированный подход проектированияинформационной системы
2.1 Основные принципы построения объектной модели
2.2 Языки объектно-ориентированного моделирования и программирования
Концептуальной основой объектно-ориентированного подхода является объектная модель. Ее основными понятиями являются: объекты и атрибуты, целое и часть, классы и экземпляры.
Объект определяется как осязаемая реальность – предмет или явление, имеющее четко определяемое поведение. Объект обладает состоянием, поведением и индивидуальностью. Структура и поведение схожих объектов определяют общий для них класс. Термины «экземпляр класса» и «объект» являются эквивалентными. Состояние объекта характеризуется перечнем всех возможных статических свойств данного объекта и текущими динамическими значениями каждого из этих свойств. Поведение характеризует воздействие объекта на другие объекты и наоборот, с точки зрения изменения состояния этих объектов и передачи сообщений. Поведение объекта полностью определяется его действиями. Индивидуальность — это свойства объекта, отличающие его от всех других объектов.
Определенное воздействие одного объекта на другой с целью вызвать соответствующую реакцию называется операцией. В объектно-ориентированных языках операции, выполняемые над данным объектом, называются методами и являются составной частью определения класса (Java, C#).
Класс — это множество объектов, связанных общностью структуры и поведения [[12]]. Класс инкапсулирует (объединяет) в себе данные (атрибуты) и поведение (операции). Любой объект является экземпляром класса.
В объектно-ориентированном подходе акцент переносится на конкретные характеристики физической или абстрактной системы, являющейся предметом программного моделирования. Объекты также обладают целостностью, которая не может быть нарушена. Свойства, характеризующие объект и его поведение, остаются неизменными. Объект может только менять состояние, управляться или становиться в определенное отношение к другим объектам.
Основными механизмами объектной модели являются [[13]]:
- абстрагирование;
- инкапсуляция;
- наследование;
- полиморфизм;
- модульность;
- иерархия.
Все языки объектно-ориентированного программирования (C#, Java, Objective-C, Python, Swift), включая С++, основаны на этих положениях.
Абстрагирование — это выделение наиболее важных, существенных характеристик некоторого объекта, которые отличают его от всех других видов объектов и четко определяют его концептуальные границы с точки зрения дальнейшего рассмотрения и анализа, и игнорирование менее важных или незначительных деталей [[14]]. Абстрагирование позволяет управлять сложностью системы, концентрируясь на существенных свойствах объекта. Абстрагирование концентрирует внимание на внешних особенностях объекта и позволяет отделить самые существенные особенности его поведения от деталей их реализации. Выбор правильного набора абстракций для заданной предметной области представляет собой главную задачу объектно-ориентированного проектирования. Абстракция зависит от предметной области и точки зрения — то, что важно в одном контексте, может быть не важно в другом. Объекты и классы — основные абстракции предметной области.
Инкапсуляция — физическая локализация свойств и поведения в рамках единственной абстракции (рассматриваемой как «черный ящик»), скрывающая их реализацию за общедоступным интерфейсом. Инкапсуляция — это процесс отделения друг от друга отдельных элементов объекта, определяющих его устройство и поведение. Инкапсуляция служит для того, чтобы изолировать интерфейс объекта, отражающий его внешнее поведение, от внутренней реализации объекта. Объектный подход предполагает, что собственные ресурсы, которыми могут манипулировать только операции самого объекта, скрыты от внешней среды. Свойство инкапсуляции позволяет объединить данные и методы, работающие с ними в классе и скрыть детали реализации от пользователя. В объектно-ориентированном программировании код и данные могут быть объединены вместе, то есть, создаётся так называемый "чёрный ящик". Когда коды и данные объединяются таким способом, создаётся объект. Другими словами, объект — это то, что поддерживает инкапсуляцию.
В объектно-ориентированном языке все элементы так называемой предметной области выражаются через концепцию объектов. Внутри объекта коды и данные могут быть закрытыми. Закрытые коды или данные доступны только для других частей этого объекта. Таким образом, закрытые коды и данные недоступны для тех частей программы, которые существуют вне объекта. Если коды и данные являются открытыми, то несмотря на то, что они заданы внутри объекта, они доступны и для других частей программы. Характерной является ситуация, когда открытая часть объекта используется для того, чтобы обеспечить контролируемый интерфейс закрытых элементов объекта.
Объект является переменной определённого пользователем типа. Может показаться странным, что объект, который объединяет коды и данные, можно рассматривать как переменную. Однако применительно к объектно-ориентированному подходу это именно так. Каждый элемент данных такого типа является составной переменной.
Абстрагирование и инкапсуляция являются взаимодополняющими. Абстрагирование фокусирует внимание на внешних особенностях объекта, а инкапсуляция не позволяет объектам-пользователям различать внутреннее устройство объекта. Инкапсуляцию можно описать, сказав, что приложение разделяется на небольшие фрагменты связанной функциональности. Инкапсуляция подобна понятию сокрытия информации. Это возможность скрывать многочисленные детали объекта от внешнего мира. Внешний мир объекта — это все, что находится вне его, включая остальную часть системы. Сокрытие информации предоставляет то же преимущество, что и инкапсуляция, — гибкость.
Инкапсуляция реализуется с использованием модификаторов доступа или спецификации. Модификатор доступа определяет область видимости члена класса. Например, C # поддерживает следующие спецификации [[15]]:
- общественный (public). Такой член класса доступен из любого места в коде, а также из других программ и сборок;
- частный (private). Такой закрытый класс или член класса доступен только из кода в том же классе или контексте;
- защищенный (protected) – член класса доступен из любого места в текущем классе или в производных классах. При этом производные классы могут располагаться в других сборках;
- внутренний (internal) – класс и члены класса с подобной спецификацией доступны из любого места кода в той же сборке, однако он недоступен для других программ и сборок;
- защищенный внутренний (internal protected) – совмещает функционал двух спецификаций. Классы и члены класса с такой спецификацией доступны из текущей сборки и из производных классов.
Целью инкапсуляции является обеспечение согласованности внутреннего состояния объекта. В C# для инкапсуляции используются публичные свойства и методы объекта. Переменные, за редким исключением, не должны быть публично доступными. Предположим, что необходимо хранить вещественное значение и его строковое представление. Для того чтобы не производить каждый раз конвертацию в случае частого использования пример реализации без инкапсуляции будем таким:
class NoEncapsulation
{
public double Value;
public string ValueString;
}
При этом возможно отдельно изменять как само значение Value, так и его строковое представление, и в некоторый момент может возникнуть их несоответствие. Например, в результате исключения.
Пример реализации с использованием инкапсуляции:
class EncapsulationExample
{
private double valueDouble;
private string valueString;
public double Value
{
get { return valueDouble; }
set
{
valueDouble = value;
valueString = value.ToString();
}
}
public string ValueString
{
get { return valueString; }
set
{
double tmp_value = Convert.ToDouble(ValueString); // здесь может возникнуть исключение
valueDouble = tmp_value;
valueString = ValueString;
}
}
}
Здесь доступ к переменным valueDouble и valueString возможен только через свойства Value и ValueString. Если попытаться присвоить свойству ValueString некорректную строку и возникнет исключение в момент конвертации, то внутренние переменные останутся в прежнем, согласованном состоянии, поскольку исключение вызывает выход из процедуры.
В примере ниже на Java закрыты свойства «a» и «b» для класса A с целью предотвращения повреждения этих свойств другим кодом, которому необходимо предоставить только права на чтение.
Java
class A {
private int a;
private int b;
private void doSomething() { //скрытый метод
//actions
}
public int returnSomething() { //открытый метод
return a;
}
}
Наследование означает построение новых классов на основе существующих с возможностью добавления или переопределения данных и методов. Наследование — это свойство системы, позволяющее описать новый класс на основе существующего с частично или полностью заимствующейся функциональностью. Класс, от которого производится наследование, называется базовым, родительским или суперклассом. Новый класс — потомком, наследником или производным классом.
Наследование — это процесс, посредством которого один объект может приобретать свойства другого [[16]]. То есть, объект может наследовать основные свойства другого объекта и добавлять к ним черты, характерные только для него. Наследование позволяет поддерживать концепцию иерархии классов. Применение иерархии классов делает управляемыми большие потоки информации. Например, описание жилого дома. Дом — это часть общего класса, называемого строением. С другой стороны, строение — это часть более общего класса – конструкции, который является частью ещё более общего класса объектов, который можно назвать созданием рук человека. В каждом случае порождённый класс наследует все, связанные с родителем, качества и добавляет к ним свои собственные определяющие характеристики. Без использования иерархии классов, для каждого объекта пришлось бы задать все характеристики, которые бы его определяли. Однако при использовании наследования можно описать объект путём определения того общего класса или классов, к которому он относится, с теми специальными чертами, которые делают объект уникальным.
Полиморфизм — это свойство системы использовать объекты с одинаковым интерфейсом без информации о типе и внутренней структуре объекта. Полиморфизм позволяет одно и то же имя использовать для решения двух или более схожих, но технически разных задач. Целью полиморфизма, применительно к объектно-ориентированному подходу, является использование одного имени для задания общих для класса действий. Выполнение каждого конкретного действия будет определяться типом данных. Например, для языка Си, в котором полиморфизм поддерживается недостаточно, нахождение абсолютной величины числа требует трёх различных функций: abs(), labs() и fabs(). Эти функции подсчитывают и возвращают абсолютную величину целых, длинных целых и чисел с плавающей точкой соответственно. В С++ каждая из этих функций может быть названа abs(). Тип данных, который используется при вызове функции, определяет, какая конкретная версия функции действительно выполняется. В С++ можно использовать одно имя функции для множества различных действий. Это называется перегрузкой функций.
Концепцией полиморфизма является идея "один интерфейс, множество методов". Это означает, что можно создать общий интерфейс для группы близких по смыслу действий. Преимуществом полиморфизма является то, что он помогает снижать сложность программ, разрешая использование того же интерфейса для задания единого класса действий. Выбор же конкретного действия, в зависимости от ситуации, возлагается на компилятор. Программисту, не нужно делать этот выбор самому, а нужно помнить и использовать общий интерфейс. Пример из предыдущего абзаца показывает, как, имея три имени для функции определения абсолютной величины числа вместо одного, обычная задача становится более сложной, чем это действительно необходимо.
Полиморфизм может применяться также и к операторам. Фактически во всех языках программирования ограниченно применяется полиморфизм, например, в арифметических операторах. Так, в Си, символ «+» используется для складывания целых, длинных целых, символьных переменных и чисел с плавающей точкой. В этом случае компилятор автоматически определяет, какой тип арифметики требуется. В С++ возможно применить эту концепцию и к другим, заданным типам данных. Такой тип полиморфизма называется перегрузкой операторов.
Ключевым в понимании полиморфизма является то, что он позволяет манипулировать объектами различной степени сложности путём создания общего для них стандартного интерфейса для реализации похожих действий.
Модульность — это свойство системы, связанное с возможностью ее декомпозиции на ряд внутренне сильно сцепленных, но слабо связанных между собой подсистем-модулей. Модульность снижает сложность системы, позволяя выполнять независимую разработку отдельных модулей. Инкапсуляция и модульность создают барьеры между абстракциями.
Иерархия — это ранжированная или упорядоченная система абстракций, расположение их по уровням [[17]]. Основными видами иерархических структур применительно к сложным системам являются структура классов, что является иерархией по номенклатуре и структура объектов – иерархия по составу. Примерами иерархии классов является простое и множественное наследование. Это когда один класс использует структурную или функциональную часть соответственно одного или нескольких других классов. А примером иерархии объектов является агрегация.
Объектно-ориентированная система изначально строится с учетом ее эволюции. Наследование и полиморфизм обеспечивают возможность определения новой функциональности классов с помощью создания производных классов – потомков базовых классов. Потомки наследуют характеристики родительских классов без изменения их первоначального описания и добавляют при необходимости собственные структуры данных и методы. Определение производных классов, при котором задаются только различия или уточнения, в огромной степени экономит время и усилия при производстве и использовании спецификаций и программного кода.