I went to an OOP workshop by Sandi Metz several years ago. She made a comment that at one of her previous jobs, they didn't use statements. if What? I had no idea how that was even possible. I recently got interested in this idea again while refreshing my knowledge of design patterns. That's when I began to come across things like the and " " anti-IF campaign Death to the IF statement. At this point, I didn't know if coding without conditionals was really a idea, but I saw that at least there were other presumably intelligent people who've thought about it and had strong opinions. good Assuming for a second that you can code without statements, why should you? if The guiding idea behind coding without statements is the Open/Closed Principle (the "O" from SOLID). if From Wikipedia: In , the open/closed principle states "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification"; that is, such an entity can allow its behaviour to be extended without modifying its . object-oriented programming [1] source code The last line is the important one. To follow the Open/Closed principle, you've got to be able to add new functionality to an entity (or ) without changing its source code. class When you don't follow this principle, you end up with conditional spaghetti monsters. Why? Because as requirements change or get added, you can always just tack on an extra . This can lead to wildly complex code that's next to impossible to change. if So how can you do it? Let's look at a quick example. First, keep in mind that this is a trivial example, and it might not actually be a good candidate in a real work environment for this kind of refactoring. (It's also just using instead of doing anything real.) puts But, to keep this somewhat short, we need a simple example. So here goes. Here's a bit of code about paying an employee in Ruby. Essentially it's simulating sending out monthly payments based on either your salary or the number of hours you've worked. It's got a conditional in the method that we want to eliminate. #send_payment , @name = name @payment_details = payment_details !payment_details[ ]. ? hourly_rate = payment_details[ ].to_f number_of_hours = payment_details[ ] amount = (hourly_rate * number_of_hours).round( ) puts amount = (payment_details[ ].to_f / ).round( ) puts jennifer = Employee.new( , { }) jennifer.send_payment max = Employee.new( , { , }) max.send_payment class Employee attr_reader :name :payment_details def initialize (name, payment_details = {}) end def send_payment if :hourly_rate nil :hourly_rate :number_of_hours 2 "Sending $ to " #{amount} #{name} else :salary 12 2 "Sending $ to " #{amount} #{name} end end end "Jennifer Smith" salary: 135000 "Max Baxter" hourly_rate: 92.50 number_of_hours: 122 If we want to pull the statement out of the method, we can refactor this using the . if Strategy Pattern @payment_details = payment_details (payment_details[ ].to_f / ).round( ) @payment_details = payment_details hourly_rate = payment_details[ ].to_f number_of_hours = payment_details[ ] amount = (hourly_rate * number_of_hours).round( ) , @name = name @payment_details = payment_details strategy = strategy_class.new(payment_details) amount = strategy.amount puts jennifer = Employee.new( , { }) jennifer.send_payment(SalaryStrategy) max = Employee.new( , { , }) max.send_payment(HourlyStrategy) class SalaryStrategy attr_reader :payment_details def initialize (payment_details = {}) end def amount :salary 12 2 end end class HourlyStrategy attr_reader :payment_details def initialize (payment_details = {}) end def amount :hourly_rate :number_of_hours 2 end end class Employee attr_reader :name :payment_details def initialize (name, payment_details = {}) end def send_payment (strategy_class) "Sending $ to " #{amount} #{name} end end "Jennifer Smith" salary: 135000 "Max Baxter" hourly_rate: 92.50 number_of_hours: 122 As you can see, we're injecting the strategy into the method to send payment, and now our if statement is gone. Well, sort of... Deep down, we all know that up in our controller (or wherever) we'd have something like this: ... @employee.hourly? @employee.send_payment(HourlyStrategy) @employee.send_payment(SalaryStrategy) ... < ApplicationController class PaymentsController def run if else end end end We could refactor that to make it look less duplicated, but in the end, there would still be an if statement buried in there. So how can we truly get rid of that statement? if In my example, there is some execution code at the bottom. It creates a couple of employees and them pays them. Let's update that to contain a type attribute as well. payment_details = { , } jennifer = Employee.new( , payment_details) jennifer.send_payment(SalaryStrategy) payment_details = { , , } max = Employee.new( , payment_details) max.send_payment(HourlyStrategy) salary: 135000 type: "salary" "Jennifer Smith" hourly_rate: 92.50 number_of_hours: 122 type: "hourly" "Max Baxter" Since we're using Ruby, now we can do something like this: Module.const_get( ) class StrategyFactory . def self for (payment_details) " Strategy" #{payment_details[ ].capitalize} :type end end Now, we can refactor our execution code to just use the factory. payment_details = { , } jennifer = Employee.new( , payment_details) jennifer.send_payment(StrategyFactory. (payment_details)) payment_details = { , , } max = Employee.new( , payment_details) max.send_payment(StrategyFactory. (payment_details)) salary: 135000 type: "salary" "Jennifer Smith" for hourly_rate: 92.50 number_of_hours: 122 type: "hourly" "Max Baxter" for If we assume that the attribute is coming from the database (or similar), We just need to tag people with the right in the database and then add a new strategy class. type we can now add new payment strategies without ever modifying the Employee class. type So, it follows the Open/Closed principle. Nothing in engineering is free though, so what are the tradeoffs? First of all, for simple situations, the new version is much more challenging to get your head around. There are several classes that are likely all in different files. Before we made the change, we could read one simple paragraph and understand what was going on. Now we need to look at a system of small objects. Personally, I prefer the small objects, but in reality, I'd leave the code alone until a new requirement was added. Conclusion I'm probably going to continue using conditionals in my code, but exercises like this are great to do so that you have fresh ideas while you're doing your real work. It's also important to keep things like the Open/Closed principle in the back of your mind so you know when you are violating it and can decide when it's worth it make updates in order to adhere to it.