Procedural programming follows top down approach. Control flows from the top to the bottom.
Let's assume that we are building a ticketing system for a park. Right now there is only one rule. The adults will pay the full price and the young people, who are of age less than 18, will get a 20% discount on the price.
Let's see how we can implement this solution using procedural style of programming.
1 # This is an input to the program. 2 # Let's assume that the age of the person is 12. 3age = 12 4 5FULL_PRICE = 20 6DISCOUNT_IN_PERCENTAGE_FOR_YOUNG = 20 7 8def is_young 9 age < 18 ? true : false 10end 11 12new_price = is_young ? FULL_PRICE * (1 - (DISCOUNT_IN_PERCENTAGE_FOR_YOUNG.to_f/100)) : FULL_PRICE 13 14puts "The price of ticket for a #{age} years old person will be $#{new_price}."
In the above case we have a method called is_young. It's a bit of simplification but in the older programming languages it is also called subroutines or procedures. This is why this style of programming is called "procedural style" because this style makes use of procedures.
In the Object Oriented World we would solve the same problem using classes. Let's now solve the same problem using Object Oriented style.
1class Person 2 attr_reader :age 3 4 def initialize(age) 5 @age = age 6 end 7 8 def is_young 9 age < 18 10 end 11end 12 13class Ticket 14 FULL_PRICE = 20 15 DISCOUNT_IN_PERCENTAGE_FOR_YOUNG = 20 16 attr_reader :person 17 18 def initialize(person) 19 @person = person 20 end 21 22 def price 23 person.is_young ? FULL_PRICE * (1 - (DISCOUNT_IN_PERCENTAGE_FOR_YOUNG.to_f / 100)) : FULL_PRICE 24 end 25end 26 27age = 12 28person = Person.new(12) 29ticket = Ticket.new(person) 30puts "The price of ticket for a #{age} years old person will be $#{ticket.price}.
Both the style of programming gets the work done. However the procedural style takes only 11 lines of code while the object oriented style takes a whopping 30 lines of code.
At this time it might seem that procedural style of programming is better. It's shorter and it's easier to follow.
Summer break and more discounts
Our park is doing well and after a few months of the opening of the park we got the following requirements.
- All folks above the age of 60 should have 10% discount.
- All Adults will get 5% discount but only on Tuesdays.
- During summer break (month of June) people below the age of 18 will get an additional 10% discount.
Let's incorporate the above requirements in the procedural style first.
1require "date" 2age = 12 3 4FULL_PRICE = 20 5DISCOUNT_IN_PERCENTAGE_FOR_YOUNG = 20 6DISCOUNT_IN_PERCENTAGE_FOR_ADULT_ON_TUESDAY = 5 7DISCOUNT_IN_PERCENTAGE_FOR_SENIOR = 10 8DISCOUNT_IN_PERCENTAGE_FOR_YOUNG_IN_SUMMER = 10 9 10def is_young 11 age < 18 ? true : false 12end 13 14def is_adult 15 ((age >= 18) && (age < 60)) ? true : false 16end 17 18def is_senior 19 age >= 60 ? true : false 20end 21 22def is_today_tuesday? 23 Date.today.strftime("%A").downcase == "tuesday" 24end 25 26def is_current_month_june? 27 Date.today.strftime("%B").downcase == "june" 28end 29 30def discounted_price(discount_in_percentage) 31 FULL_PRICE * (1 - (discount_in_percentage.to_f/100)) 32end 33 34new_price = FULL_PRICE 35 36if is_young 37 new_price = discounted_price(DISCOUNT_IN_PERCENTAGE_FOR_YOUNG) 38 39 if is_current_month_june? 40 new_price = new_price * (1 - DISCOUNT_IN_PERCENTAGE_FOR_YOUNG_IN_SUMMER/100) 41 end 42end 43 44if is_senior 45 new_price = discounted_price(DISCOUNT_IN_PERCENTAGE_FOR_SENIOR) 46end 47 48if is_adult && is_today_tuesday? 49 new_price = discounted_price(DISCOUNT_IN_PERCENTAGE_FOR_ADULT_ON_TUESDAY) 50end 51 52puts "The price of ticket for a #{age} years old person will be $#{new_price}."
Here is the Object Oriented version.
1require 'date' 2 3class Person 4 attr_reader :age 5 6 def initialize(age) 7 @age = age 8 end 9 10 def is_young 11 age < 18 12 end 13 14 def is_adult 15 (age >= 18) && (age < 60) ? true : false 16 end 17 18 def is_senior 19 age > 60 20 end 21end 22 23class Ticket 24 FULL_PRICE = 20 25 DISCOUNT_IN_PERCENTAGE_FOR_YOUNG = 20 26 DISCOUNT_IN_PERCENTAGE_FOR_ADULT_ON_TUESDAY = 5 27 DISCOUNT_IN_PERCENTAGE_FOR_SENIOR = 10 28 DISCOUNT_IN_PERCENTAGE_FOR_YOUNG_IN_SUMMER = 10 29 30 attr_reader :person 31 32 def initialize(person) 33 @person = person 34 end 35 36 def price 37 if person.is_young && is_current_month_june? 38 new_price = discounted_price(DISCOUNT_IN_PERCENTAGE_FOR_YOUNG + DISCOUNT_IN_PERCENTAGE_FOR_YOUNG_IN_SUMMER) 39 elsif person.is_young 40 discounted_price(DISCOUNT_IN_PERCENTAGE_FOR_YOUNG) 41 elsif person.is_senior 42 discounted_price(DISCOUNT_IN_PERCENTAGE_FOR_SENIOR) 43 elsif person.is_adult && is_today_tuesday? 44 discounted_price(DISCOUNT_IN_PERCENTAGE_FOR_ADULT_ON_TUESDAY) 45 end 46 end 47 48 private 49 50 def discounted_price(discount_in_percentage) 51 FULL_PRICE * (1 - (discount_in_percentage.to_f / 100)) 52 end 53 54 def is_today_tuesday? 55 Date.today.strftime('%A').downcase == 'tuesday' 56 end 57 58 def is_current_month_june? 59 Date.today.strftime('%B').downcase == 'june' 60 end 61end 62 63age = 12 64person = Person.new(12) 65ticket = Ticket.new(person) 66puts "The price of ticket for a #{age} years old person will be $#{ticket.price}." 67
Notice that in the Procedural style we keep adding methods as we need them because of its top down approach.
In the Object Oriented style we have a place for everything. Anything that has to do with the attributes of a person will go to the Person class and anything that has to do with ticket and pricing will go to the Ticket class.
In the Object Oriented style if the complexity in the Ticket class grows too much the we can create a new classes to take some load off of the Ticket class.
Group buying and reservations
A few months later we got some new requirements.
- People should be able buy tickets online for future date. It means now we need to deal with reservation. People should be able to cancel the reservations.
- Park has limited parking facility and now folks can also reserve parking spot.
- Park has started offering group purchase. If a group of 10 people buy the tickets together then there is 20% discount. If the group consists of 20 people or more than there is 25% discount.
As we can see the complexity in the logic keeps increasing.
In a procedural style because of its top down approach we will have many methods all one after another and soon things will be less manageable.
In the Object Oriented style we can create new classes like Reservation, GroupPurchase, Parking to manage such complexities.