2
\$\begingroup\$

Problem statement:

Design a system for the following scenario:

  1. An item list contains item code, name, rate, and quantity for several items.

  2. Whenever a new item is added in the list uniqueness of item code is to be checked. Register a new product with its price.

  3. Time to time rate of the items may change.

  4. Whenever an item is issued or received existence of the item is checked and quantity is updated.

  5. In case of issue, availability of quantity is also to be checked.

  6. User may also like to know price/quantity available for an item.

  7. Find how many items cost more than a given amount. The amount will be a parameter.

  8. Remember that the methods have to return an error code if for example an invalid item code is given.

I'm looking for suggestions, improvements and comments about Object oriented approach, style, readability or anything else.

ItemDemo class containing main() method

    package items;

import java.util.Scanner;

public class ItemDemo {

    public static void main(String args[]) {

        long code;
        char choice;
        Shop aShop = new Shop();
        Scanner sc = new Scanner(System.in);

        System.out.println("-----ITEM------");
        do {
            System.out.println("1. Add items to list");
            System.out.println("2. Issue item");
            System.out.println("3. Update item list");
            System.out.println("4. Display item details");
            System.out.println("5. Check price for a item");
            System.out.println("6. Exit");
            System.out.println("Choice:");
            choice = sc.nextLine().charAt(0);
            switch (choice) {
            case '1':
                aShop.addItem();
                break;

            case '2':
                aShop.updateStock();
                break;

            case '3':
                aShop.issueItem();
                break;

            case '4':
                aShop.display();
                break;

            case '5':

                System.out.println("Price of the Item is:"
                        + aShop.checkPrice(inputCode()));

            case '6':
                System.out.println("Thank you!\n");
                break;
            }
        } while (choice != '6');
        sc.close();
    }

    public static long inputCode() {
        Scanner sc = new Scanner(System.in);
        System.out.println("Enter Item code:");
        if (sc.hasNextLong()) {
            return sc.nextLong();
        } else {
            System.out.println("Invalid Input");
            return 0;
        }

    }
}

Shop class

        package items;

import java.util.ArrayList;
import java.util.InputMismatchException;
import java.util.Iterator;
import java.util.Scanner;

public class Shop {

    private ArrayList<Item> ItemList;
    private Scanner sc = new Scanner(System.in);

    public Shop() {
        System.out.println("New Shop for Items created.");
        ItemList = new ArrayList<Item>();
    }

    public int getSize() {
        return ItemList.size();

    }

    private Item search(long code) {
        Iterator<Item> itr = ItemList.iterator();
        Item item;
        while (itr.hasNext()) {
            item = new Item(itr.next());
            if (item.getCode() == code) {
                return item;
            }
        }
        return null;
    }

    public Item search(String name) {
        Iterator<Item> itr = ItemList.iterator();
        Item item;
        while (itr.hasNext()) {
            item = new Item(itr.next());
            if (item.getName() == name) {
                return item;
            }
        }
        return null;
    }

    public void addItem() {
        long aCode;
        String aName;
        double aRate;
        int aQuantity;
        Item foundItem;

        System.out.println("Enter Item code:");
        aCode = sc.nextLong();
        foundItem = search(aCode);
        if (foundItem == null) {
            System.out.println("Item name : ");
            aName = sc.next();
            System.out.println("Rate : ");
            aRate = sc.nextDouble();
            System.out.println("Quantity : ");
            aQuantity = sc.nextInt();
            Item aItem = new Item(aName, aRate, aCode, aQuantity);
            ItemList.add(aItem);
        } else if (foundItem != null) {
            System.out.println("Item exists");
        }

    }

    public void updateStock() {
        int choice, quantity;
        long code;
        double price;
        Item foundItem;

        System.out.println("1. Update quantity.");
        System.out.println("2. Update rate.");
        System.out.println("Choice:");
        choice = sc.nextInt();

        System.out.println("Enter Item code:");
        code = sc.nextLong();
        foundItem = search(code);
        if (foundItem == null) {
            System.out.println("Item not found");
            return;
        }

        if (choice == 1) {

            System.out.println("Enter quantity to add: ");
            quantity = sc.nextInt();
            foundItem.setQuantity(foundItem.getQuantity() + quantity);
            System.out.println("\n Quantity updated\n");
            System.out.println("Present quantity: " + foundItem.getQuantity());
        }

        else if (choice == 2) {

            System.out.println("Enter new price: ");
            price = sc.nextDouble();
            foundItem.setRate(price);
            System.out.println("\n Price updated\n");
            System.out.println("Present Price: " + foundItem.getRate());
        }

        else {
            System.out.println("Wrong choice!!");
            updateStock();
        }

    }

