Supplementary exercise 04 – the Cafe project
In this exercise, you will not need to do any coding yourself! Instead, you have to download the BlueJ project called Café from the class website. The project is found under Documents > SWC > BlueJ Project Examples
The Café project is a simple simulation of a real-life café. Customers can enter the café and order various things to drink at the bartender. Things have different prices, and at some point the customer receives a tab (i.e. a list of the things ordered, the price for each thing, and the total). The bartender will process the orders, and manage the tab for each customer.
When you have downloaded the Café project, your task is to answer various questions about the project, to the best of your abilities. The questions follow on the next pages. Before starting, take some time to get an overview of the project, including having a look inside the test class called CafeTest.
The questions are divded into three categories: Identification, Understanding and Reflection
Identification: These questions are all concerned with identifying various parts of the code. In order to answer the questions, you must look inside the code of the classes, and identify the relevant part of the code. These questions are supposed to be fairly easy.
Understanding: These questions test your ability to actually understand the code. You will need to figure out what various parts of the code actually does, how it is done, what conditions that apply, and so on. These questions will be more challenging.
Reflection: These questions require you to think and reflect about parts of the code. What might be the reason for certain choices in the design of the code, what other possible solutions exist, could it be beneficial to restructure the code somehow, etc.. These questions are rather hard, and will require deeper thinking and creativity.
Try to get as far as possible, i.e. answer as many questions as you can, within the given time limit. The purpose is to let me (Per) know how the class as a whole is doing right now with regards to analysing Java code, not to make assessments of individual students.
Part I – Identification
Question / Your answerLook in the class Bartender. How many methods does this class contain? / A total of 7 methods
receiveOrder, getTab, setupMenu, processOrder, customerHasTab, addItemToTab, getTabIndex
NOTE: The constructor can be considered a method as well.
What are the names and types of the instance fields in the class Bartender? / tabs of type ArrayList<Tab>
theMenu of type Menu
How many parameters does the constructor in the class Tab have? / One parameter: String name
In the class Tab, what is the return type of the method getCustomerName()? / String
In the class Menu, what are the names and types of the local variables in the method getItemIndex()? / index of type int
itemIndex of type int
In the class Menu, which of the methods contain a conditional statement? / The methods:
addMenuItem
getItemPrice
getItemIndex
In the class MenuItem, what are the names and types of the parameters to the constructor? / itemName of type String
price of type int
Which of the classes in the project use an ArrayList? / The classes:
Bartender
Menu
Tab
Part II – Understanding
Question / Your answerExplain what happens in the constructor for the Tab class / The instance field customerName is set to the value provided in the parameter name to the constructor.
Also, the instance field itemsOrdered is initialised to refer to an object of type ArrayList<MenuItem>, i.e. an empty array list of menu items
In the Tab class, try to explain what the method calculateTotal does, and how / The method calculates the total price for all the items in the tab. A local variable total is initialised to zero, and for each item in the tab, total is incremented with the price for that specific item.
In the Menu class, try to explain what happens if we try to insert the same menu item twice into the list of menu items. / Nothing happens; the conditional statement in the method addMenuItem prevents us from entering the same menu item twice into the menu
In the Menu class, what happens if we try to get the price for an item which is not on the menu? / First, we try to find the item index for the given item. If the index is negative – i.e. the item was not found in the menu – a price of zero is returned.
Part of the Café simulation involves setting up a menu of the items you can order. Where in the code does this happen? / In the method setupMenu, in the class Bartender
When is the piece of code that sets up the menu executed? / The method setupMenu is called from the constructor of the Bartender class. This means that the method will be called when a new Bartender object is created.
Explain in your own words what happens when the method receiveOrder is called on an object of the class Bartender. / We check if the ordered item is present in the menu, by calling theMenu.contains (which returns a boolean value).
If the item is on the menu, we call processOrder, which will add the item to the customers tab, and “serve” the item (by printing “…here is your…”).
If the item is not on the menu, we inform the customer about this, by printing “Sorry…”
Explain in your own words how the method getTabIndex in the class Bartender works / We need to find the index of that Tab object in the tabs instance variable, that has a customer name that matches the customer name given as a parameter.
We define that an index of -1 indicates “not found”, and initialise a local variable tabIndex to this value.
We then search through tabs (i.e. the array list of Tab objects), to find a Tab object with a matching name. If we find such an object, we set tabIndex equal to the index of that object, and stop the search.
Part III – Reflection
Question / Your answerSuppose we want to be able to change the price of an item on the menu. Explain – in words, not in code – what we would need to change in the project in order to be able to do this / We could do this e.g. by creating a new method updateMenuItem in the Menu class, taking a menu item name plus the new price as parameters. This method should look up the given menu item, remove it, and insert a new menu item with the new price.
Compare the methods getTabIndex in Bartender and getItemIndex in Menu. They seem to be almost identical. Is that a problem? If yes, is it possible to fix it somehow? / They look quite identical, the only difference being the name of the parameter (the type is the same), and the array list that is being searched. One could therefore consider making a common method where the array list is a parameter as well, perhaps placed in a new class, in order to avoid code duplication. However, the types of the array lists are not the same (ArrayList<Tab> vs. ArrayList<MenuItem>), which makes it harder to make a common method.
So, yes, there is a potential problem of code duplication, but it is not that easy to fix…
What do you think of the read-ability of the getTabIndex method in Bartender? Is it hard to understand? If yes, how could it be made easier to understand? / The line:
tabs.get(index).getCustomerName().equals(customerName)
can be somewhat hard to understand, since it involves three method calls on a single line. Introduction of some local variables could make the method easier to read:
Tab theTab = tabs.get(index);
String name = theTab.getCustomerName();
boolean match = name.equals(customerName);
if (match) …
The instance field items in the class Menu contains MenuItem objects. This makes it a bit difficult to check if itemscontains a menu item for a specific item name.
Suppose instead that we stored the menu item names in one arrayList, and the prices in another arrayList. Discuss what advantages and draw-backs this solution might have. / We could have:
ArrayList<String> itemNames;
ArrayList<Integer> itemPrices;
Then getItemIndex would become quite simple:
private int getItemIndex(String item)
{
return itemNames.indexOf(item);
}
The drawback would be that we have to make sure that the two lists are always “in sync”, so that an item and the corresponding price always have the same index in the respective array lists.
If a customer has ordered the same item more than once, the tab will contain this item more than once. On a real-life tab, you will probably only have each item once, but the tab will show how many you have ordered of each item. What changes are needed in order to do this in the project? / One solution could be to create a class TabItem, which has two instance fields:
MenuItem item;
int quantity;
The Tab class would then contain an array list of TabItem objects instead of MenuItem objects.
When adding an ordered item to the tab, you will then have to see if a TabItem for that item has already been added to the tab; if no, create a new TabItem, set the quantity to 1, and add it to the tab. If yes, find the correct TabItem object, and increment the quantity by one.
This approach will of course also mean that we have to change the code in the print and calculateTotal methods
If we were to create a more realistic simulation of a real-life café, how should we extend the current model? / We could e.g. have some kind of time-based element – customers could place orders at irregular intervals, there could be a variable number of bartenders to process the orders. We could also include a kitchen with (a variable number of) chefs, that could handle orders for food.
We could have a fixed amount of each item available, so the menu might change dynamically, etc..