I am going in a circle over and over trying to write a "supermarket" application using OOP.

The app should be useful for the employees of a supermarket. The app reads data from a CSV file which looks like this:


The supermarket has cashiers and managers. Cashiers should only be able to view the amount for a product. Managers can view but also change an amount.

Here's the code I came up with:

import pandas

class Data:
    """Creates a pandas dataframe out of a text file"""
    def __init__(self, datafile = "products.txt"):
        self.datafile = datafile

    def get_dataframe(self):
        df = pandas.read_csv("products.txt", index_col = "name")
        return df

    def save_to_csv(self):
        df = pandas.read_csv("products.txt", index_col = "name")

class Product:
    """Represent a product from the dataframe table"""

    def __init__(self, name, dataframe = Data().get_dataframe()):
        self.name = name
        self.dataframe = dataframe

    def get_amount(self):
        """Return the available amount of the product object taken from the dataframe"""
        return self.dataframe.loc[self.name, "amount"]

    def add_amount(self, amount, password):
        """Changes the dataframe by adding an amount to the existing amount"""
        if password == 1234:
            self.dataframe.loc[self.name, "amount"] += amount
            data = Data()
            return "You're not a manager"

    def remove_component(self, person):
        """Changes the dataframe by removing an amount from the existing amount"""
        if password == 1234:
            self.dataframe.loc[self.name, amount] -= 1
            return "You're not a manager"

    def __del__(self):
        """Delete the dataframe from memory when Product is destroyed"""
        del self.dataframe

I think the authentication layer is very poorly implemented here. I simply added a conditional in the add and remove methods. Is there any better way to do the authentication part?

Should I also create Manager and Cashier classes in case I expand the program later. For example, adding info about salaries for managers and cashiers. That would require to have Manager and Cashier objects I guess.

Will the code load many Data objects? Should I use a singleton for the Data object?

What other design pattern could I have used for this app?

  • \$\begingroup\$ Can the downvoter expain the techical reason of the downvote? \$\endgroup\$ – multigoodverse Jul 30 '18 at 17:55
  • \$\begingroup\$ I don't see why this got downvoted either. This question seems on topic to me. The only thing I can imagine may have triggered a downvote is that your concerns are quite broad, i.e. we wouldn't be able to answer the questions without more context. Will the code load many Data objects? Who knows? Should you use a singleton? Maybe. Why do you think you potentially need one here? Should you create additional classes? What do I (as a reviewer) know? It all depends on the situation. \$\endgroup\$ – Daniel Jul 30 '18 at 19:19
  • \$\begingroup\$ authentication - I would raise exception rather than return malformed data. Also, while hardcoding password in code may be acceptable in such exercise - it would be better to have one function returning it rather than duplicating it multiple places. \$\endgroup\$ – reducing activity Jul 30 '18 at 20:24
  • \$\begingroup\$ Your wording makes it sound like it's not working as intended. Specifically I am going in a circle over and over trying to [...] and Will the code load many Data objects? sound like the code is either not done/working or you don't understand it. Perhaps rewording the question can help. \$\endgroup\$ – yuri Jul 30 '18 at 21:01

From an OOP design perspective, you've duplicated the sales items. Data is the products, and Products are the products too (hope that makes sense?).

Think back for a second regarding what entities are at work here, and their specific functions. We have:

  • a manager,
  • a cashier,
  • a terminal (which the cashier and manager can both use),
  • and all the products on the store shelves.

Now, both managers and cashiers are of type Person, however Manager can override the Person class with an Edit function (for the products), whereas Cashier would just inherit Person with the in-built View function, correct? (are you with me so far?)
Now, we can be cheeky and assume that the Terminal has Loading and Saving functions - in lieu of the mainframe in the manager's office (typically terminals are just dumb devices and the price editing is handled by the manager with a list of products sent by head office).
Given that the Manager and the Cashier both need to use the Terminal, you would need to have a Logon and Logoff function, correct? That implies a state pattern, which I'll leave you to research.

Now, your question listed the desired functionality:

  • read/write CSV
  • Cashiers have view functionality
  • Managers have view and edit functionality.
  • Authentication
  • Potentially having salaries on managers and cashiers

All these can be achieved in the OOP layout I wrote above. The Authentication component of course would be tied into the Type of which (inherited) Person is logged onto the Terminal (that implies you either need to do some reflection on the logged on user or have an attribute which gives the answer to the terminal).
You also ask:

Will the code load many Data objects?

That's hard to say, but it sounds like if you stick with a simple approach, it should keep them to a minimum. Also you ask:

Should I use a singleton for the Data object?

Given the Terminal is responsible for the product data, if the Terminal loads and saves the product data, I don't think you need to worry about that.

Hope this helps!


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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