0% found this document useful (0 votes)
73 views18 pages

Seminar 3

The document summarizes the process and results of Seminar 3, which involved demonstrating object-oriented programming skills. Key steps included thoroughly reviewing course materials, applying best practices like encapsulation and low coupling during coding, testing the program functionality through automated tests, and refactoring code for quality. The resulting GitHub project implemented a receipt for a sales transaction, displaying item quantities, prices, and totals to visualize the purchase.

Uploaded by

Seema Bashir
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
73 views18 pages

Seminar 3

The document summarizes the process and results of Seminar 3, which involved demonstrating object-oriented programming skills. Key steps included thoroughly reviewing course materials, applying best practices like encapsulation and low coupling during coding, testing the program functionality through automated tests, and refactoring code for quality. The resulting GitHub project implemented a receipt for a sales transaction, displaying item quantities, prices, and totals to visualize the purchase.

Uploaded by

Seema Bashir
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 18

Seminar 3

Object-Oriented Design, IV1350

Seema Fatima Bashir

[email protected]

4/5-2023
Object-Oriented Design, IV1350 Seminar 3 Solution

1. Introduction
I have collaborated with Razan Yakoub and Esra Salman to devise a solution for this seminar
and present it jointly.

The primary objective of Seminar 3 was to demonstrate the development of an object-oriented


program using established guidelines for object-oriented architecture, design, and programming.
The purpose was to create a program that adheres to the principles of object-oriented
programming, including structure, encapsulation, high cohesion, low coupling, and architecture,
while implementing the Basic flow, the Startup scenario, and parts of the Alternative flow as
described and discussed in earlier seminars.

To prepare for this seminar, participants were required to read chapters 6 and 7 of the provided
course literature, "A First Course in Object-Oriented Development," and attend lectures on
module 3, which covered the fundamentals of implementation. These lectures delved into the
specifics of coding, such as how to structure code, how to ensure encapsulation by limiting the
visibility of internal details through the use of public and private methods, how to create classes
with high cohesion and low coupling, and how to design an architecture that provides a clear
view of the system and its components.

In addition to coding, participants were required to apply best practices such as dividing the code
into packages, maintaining code conventions, including comments, refactoring code to improve
it, avoiding duplication of code and lengthy methods, reducing excessive primitive variables, and
simplifying flow control.

To ensure the program's functionality, it was essential to modify the code as necessary, resulting
in a flexible code that could accommodate changes in requirements or modifications to the
system. This was accomplished through automated testing, which evaluated the program's input
and output, providing valuable insights into the program's functionality. Overall, Seminar 3
provided an excellent opportunity to practice object-oriented programming and apply best
practices to develop a high-quality program.

1
Object-Oriented Design, IV1350 Seminar 3 Solution

Method
To prepare for this seminar, extensive preparation was undertaken, which involved a
comprehensive review of the course literature and lectures from Module 3 (Implementation).
Specifically, Chapter 6 and 7 in "A First Course in Object Oriented Development" were
thoroughly examined to gain a better understanding of the concepts involved.

The primary focus of seminar 3 was on translating the design to source code. To ensure that the
coding adhered to the required standards, a range of factors, including program structure,
encapsulation, cohesion, coupling, and code quality, were taken into consideration.
Encapsulation, which involves concealing irrelevant internal details and delineating between
public and private aspects of an object, was meticulously applied throughout the coding process.
High cohesion, which ensures that the various components of a class work together coherently,
and low coupling, which minimizes dependencies between classes, were also prioritized to
ensure that the code was efficient and effective.

One of the first steps in the coding process was to divide the code into packages. Each package
was identified by a unique reverse internet domain of the organization, followed by components
that identified the product and package within the product. The packages were also separated by
dots, and the components were categorized according to functionality, ensuring a high level of
cohesion.

Another important consideration during the coding process was the implementation of Java code
conventions. This included adhering to conventions for packages, classes, interfaces, methods,
variables, fields, parameters, and constants. Additionally, comments were required for each
declaration belonging to a public interface. These comments described what the unit does rather
than how it works. For methods, the Javadoc was used to explain what the methods do, as well as
their parameters and return values. Java keywords, names, and code samples were tagged with
the <code> tag, and clickable links to declarations were provided using the @link tag. Finally,
HTML files were generated with API documentation to provide a comprehensive guide to the
code.

