Designing a Next Level Parking Lot System in Python
Tags: python, beginners
Published: 2022-05-17 11:48:31

Hi, today we will be building a Parking Lot System which has multiple features and supports different types of vehicles to be parked, and the most important feature will be its extendibility.
Before designing a software lets first write down its features.

- Parking Lot should have floors on which vehicles are parked.

- On parking floors there can be different parking space for different types of vehicles.

- A vehicle can only be parked in its own type of parking space. For example, A bike cannot be parked in parking space of a car, since that will be waste of space.

- Tickets should be generated after vehicle is parked.

- Later these tickets can be used to unpark or retrieve the parked vehicle.

- Also for convenience a vehicle should be parked at the closest parking space possible.

These are the basic features that we need to implement in our parking system, but we will need to design the software in such a way that new features can be introduced without any problem, like introducing a new vehicle type that is allowed by parking lot or a limitation on a certain type of vehicle category.

The approach I am choosing for this problem is factory design pattern (I will explain later in implementation section).
In our case vehicles and parking space are two different entity which are bound by vehicle's type.

First lets start by designing parking space, I will call it slot.
{% gist https://gist.github.com/dhrvjha/da96674ba381f9d57956627b32e16cc5 
file=slot.py  %}
Here I have made different classes for different types of parking slots, this will help us if we would later want a certain parking slot should behave different than others. For example, a truck slot can have higher ticket cost than a car or bike slot and this can be defined separately in its own class without needing to change other classes.

Now to vehicles which will be parked in parking slot,
{% gist https://gist.github.com/dhrvjha/da96674ba381f9d57956627b32e16cc5 
file=vehicle.py  %}
It is the same case with vehicle class too, if we would later want to add additional properties to a vehicle type than it would be lot easier to change its own class than to make a mess of if and else statements.

How do we make sure a vehicle is parked in its own category of parking slot?
We will use factory design pattern for that.
What is factory design pattern?
Well it is the highlight of this problem,
> In class-based programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. [- Wikipedia](https://en.wikipedia.org/wiki/Factory_method_pattern)

So here we will create object of vehicle and map to proper slot using dictionary.
{% gist https://gist.github.com/dhrvjha/da96674ba381f9d57956627b32e16cc5 
file=settings.py  %} 
<code>VEHICLES_MAP</code> maps input string to its vehicle class and <code>SLOTS_MAP</code> maps vehicle class to its slot class.

<code>DEFAULT_FLOOR_MAP</code> is location of where each type of vehicle will be store on parking floor.
So with parking floor in discussion lets first see the floor class.
{% gist https://gist.github.com/dhrvjha/da96674ba381f9d57956627b32e16cc5 
file=floor.py  %}
Floor covers a lot of functionalities for our parking lot. Lets start exploring each

- <code>park_vehicle()</code> should park vehicle in the first empty slot of its type.

- <code>unpark_vehicle()</code> should take a ticket and remove the vehicle and empty the slot.

- <code>floor_map</code> is dictionary of vehicle types mapped to its starting and end location of slots on floor.

- <code>busy_slot_map</code> is a dictionary which keeps track of all the busy parking slots of a vehicle type.

By now we can add or remove a vehicle type without needing to change anything in floor, hence we have decoupled vehicles and parking slot with floor.

At last we need to design parking lot which will be made up of floors.
{% gist https://gist.github.com/dhrvjha/da96674ba381f9d57956627b32e16cc5 
file=parkinglot.py  %}

- <code>park_vehicle()</code> will park a vehicle in the first empty floor it will find.

- <code>unpark_vehicle()</code> will remove vehicle from floor and close the ticket.

Interesting part is that <code>park_vehicle()</code> of parking lot finds the first empty floor and <code>park_vehicle()</code> finds the first empty slot to park.
Also <code>ParkingLot</code> is decoupled from the entire parking system it just manages floors and that is how it should be. No feature or entity should be least dependent on others.

Now about Tickets which I skipped.
{% gist https://gist.github.com/dhrvjha/da96674ba381f9d57956627b32e16cc5 
file=ticket.py  %}

Static variable of class is property of a class not of an instance. I use this property to manage all the Ticket instances.

- <code>tickets</code> is static variable of type dictionary which will store all the instances created.

- <code>generateTicket()</code> generates a string based on parking lot, floor and slot the vehicle is parked in.

- <code>openTicket()</code> adds ticket to <code>tickets</code> variable.

- <code>getTicket()</code> is class method which returns the Ticket instance if the ticket string passed is in <code>tickets</code>.

- <code>closeTicket()</code> removes ticket from <code>tickets</code>.

These are the basic features that a ticket manager needs to have,
being able to open, close and find a ticket.

Up to this point we have created a parking system which parks and unparks a vehicle at the closest point and generates a ticket.

Taking the input and managing Parking Lot does not have a lot of new things to discuss so I am skipping that part but here is the [link](https://github.com/dhrvjha/ParkingLotSystem) to source which takes input from console.

Thank you for reading till the end, I am new to writing articles so let me know about the mistakes that I made.