How to create the perfect OOP application [closed]

Solution 1:

First off good heavens do not do financial calculations in double. Do financial calculations in decimal; that is what it is for. Use double to solve physics problems, not financial problems.

The major design flaw in your program is that policy is in the wrong place. Who is in charge of computing the taxes? You've put the product in charge of computing the taxes, but when you buy an apple or a book or a washing machine, the thing you are about to buy is not responsible for telling you how much tax you're going to pay on it. Government policy is responsible for telling you that. Your design massively violates the basic OO design principle that objects should be responsible for their own concerns, and not anyone else's. The concern of a washing machine is washing your clothes, not charging the right import duty. If the tax laws change, you don't want to change the washing machine object, you want to change the policy object.

So, how to approach these sorts of problems in the future?

I would have started by highlighting every important noun in the problem description:

Basic sales tax is applicable at a rate of 10% on all goods, except books, food, and medical products that are exempt. Import duty is an additional sales tax applicable on all imported goods at a rate of 5%, with no exemptions. When I purchase items I receive a receipt which lists the name of all the items and their price (including tax), finishing with the total cost of the items, and the total amounts of sales taxes paid. The rounding rules for sales tax are that for a tax rate of n%, a shelf price of p contains (np/100 rounded up to the nearest 0.05) amount of sales tax.

Now, what are the relationships between all those nouns?

  • Basic Sales Tax is a kind of Sales Tax
  • Import Duty is a kind of Sales Tax
  • A Sales Tax has a Rate which is a Decimal
  • Books are a kind of Item
  • Food is a kind of Item
  • Medical Products are a kind of Item
  • Items may be Imported Goods
  • An Item has a Name which is a String
  • An Item has a Shelf Price which is a Decimal. (Note: does an item really have a price? two identical washing machines might be for sale for different prices at different stores, or at the same store at different times. A better design might be to say that a Pricing Policy relates an Item to its Price.)
  • A Sales Tax Exemption Policy describes the conditions under which a Sales Tax is inapplicable on an Item.
  • A Receipt has a list of Items, their prices and their taxes.
  • A Receipt has a total
  • A Receipt has a total tax

... and so on. Once you have all the relationships between all the nouns worked out, then you can start designing a class hierarchy. There is an abstract base class Item. Book inherits from it. There is an abstract class SalesTax; BasicSalesTax inherits from it. And so on.

Solution 2:

If company tells something about libraries like NUnit, JUnit or Test::Unit is more than probable that TDD is really importat to them. In your code sample is no tests at all.

I would try to demonstrate practical knowledge of:

  • Unit tests (eg. NUnit, XUnit, ArchUnitNet, ...)
  • Design patterns
  • SOLID principles
  • Clean Architecture
  • Persistence (eg. Entity Framework, NHibernate)
  • IoC Containers (eg. AutoFac)

I would like to recomend the www.dimecasts.net as impressive source of free, good quality screencasts which covers all above mentioned topics.

Solution 3:

This is highly subjective but here are a few points that I'd make about your code:

  • In my opinion you mixed Product and ShoppingCartItem. Product should have the product name, tax status, etc. but not quantity. Quantity is not a property of a product - it'll be different for each customer of the company who buys that particular product.

  • ShoppingCartItem should have a Product and the quantity. That way the customer can freely buy more or less of the same product. With your current setup that's not possible.

  • Calculating the final tax also shouldn't be part of the Product - it should be part of something like ShoppingCart since the final tax calculation may involve knowing all products in the cart.

Solution 4:

First of all, this is a very good interview question. It's a good gauge of many skills.

There're many things you need to understand to provide a good answer (there is no perfect answer), both high-level and low-level. Here're a couple:

  • Domain Modeling -> how do you create a good model of the solution? What objects do you create? How will they solve the requirements? Looking for the nouns is a good start, but how do you decide if your choice of entities is good? What other entities do you need? What domain knowledge do you need to solve it?
  • Separation of concerns, loose coupling, high cohesion -> How do you separate out the parts of the design that have different concerns or rates of change and how do you relate them? How do you keep your design flexible and current?
  • Unit testing, refactoring, TDD -> What's your process for coming up with a solution? Do you write tests, use mock objects, refactor, iterate?
  • Clean code, Language idioms -> Do you use the features of your programming language to help you? Do you write understandable code? Do your levels of abstraction make sense? How maintainable is the code?
  • Tools: Do you use source control? Build tools? IDEs?

From there, you can have many interesting discussions, involving design principles (like the SOLID principles), design patterns, analysis patterns, domain modeling, technology choices, future evolution paths (e.g. what if I add a database, or a rich UI layer, what needs to change?), trade-offs, non-functional requirements (performance, maintainability, security, ...), acceptance testing, etc...

I won't comment on how you should change your solution, just that you should focus more on these concepts.

But, I can show you how I (partially) solved this problem, just as an example (in Java). Look in the Program class to see how it all comes together to print this receipt:

------------------ THIS IS YOUR ORDER ------------------
(001)                Domain Driven Design -----   $69.99
(001)    Growing Object Oriented Software -----   $49.99
(001)                 House M.D. Season 1 -----   $29.99
(001)                 House M.D. Season 7 -----   $34.50
(IMD)    Growing Object Oriented Software -----    $2.50
(BST)                 House M.D. Season 1 -----    $3.00
(BST)                 House M.D. Season 7 -----    $3.45
(IMD)                 House M.D. Season 7 -----    $1.73
                                SUB-TOTAL -----  $184.47
                                TAX TOTAL -----   $10.68
                                    TOTAL -----  $195.15
---------------- THANKS FOR CHOOSING US ----------------

You should definitely take a look at those books :-)

Just as a caveat: my solution is still very incomplete, I just focused on the happy path scenario in order to have a good foundation to build on.