2
Object-Oriented Design, IV1350 Seminar 3 Solution

Thirdly, a key aspect of improving code quality is the process of refactoring, which involves
making enhancements to the code without altering its functionality. Poorly written code can
often be identified by its unpleasant odor, and there are several techniques available to mitigate
these issues and improve the quality of the codebase.

One example of smelly code is duplicated or identical code present in multiple locations within
the program. This can result in inefficiencies and make the codebase difficult to maintain, as any
changes to one instance of the duplicated code must be replicated across all other instances.

To address this issue, developers can use refactoring techniques such as Extract Method or
Extract Class to consolidate the duplicated code into a single location, thereby improving the
program's cohesion, encapsulation, and coupling.

Fourthly, it is important to ensure that method names accurately reflect the functionality they
provide. A good method name should be descriptive and provide insight into what the method
does, allowing other developers to easily understand and utilize it. Additionally, excessively long
methods can be difficult to read and maintain, so it is recommended to keep them concise and
well-structured.

Another factor to consider when improving code quality is the size of the class. If a class
becomes too large, it can be difficult to maintain good cohesion, so developers should consider
splitting it into smaller, more focused classes to improve its readability and maintainability.

Finally, it is also recommended to keep parameter lists short, as lengthy lists can negatively
impact encapsulation and coupling. Techniques such as Preserve Whole Object or Introduce
Parameter Object can be used to simplify parameter lists and improve code quality. Additionally,
developers should carefully consider which parameters are truly necessary, and use techniques
like Replace Parameter with Method to eliminate unnecessary parameters.

Additionally, In software development, it is essential to consider several aspects of code quality,


and one of these is encapsulation. Excessive use of primitive variables can lead to poor

3
Object-Oriented Design, IV1350 Seminar 3 Solution

encapsulation, low cohesion, and increased coupling, making it difficult to manage the code.
Additionally, a long list of fields in a class can also indicate low cohesion, which can be
improved using the refactoring technique, Extract Class. This method involves encapsulating the
fields into a new class, thereby improving cohesion.

Moreover, using an array of primitive data instead of an object can result in confusion, making it
challenging to understand the code. To improve code clarity, it is preferable to use enumerations
instead of strings to represent constants. Meaningful names for packages and values in
statements can also enhance code readability.

Once the code is completed, it is crucial to test it thoroughly to ensure it works as expected.
Automated tests can help with this task, where the test program provides input to the program
being tested and evaluates the output. By implementing extensive tests that cover most possible
execution paths with various variable values, a comprehensive evaluation of the method is
possible.

Various testing techniques can be applied to different parts of the program. For example, unit
testing can be used to test the smallest possible piece of code, often a method. JUnit 5
framework, based on annotations, can be used to verify the results of unit tests. Using assert
methods, which verify that a method's parameters meet specific constraints, can help ensure that
the test passes.

It is important to note that tests should be written for every known bug, with no need to over-
design them. Organizing test classes in the same package as the class being tested can also help
manage the code better. Other considerations when testing code include focusing on quick and
easy executional tests, testing public, protected, and package private code, and avoiding testing
private methods. Additionally, it is essential to cover all branches of if-statements, test boundary
conditions, and extreme parameter values.

4
Object-Oriented Design, IV1350 Seminar 3 Solution

Result
The following link displays the GitHub project for this seminar:
https://github.com/RazanYakoub01/IV1350_Seminar_3.git

Receipt:

Figure 3.1: Receipt output

The figure above displays the receipt for a given sale. It visualizes the Time for sale as well as
the items purchased. The first column next to the items purchased states the quantity purchased
for each type of item. The second column states the price for one item. Lastly the last column
displays the total price, which is signified by item purchased multiplied with the quantity bought
for that specific item. Moreover, the end of the receipt gives further information to the customer.
The total price of the purchase is given on the first row by Total Sale Amount. The second row
displays the Sale VAT for the purchase, which consists of the sum of all item’s itemVAT.

5
Object-Oriented Design, IV1350 Seminar 3 Solution

