On 25/09/2013, at 3:17 PM, James Coleman <[email protected]> wrote:

> Using exceptions as flow control is an anti-pattern, so I'd prefer to not add 
> this.

Every time anyone does anything with exceptions an answer like this comes up.  
People confuse "don't use exceptions as flow control" for "never ever use 
exceptions omg what's wrong with you?!".

If you *know* your code is going to do something stupid if a customer doesn't 
have an associated credit card, and that every customer passed into this code 
should *always* have an associated credit card, then having code like this 
makes perfect sense.

def charge_customer_money(customer, amount)
  if customer.credit_card.nil?
    raise ArgumentError, "Attempted to charge #{customer.inspect} 
#{amount.inspect} but there was no associated credit card"
  end
  …

It's just simple defensive programming, you're often better off getting an 
exception that crashes you than maybe charging the wrong user or causing an 
exception deep inside your payment gateway library which no one can debug.

While this code *could* be used for flow control like:

  def charge_every_customer
    Customer.needs_billing.each do |customer|
      begin
        charge_customer_money(customer, 4.0)
      rescue ArgumentError => err
        print "skipping #{customer.id} because they don't have a credit card"
      end
    end
  end

But it could also be used to simply act as a guard condition in case your 
billing code accidentally loops over Customer.trialling vs Customer.paying.

Don't be scared of assertions or exceptions, or reject their use cases out of 
hand.

Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to