• 4 hours
  • Hard

Free online content available in this course.



Got it!

Last updated on 2/21/22

Refactor using the MVC pattern

Log in or subscribe for free to enjoy all this course has to offer!

We have a couple of options when it comes to making our architectural modifications. We can just run in and make changes like a barbarian...but this approach led to our existing problems. Instead, let’s look at a more systematic way of incorporating change. This step-by-step approach is called refactoring. 

Refactor Existing Code

Refactoring involves making changes to the existing code so that it still does the same thing; only the code is better.

If it’s doing the same thing, how is this possibly better?

Well, the result is the same; it’s the code generating the better result. Before looking at our airline application, let's examine a few general examples. Here’s one from a medical system I worked on. Can you figure out what it’s meant to do?

public void handlePatientVisit(Patient patient, PatientVisit patientVisitRecord) {
LocalDate today = LocalDate.now();
LocalDate dob = patient.getDateOfBirth();
Period period = Period.between(dob, today);
if (period.getYears() < 18) {
patientVisitRecord.segment[“5.1”].append(patient.parentInfo != null ?
patient.parentInfo : lookupNext(patient));

 Not so easy. The logic is all in-line, and the programmer assumes you know the format of the  patientInfo  object (whatever that is). Here is a way to refactor the code so it is easier to understand. See if you can figure out what it does now: 

public void handlePatientVisitRefactored(Patient patient) {
if (isPatientAMinor(patient)) {

First, the code checks if the patient is a minor. If that’s the case, then add a next of kin info segment. All the details of calculating the patient’s age, and modifying the correct section of the patient record have been abstracted into function calls, at a high level.

Wait, where are the other parts? 

Of course, the details for determining if the patient is a minor, and adding the next of kin segment need to exist. But we'll move them to functions that only do their one thing. Let’s look at the calculation of being a minor:

private boolean isPatientAMinor(Patient patient) {
Period period = Period.between(patient.getDateOfBirth(), LocalDate.now());
return period.getYears() < 18;

The code is still performing the same functionality. But we’ve modified it to be more understandable and maintainable. It’s also a lot easier to test. In the original version, we can’t independently test the age calculation portion of the code. We would have to pass in a patient record, then check if there was a  nextOfKin  segment added, or not. In the refactored version, we can test the minor age method by itself.  Separating these into single responsibilities is critical.

We can make similar changes at the architectural level as well.

Refactor using Model-View-Controller

Our major architectural refactoring will be putting in the model-view-controller pattern.

The goal of MVC is to have very specific responsibilities for each layer or section in our system. We will divide the code into three distinct sections. One will be the model, another, the view, and a third will be the controller. We'll also have a data layer that manages the persistence of our model objects. We’ll see the specifics of each of these in the following chapters!

User interface = View, Connecting Layer = Controller, Entity layer = Model, Data layer is separate
MVC architecture

Seems like a lot of work. Why bother?

Here’s a real-life example of the benefits. Many years ago, I wrote a math quiz program for my daughter. It ran on the Palm Pilot (yes, it was a while ago, that’s the point). Over the years, I’ve had a couple more kids, and I’ve updated that program to run on iPod, iPhone, Android devices, and even PC and Mac for my local school district. Since I followed MVC, it was easy to generate each version. Here’s why.

The model represents the state of our system. In my quiz game, one of the model objects was the question. Something needs to know that we’re asking what 5 + 3 is, and the answer is 8. It went into a MathProblem class.

The controller makes sure the use case is sequenced correctly. In the math game, something needs to ask the question, and then wait for the user to enter an answer. That’s the controller’s job. Once entered, the answer is checked, and the appropriate smiley or frowny face is displayed.

The core of the math application, the model and controller, have stayed the same. (OK, I did have to rewrite the code from C++ to Objective-C, to Swift and Java. But the classes ported easily.)

Lastly, the view is responsible for interacting with the user—both input and output. In my quiz game, the view needed to change to support the various environments, but it was easy to make the changes. But since I had abstracted out this layer, it was easy to change the interface, while keeping the rest of the code intact.

OK, I get it, but how does this apply to our airline application?

Here a few things we’ll focus on:

  • Many things should be model objects but are condensed down into just the four: client, reservation, pilot, and plane. We will need to modify them to be more in line with the SOLID design principles.

  • We will look at several opportunities to introduce controllers into our charter application. This will separate the direct connection between model and view components, and allow us to insert business logic in between.

  • And, speaking of view components, we will need to modify the Java Swing components to something that will render HTML pages that can be accessed from browsers or mobile clients.

Fortunately, the Spring Boot framework, which uses MVC, can be leveraged to help us get there. Let’s get started in the next chapter.

Let's Recap! 

  • Refactoring is replacing existing design with better-architected design.

  • Using MVC helps us separate responsibilities and create a more maintainable application. 

Example of certificate of achievement
Example of certificate of achievement