de_DEen_USes_ESfa_IRfr_FRhi_INid_IDjapl_PLpt_PTru_RUvizh_CNzh_TW

مقدمه

اگرچه زبان مدلسازی یکپارچه (UML) استاندارد بی‌بدیل صنعتی برای نمایش معماری نرم‌افزار است، اما دارای یک محدودیت ذاتی است: نمودارها عالی هستند در نشان دادن اینکه یک سیستم از چه چیزی ساخته شده است، اما در بیان قوانین کاربردی پیچیده و ظریفی که رفتار آن را کنترل می‌کنند، مشکل دارند.چهسیستم از چه چیزی ساخته شده است، اما در بیان قوانین کاربردی پیچیده و ظریفی که رفتار آن را کنترل می‌کنند، مشکل دارند.چگونهرفتار آن را دارد. وابستگی صرفاً به عناصر بصری مانند ضرایب و انواع پایه معمولاً منطق حیاتی سیستم را مبهم می‌گذارد و باعث اشتباه تفسیر در طول فاز توسعه می‌شود.
ورود به زبان محدودیت شیء (OCL). اگر UML استخوان‌بندی مدل سیستم شما باشد، OCL سیستم عصبی آن است—که قوانین دقیق، بدون ابهام و رسمی را ارائه می‌دهد که نحوه عملکرد استخوان‌بندی را تعیین می‌کند. با ادغام OCL با UML، مدل‌سازان می‌توانند فاصله بین طراحی بصری سطح بالا و مشخصات ریاضی دقیق را پر کنند، بدون اینکه نیاز به نوشتن کد واقعی داشته باشند.
این راهنما جامع، هم‌افزایی قدرتمند بین UML و OCL را بررسی می‌کند. ما مفاهیم اصلی OCL را تجزیه خواهیم کرد، نحوه اتصال محدودیت‌ها به کلاس‌ها، عملیات و ماشین‌های حالت را نشان خواهیم داد و مثال‌های عملی و قابل تکرار PlantUMLرا ارائه خواهیم داد. چه شما محدودیت‌های ساده کلاسی را تعریف می‌کنید یا قوانین کاربردی پیچیده متقابل بین ارتباطات را می‌نویسید، این راهنما شما را با دانشی تجهیز خواهد کرد که مدل‌های شما را از طرح‌های ساده به مشخصات مقاوم و با کیفیت مهندسی بالا ارتقا دهد.

UML + OCL = Unambiguous Design by Visual Paradigm

اگرچه UML (زبان مدلسازی یکپارچه) برای نمایش ساختار یک سیستم استثنایی است، اما دارای دقت کافی برای بیان قوانین کاربردی پیچیده و معنایی قوانین کاربردی و معانی. اینجا جایی است که زبان محدودیت شیء (OCL) ورود پیدا می‌کند. OCL به عنوان «چسب رسمی» عمل می‌کند که نمودارهای UML را به منطق کاربردی سخت و بدون ابهام متصل می‌کند.

این راهنما توضیح می‌دهد که OCL چگونه با UML ادغام می‌شود، مفاهیم کلیدی که باید بدانید، و مثال‌های عملی PlantUML مثال‌ها را برای نمایش این محدودیت‌ها ارائه می‌دهد.


1. هم‌افزایی: OCL چگونه با UML تکمیل می‌شود

UML را به عنوان «استخوان‌بندی» سیستم خود (کلاس‌ها، ارتباطات، وضعیت‌ها) و OCL را به عنوان «سیستم عصبی» (قوانین، شرایط و منطقی که نحوه رفتار استخوان‌بندی را کنترل می‌کند) در نظر بگیرید.

نمایش بصری در UML

در UML استاندارد، محدودیت‌های OCL معمولاً با استفاده از یادداشت‌ها که به عناصر مدل مربوطه (کلاس‌ها، عملیات یا وضعیت‌ها) متصل می‌شوند.

  • استرئوتایپ:اغلب، نوت‌های حاوی OCL به عنوان{محدودیت}استریوتایپ.

  • زمینه:هر عبارت OCL با کلمه کلیدیزمینهشروع می‌شود که مشخص می‌کند قانون به کدام عنصر UML اعمال می‌شود.


