classDiagram
direction LR
Review "*" o-- "1" Movie : has
Review "*" o-- "1" Critic : is done by
Critic "1" *-- "*" Review : can do
Movie "*" *-- "*" Critic : is reviewed by
class Movie{
-title: String
-year: int
-critics: Set
}
class Critic {
-name: String
-reviews: Set
}
class Review {
-movie: Movie
-rating: int
-comment: String
-critic: Critic
}
LAB#SE02-1: Movie/Review, model
Introduction
Basic understanding of Java programming language is required, as well as some familiarity with Maven or Gradle for managing dependencies and building the project.
Knowledge of algotighms and data structures to implement the required classes.
Create three classes in Java (Movie, Critic and Review) that implement different algorightms or data structures.
Test these classes using JUnit.
- Create a new Maven or Gradle project and setting up the project structure
- Modify the project’s
pom.xmlorbuild.gradlefile to import necessary dependencies, including JUnit for testing - Implement the three required classes in Java
- Implement two basic patter-designs: singleton and think about factory
- Write JUnit tests to verify that classes work as expected
- Allow the user to input data via the console, rather than using
hard-coded test datain JUnit tests
Tasks
Model design
TODO: Review multiplicity concept and apply it to the UML!!
An association (the UML equivalent to a relationship in data modeling circles) has a multiplicity for each direction.
Dependencies
- Lombok (both dependency and Maven plugin):
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok-maven-plugin -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>1.18.20.0</version>
<scope>provided</scope>
</dependency>- Junit:
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.9.1</version>
<scope>test</scope>
</dependency>- Java Faker: dependency used to generate stub data for testing
First approach
Domain design
Movie
A Movie class shall represent a movie being reviewed. It should have the following attributes:
title: aStringrepresenting the title of the moviereviews: aSetofReviewobjects representing the reviews that have been written for this moviecritic: TheCriticclass represents a critic who writes reviews
Critic
A Critic class shall represent a critic and a Review of its own. It should have the following attributes:
name: a String representing the name of the criticReview: theReviewclass represents a review of a movie written by a critic
Review
A Review class shall represent the information that identifies a review of a movie. It shall have the following attributes:
movie: aMovieobject representing the movie being reviewedcritic: aCriticobject representing the critic
UML diagram
.mmd files attachment through the file directive (as explained here) isn’t working, there’s an open bug in github.
Once the bug is solved, replace any {mermaid} snippet with a link to the uml.mmd file attached to each lab approach like this:
Second approach - Less coupling between classes
In this approach we remove redundant or unnecessary associations between the classes.
Changes in previous Domain
Movie
- This time
Moviehas aReviewset instead of aCriticset
Critic
- This time
Criticdoesn’t include any reference to the classReview
Review
Reviewclass is the same as in the first approach
UML diagram
classDiagram
direction LR
Movie "1" *-- "*" Review : may have
Review "*" o-- "1" Movie : talks about
Review "1" o-- "1" Critic : is written by
class Movie {
-title: String
-reviews: Set
}
class Review {
-movie: Movie
-critic: Critic
-rating: int
-comment: String
}
class Critic {
-name: String
}
Third approach - Use Manager classes
In this approach, instead of heavily binding classes between them, we delegate the responsibility to an external class, called MovieManager
Logic
MovieManager (non-static)
The non-static approach requests the user to create a MovieManager object in order to access its methods.
classDiagram
class MovieManager {
}
MovieManager (static)
A static method is a method that is owned only by the class, not by the class objects. You don’t instantiate a class object to access the static methods.
A static class is a class that doesn’t instantiate objects; thus, static class’ methods are accessed through the class name.
classDiagram
class MovieManager {
}
<<Static>> MovieManager
UML diagram
Fourth approach - Create a superclass Person
Let’s say that we want to add information about the FilmMaker and the Actors of a Movie to our model. Now we have three classes (Critic, FilmMaker and Actor) that have something in common: they are all persons. Thus, we can encapsule their common treats into a new class Person and make these classes inherit it.
Changes in Domain
Person
The Person class defines the common treats of any human being:
name: aStringrepresenting the name of the personbirthDate: aStringrepresenting the birth date of the person (it can also be aDatetype)
FilmMaker
FilmMaker is a Person subclass that contains info about its works:
movies: a Set ofMoviecontaining all the movies that thisPersonhas filmed
Actor
Actor is a Person subclass that contains info about its works:
movies: a Set ofMoviecontaining all the movies where thisPersonhas performed in
Critic
Critic now is a Person subclass that contains info about the reviews it has written:
reviews: a Set ofReviewcontaining all its reviews
Logic
Now the MovieManager class must take into account all these changes in its methods