It can be noted that the receipt also displays Total Sale Discount. The receipt shows that the total
sale discount is zero. This is due to the fact that the discount is not handled as part of seminar 3.
Hence no discount is applied on the sale.

Moreover, note also that the discountPackage which lies under integration should not be taken
into consideration for Seminar 3.

Lastly at the end of the receipt, it can be noted that the Total Amount Paid is displayed, following
the Total Change Amount which the customer receives in turn once payment is registered.

Figure 3.2: Figure displays method called printReceipt from class Receipt. The method returns a
StringBuilder.

This code is a method that returns a StringBuilder object. The purpose of this method is to print
out a sales receipt, containing information about a sale and the items that were purchased.

The first thing the method does is create a new StringBuilder object called saleReceipt. It also
creates a new SaleDTO object called finalSaleInformation which is initialized to the value of the
saleInfo object.

The method then appends several lines of text to the saleReceipt object. These lines contain
information about the sale, such as the time of the sale and a separator line. Then, the method

6
Object-Oriented Design, IV1350 Seminar 3 Solution

calls another method called printItemInfo() which returns a string containing information about
the items that were purchased. This string is appended to the saleReceipt object.

Next, the method appends more lines of text to the saleReceipt object, containing information
about the total sale amount, VAT, and discount. Another separator line is added after this
information. Then, the method appends information about the amount paid by the customer and
the change that is due.

Finally, the method returns the saleReceipt object, which now contains all of the information
about the sale and the purchased items.

Sale:

Figure 3.3: Public class Sale, declaration of variables and their names.

Figure 3.4: Creating Sale constructor.

7
Object-Oriented Design, IV1350 Seminar 3 Solution

The code displayed above is part of class Sale. This code sets up the initial state of a Sale object
and its associated variables. It contains several private instance variables, including the
timeOfSale, amountPaid, totalSaleAmount, totalSaleVAT, totalSaleDiscount, and changeAmount.

The Sale object also has references to a SaleDTO object named saleInfo, a Receipt object named
receipt, and a CurrentItem object named currentItem. Additionally, there is a List of CurrentItem
objects named currentItemList, which is initialized as an empty ArrayList.

The code also includes a constructor for the Sale object, which sets the timeOfSale instance
variable using the setTimeOfSale() method.

Figure 3.5: Private method called updateItemQuantity ( ) returns a Boolean. The method also has
parameters newItem of type itemDTO and itemQuantity of type int.

The code above defines a private method called updateItemQuantity() that takes an
ItemDTO object representing a new item and an integer value representing the quantity of
that item to add. The method returns a boolean value indicating whether the operation
was successful or not.

Inside the method, a boolean variable status is initialized to false. Then, a for loop is used
to iterate over the currentItemList which is a list of CurrentItem objects. Each
CurrentItem object contains an ItemDTO object and its corresponding quantity.

8
Object-Oriented Design, IV1350 Seminar 3 Solution

Inside the loop, the code checks if the name of the new item matches the name of an item
in the current item list using the getItemName() method. If a match is found, the current
quantity of that item is retrieved, and the item quantity is updated by adding the new
quantity to the current quantity. The setItemQuantity() method is then used to update the
quantity of that item in the currentItemList.

Finally, the status variable is set to true to indicate that the operation was successful. If no
match is found, the method returns false indicating that the item was not found in the
current item list and thus not updated.

In summary, the purpose of this method is to update the quantity of an item in the
currentItemList. If the item is already present in the list, its quantity is updated. If the
item is not present, the method returns false.

Figure 3.6: A method called addItemInfo method adds the new item to the CurrentItem list. The
method is public of type void.

The code above displays the implementation of the addItemInfo () method in a class. This
method is responsible for adding the details of an item, such as its quantity and
information, to the current sale being processed.

The method takes two arguments, itemInfo of type ItemDTO and itemQuantity of type
int, which represent the item details and the quantity of the item being added to the
current sale, respectively.

9
Object-Oriented Design, IV1350 Seminar 3 Solution

Inside the method, it checks if the item already exists in the currentItemList by calling the
updateItemQuantity () method. If the item already exists, the updateItemQuantity method
updates the item's quantity and returns true. If the item does not exist, it creates a new
CurrentItem object with the specified item details and quantity and adds it to the
currentItemList.