2. مفاهیم کلیدی OCL در UML

الف. موارد ثابت کلاس (inv)

موارد ثابت شرایطی هستند که بایدهمیشه درست باشندبرای هر نمونه‌ای از کلاس، بسته به اینکه چه عملیاتی فراخوانی شوند یا نشوند.

مفهوم کلیدی:اگر یک مورد ثابت نقض شود، سیستم در حالت نامعتبر قرار دارد.

@startuml
skinparam classAttributeIconSize 0
skinparam noteBackgroundColor #FFF9C4

class BankAccount {
  - accountNumber: String
  - balance: Real
  - isOverdraftEnabled: Boolean
  + withdraw(amount: Real)
  + deposit(amount: Real)
}

note right of BankAccount
  **موارد ثابت کلاس:**
  context BankAccount
  
  -- مانده هرگز منفی نمی‌تواند باشد مگر اینکه وام بیش از حد فعال باشد
  inv balanceRule: 
    self.balance >= 0 or self.isOverdraftEnabled
  
  -- حد وام بیش از حد نمی‌تواند بیش از 500 باشد
  inv overdraftLimit: 
    self.isOverdraftEnabled implies self.balance >= -500
end note
@enduml

ب. قراردادهای عملیات (prepostبدن)

عملیات (روش‌ها) می‌توانند محدودیت‌هایی داشته باشند که رفتار آن‌ها قبل و بعد از اجرای عملیات را تعریف می‌کنند.

  • شرایط پیش از (pre):چیزی که باید درست باشدقبل ازشروع عملیات. (مسئولیت فراخوان).

  • شرایط پس از (پس):چیزی که درست خواهد بودبعد ازپایان عملیات. (ضمانت عملیات).

  • بدنه (بدنه):مقدار دقیق بازگشتی برای عملیات پرس و جو را تعریف می‌کند.

@startuml
skinparam classAttributeIconSize 0
skinparam noteBackgroundColor #E8F5E9

class ShoppingCart {
  - items: Bag<Product>
  - totalAmount: Real
  + checkout(): Receipt
  + getTotal(): Real
}

note right of ShoppingCart
  **قراردادهای عملیاتی:**
  
  -- شرط پیش از: سبد خالی نباشد
  context ShoppingCart::checkout(): Receipt
  pre: self.items->notEmpty()
  
  -- شرط پس از: سبد خالی شود، فاکتور تولید شود
  post: self.items->isEmpty() and result <> null
  
  -- بدنه: تعریف عملیات پرس و جو
  context ShoppingCart::getTotal(): Real
  body: self.items->collect(price)->sum()
end note
@enduml

ج. مقادیر مشتق شده و اولیه (مشتق شدهاولیه)

به جای ذخیره‌سازی داده‌های تکراری، UML به ویژگی‌ها اجازه می‌دهد که به عنوان{مشتق شده}یا{اولیه}علامت‌گذاری شوند، که OCL مقدار دقیق آن‌ها را تعریف می‌کند.

@startuml
skinparam classAttributeIconSize 0
skinparam noteBackgroundColor #E3F2FD

class Employee {
  - firstName: String
  - birthDate: Date
  - {derived} age: Integer
  - {initial} isActive: Boolean = true
}

note right of Employee
  **مقادیر مشتق شده و اولیه:**
  
  -- محاسبه سن به صورت پویا
  context Employee::age: Integer
  derive: self.birthDate.yearsSinceToday()
  
  -- حالت اولیه در زمان ایجاد
  context Employee::isActive: Boolean
  init: true
end note
@enduml

د. محافظ‌های ماشین حالت

در نمودارهای ماشین حالت، انتقال‌ها می‌توانند داشته باشندمحافظ‌ها—عبارات منطقی که باید به درستی ارزیابی شوند تا انتقال انجام شود. OCL زبان استاندارد برای نوشتن این محافظ‌هاست.

@startuml
skinparam stateBackgroundColor #F3E5F5

[*] --> Created
Created --> PendingApproval : submit()

state PendingApproval {
}

