A Tale of Object-Oriented Programming: A Realistic Look at Python Interfaces

Photo by Andrew Neel on Unsplash

A Tale of Object-Oriented Programming: A Realistic Look at Python Interfaces

Defining the Problem and implementing a first solution...

ยท

7 min read

In this series of articles, we are going to be talking about interfaces in Python. Interfaces are a powerful resource to use in several real-life scenarios.

Because of that, we are going to approach learning them by using an example that is very likely to occur in real life. Even if this exact case does not happen exactly as we will show, it is easy to find similar cases and use similar solutions to the ones we are going to be talking about.

So, let's dive in!

Real-Life Problem and Motivation

Suppose there is a Research Center that is conducting some important experiments. This Research Center would like to verify the access to its facilities. For that reason, it has a list of visitors authorized to enter. These visitors can be persons or vehicles. For the persons, it is only needed to store their identity number and name. And for the vehicles, it is only needed to store their plate number and the type of vehicle (car, bus, or truck). We are asked to implement an access verification mechanism for the Research Center.

As we can see, this scenario is likely to happen in real life. Many institutions need to keep track of the visitors they have to their facilities, and need to be able to tell if a certain person or vehicle is allowed to enter it or not.

Let's see how we can make an initial solution to this problem using object-oriented programming in Python.

First Approach

We need to start by creating a way to represent all the elements involved in this problem. On the one hand, we have persons and vehicles, and on the other hand, we have the research center. The first ones are the visitors, and the latter is the entity responsible for handling the access verifications.

Let's create our first solution.

The Person Class

To represent a Person we will create a class that contains two attributes:

  • An id attribute, which is of type string. This attribute is unique for every person.

  • A name attribute, also a string.

A possible implementation in Python would be like this:

class Person:

    def __init__(self, id: str, name: str):
        self.id = id
        self.name = name

    def __str__(self) -> str:
        return self.id

This is a simple class, just for representational purposes. Because of that, it does not have any methods except for the special __str__ to give a more human-readable representative string as its identifier.

The Vehicle Class

Similar to the above example, to represent a Vehicle we will also create a class with two attributes:

  • A license plate attribute, which is of type string and it is unique for every vehicle.

  • A vehicle type attribute, which will be an enum type, since we only have three possible choices: car, bus, or truck.

An example of this class would be the following:

from enum import Enum

class VehicleType(Enum):

    AUTO = 1
    TRUCK = 2
    BUS = 3


class Vehicle:

    def __init__(self, license_plate: str, vehicle_type: VehicleType):
        self.license_plate = license_plate
        self.vehicle_type = vehicle_type

    def __str__(self) -> str:
        return self.license_plate

Once again, since this class is just for representational purposes, it will not have any methods except the __str__ method, which we can use to easily identify our vehicle instances.

The Research Center Class

Now that we know what our visitor classes look like, it is time for us to figure out a way to handle access verifications properly. For this reason, we are going to create a third class: the Research Center.

This class needs to have the capacity of checking if a person or vehicle can access it. Let's see one way to achieve this.

Let's create a Research Center class that will consist of the following:

  • An allowed_persons attribute, which will be a list of persons, as defined above. This list will contain all the persons allowed to enter the research center.

  • An allowed_vehicles attribute, which will be a list of vehicles, as defined above. Similar to the allowed_persons list, this one will contain all the vehicles allowed to enter the research center.

  • An add_person method. This will add a new person to the list of allowed persons.

  • An add_vehicle method. This will add a new vehicle to the list of allowed vehicles.

  • A verify_person_access method. This one will check if a particular person can access the research center.

  • A verify_vehicle_access method. This one will check if a particular vehicle can access the research center.

As we can see, this class is more complex than the person or vehicle classes. It contains attributes as well as methods to handle the addition of new visitors and check the access of a particular visitor as well. An example of this class in Python would be like this:

class ResearchCenter:

    def __init__(self):
        self.allowed_persons = []
        self.allowed_vehicles = []

    def add_person(self, person: Person):
        self.allowed_persons.append(person)

    def add_vehicle(self, vehicle: Vehicle):
        self.allowed_vehicles.append(vehicle)

    def verify_person_access(self, person: Person) -> bool:
        for registered_person in self.allowed_persons:
            if registered_person.id == person.id:
                return True
        return False

    def verify_vehicle_access(self, vehicle: Vehicle) -> bool:
        for registered_vehicle in self.allowed_vehicles:
            if registered_vehicle.license_plate == vehicle.license_plate:
                return True
        return False

We should notice how the verify_person_access method iterates through the list of allowed persons and checks if any of them shares the same id as the person being checked. Similarly, the verify_vehicle_access does the same for the allowed vehicles, and checks against the license_plate attribute.

Remember that we are assuming that these attributes are unique, so they are a correct way of uniquely identifying either persons or vehicles.

Flaws of our First Approach

The solution above seems to handle this particular problem very well. It sure can add new persons or vehicles and check for the access of some particular visitor by comparing their identifying attributes against the allowed persons or vehicles, depending on the case. So, what is wrong with this approach?

Well, let's imagine that the research center suddenly realized that it has not been tracking the animals they use for regular experiments. They would like to have a mechanism that allows them to check if some specific animal is part of the list of allowed animals. How would we modify our solution so that it can handle this new type of visitor?

A natural answer would be to create an Animal class, with some id attribute, and add the corresponding allowed_animals list and the add_animal and verify_animal_access methods to our Research Center class. This way we handle the case of animals.

But, what if they are also not keeping track of drones or robots, or any other entity they consider should be verified for access?

We would have to add the corresponding classes to represent these new entities and also add methods and properties to the Research Center class to handle the tracking and access checks.

These constant changes in the Research Center class could lead to introducing errors in our program. And this happens because we are letting all the responsibility for checking the access to the "almighty" Research Center class.

Conclusions

So far we have seen how to approach a real-life problem using object-oriented programming. We have seen how to create classes and use them together to create a correct solution which still has some design issues.

So, how can we address these issues? That will be the subject of the Part II of this series of articles. In the meantime, feel free to reach me and tell me about how would you solve this problem using object-oriented programming. A little hint is on the title of this article itself!

If you want to check a more complete version of the code examples shown in this article you can do it here.

If you enjoy this article, please show your support by reacting, commenting, or just spending a few minutes thinking about the topics exposed here. Don't be a passive reader, think about what you read and share your thoughts. See you soon!


๐Ÿ‘‹ Hello, I'm Alberto, Software Developer at doWhile, Competitive Programmer, Teacher, and Fitness Enthusiast.

๐Ÿงก If you liked this article, consider sharing it.

๐Ÿ”— All links | Twitter | LinkedIn

Did you find this article valuable?

Support Alberto Gonzalez by becoming a sponsor. Any amount is appreciated!

ย