Panduan Lengkap Menggunakan OCL dalam UML dengan Contoh PlantUML
Pendahuluan

Meskipun UML (Bahasa Pemodelan Terpadu) sangat luar biasa untuk memvisualisasikan struktursistem, ia kekurangan presisi untuk mengekspresikan kompleks aturan bisnis dan semantik. Di sinilah Bahasa Kendala Objek (OCL)masuk. OCL berperan sebagai ‘perekat’ formal yang menghubungkan diagram UML dengan logika bisnis yang ketat dan tidak ambigu.
Panduan ini menjelaskan bagaimana OCL terintegrasi dengan UML, konsep-konsep kunci yang perlu Anda ketahui, dan memberikan contoh praktis PlantUMLcontoh untuk memvisualisasikan kendala-kendala ini.
1. Sinergi: Bagaimana OCL Melengkapi UML
Bayangkan UML sebagai ‘kerangka’ sistem Anda (kelas, asosiasi, keadaan) dan OCL sebagai ‘sistem saraf’ (aturan, kondisi, dan logika yang mengatur bagaimana kerangka tersebut berperilaku).
Representasi Visual dalam UML
Dalam UML standar, kendala OCL biasanya direpresentasikan menggunakan Catatan yang dilampirkan pada elemen model yang relevan (kelas, operasi, atau keadaan).
-
Stereotip:Seringkali, catatan yang berisi OCL diberi label
{kendala}steriotip. -
Konteks:Setiap ekspresi OCL dimulai dengan
kontekskata kunci, yang menyatakan elemen UML mana aturan ini berlaku.
2. Konsep Kunci OCL dalam UML
A. Invarian Kelas (inv)
Invarian adalah kondisi yang harusselalu benaruntuk setiap instance kelas, terlepas dari operasi apa yang dipanggil.
Konsep Kunci:Jika invarian dilanggar, sistem berada dalam keadaan tidak valid.

@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
**Invarian Kelas:**
context BankAccount
-- Saldo tidak pernah bisa negatif kecuali overdraft diaktifkan
inv balanceRule:
self.balance >= 0 atau self.isOverdraftEnabled
-- Batas overdraft tidak boleh melebihi 500
inv overdraftLimit:
self.isOverdraftEnabled mengimplikasikan self.balance >= -500
end note
@enduml
B. Kontrak Operasi (pre, post, body)
Operasi (metode) dapat memiliki kendala yang mendefinisikan perilaku mereka sebelum dan sesudah eksekusi.
-
Prasyarat (
pre): Apa yang harus benar sebelum operasi dimulai. (Tanggung jawab pemanggil). -
Kondisi pasca (
post): Apa yang akan benar setelah operasi selesai. (Jaminan operasi). -
Badan (
badan): Menentukan nilai kembalian yang tepat untuk operasi kueri.

@startuml
skinparam classAttributeIconSize 0
skinparam noteBackgroundColor #E8F5E9
class ShoppingCart {
- items: Bag<Product>
- totalAmount: Real
+ checkout(): Receipt
+ getTotal(): Real
}
note right of ShoppingCart
**Kontrak Operasi:**
-- Prasyarat: Keranjang tidak boleh kosong
context ShoppingCart::checkout(): Receipt
pre: self.items->notEmpty()
-- Kondisi pasca: Keranjang dikosongkan, struk dibuat
post: self.items->isEmpty() dan result <> null
-- Badan: Definisi operasi kueri
context ShoppingCart::getTotal(): Real
body: self.items->collect(price)->sum()
end note
@enduml
C. Nilai yang Diturunkan dan Nilai Awal (turunkan, inisialisasi)
Alih-alih menyimpan data yang berulang, UML memungkinkan atribut ditandai sebagai {diturunkan} atau {awal}, dengan OCL yang menentukan nilai tepatnya.

@startuml
skinparam classAttributeIconSize 0
skinparam noteBackgroundColor #E3F2FD
class Employee {
- firstName: String
- birthDate: Date
- {derived} age: Integer
- {initial} isActive: Boolean = true
}
note right of Employee
**Nilai Turunan & Awal:**
-- Hitung usia secara dinamis
context Employee::age: Integer
derive: self.birthDate.yearsSinceToday()
-- Status awal saat pembuatan
context Employee::isActive: Boolean
init: true
end note
@enduml
D. Penjaga Mesin Status
Pada diagram Mesin Status, transisi dapat memiliki penjaga—ekspresi boolean yang harus bernilai benar agar transisi terjadi. OCL adalah bahasa standar untuk menulis penjaga ini.