PendingApproval --> Approved : [total < 10000]
PendingApproval --> Rejected : [total >= 10000]

Approved --> Shipped : ship()
Shipped --> [*]

note right of PendingApproval
  **پایداری حالت:**
  context Order
  inv: self.status = 'Pending' implies 
       self.submittedBy->notEmpty()
end note

note right of Approved
  **شرایط پس از تأیید():**
  context Order::approve()
  post: self.status = 'Approved' and 
        self.approvedDate <> null
end note
@enduml

3. مطالعه موردی جامع: مدل شرکت

بیایید OCL را به یک نمودار کلاس UML پیچیده که شامل کارمنداداره, و پروژه. این نشان می‌دهد که OCL چگونه به ارتباطات می‌پردازد و از تکرارکننده‌های مجموعه استفاده می‌کند (selectforAllsize).

@startuml
skinparam classAttributeIconSize 0
skinparam noteBackgroundColor #FFFDE7
skinparam noteBorderColor #FBC02D

class Employee {
  - SSN: String
  - firstName: String
  - birthDate: Date
  - hireDate: Date
  - salary: Float
  + age(): Integer
}

class Department {
  - number: Integer
  - name: String
  - locations: Set<String>
  - {derived} nbrEmployees: Integer
}

class Project {
  - number: Integer
  - name: String
  - location: String
}

Employee "0..*" -- "1" Department : worksFor > department
Employee "0..*" -- "0..*" Project : worksOn > project
Employee "1" -- "0..1" Department : manages > managedDept
Department "1" -- "0..*" Project : controls > projects
Employee "1" -- "0..*" Employee : supervisor > subordinates

note right of Employee
  **پایداری‌های پیچیده و کاوش در ارتباطات:**
  context Employee
  
  -- 1. قانون ویژگی پایه
  inv ageCheck: self.age() >= 18
  
  -- 2. کاوش در ارتباطات (چندگانگی)
  inv maxProjects: self.worksOn->size() <= 4
  
  -- 3. استفاده از تکرارکننده‌ها (forAll)
  -- مدیر باید قبل از زیردست‌ها استخدام شود
  inv hireOrder: self.subordinates->forAll(
    sub | sub.hireDate > self.hireDate
  )
  
  -- 4. قانون بین ارتباطات
  -- کارمند فقط می‌تواند در پروژه‌هایی که توسط اداره‌اش کنترل می‌شوند کار کند
  inv projectControl: 
    self.worksFor.controls->includesAll(self.worksOn)
    
  -- 5. شناسه منحصر به فرد (کلید)
  inv uniqueSSN: Employee.allInstances()->forAll(e1, e2 | 
    e1 <> e2 implies e1.SSN <> e2.SSN
  )
end note

note bottom of Department
  **ویژگی مشتق شده:**
  context Department::nbrEmployees: Integer
  derive: self.worksFor->size()
end note

note right of Project
  **پایداری پروژه:**
  context Project
  
  -- مکان پروژه باید یکی از مکان‌های اداره باشد
  inv validLocation: 
    self.controls.locations->includes(self.location)
end note

@enduml

4. تکنیک‌های پیشرفته OCL در UML

الف. استفاده از تعریفبرای خوانایی

وقتی یک عبارت OCL خیلی پیچیده می‌شود، از کلمه کلیدی تعریفبرای تعریف متغیرهای محلی درون محدودیت استفاده کنید. این کار نوت UML را بسیار خوانا‌تر می‌کند.

@startuml
skinparam classAttributeIconSize 0

class Employee {
  - worksOn: Set<Project>
}

note right of Employee
  **استفاده از 'let' برای منطق پیچیده:**
  context Employee
  
  -- محاسبه کل ساعت‌ها و بررسی محدودیت‌ها
  inv workingHours: 
    let totalHours: Integer = 
      self.worksOn->collect(hours)->sum() 
    in totalHours >= 30 و totalHours <= 50
end note
@enduml

ب. مدیریت مقادیر قبلی در شرایط پس‌از عملیات (@pre)

