From Diagram to Code
Translate the model one responsibility at a time: fields become instance attributes; operations become methods; associations become references to other objects.
The UML activity diagram shows the translation workflow; rounded boxes are actions read from the start circle to the end bullseye.
Define the Model
None means no grade has been assigned. A list comprehension builds a new list by reading the enrollment links. raise ValueError(...) rejects an input that breaks a model rule.
class Student:
def __init__(self, student_id, name):
self.student_id = student_id
self.name = name
self._enrollments = []
def enroll(self, course):
for enrollment in self._enrollments:
if enrollment.course is course:
raise ValueError("Already enrolled")
enrollment = Enrollment(self, course)
self._enrollments.append(enrollment)
course._enrollments.append(enrollment)
return enrollment
def course_codes(self):
return [enrollment.course.course_code for enrollment in self._enrollments]
class Course:
def __init__(self, course_code, title, credits):
if not isinstance(credits, int) or isinstance(credits, bool) or credits <= 0:
raise ValueError("Credits must be a positive integer")
self.course_code = course_code
self.title = title
self.credits = credits
self._enrollments = []
def student_names(self):
return [enrollment.student.name for enrollment in self._enrollments]
class Enrollment:
def __init__(self, student, course):
self.student = student
self.course = course
self._grade = None
@property
def grade(self):
return self._grade
def set_grade(self, value):
if value not in {"A", "B", "C", "D", "F"}:
raise ValueError("Grade must be A, B, C, D or F")
self._grade = valueThe definitions produce no visible output. Use Student.enroll to create and register a link on both sides; directly constructing Enrollment would not register it.
Create the Object Snapshot
Continue with all three class definitions above:
ada = Student("S001", "Ada Lovelace")
cs101 = Course("CS101", "Intro to CS", 6)
enr1 = ada.enroll(cs101)
enr1.set_grade("A")
print(ada.course_codes())
print(cs101.student_names())
print(enr1.grade)Output
['CS101']
['Ada Lovelace']
A
The returned enrollment links Ada and CS101; its grade becomes A. Each query builds a new list from those links.
Keep one Course object per catalog code: duplicate detection here uses object identity. Data is held only in memory.
Try it: enroll Grace in CS101, grade her enrollment B, and check that Ada’s grade remains A. Then reject grade Z and confirm that the stored grade is unchanged.
The model now supports enrollment and grading. Application design begins by asking who uses these operations and what they want to achieve.