На этом шаге рассмотрим примеры ограничений.
Ограничение (constraint) — это выражение определенного семантического условия, которое должно быть выполнено. Иначе говоря, ограничение — это инвариант класса или отношение, которое должно выполняться, пока система находится в устойчивом состоянии. Следует подчеркнуть, что система должна пребывать именно в устойчивом состоянии, поскольку существуют промежуточные ситуации, в которых состояние системы изменяется (а значит, является временным).
Все ограничения, касающиеся системы, находящейся в промежуточном состоянии, выполнить невозможно. Ограничения — это гарантии, выполняющиеся только, если система находится в устойчивом состоянии. Примеры ограничений — предусловия и постусловия, применяемые к системе, находящейся в устойчивом состоянии, т.е. в специальные моменты времени, когда операция активизируется или завершается [Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, р. 285.].
В ходе проектирования системы разработчики должны гарантировать, что все наложенные ограничения будут выполнены. Ограничения могут распространяться практически на все элементы модели. Смысл ограничений формулируется в виде строки, заключенной в фигурные скобки {} и размещенной рядом с классом или отношением, на которые они распространяются. Это выражение может быть сформулировано как на естественном языке (в виде текста), так и с помощью более формальной системы обозначений OCL (UML Object Constraint Language).
Одним из преимуществ формальной системы обозначений является возможность верификации ограничений. Как правило, ограничения формулируются в виде текста в определенном стиле, принятом среди разработчиков [Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, pp. 285-288.].
Размещение ограничения на визуальной диаграмме зависит от количества элементов, на которые оно распространяется:
Однако следует иметь в виду, что на размещение ограничений, помимо общих принципов, влияют особенности используемого программного обеспечения.
Ограничения, применяемые к ассоциациям обобщения, означают, является ли классификатор отношения полным. Они разделяются на четыре вида [Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, pp. 374-375.]:
Рассмотрим эти ограничения на рис. 1. Ограничение {incomplete} ({неполный}), наложенное на обобщения класса Plan (План), означает, что кроме планов выращивания и полива существуют и другие типы планов. Это значит, что экземпляр класса Plan может не быть экземпляром класса GrowingPlan (ПланВыращивания) или GardeningPlan (СадовническийПлан).
Рис.1. Примеры ограничений
Ограничение {disjoint} ({отдельный}) означает, что план не может быть одновременно планом выращивания и садовническим планом, по крайней мере, при указанных определениях классов. Иначе говоря, экземпляр класса GrowingPlan не может быть экземпляром класса GradeningPlan.
В диаграммах классов существуют и другие типы ограничений, относящихся к самим классам. К ним, например, относится ограничение {list} ({список}). Это ограничение означает, что измерения могут быть упорядоченными и повторяющимися.
Как показано на рис. 2, ограничения могут накладываться на отдельные классы, ассоциации в целом, а также на части ассоциаций.
Рис.2. Примеры ограничений
На данной диаграмме продемонстрировано ограничение кратности, наложенное на класс EnvironmentalController, означающее, что количество экземпляров этого класса в системе не может превышать семи.
Класс Cooler (Кондиционер) имеет разные виды ограничений. На его диаграмме показано, что операции с кондиционером обладают гистерезисом — кондиционер нельзя включить раньше, чем через пять минут после его выключения. Это ограничение приписано классу Cooler, поскольку требуется, чтобы этот инвариант выполнялся для всех экземпляров этого класса.
На данной диаграмме показаны также два ограничения на ассоциации. В ассоциации между классами EnvironmentalController и Light требуется, чтобы отдельные осветительные приборы имели уникальные индексы. Кроме того, на диаграмме показано ограничение "исключающее или" {хоr} на ассоциацию между контроллерами Heater и Cooler, утверждающее, что класс EnvironmentalController не может активизировать нагреватель и кондиционер одновременно. Это ограничение накладывается на ассоциацию, а не на классы Heater и Cooler, так как эти контроллеры нагревателя и кондиционера не в состоянии обеспечить выполнение этого инварианта.
Ограничения могут оказаться полезными для выражения вспомогательных классов, атрибутов и ассоциаций. Например, рассмотрим классы Adult (Взрослый) и Child (Ребенок), каждый из которых является подклассом абстрактного класса Person (Человек). В класс Person можно было бы включить атрибуты dateOfBirth (дата рождения) и age (возраст). Однако атрибут age является вторичным: его можно вычислить по значению атрибута dateOfBirth. Таким образом, в нашу модель можно включить оба атрибута, одновременно сформулировать ограничение, указывающее, что один из них вычисляется на основании другого. Выбор вторичного атрибута относится к тактическим решениям, но ограничение в любом случае является его неотъемлемой частью.
Аналогично, между классами Adult и Child может существовать ассоциация Parent (Родитель). Кроме того, в зависимости от цели модели между ними можно установить ассоциацию Caretaker (Опекун). Например, такая ситуация возникает, когда моделируются юридические отношения между родителями и ребенком в системе социального обеспечения. Класс Caretaker является вторичным. Он выводится из ассоциации Parent и этот факт можно сформулировать в виде ограничения, наложенного на ассоциацию Caretaker.
На следующем шаге рассмотрим классы ассоциаций и примечания.