وقتی شرط پس‌از عملیات را تعریف می‌کنید، اغلب نیاز دارید تا حالت جدید را با حالت قدیمی مقایسه کنید.جدیدحالت را با حالت قدیمیمقایسه کنید. OCL از علامت @preپس‌وند برای دسترسی به مقدار یک ویژگی دقیقاً همان‌طور که قبل از شروع عملیات بود، استفاده می‌کند.

@startuml
skinparam classAttributeIconSize 0

class Company {
  - employees: Set<Employee>
  + hireEmployee(p: Employee)
}

note right of Company
  **استفاده از @pre در شرایط پس‌از عملیات:**
  context Company::hireEmployee(p: Employee)
  
  -- مجموعه کارمندان جدید، مجموعه قدیمی به علاوه فرد جدید است
  post: self.employees = self.employees@pre->including(p)
end note
@enduml

5. بهترین روش‌ها برای OCL در UML

  1. محدودیت‌های خود را نام‌گذاری کنید:همیشه محدودیت‌ها و شرایط خود را نام‌گذاری کنید (مثلاً inv maxProjects:). این کار باعث می‌شود که در مستندات یا ماتریس‌های ردیابی به آن‌ها به راحتی ارجاع داده شود.

  2. از نوت‌ها به صورت استراتژیک استفاده کنید:در PlantUML و ابزارهای بصری UML، جعبه کلاس را با OCL پر نکنید. OCL را در نوت‌های مجاور قرار دهید. این کار نمودار را تمیز و خوانا نگه می‌دارد.

  3. از محدود کردن بیش از حد خودداری کنید:فقط OCL را برای قوانینی بنویسید که به راحتی با ضرایب UML بیان نمی‌شوند (مثلاً0..11..*) یا انواع پایه. اگر قانونی بتواند به صورت بصری نشان داده شود، آن را به صورت بصری نشان دهید.

  4. از تکنیک‌های تکرارگر گروه‌ها بهره ببرید:مسلط شوید->select()->forAll()->exists(), و->collect(). این‌ها قوی‌ترین ابزارها برای پیمایش ارتباطات UML در OCL هستند.

  5. بررسی کنید که آیا مقدار null یا مجموعه خالی وجود دارد یا خیر:هنگام پیمایش ارتباطات اختیاری (ضریب0..1یا0..*) همیشه از->notEmpty()یا->isEmpty()قبل از دسترسی به ویژگی‌ها برای جلوگیری از خطاهای ارزیابی نامشخص استفاده کنید.

 

نتیجه‌گیری

در حوزه مهندسی نرم‌افزار، ابهام دشمن کیفیت است. هرچند UML یک دایره واژگان بصری بی‌قیمت برای بحث درباره معماری سیستم فراهم می‌کند، اما ادغام زبان محدودیت شیء (OCL) است که آن دیاگرام‌های بصری را به مشخصات دقیق و بدون ابهام تبدیل می‌کند.
همان‌طور که در طول این راهنما کشف کردیم، OCL به عنوان پل حیاتی بین طراحی سطح بالا و اجرا عمل می‌کند. با مسلط شدن بر ناوردایی‌های کلاس، قراردادهای عملیاتی و تکنیک‌های تکرارگر گروه‌ها، اطمینان حاصل می‌کنید که قوانین کسب‌وکار شما در ترجمه بین تیم طراحی و توسعه‌دهندگان از دست نمی‌رود. علاوه بر این، استفاده از ابزارهایی مانند PlantUML به شما امکان می‌دهد تا محدودیت‌های OCL خود را کنترل نسخه، قابل خواندن و به‌صورت هماهنگ در کنار دیاگرام‌های بصری خود نگه دارید.
در نهایت، پذیرش OCL عملکرد مدل‌سازی شما را ارتقا می‌دهد. این کار نقش شما را از صرفاً «کشیدن مربع‌ها و خطوط» به تعریف معانی دقیق و ریاضی سیستم تغییر می‌دهد. با پذیرش هم‌افزایی شفافیت بصری UML و دقت رسمی OCL، پایه‌ای محکم برای ساخت نرم‌افزاری ایجاد می‌کنید که نه تنها به درستی طراحی شده، بلکه به‌طور دقیق با نیازهای واقعی کسب‌وکار هم‌خطی دارد.