Skip to content

Commit

Permalink
Sequence Diagram for set-genre and label
Browse files Browse the repository at this point in the history
  • Loading branch information
yeozongyao committed Apr 3, 2024
1 parent 08ba060 commit 6bd82ca
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 51 deletions.
131 changes: 80 additions & 51 deletions docs/DeveloperGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,88 +17,117 @@ Reference to AB-3 diagrams code
## Design & implementation

{Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.}
### Categorising the different books by their genres

### FEATURE: Categorising the different books by their genres
This functionality enables the categorization of books into distinct groups based on their genres, facilitating better
organization and tracking. The implementation of this feature involves interactions across multiple classes within the
system.

#### Overview
The process of categorizing books by genre is a multi-step operation that involves the following classes:
1. `BookDetails`: This class contains methods that handle the categorization of books.
2. `Book`: Individual book objects are updated with their respective genres directly in this class.
3. `Parser`: This class is responsible for parsing the input command to extract the specific index and genre.
1. `ParserGenre`: This class contains methods that handle the categorization of books.
2. `BookGenre`: Individual book objects are updated with their respective genres directly in this class.
3. `ParserMain`: This class is responsible for parsing the input command to extract the specific index and genre.

#### Detailed Workflow
Below is an example usage:
Here’s a step-by-step guide on how the feature works:
Step 1: The user initiates the process by inputting a command like `set-genre 1 Fantasy`. Here, the `Parser` class plays
a crucial role as it interprets the command and segregates it into a manageable array. The first part of this array holds
the command `set-genre`, which indicates the action to be executed.
#### Architecture-Level Design:

Step 2: The second segment of the input string is then further dissected into two components, which are the index (`1`)
and the genre (`Fantasy`). This step is essential for identifying the specific book and the genre it needs to be
associated with.
- The book management system is structured using a layered architecture model, comprising the UI layer, the command
- parser layer, and the data model layer.
- The `set-genre` feature is primarily situated in the command parser layer but interacts closely with the data model
- layer to update the genre of a book.

Step 3: With the index and genre clearly identified, these parameters are passed to the `setBookGenreByIndex` method
within the `BookDetails` class. This method is then responsible for assigning the specified genre to the book located at
the given index.
#### Component-Level Design:

- `UI Layer`: Receives input from the user and displays the results of operations. It's where the user's request to set
- a genre starts and ends with feedback.
- `ParserMain` (Command Parser Layer): Acts as the central hub for command processing, determining the type of command
- and delegating to the specific parser.
- `ParserGenre` (Command Parser Layer): Specializes in handling the set-genre command. It prompts the user for inputs
- and validates them.
- `BookList` (Data Model Layer): Maintains the list of books and genres. It's queried to ensure the book index is valid
- and to retrieve or update the list of genres.
- `BookGenre` (Data Model Layer): Provides the functionality to set the genre of a book in the `BookList`.

#### Implementation Details:

- Upon invoking the `set-genre` command, `ParserMain` interprets the command and forwards it to `ParserGenre`.
- `ParserGenre` then guides the user through selecting an existing genre or adding a new one, ensuring valid inputs at
- each step.
- The chosen genre is then applied to the specified book through `BookGenre`, which interfaces with `BookList` to make
- the update.
- Throughout this process, `Ui` is called upon to display messages, guiding the user and confirming the successful
- update.

#### Rationale for Design:

- The command pattern used allows for easy addition of new commands and features without altering existing code
- structures, adhering to open/closed principles.
- The clear separation of concerns makes the system robust, with each component focusing on a single responsibility,
- enhancing maintainability and scalability.

#### Alternatives Considered:

- An embedded approach, where genre setting logic is part of a larger class managing all book attributes, was
- considered. However, this was rejected due to potential scalability issues and difficulty in maintaining code.

(![SetGenreSequenceDiagram.png](SetGenreSequenceDiagram.png))