@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
**Invarian Status:**
context Order
inv: self.status = 'Pending' mengimplikasikan
self.submittedBy->notEmpty()
end note
note right of Approved
**Kondisi Pasca approve():**
context Order::approve()
post: self.status = 'Approved' dan
self.approvedDate <> null
end note
@enduml
3. Studi Kasus Komprehensif: Model Perusahaan
Mari kita terapkan OCL pada diagram kelas UML yang kompleks yang melibatkan Karyawan, Departemen, dan Proyek. Ini menunjukkan bagaimana OCL menavigasi asosiasi dan menggunakan iterator koleksi (select, forAll, size).

@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
**Invarian Kompleks & Navigasi:**
context Employee
-- 1. Aturan Atribut Dasar
inv ageCheck: self.age() >= 18
-- 2. Menavigasi Asosiasi (Multiplikitas)
inv maxProjects: self.worksOn->size() <= 4
-- 3. Menggunakan Iterator (forAll)
-- Supervisor harus dipekerjakan sebelum bawahan
inv hireOrder: self.subordinates->forAll(
sub | sub.hireDate > self.hireDate
)
-- 4. Aturan Asosiasi Silang
-- Karyawan hanya boleh bekerja pada proyek yang dikendalikan oleh departemennya
inv projectControl:
self.worksFor.controls->includesAll(self.worksOn)
-- 5. Pengidentifikasi Unik (Kunci)
inv uniqueSSN: Employee.allInstances()->forAll(e1, e2 |
e1 <> e2 mengimplikasikan e1.SSN <> e2.SSN
)
end note
note bottom of Department
**Atribut Turunan:**
context Department::nbrEmployees: Integer
derive: self.worksFor->size()
end note
note right of Project
**Invarian Proyek:**
context Project
-- Lokasi proyek harus salah satu lokasi departemen
inv validLocation:
self.controls.locations->includes(self.location)
end note
@enduml
4. Teknik Lanjutan OCL dalam UML
A. Menggunakan let untuk Kemudahan Membaca
Ketika ekspresi OCL menjadi terlalu rumit, gunakan letkata kunci untuk mendefinisikan variabel lokal dalam batasan. Ini membuat catatan UML jauh lebih mudah dibaca.

@startuml
skinparam classAttributeIconSize 0
class Employee {
- worksOn: Set<Project>
}
note right of Employee
**Menggunakan 'let' untuk logika kompleks:**
context Employee
-- Hitung total jam dan periksa batasannya
inv workingHours:
let totalHours: Integer =
self.worksOn->collect(hours)->sum()
in totalHours >= 30 dan totalHours <= 50
end note
@enduml
B. Menangani Nilai Sebelumnya dalam Post-Kondisi (@pre)
Ketika mendefinisikan post-kondisi, Anda sering perlu membandingkan baru keadaan dengan lama keadaan. OCL menggunakan @pre pasif untuk mengakses nilai properti persis seperti yang ada sebelum operasi dimulai.

@startuml
skinparam classAttributeIconSize 0
class Company {
- employees: Set<Employee>
+ hireEmployee(p: Employee)
}
note right of Company
**Menggunakan @pre dalam Post-Kondisi:**
context Company::hireEmployee(p: Employee)
-- Himpunan karyawan baru adalah himpunan lama ditambah orang baru
post: self.employees = self.employees@pre->including(p)
end note
@enduml
5. Praktik Terbaik untuk OCL dalam UML
-
Berikan Nama pada Batasan Anda: Selalu beri nama pada invarian dan kondisi Anda (misalnya
inv maxProjects:). Ini membuat lebih mudah untuk merujuk mereka dalam dokumentasi atau matriks pelacakan. -
Gunakan Catatan Secara Strategis: Dalam PlantUML dan alat UML visual, jangan memenuhi kotak kelas dengan OCL. Letakkan OCL di catatan yang berdekatan. Ini membuat diagram tetap bersih dan mudah dibaca.
-
Jangan Terlalu Mengikat: Tulis OCL hanya untuk aturan yang tidak dapat dengan mudah dinyatakan melalui kelipatan UML (misalnya
0..1,1..*) atau tipe dasar. Jika suatu aturan dapat ditampilkan secara visual, tampilkan secara visual. -
Manfaatkan Iterator Koleksi: Kuasai
->select(),->forAll(),->exists(), dan->collect(). Mereka adalah alat paling kuat untuk menavigasi asosiasi UML dalam OCL. -
Periksa Nilai Null/Himpunan Kosong: Saat menavigasi asosiasi opsional (kelipatan
0..1atau0..*), selalu gunakan->notEmpty()atau->isEmpty()sebelum mengakses properti untuk menghindari kesalahan evaluasi yang tidak terdefinisi.