Then, the updateItemQuantity method is called with the itemInfo and itemQuantity
arguments to check if the item already exists in the currentItemList. If the item exists, the
method updates the item's quantity by adding the new quantity to the existing quantity,
and returns true. If the item does not exist, the method returns false.

If the updateItemQuantity method returns false, indicating that the item is not in the
current sale, the method creates a new CurrentItem object with the specified item details
and quantity, and adds it to the currentItemList by calling the add method on the list.

Overall, the addItemInfo method updates the quantity of an item in the current sale if it
already exists, or adds a new item to the current sale if it does not exist.

10
Object-Oriented Design, IV1350 Seminar 3 Solution

Tests

Figure 3.8: A Junit test, testing method receipt Info.

The code above defines the test method “receipt info”. This tests if the printed receipt
generated by the “sale Receipt.print Receipt()” method contains the expected values for
the different fields such as VAT, change amount, total amount paid, total sale amount,
and itemized product information.

The test method first obtains the generated receipt as a String Builder object and then
performs a series of boolean checks using the default “contains ()” method of the
StringBuilder object to verify if the expected values exist in the generated receipt. If any
of the boolean checks fail, the test method fails and displays an error message indicating
which check failed. If all the boolean checks pass, the test method passes.

11
Object-Oriented Design, IV1350 Seminar 3 Solution

Figure 3.9: An implementation of how necessary parameters are sent in to the testing method.

This code above is a JUnit test setup method. The method is called "setUp()" and is annotated
with "@BeforeEach", which means that it will be executed before each test method in the class.

The aim of this test is to set up a test scenario where a sale is created, several items are added to
the sale, a payment is made, and a sale receipt is generated.

The code initializes a new instance of some "contr" object, and then calls its "startNewSale()"
method to start a new sale. It then initializes two arrays of integers, "itemIdentifier" and
"itemQuantity", and uses them to add items to the sale using the "addItem()" method of the
"contr" object.

After adding the items, the code adds one more item with identifier 123456 and quantity 1. It
then calls the "pay()" method of the "contr" object, passing in the payment method ("Cash") and
the payment amount (500). Finally, it calls the "print()" method of the "currentSale" object,
passing in a new instance of a "Printer" object, to generate a sale receipt.

12
Object-Oriented Design, IV1350 Seminar 3 Solution

Figure 3.9: A JUnit test, testing if-statements.

The code above first defines a JUnit test method named "addNoItem()". The test checks the
functionality of a method named "addItemInfo()" of a "currentSale" object when the boolean
parameter passed to it is true. According to the comment, in this case, the method should
increase the quantity of an existing item in the sale.

The test sets up an expected list of items in the sale, containing two "CurrentItem" objects with
quantities 2 and 4, representing "Tomat" and "Körsbärstomat" items respectively. It then calls the
"addItemInfo()" method, passing in a new "ItemDTO" object representing "Körsbärstomat" with
quantity 3.

The test then retrieves the final items list using the "getFinalItems()" method and compares it
with the expected list using the "assertEquals()" method. It checks that the quantities and the
items in the expected and the final lists match for each item in the expected list. If any of the
assertions fail, the test will throw an AssertionFailedError.

13
Object-Oriented Design, IV1350 Seminar 3 Solution

Additionally, the code also displays a test for a method called “addItem ()”. The test checks the
functionality of a method named "addItemInfo()" of a "currentSale" object when a new item is
added to the sale.

The test sets up an expected list of items in the sale, containing three "CurrentItem" objects with
quantities 2, 1, and 1, representing "Tomat", "Körsbärstomat", and "Ekologisk tomat" items
respectively. It then calls the "addItemInfo()" method, passing in a new "ItemDTO" object
representing "Ekologisk tomat" with quantity 1.

The test then retrieves the final items list using the "getFinalItems()" method and compares it
with the expected list using the "assertEquals()" method. It checks that the quantities and the
items in the expected and the final lists match for each item in the expected list. If any of the
assertions fail, the test will throw an AssertionFailedError.

Figure 3.10: An Junit test, testing if the item identifier is valid or not.