#### Implementation and Rationale
The decision to involve multiple classes in this operation is driven by the principles of object-oriented programming,
which emphasize modularity, encapsulation, and separation of concerns. By distributing responsibilities across different
classes, the system remains flexible, with each class focusing on a specific aspect of the functionality.

* The `BookDetails` class is central to managing book attributes and behaviors, making it the logical location for methods
* that categorize books.
* The `Book` class represents individual books, and it is here that genre information is ultimately stored, aligning with
* the principle that objects should manage their own state.
* The `Parser` class abstracts the complexity of command interpretation, ensuring that user inputs are correctly understood
* and acted upon by the system.

#### Alternatives Considered
An alternative design could have centralized the categorization logic within a single class, such as `BookDetails` or
`Parser`. However, this approach was discarded in favor of the current design to avoid overloading a single class with
multiple responsibilities and to adhere to the Single Responsibility Principle. By distributing the tasks, the system
gains in maintainability and scalability, facilitating future enhancements and modifications.

### BookList Class Component
The `BookList` class is responsible for all actions involving the list of books that the user has.

#### Overview
The `BookList` class contains one protected static ArrayList named books. This ArrayList will contain Book objects. The methods in
The `BookList` class contains one protected static ArrayList named books. This ArrayList will contain Book objects.
The methods in
this class all change the ArrayList according to the command given.

#### Detailed Workflow
Apart from the constructor, the methods of this class like getSize(), addBook() all either return a piece of information about the ArrayList,
the book object that is selected or change an attribute of the ArrayList or selected book object. For the printAllBooks() method, the ArrayList
is iterated through, with the details of each book being printed out according to the toString() format of each book. Other than that, methods like
markDoneByIndex() and markUndoneByIndex() both will change the isRead() attribute of the book of the given index. This class handles errors related to the
ArrayList, throwing exceptions for invalid indexes and invalid actions based on current state (if trying to mark a book that is already read).
Apart from the constructor, the methods of this class like getSize(), addBook() all either return a piece of
information about the ArrayList,
the book object that is selected or change an attribute of the ArrayList or selected book object. For the
printAllBooks() method, the ArrayList
is iterated through, with the details of each book being printed out according to the toString() format of each book.
Other than that, methods like
markDoneByIndex() and markUndoneByIndex() both will change the isRead() attribute of the book of the given index. This
class handles errors related to the
ArrayList, throwing exceptions for invalid indexes and invalid actions based on current state (if trying to mark a book
that is already read).

#### Implementation and Rationale

### Parser Class Component
The `Parser` class is responsible for parsing any input from the user and making sense of them to execute the correct commands.
The `Parser` class is responsible for parsing any input from the user and making sense of them to execute the correct
commands.

#### Overview
The `Parser` class contains several predefined string constants representing the valid commands and a public method to parse the
The `Parser` class contains several predefined string constants representing the valid commands and a public method to
parse the
input from the user.

#### Detailed Workflow
Whenever input from the user is detected by the program, the `Parser` class will split the command into 2 parts, with the first part
containing the command and the second containing details of the command (if present). The command entered is then evaluated using a
switch statement, with the value of it being compared to the values of each case. In the case of a match, the `Parser` class will then
execute the respective action associated with that command by calling other classes from the program such as `BookList` or `BookDetails`.
This class also handles errors and exceptions associated with the users input. For example, if the user were to give the command `mark` without
specifying an index for which book to mark, or gives a negative number, an appropriate error message will be shown and the command will be rendered
Whenever input from the user is detected by the program, the `Parser` class will split the command into 2 parts, with
the first part
containing the command and the second containing details of the command (if present). The command entered is then
evaluated using a
switch statement, with the value of it being compared to the values of each case. In the case of a match, the `Parser`
class will then
execute the respective action associated with that command by calling other classes from the program such as `BookList`
or `BookDetails`.
This class also handles errors and exceptions associated with the users input. For example, if the user were to give
the command `mark` without
specifying an index for which book to mark, or gives a negative number, an appropriate error message will be shown and
the command will be rendered
invalid.

