Analysis and Design:
Designing the components prior to coding is pretty useful. Better the designing, easier it is to code and lesser the rework. We will be digging pretty deep into the design to throw light on some of the design principles. If you are not interested in designing and stuff, you may want to glance through the UML diagrams and move on to code.
Let us analyze the requirements, and try to identify the different components needed for this workshop. For our analysis, we try to identify components based on Model-View-Controller (MVC) design.
We need to create a ModelList page, with ‘Add to cart’ button.
Technically speaking, what does a cart comprise? It is a collection of items added to the session. Let us use, ArrayList for our cart. So, the basic idea is to have an ArrayList added to session object.
We will refine this a bit. Going forward, we may need the cart item to hold other things than just CartItems. Something like Promotion code data. So, we will maintain a special cart object. And the cart will contain ArrayList of cart items.
But, what will the ArrayList comprise? String will not do for sure. Probably, we need a special item bean. Right, so we will have ItemBean added to ArrayList, and the ArrayList will be added to session. This sounds great!
We need a shopping cart jsp. It would need to pull ArrayList out of the session and iterate this, and display it in the JSP.
Aren’t we missing something? We need something to control the events coming from the ‘Add to cart’, ‘Update Item’ and ‘Delete Item’. We need a rockin controller to handle these events. The servlet should be the one to do this job.
Based on the above analysis, let us summarize the components we had identified:
Identifying attributes for cart:
Now, let us try to identify more information for the cart related classes.
- ArrayList of CartItemBean
- totalCost of items in cart
- Part number for the model
- Model description
- Unit cost
- Total item cost
This servlet controller needs to implement the doGet/doPost methods. It needs to handle the events for addToCart, updateCart and deleteCart. It is a better design to handle each of these events separately. So, based on this discussion, the CartController will need to have the following methods:
- doGet/doPost – Delegates request to different event methods like addToCart etc.
- addToCart – Handle the add to cart functionality
- updateCart – Handle the update cart item functionality
- deleteCart – Handle delete cart item from cart functionality
Let us work through the ‘Calculate the cart total’ and ‘Add to cart’ functionality to analyze and come up with methods related to it.
Calculating the cart total:
This is a major functionality, which needs to be utilized every time an item is added, removed or updated. Let us discuss considering different design principles and try to come up with a realization for this functionality.
Information expert principle says that, any object which has the information to perform an operation should do the job.
For calculating the total price, we need to first know the total for each line item. So, let us apply expert principle to get the line item total. Since, CartItemBean has both quantity and unit cost, based on expert, it is the right candidate.
Just to understand the association between the different objects, we know, that CartBean houses a list of CartItemBean. The CartController on the other hand will be one to add the CartBean in session. Now, this means, CartBean is associated with CartItemBean and CartBean is associated also with CartController.
Coupling design principle says that, the association or coupling between different objects should be as less as possible. More the coupling, more sphghetti code syndrome. You make changes to code in one class; all the associated classes need changes.
Since CartController has access to CartBean, we can write a calculateTotal method in the CartController, where we will have to pull the list of CartItemBeans from CartBean in this method and calculate the total price. However, this means, iterating through the CartItemBean list in CartController and also calls on CartItemBean.getSubtotal(). This introduces CartItemBean to CartController coupling.
Hmmmm…. Not that good news isn’t it.
But, do we have a choice? Going again by expert, CartBean does have access to all CartItemBeans. So, it is an expert to calculate the order total. Also, it does not have a CartItemBean to CartController coupling. So, this is a better choice.
Add to Cart functionality:
We said that CartBean will house an ArrayList of CartItemBeans. So, we will have a getter/setter for setting this ArrayList inside CartBean. But, who will create the ArrayList of CartItemBeans and then call setCartItems? It has to be CartController. This intern means, CartItemBean creation, setting values and adding to ArrayList, needs to be performed in CartController. Hmmm….But, we have been working so hard eliminate the CartController to CartItemBean coupling while designing the ‘calculate order total’ functionality. Even with this, creating the ArrayList of CartItemBeans and setting it in CartBean everytime is a tall order. We need something like addCartItem(CartItemBean) in CartBean. This will add to the ArrayList of CartItemBeans everytime this is called. So, the CartController does not have to worry above the ArrayList and setting the ArrayList using the setCartItem method. That is a great relief!!
Hey, hold on! But, when we still will call setters in CartItemBean from CartController and then call the CartBean.addCartItem(CartItemBean). Isn’t it not adding coupling between CartController and CartItemBean. Well, sad but true! Let us try to look for any some more options.
It would be dreamy, if CartBean can take complete control of the CartItemBean, without any CartController intervention. Hmmm… Let us try to delegate the task of creating CartItemBean and setting values into it to CartBean. But, is it possible; is the question to be answered? How will the CartBean know, what should be the state of the CartItemBean created? Well, since the CartController has this information, it can pass on this information to CartBeans method as parameters. Like
- addCartItem(String strModelNo, String strDescription, String strUnitCost, String strQuantity)
Passing 4 parameters in the method call may not be that bad! But, in a real production cart scenario, we may need more parameters. We can generally work around this by using a value object. But for our example this is fine.
Party time! We just designed the addToCart without increasing the coupling. Note here that, CartController is the information expert. The CartBean may be considered as a partial expert. However, we considered both coupling and expert to come up with this design. This leads us to something very important while using design principles. No single design principle can be used in isolation to design functionality. We need to consider different design principles to come up with a design.
We will use the same principle for updateCartItem and deleteCartItem functionality. You may want to think over it.
So, based on the above discussion, below the class diagram for our cart sub-system.
Sequence diagram for Add To Cart: