This repository is intended to store a complex user-website interaction simulation. It is part of a computer science assignment (POO / 2nd year, 1st semester).
You can check out the first stage of the project here.
Full completion date: 03 Jan. 2023
Deadline: 16 Jan. 2023
This project will be available on Github once the deadline passes. The original homework is available on our OCW, but a copy of the text shall be provided in this repository.
Once the deadline passes, this project will be available under the MIT license. For more info about the author of the code, please check out my personal website. Other interesting projects are made available on my GitHub page (a follow would be greatly appreciated!).
In the previous stage of the project, even when the design patterns were outlined separately, to this day, they did not help the project receive any bonuses (at that point, four design patterns were implemented). For this reason, this section was moved up a little, in order to help the POO team correctly identify them and mark them.
All the design patterns used throughout the project are explained in this section. All of them are actually further explained in the "Design Patterns: Elements of Reusable Object-Oriented Software" book (written by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides).
For a better readability, articles for each design pattern were provided.
Pages are static and (usually) independent of the logged-in user. For this reason, all the pages are actually instantiated only once, thus implementing the singleton design pattern.
More information about the singleton design pattern can be found here.
Whenever a page is queried, it responds with a custom page response - this structure is created using a builder, thus making use of the builder design pattern.
More information about the builder design pattern can be found here.
Whenever the interpreter is asked to follow a request, a structure (called a page request) is generated and sent over to the appropriate sub-interpreter, and from there, it is sent to the correct page. This makes use of the strategy design pattern.
More information about the strategy design pattern can be found here.
The Interpreter
class is a great example of making use of the facade design pattern - the
class hides the complexity of the whole action-processing and provides a simple and easy to use API
comprised of a constructor and a runActions()
method.
More information about the facade design pattern can be found here.
A certain page can be generated (since singleton is used, it will simply be returned instead)
using its name. This comes in handy whenever a change page
action is queried. This is the
reasoning behind PageFactory
, a class that makes use of the factory design pattern.
More information about the facade design pattern can be found here.
The methods and variables will follow Oracle's file organization convention, so:
- Class (static) variables: First the public class variables, then the protected, and then the private.
- Instance variables:First public, then protected, and then private.
- Constructors
- Methods: These methods should be grouped by functionality rather than by scope or accessibility. For example, a private class method can be in between two public instance methods. The goal is to make reading and understanding the code easier.
Some students were wrongly marked down for implementing this method (and I want to call out Mihai Soare, he is responsible for doing this).
Since it is best practice to implement a toString()
method, important classes that required it
during the debugging stages of the project might still have them implemented to this day.
It
is
best
practice!
Even the docs say that
"It is recommended that all subclasses override this method"!
In short, the control is passed down from the Main
class to the Interpreter
class - the latter
piece of code understands the commands and translates them to an actual user-website interaction.
There are multiple subinterpreters used throughout the project that split the work based on its
actual meaning, including:
BackInterpreter
- specifically designed for theback
command;ChangePageInterpreter
- called whenever achange page
action is to be resolved;DatabaseInterpreter
- used when the administrator has to update the movie database;OnPageInterpreter
- called when aon page
action is queried.
All of these interpreters implement the GeneralInterpreter
interface, which exposes the
executeAction()
interface required everywhere.
Users and movies are stored in two different ways:
- As individual entities (the
User
andMovie
classes) - this is their main representation, but this might not always suffice; - As collective entities (the
UsersDB
andMoviesDB
classes) - these are the database representations of the individual instances.
This way, whenever a mass of users has to be notified / a slice of the movies database is requested (e.g. filtered), the interaction is seamless.
A notification, as of right now, is only intended to hold information about a specific movie, be it
a new arrival, a deletion or a recommendation. Thus, whilst multiple notification types are possible
(check out the code for NotificationType
), notifications should only hold the information about a
movie and the notification type itself.
Pages are naturally split based on their required login status, meaning that the following packages arise:
unauth
- intended to store pages on which the used should be unauthenticated:UnauthHomePage
(internally calledunauth-homepage
) - the homepage for unauthenticated users;LoginPage
(internally calledlogin
) - the page that allows a user to log in to the platform;RegisterPage
(internally calledregister
) - the page that allows a user to register to the platform;
auth
- intended to store pages on which the user has to be authenticated:AuthHomePage
(internally calledauth-homepage
) - the homepage for authenticated users;LogoutPage
(internally calledlogout
) - the page that redirects the user tounauth-homepage
;MoviesPage
(internally calledmovies
) - the page that holds the information about the movie database;SeeDetailsPage
(internally calledsee details
) - the page that holds the information about a specific movie;UpgradesPage
(internally calledupgrades
) - the page that allows a user to upgrade to a premium account or buy tokens.
A PageFactory
class is provided that converts the internal name of a page into the actual instance
of the class (there is a single instance of each page since the singleton design pattern is used).
The interpreter(s) communicate with the pages via PageQuery
instances and the pages communicate
back to the Interpreter
via PageResponse
instances.