#### Implementation and Rationale
The `Parser` class incorporates exception handling to detect invalid or unrecognized commands. This allows the program to continue running
The `Parser` class incorporates exception handling to detect invalid or unrecognized commands. This allows the program
to continue running
while prompting the user for valid input

By abstracting out the parsing functionality of BookBuddy into a separate `Parser` class, the complexity of parsing user input is removed
from the main code. It is instead replaced by a simple interface for the user to work with, adhering to the abstraction concept of
object-oriented programming.
By abstracting out the parsing functionality of BookBuddy into a separate `Parser` class, the complexity of parsing
user input is removed
from the main code. It is instead replaced by a simple interface for the user to work with, adhering to the abstraction
concept of object-oriented programming.

## Product scope
### Target user profile
Expand Down
Binary file added docs/SetGenreSequenceDiagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 45 additions & 0 deletions docs/sequenceDiagram/SetGenreSequenceDiagram.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@


@startuml
participant User
participant "ParserMain" as ParserMain
participant "ParserGenre" as ParserGenre
participant "BookList" as BookList
participant "BookGenre" as BookGenre
participant "Ui" as Ui

User -> ParserMain : set-genre [BOOK_INDEX]
ParserMain -> ParserGenre : executeParseSetGenre(books, inputArray)
ParserGenre -> BookList : validate index
ParserGenre -> ParserGenre : genreSelectionPrinter()
ParserGenre -> User : Display available genres

alt selecting existing genre
User -> ParserGenre : Select genre number
ParserGenre -> BookList : getAvailableGenres()
ParserGenre -> BookGenre : setBookGenreByIndex(index, selectedGenre, books)
BookGenre -> BookList : getBook(index)
BookGenre -> Ui : setGenreBookMessage(title, genre)
Ui -> User : confirmation message
else adding new genre
User -> ParserGenre : 6 (Add new genre)
ParserGenre -> User : Enter new genre
User -> ParserGenre : Input custom genre
ParserGenre -> BookList : Add new genre to list
ParserGenre -> BookGenre : setBookGenreByIndex(index, newGenre, books)
BookGenre -> BookList : getBook(index)
BookGenre -> Ui : setGenreBookMessage(title, genre)
Ui -> User : confirmation message
end

@enduml



Flow:
1. The user initiates the set-genre command.
2. ParserMain processes the input and delegates the command to ParserGenre.
3. ParserGenre then interacts with BookList to validate the book index and displays the available genres.
4. The user selects a genre or adds a new one, which ParserGenre processes.
5. If a new genre is added, it is included in the available genres in BookList.
6. Finally, BookGenre sets the genre for the specific book.
39 changes: 39 additions & 0 deletions docs/sequenceDiagram/SetLabelSequenceDiagram.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
@startuml
participant User
participant "ParserMain" as ParserMain
participant "ParserLabel" as ParserLabel
participant "BookList" as BookList
participant "BookLabel" as BookLabel
participant "Ui" as Ui

User -> ParserMain : label [BOOK_INDEX] [LABEL]
activate ParserMain
ParserMain -> ParserLabel : executeParseSetLabel(books, inputArray)
activate ParserLabel

ParserLabel -> BookList : getBook(index)
activate BookList
BookList --> ParserLabel : book
deactivate BookList

ParserLabel -> BookLabel : setBookLabelByIndex(index, label, books)
activate BookLabel

BookLabel -> Ui : labelBookMessage(title, label)
activate Ui
Ui -> User : confirmation message
deactivate Ui

deactivate BookLabel
deactivate ParserLabel
deactivate ParserMain
@enduml



Flow:
1. The user initiates the label command with a book index and a label.
2. ParserMain receives the command and delegates to ParserLabel.
3. ParserLabel parses the command, validates the input, and then calls BookLabel to set the label for the specified book.
4. BookLabel updates the label in the BookMain instance.
5. Finally, a confirmation message is displayed to the user.

0 comments on commit 6bd82ca

Please sign in to comment.