Review and Refactor
By the end of this lesson, you'll be able to:
- Identify duplicated record-fetching logic across LibraryService methods
- Extract a private helper method to remove that duplication
- Confirm the refactor preserves every method's existing behavior
Prerequisites: "Handle Errors"
Spotting the duplication
public Checkout__c checkOutBook(Id bookId, String memberName) {
Book__c book = [SELECT Id, Is_Checked_Out__c FROM Book__c WHERE Id = :bookId];
// ...
}
public List<Book__c> getBookDetails(Id bookId) {
Book__c book = [SELECT Id, Title__c, Author__c, Is_Checked_Out__c FROM Book__c WHERE Id = :bookId];
// ...
}
public Checkout__c checkOutBook(Id bookId, String memberName) {— one method.Book__c book = [SELECT Id, Is_Checked_Out__c FROM Book__c WHERE Id = :bookId];— queriesBook__cbyId.// ...— the rest of the method.}— closes it.- (blank line)
public List<Book__c> getBookDetails(Id bookId) {— a different method.Book__c book = [SELECT Id, Title__c, Author__c, Is_Checked_Out__c FROM Book__c WHERE Id = :bookId];— the same underlying "fetch this one book" shape, slightly different field lists, repeated across the class.// ...— the rest of the method.}— closes it.
Extracting a shared private helper
private Book__c getBookById(Id bookId) {
return [SELECT Id, Title__c, Author__c, Is_Checked_Out__c FROM Book__c WHERE Id = :bookId];
}
public Checkout__c checkOutBook(Id bookId, String memberName) {
Book__c book = getBookById(bookId);
if (book.Is_Checked_Out__c) {
throw new LibraryException('This book is already checked out.');
}
book.Is_Checked_Out__c = true;
update book;
Checkout__c checkout = new Checkout__c(Book__c = bookId, Member_Name__c = memberName, Checkout_Date__c = Date.today());
insert checkout;
return checkout;
}
private Book__c getBookById(Id bookId) {—private— an internal implementation detail, exactly like the helper methods extracted in Modules 12 and 17.return [SELECT Id, Title__c, Author__c, Is_Checked_Out__c FROM Book__c WHERE Id = :bookId];— a slightly wider field list, covering every field any method needs.}— closes the helper.- (blank line)
public Checkout__c checkOutBook(Id bookId, String memberName) {— now delegates instead of repeating the query.Book__c book = getBookById(bookId);— every caller gets a consistent, completeBook__cwithout repeating the query's field list.if (book.Is_Checked_Out__c) {— the existing guard, unchanged.throw new LibraryException('This book is already checked out.');— unchanged.}— closes theif.book.Is_Checked_Out__c = true;— unchanged.update book;— unchanged.- (blank line)
Checkout__c checkout = new Checkout__c(Book__c = bookId, Member_Name__c = memberName, Checkout_Date__c = Date.today());— unchanged.insert checkout;— unchanged.return checkout;— unchanged.}— closes the method.
Confirming behavior hasn't changed
LibraryService library = new LibraryService();
Checkout__c checkout = library.checkOutBook(someBookId, 'Amara Nkosi'); // still works exactly as before
LibraryService library = new LibraryService();— creates the service.- (blank line)
Checkout__c checkout = library.checkOutBook(someBookId, 'Amara Nkosi');— still works exactly as before — this refactor only changed how the class fetches aBook__cinternally, not what any of its public methods promise to callers.
This is the whole point of refactoring, revisited one final time to close out this project.
Exercise
Refactor returnBook to use the new getBookById helper instead of writing its own query for the related Book__c.
Show hint
Replace the inline query with a call to getBookById(checkout.Book__c).
Review and Refactor Quiz
My Notes
Log in to keep private notes on this lesson.
Questions about this lesson
No questions yet — be the first to ask.
Log in to ask a question about this lesson.
Summary
The final lesson reviews LibraryService as a whole, extracting a repeated "fetch the book and check it exists" pattern into a shared private method — the same refactoring discipline from Modules 12 and 17.