    public void display() {

        long code;
        Item foundItem;

        System.out.println("Enter Item code:");
        code = sc.nextLong();
        foundItem = search(code);
        if (foundItem == null) {
            System.out.println("Item not found");
            return;
        }

        System.out.println(foundItem.toString());
    }

    public void issueItem() {
        int numberOfItem;
        long code;
        Item foundItem;

        System.out.println("Enter Item code:");
        code = sc.nextLong();
        foundItem = search(code);
        if (foundItem == null) {
            System.out.println("Item not found");
            return;
        }

        System.out.println("Number of Item : ");
        numberOfItem = sc.nextInt();
        if (numberOfItem > foundItem.getQuantity()) {
            System.out.println("\nRequired number of Items not in stock\n\n");
            return;
        }

        else {
            System.out.println("\nCost of " + numberOfItem + " copies : rs. "
                    + numberOfItem * foundItem.getRate());
            foundItem.setQuantity(foundItem.getQuantity() - numberOfItem);
        }
    }

    public double checkPrice(long code) {
        Item foundItem = search(code);
        if (foundItem == null) {
            System.out.println("Item not found");
            return 0.0;
        }

        else
            return foundItem.getRate();
    }
}

Item Class

    package items;

public class Item {
    private String name;
    private double rate;
    private long code;
    private int quantity;

    public Item() {
        this.name = "";
        this.rate = 0;
        this.code = 0;
        this.quantity = 0;
    }

    public Item(String name, double rate, long code, int quantity) {
        this.name = name;
        this.rate = rate;
        this.code = code;
        this.quantity = quantity;
    }

    public Item(Item item) {
        this.name = item.name;
        this.rate = item.rate;
        this.code = item.code;
        this.quantity = item.quantity;

    }

    @Override
    public String toString() {
        return "Item [name=" + name + ", rate=" + rate + ", code=" + code
                + ", quantity=" + quantity + "]";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getRate() {
        return rate;
    }

    public void setRate(double rate) {
        this.rate = rate;
    }

    public long getCode() {
        return code;
    }

    public void setCode(long code) {
        this.code = code;
    }

    public int getQuantity() {
        return quantity;
    }

    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }
}
\$\endgroup\$
4
  • \$\begingroup\$ Do you know what the programming idea of a a map or hashmap or dictionary is, or have you not covered that yet? \$\endgroup\$ Nov 16, 2014 at 12:09
  • \$\begingroup\$ No, when I learned about maps and hashmaps, I was already halfway in my project. \$\endgroup\$
    – SouvikMaji
    Nov 16, 2014 at 12:25
  • \$\begingroup\$ just flying over the code noticed this if (item.getName() == name) { in your Shop class's method search, are you sure about it? Please read the answer. \$\endgroup\$
    – A4L
    Nov 16, 2014 at 14:04
  • \$\begingroup\$ Great, that is nice! Looks good. \$\endgroup\$
    – Ewer Ling
    Nov 16, 2014 at 14:54

1 Answer 1

3
\$\begingroup\$

The class design is not so good. For example, why does an item have a quantity property? When you buy 3 cartons of milk, is that a milk object with quantity = 3? No, quantity is the property of your shopping basket, not the milk.

I recommend to rewrite Item this way:

public class Item {
    private final long code;
    private final String name;
    private double rate;

    protected Item(long code, String name, double rate) {
        this.code = code;
        this.name = name;
        this.rate = rate;
    }

    @Override
    public String toString() {
        return "Item [name=" + name + ", rate=" + rate + ", code=" + code + "]";
    }

    public long getCode() {
        return code;
    }

    public String getName() {
        return name;
    }

    public double getRate() {
        return rate;
    }

    public void setRate(double rate) {
        this.rate = rate;
    }
}

That is:

  • name and code cannot be changed (why should they)
    • so I made them final
    • no setters
  • Only rate is allowed to change, as that's a requirement
  • Only one constructor, no need for others, and definitely no need for a default constructor setting meaningless dummy values

I made the constructor protected. The reason is that you have a requirement to ensure unique codes. That's a form of instance control, and a common way to implement is the factory pattern. So I suggest to create an ItemFactory class with a public createItem method that can create Item objects, and keep track of their codes in a Map, to check and prevent duplicates.

In the Shop class, instead of ArrayList<Item> ItemList, there should be a Map<Item, Integer> items to track the available items and their quantities.

Finally, make sure that all classes have one clear responsibility. For example, if the main responsibility of the Shop class is to manage the inventory (items and their quantities), then it should not have the responsibility of parsing user input from the console. That responsibility should go to another class.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.