NUPlannerMarch - April 2024

Northeastern University

Skills Learned: Java, Object-Oriented Programming, MVC Design Pattern, Java Swing, JUnit, Access Modifiers, Large Codebase Design Principles

Code Available Upon Request

NUPlanner, built by myself and partner Calli Colvin (ccolv22@gmail.com) is a personal scheduling application (similar to Google Calendar) that allows clients to manage their week by creating, modifying, and removing events from their schedule. An event is defined by the following parameters:

In the system, the user can perform the following actions:

Below are screenshots of the main windows of the application. The left-most window is the schedule frame that allows the user to interact with the selected schedule. Using the combo box in the bottom left, they can select which schedule they would like to view. Once they have selected a schedule, they can click on the "Create Event" button, which will open a new window (2nd image from the left) to allow the user to enter in details for a new event. They can also click on the "Schedule Event" button, which will open a window (3rd image from the left) that allows the user to enter in details for a new event along with specifing a desired duration. The system will then determine the start and end times of the event based on the availability of the host (event creator) and all invites. The user can also click on any event currently on their schedule (represented by a colored block) to open a window (4th image from the left) that shows the current details of the event. From here, they can change any of the event parameters (title, location, start time, invites, etc) and save the changes by clicking on the "Modify Event" button. They can also click on the "Remove Event" button, which will subsequently remove the event from their schedule. If the user who removes the event is also the event's host, then the event will also be removed from the schedules of all invites.

Finally, in the top left of the schedule frame, the user can click on the "File" tab that allows them to upload a new user's schedule or save all schedules in the system to a specified location. Screenshots of this functionality can be seen below.

It is important to note that there are no conflicting events within a user's schedule. This is an invariant of the model. A user cannot have two events occurring at the same time unless an event starts at the same time another event ends. If the user attempts to perform an action that would cause a conflict, the view displays an error message to the user stating that this action is not valid.

Codebase Overview and Design Principles

The overall design for NUPlanner follows a Model-View-Controller (MVC) architecture that relies on the view being given access to read-only characteristics of the model in order to display the information in the system. An asynchronous controller is then used to respond to inputs made in the view, subsequently relaying commands to the model to make mutations. In addition to these three components, a file input/output component is used to allow the model to read/write data to files. A "PlannerFeatures" interface is used to allow the view and controller to communicate without the need for either component to understand each other's implementations. Finally, a scheduling strategy component is used to allow the controller to create an auto scheduled event based on the parameters provided by the view and subsequently add that event to the model. A simple class diagram featuring these components can be seen below:

This structure excels in ensuring that the entire codebase follows good design principles and practices. To start, all fields of all classes are private/protected to ensure classes only communicate through public methods while keeping its own data safe. Final fields are also used to ensure appropriate references cannot change, forcing them to be non-null on object creation. We tried to keep as many classes non-public as possible within each package (model, view, controller) to ensure that our components could not be tightly coupled. For example, our model component/package uses 5 individual classes to represent data/actions in the planner, such as representing a schedule or a duration. However, only two of these classes are public, one being NUPlanner (implementation of the model interface), and the second being a value class called Event (a class to represent an Event). This forces other classes in other packages to only communicate with these public classes, thus reducing coupling.

Another important design principle of our system was modularity. We wanted to make it easy for different components of our system to be swapped with other implementations, such as replacing our view (built with Java Swing) with another view (perhaps built with a different graphics library). Most of this was solved using interface types in all public method signatures, allowing new implementations for different components to be made without needing to change existing code. As mentioned above, our use of a PlannerFeatures interface, which specifies all actions a user can make in the system (how they can interact with the view), allows the controller and view to know nothing about each other's implementation. So long as the controller is able to correctly respond to all method calls, and the view is implemented to correctly call on those actions when necessary, neither component needs to know how the other does its job. This allows for complete modularity between the components.

Our codebase's modularity was actually tested when we were asked to swap code with another group of students working on the same project. Each group's goal was to make each other's view work with their code base. On our end, we wrote object adapters to adapt their view implementations and interfacse to our code, thus allowing their view to commmunicate with our controller and model through the adapters. Because we had followed good design principles in creating our codebase, we only had to write three simple adapters between our components and their view to make their view work in our system.

Difficulties and Learning Outcomes

Over the course of two months, Calli and I wrote almost 50 files (classes, interfaces, and unit tests) within numerous packages to create this application. I'd estimate over 60 hours of work was put into creating this program, making it by far the largest codebase I've ever designed. The scale of this project is what made NUPlanner difficult; trying to organize code, writing comments and javadoc to make sure we remembered each class and method's purpose, and bringing multiple components together without loosing sight of the design principles the code needed to follow. This project was the accumulation of two semesters worth of object-oriented learning, allowing me to bring together all my programming knowledge to create an application which myself and my partner can be proud of. This project showed us the pros and cons of different design strategies, how to debug large programs, how to keep code organized, and how to work with other people when creating large programs. Overall, I'd say that NUPlanner has been one of my favorite projects so far, and I'm excited to use these lessons when desiging future applications.

I'd like to thank Calli Colvin for her tremendous work on this project. I would also like to thank our professor, Lucia Nunez, for her constant guidance and support throughout the semester.