Introduction
In this lesson, we delve into a practical case study illustrating Object-Oriented Programming (OOP) principles in Python by building a simple domain model. We will cover the identification of entities, designing Python classes based on a real-world problem domain, defining attributes and methods to represent domain behavior, and using composition and aggregation to express object relationships. This session will also touch on implementing business rules through class interactions and refactoring the model to enhance readability and reduce coupling.
Identifying Entities and Designing Classes
To begin building a simple domain model, identify the significant entities in your domain. Suppose we are modeling a library system. Key entities might include Book, Author, and LibraryMember. Each of these will be represented by a class.
Here's how we might define a Book class:
class Book:
def __init__(self, title, author, isbn):
self.title = title
self.author = author
self.isbn = isbn
def __str__(self):
return f"{self.title} by {self.author} (ISBN: {self.isbn})"
Defining Attributes and Methods
Attributes are the properties of an object, whereas methods define its behavior and how it interacts with other objects. Continuing with our Book class, the attributes are title, author, and isbn. The __str__ method provides a way to display book information clearly.
book = Book("The Great Gatsby", "F. Scott Fitzgerald", "9780743273565")
print(book)
// Output
The Great Gatsby by F. Scott Fitzgerald (ISBN: 9780743273565)
Using Composition and Aggregation
Composition implies a strong relationship where the composed object cannot exist independently of the whole. Aggregation indicates a weaker relationship where parts can exist separately. For example, a LibraryMember may hold multiple Book instances.
class LibraryMember:
def __init__(self, name, membership_id):
self.name = name
self.membership_id = membership_id
self.borrowed_books = []
def borrow_book(self, book):
self.borrowed_books.append(book)
def __str__(self):
return f"{self.name} ({self.membership_id}), Books Borrowed: {[book.title for book in self.borrowed_books]}"
Implementing Business Rules
Business rules can be enforced through methods. For instance, preventing members from borrowing more than three books:
class LibraryMember:
# previous initialization method here...
def borrow_book(self, book):
if len(self.borrowed_books) >= 3:
print("Cannot borrow more than three books.")
return
self.borrowed_books.append(book)
Refactoring for Cohesion and Readability
Good software engineering involves regularly revisiting code to enhance cohesion (components of classes logically grouped together) and decouple (minimize dependency on one another). For example, ensuring LibraryMember doesn’t delve too deeply into book management can be achieved by having distinct roles for borrowing versus managing book inventory.
Summary / Key Takeaways
In this lesson on building a simple domain model using OOP principles in Python, you have learned:
- Identifying Entities: Recognize entities in a domain to create relevant Python classes.
- Attributes and Methods: Notify how to properly define attributes and methods that represent the state and behavior of the domain.
- Composition vs. Aggregation: Implement relationships between objects using composition for strong ties and aggregation for independent coexistence.
- Business Rules Implementation: Utilize instance methods to enforce business constraints effectively.
- Refactoring Code: Understand the importance of refactoring to improve code cohesion, reduce unnecessary coupling between objects, and improve readability.