These are two JUnit test methods for testing the "InventorySystem" class. The first test method is
named "validItemIdentifier()". The test checks if the "findItemInformation()" method of the
"InventorySystem" class returns the expected "ItemDTO" object for a valid item identifier.

The test first sets up an "expectedItem" object representing a "Tomat" item with a price of 5 and
a VAT rate of 2. It then calls the "findItemInformation()" method, passing in a valid item

14
Object-Oriented Design, IV1350 Seminar 3 Solution

identifier of 123456, and assigns the result to the "resultItem" variable. Finally, it checks that the
"resultItem" matches the "expectedItem" using the "assertEquals()" method.

The second test method is named "getNullItem()". The test checks if the "findItemInformation()"
method of the "InventorySystem" class returns null for an invalid item identifier.

The test calls the "findItemInformation()" method, passing in an invalid item identifier of
123450, and assigns the result to the "resultItem" variable. Finally, it checks that the "resultItem"
is null using the "assertNull()" method. If the "resultItem" is not null, the test will throw an
AssertionFailedError.

Discussion

15
Object-Oriented Design, IV1350 Seminar 3 Solution

The code presented in seminar 3 is easily understood. To ensure this many basic practices are
followed such that the code presented does not have a foul “smell”. These practices include
dividing the code into packages. This is directly taken from the implementation in the design for
seminar 2, hence applied in the code. The code presented in this seminar is divided into
packages: view, model, controller, startup and the View. This idea is achieved using the MVC
and layer architectural patterns.

Moreover, all declarations have names which contain explanations. Everything declared in the
program, part of the classes and methods have meaningful names. An example of a meaningful
name in a declaration is seen in the class External Inventory System in the integration package.
The Method is called findItemInformation. This declaration has a self-explaining name. One is
easily able to understand that the purpose of the method is to find the information in regard to a
specific item. It can also be seen in the code that the java code conventions are followed
throughout to ensure consistency.

Additionally, other conventions are also followed to make the code more concise. This included
the avoidance of duplicated code. We have consciously extracted methods where duplicated code
arrised to later replace all occurrences of that code to a newly created method. Furthermore, the
code primarily consists of methods which focus on doing one thing. This was achieved by
following a convention that states that long methods should be avoided in code overall. Instead,
we have opted for creating several methods resulting in more method calls. An example of this
can be seen in figure 3.7 where the method additemQuantity is called in the method in
addItemInfo().

In the context of testing, the project uses the JUnit 5 framework, as explained in chapter 2,
Method. Annotations are used throughout the testing process for all public methods and other
relevant methods mentioned in chapter 2. The Controller class, among others, utilizes
@BeforeAll for the method setUpBeforeClass and @AfterAll for tearDownAfterClass, as well
as @Test for each method below those.

16
Object-Oriented Design, IV1350 Seminar 3 Solution

The tests are self-evaluating, and in case of a failed test, they print out an informative message.
For instance, the PaymentTest file has a test for the method calculateChangeAmount, which
prints out "Change amount not calculated correctly" when the test fails.

All if-statements in the code are tested, as seen in the SaleTest file. In the Sale class, the public
method addItemInfo calls the private method updateItemQuantity to determine whether the new
item scanned contains new item information or previously scanned one, and adds the new item to
the current item list or increases the item quantity of a pre-existing item in the list accordingly.
The JUnit 5 framework's @BeforeEach list is set up with two items (including their itemDTO),
and a @AfterEach reset is included. Two tests are conducted to check whether the item quantity
is increased when the item is already included in the @BeforeEach, and to verify that the new
item is added as a new item when it is not pre-existing in the current item list.

The tests are placed in the same package as the System Under Test (SUT), which is system unit
tests. Each tested class has one test class, such as PaymentRegister, Payment, Receipt, Sale,
ExternalInventorySystem, and Controller. All these test classes have their own files in the test
package.

The tests pass parameter values to tested methods, with the addItemInfo method being a good
example. The tests for this method only update the parameters regarding item name and quantity.
All classes have written unit tests for all public and package private methods, except for simple
setters and getters. All methods called in the View class, which write to System.out, are tested as
well. The unit tests are complete for all classes.

17

You might also like