

iteration
John Jacob & JP Sio - Web Developers
A podcast about development and design.
We do our best to be code-agnostic but we talk a lot about Rails, JavaScript, React, React Native, design, business and startups.
We do our best to be code-agnostic but we talk a lot about Rails, JavaScript, React, React Native, design, business and startups.
Episodes
Mentioned books

Feb 4, 2019 • 38min
Modules! Modules! Modules!
Metz, Sandi. Practical Object-Oriented Design in Ruby
Chapter 7. Sharing Role Behavior with Modules
Welcome to iteration
A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
Modules! Modules! Modules!
Last episode we talked about inheritance which was kind of an extension of duck typing… but sometimes we need to combine the qualities of two existing subclasses, something that inheritance cannot readily accommodate.
Many object-oriented languages provide a way to define a named group of methods that are independent of class and can be mixed in to any object. In Ruby, these mix-ins are called modules.
Discovering the Schedulable Duck Type
The Schedule expects its target to behave like something that understands lead_days, that is, like something that is “schedulable.” You have discovered a duck type.
This specific example illustrates the general idea that objects should manage themselves; they should contain their own behavior.
Mountain Bike? Mechanic?
Now, in the code above, the dependency on Schedule has been removed from Bicycle and moved into the Schedulable module, isolating it even further.
Like Using Inheritance
COMES BACK TO AUTOMATIC MESSAGE DELEGATION
Loggable Example
When Bicycle includes Schedulable, all of the methods defined in the module become part of Bicycle’s response set.
When a single class includes several different modules, the modules are placed in the method lookup path in reverse order of module inclusion. Thus, the methods of the last included module are encountered first in the lookup path.
When a single class includes several different modules, the modules are placed in the method lookup path in reverse order of module inclusion. Thus, the methods of the last included module are encountered first in the lookup path.
Picks:
John: Type to Siri - Accessibility > Siri > Type to Siri
JP: Scrimba - https://scrimba.com/playlist/pKwrCg

Jan 28, 2019 • 44min
Inheritance At Its Core
Acquiring Behavior Through Inheritance
A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
Sani Metz - Object-Oriented Design in Ruby
“Inheritance is, at its core, a mechanism for automatic message delegation. It defines a forwarding path for not-understood messages.”
Where to Use Inheritance
Objects that share a common parent -
The objects that you are modeling must truly have a generalization-specialization relationship.
Bicycle Touring Company - FastFeet
Bikes - Mountain and Road Bikes
Bikes have an overall size, a handlebar tape color, a tire size, and a chain type.
Only mountain bikes have shocks
Only Road bikes have handlebar tape
Create a new empty Bicycle Class
Let RoadBike > Bicycle
And MountainBike > Bicycle
When in doubt put less code in the parent, it’s easier to promote code later when you need a shared code.
“The general rule for refactoring into a new inheritance hierarchy is to arrange code so that you can promote abstractions rather than demote concretions.”
A superclass may have many subclasses, but each subclass is permitted only one superclass.
This family tree image is, however, a bit misleading. In many parts of the biological world, it’s common for descendants to have two ancestors.
It’s really useful to rails a NotImplementedError in the parent class in the methods that are required from their children, for example, default tire_size -
“Creating code that fails with reasonable error messages takes minor effort in the present but provides value forever.”
Initialize > Post Initialize to append any or overrode attributes from the parent initialize method.
Initialize + post_initialize
Closes with a mic drop - Initializing a new RecumbentBike is so DRY and painless!
“Inheritance solves the problem of related types that share a great deal of common behavior but differ across some dimension.”
“The best way to create an abstract superclass is by pushing code up from concrete subclasses.”
“When your problem is one of needing numerous specializations of a stable, common abstraction, inheritance can be an extremely low-cost solution.”
PICKS
JP: Machine Learning with JavaScript
John: Refactoring UI by Adam Wathan and Steve Schoger -
Hard Wired Internet - Ran a Cat 5 Cable from my router - SO WORTH IT.

Jan 21, 2019 • 34min
Ducks! Ducks! Ducks!
Practical Object-Oriented Design in Ruby
A weekly podcast about development and design through the lens of amazing books, chapter-by-chapter.
Duck types are public interfaces that are not tied to any specific class.
Objects that are defined by their behavior than by their class name.
if an object quacks like a duck and walks like a duck, then its class is immaterial, it’s a duck.
In a way, the “+” operator is a “duck type” - because it responds differently to a different type of objects.
Preparer
TripCoordinator, Mechanic, Driver can all be a preparer - they all respond to the prepare method in their own ways.
At a higher level, what are these all doing? They are preparing something - we can trust within this shared interface.
Within mechanic - we only call prepare_trip vs gas_up or full_water_tank-
Instead of switching on type
You
Talk through this Object:
Notification Object?
https://github.com/withbetterco/wellstart/blob/master/app/models/notification.rb#L156
It has this insane method checking to see if the user’s notification settings match the notification that’s trying to send
We are wanting to extend the notification object, for another type - Push Notifications
Object (message, comment, like)
User
NotificationSettings
Notifier
Notification Policy
“The ability to tolerate ambiguity about the class of an object is the hallmark of a confident designer.”
Recognizing a duck:
“You can replace the following with ducks: • Case statements that switch on class • kind_of? and is_a? • responds_to?”
Polymorphic Objects
Went from a ParticipantNote, and ProgramNote, and ApplicantNote, to one single Note object through a Notable Module. They all have “ has _many: notes, as:: notable” instead of each having “program_notes”, applicant_notes, etc.
“you are missing an object, one whose public interface you have not yet discovered.”
Dot files - .zshrc - Custom prompt - with my git status -
Slippers from JP - Quadie

Jan 14, 2019 • 38min
Get Flexible
Chapter 4: Creating Flexible Interfaces
At an object-oriented level, applications are made up of classes but defined by messages
The design is concerned with messages that pass between objects
This conversation between objects takes places using interfaces
Defining Interfaces
Imagine a restaurant kitchen. Customers order food off a menu. The menu is a kind of public interface. Within the kitchen, messages get passed and the way a meal is prepared (implementation details) are private to the customer.
Classes are like kitchens. The class exists to fulfill a single responsibility but implements many methods
Public Interfaces
reveal primary responsibility
expected to be invoked by others
will not change on a whim
safe for other to depend on
thoroughly documented in the tests
Private Interfaces
handle implementation details
not expected to be sent by other objects
can change for any reason whatsoever
unsafe for others to depend on
may not even be referenced in tests
The public interface is a contract that articulates the responsibilities of your class
Example App: Bicycle Touring Company
FastFeet Inc. is a company that offers road and mountain bike trips
They use a paper system
Routes that are offered may occur several times during the year
Each Route has limitations on the number of customers who may go and requires a specific number of guides who double as mechanics
Each Route is rated according to its aerobic difficulty.
Mountain bike trips have an additional rating that reflects technical difficulty.
Customers have an aerobic fitness level and a mountain bike technical skill level to determine if a trip is right for them
Customers may rent bikes or they can bring their own
FastFeet Inc has a few bikes available and also shares in a pool of bike rentals from local shops
Rental bikes come in various sizes and are suitable for either road or mountain bike trips
Use case
A customer, in order to choose a trip, would like to see a list of available trips of appropriate difficulty, on a specific date, where rental bikes are available
Constructing an Intention
WHEW - where do we even start with this brand new application? A lot of requirements here.
It's important to start DESIGNING your application. Don't just dive in and start writing code! PLAN
The first thing you should do is form an intention about the objects and messages needed to satisfy the use case
Sequence diagrams can be helpful for planning because the design conversation has shifted
Instead of thinking about what classes should exist and what responsibilities they should have, we are NOW deciding what messages should be sent, where to send them, and who should receive them
You don't send messages because you have objects, you have objects because you send messages
Asking for "What" Instead of Telling "How"
The distinction between a message that asks for what a sender wants and a message that tells the receiver how to behave may seem subtle but the consequences are significant
Let's say we have two objects that need to communicate: trip and mechanic
We could have the trip send messages to the mechanic in order to prepare a bicycle:
clean bicycle
pump tires
lube chain
check breaks
The problem with this is that we're telling the mechanic HOW to prepare the bike.
We should be telling the mechanic WHAT to do and leave the implementation details up to the mechanic.
Instead, the trip should just send the message:
prepare bicycle
Doing this gives the responsibility of preparing a bicycle to the mechanic entirely. We trust the mechanic to accomplish this task. We tell what and not how
Seeking Context Independence
The best possible situation is for an object to be completely independent of its context. An object that could collaborate with others without knowing who they are or what they do could be reused in unanticipated and novel ways
We could do this with dependency injection
Using Messages to Discover Objects
Recall the use case: A customer, in order to choose a trip, would like to see a list of available trips of appropriate difficulty, on a specific date, where rental bicycles are available
This application needs an object to embody the rules at the intersection of Customer, Trip, and Bicycle
We have an unknown object; we just know we need some object to receive our message
What if we defined a TripFinder class that is responsible for finding suitable trips
It contains all the knowledge of what makes a trip suitable
it knows the roles
its job is to do whatever is necessary to respond to this message
Writing Code That Puts Its Best (Inter)Face Forward
Methods in the public interface should:
be explicitly defined as such
be more about what than how
have names that will not change
take a hash as an options parameter
Ruby provides three relevant keywords: public, protected, and private
These keywords indicate which methods are stable and unstable. It also indicates how visible a method is to other parts of your application
JP’s: HackingWithSwift
John’s Pick: MacStadium.com -

Jan 7, 2019 • 47min
Managing Dependencies
Chapter 3: Managing Dependencies
To collaborate, an object must know something about others. Knowing creates a dependency. If not managed carefully, these dependencies will strangle your application
Recognizing Dependencies
An object has a dependency when it knows:
The name of another class.
Gear expects a class named Wheel to exist
The name of a message that it intends to send to someone other than self.
Gear expects a Wheel instance to respond to diameter
The arguments that a message requires.
Gear knows that Wheel.new requires a rim and a tire
The order of those arguments.
Gear knows the first argument to Wheel.new should be rim and the second should be tire
Writing Loosely Coupled Code
Inject Dependencies
see 1_inject_dependencies.rb
Referring to a class by its name inside of another class is bad.
If the name of Wheel class changes, the gear_inches method must also change
The bigger problem is that gear_inches is explicitly saying that it is only willing to calculate gear inches for instances of Wheel
Gear will only collaborate with any other kind of object even if that object has a diameter and uses gears!
It's is not the class of the object that's important, it's the message you plan to send to it.
Gear needs access to an object that can respond to diameter - a duck type
We can use a technique called dependency injection to move the creation of a new Wheel instance outside of the class
Isolate Dependencies
see 2_isolate_dependencies.rb
Isolate Instance Creation
Sometimes you can't break all unnecessary dependencies, but you can isolate them
The first technique moves Wheel.new from gear_inches and into Gear's initialize method
The next alternative isolates the creation of a Wheel into its own wheel method
Isolate Vulnerable External Messages
gear_inches depends on Gear responding to wheel and wheel responding to diameter
by creating a different diameter method to hold wheel.diameter, we remove the dependency within gear_inches
Remove Argument-Order Dependencies
see 3_remove_arg_orer_dependencies.rb
Use Hashes for Initialization Arguments
arguments of our initialize method must be passed in the correct order. we can pass an object instead to remove this dependency
Explicitly Define Defaults
we can use the fetch method to set defaults when using hashes in our initialize method
fetch expects the key you're fetching to be in the hash and supplies several options for handling missing keys
fetch will only set the default if the key is not found in the hash
Managing Dependency Direction
All examples thus far have shown Gear depending on Wheel or diameter - but the code could have easily been written so that Wheel depends on Gear or ratio
Choosing Dependency Direction
Depend on things that change less often
John’s pick - Pick Krisp -https://krisp.ai

Dec 10, 2018 • 39min
Single Responsibility
Chapter 2: Designing Classes with a Single Responsibility
The foundation of an object-oriented system is the message, but the most visible organizational structure is the class
Questions to ask yourself:
What are your classes?
How many should you have?
What behavior will they implement?
How much do they know about other classes?
How much of themselves should they expose?
Creating Classes That Have a Single Responsibility
A class should do the smallest possible useful thing; that is, it should have a single responsibility
An Example Application: Bicycles and Gears
Let's take a look at bikes. Consider the types of gears that bikes use
Small Gears
easy to pedal, not as fast
takes many pedals just to make the tires rotate once
can help you creep along steep hills
Large Gears
harder to pedal, fast
sends you flying down those steep hills
one pedal rotation with your foot might cause the tires to rotate multiple times
Let's start with a small script and then extrapolate classes out of it:
Large Gear
chainring = 52
cog = 11
ratio = chainring / cog.to_f
puts 'Large Gear:'\
"\n#{chainring}-tooth chainring"\
"\n#{cog}-tooth cog"\
"\n#{ratio.round(2)} rotations"
Small Gear
chainring = 30
cog = 27
ratio = chainring / cog.to_f
puts "\nSmall Gear:"\
"\n#{chainring}-tooth chainring"\
"\n#{cog}-tooth cog"\
"\n#{ratio.round(2)} rotations"
Since we're talking about gears, it only makes sense that we start by creating a Gear class based on the behavior above
see 1_gear.rb
Our Gear class has three methods: chainring, cog, and ratio
Gear is a subclass of Object and thus inherits many other methods besides the three that we defined
What I'm trying to say is that the complete set of behavior / the total set of messages to which it can respond is fairly large
This is great and all - but what if we want to extend the functionality by taking into account the effect of the difference in wheels
Bigger wheels travel much farther during each wheel rotation versus smaller wheels
Consider this formula
gear inches = wheel diameter × gear ratio
(where)
wheel diameter = rim diameter + (2 × tire diameter)
see 2_gear.rb
This new code is great except our old call to Gear.new(52, 11) no longer works because we added 2 more arguments to our initialize method
Why Single Responsibility matters
Applications that are easy to change consist of classes that are easy to reuse. [...] A class that has more than one responsibility are difficult to reuse
Determining If a Class Has a Single Responsibility
How can you tell if your class is only doing a single thing? Try describing what it does in a single sentence. You'll find out very quickly
Remember that a class should do the smallest possible useful thing
When we look at our Gear class - perhaps it is doing too much
We are calculating gear_inches, which is fine - but calculating the tire size seems a little weird
When to Make Design Decisions
When we look at the Gear class, there's something off about having rim and tire in there.
Right now the code in Gear is transparent and reasonable - this doesn't mean that we have great design. All it means is that we have no dependencies
Right now, Gear lies about its responsibilities as it has multiple responsibilities in that it has to do "wheel" calculations in our gear_inches message
Write Code That Embraces Change
Here are some techniques that help you write code that embraces change
Depend on Behavior, Not Data
Behavior is captured in methods and invoked by sending messages
Objects also contain data (not just behavior)
Hide Instance Variables
Always wrap instance variables in accessor methods instead of directly referring to variables, like the ratio method does.
We can do this by using an attr_reader
BAD
def ratio
@chainring / @cog.to_f
end
GOOD
def ratio
chainring / cog.to_f
end
If your instance variable is referred to multiple times and it suddenly needs to change, you're in for a world of hurt.
Your method that wraps your instance variable becomes the single source of truth
One drawback is that because you can wrap any instance variables in methods, its possible to obfuscate the distinction between data and objects
But the point is that you should be hiding data from yourself.
Hiding data from yourself protects code from unexpected changes
Hide Data Structures
Depending on a complicated data structure can also lead to a world of hurt
For instance, if you create a method that expects the data structure is being passed to it to be an array of arrays with two items in each array - you create a dependency
see 3_obscuring_references.rb
Ruby makes it easy to separate structure from meaning
You can use a Ruby Struct class to wrap a structure
see 4_revealing_references.rb
the diameters method now has no knowledge of the internal structure of the array
diameters just know that it has to respond to rim and tire and nothing about the data structure
Knowledge of the incoming array is encapsulated in our wheelify method
Enforce Single Responsibility Everywhere
Extra Extra Responsibilities from Methods
def diameters
wheels.collect { |wheel| wheel.rim + (wheel.tire * 2) }
end
this method clearly has two responsibilities
iterate over wheels
calculate the diameter of each wheel
we can separate these into two methods that each have their own responsibility
def diameters
wheels.collect { |wheel| diameter(wheel) }
end
def diameter(wheel)
wheel.rim + (wheel.tire * 2)
end
separating iteration from the action that's being performed on each element is a common case of multiple responsibilities
Finally, the Real Wheel
New feature request: program should calculate bicycle wheel circumference
Now we can separate a Wheel class from our Gear class
see 5_gear_and_wheel.rb

Dec 3, 2018 • 38min
New Book: Practical Object Oriented Design
Discover the fascinating world of object-oriented design with insights from Sandi Metz's book. Explore the challenges of technology scaling as major companies shift from React Native to native solutions. Learn the significance of maintainable code and the balance between rapid feature delivery and thoughtful design. The hosts emphasize the importance of classic programming literature and the evolving insights that come with revisiting these texts. Plus, dive into practical tips for mastering JavaScript testing to enhance your development skills!

Nov 2, 2018 • 40min
Alternatives to Exceptions
Alternatives to Exceptions
Multiple return values in failures can be helpful -
Represent a process as an object “Download Provisionment” - This is a really interesting idea…. “MessageSend.new” - would actually handle a lot of the issues in the SMS interface concept we’ve been talking through.
“It’s tempting to raise an exception every time you get an answer you don’t like. But exception handling interrupts and obscures the flow of your business logic. Consider carefully whether a situation is truly unusual before raising an Exception.”
Diagnostics- don’t fail SO aggressively early that you don’t capture the diagnostics.
Examples of when to not "fail fast":
test suites
Sometimes you just need a way to proceed through steps and have the system tell you what parts succeeded and what parts failed
Sideband data
When communication failures without resorting to exceptions, we need a sideband: a secondary channel of communication for reporting meta-information about the status and disposition of a process.
Multiple return values
hehe, this reminds me of stuff I do in javascript
ruby supports multiple return values in the form of array splatting. in JS, you could do this with destructuring
def foo
result = 42
success = true
[result, success]
end
result, success = foo
puts "#{success ? 'succeeded' : 'failed'}; result #{result}"
Or you can use an open struct
def foo
OpenStruct.new(:result => 42, :status => :success)
end
Output parameters
Caller-supplied fallback strategy
if we're not sure we want to terminate the execution of a long process by raising an exception, we can inject a failure policy into the process
def make_user_accounts(host, failure_policy=method(:raise))
# ...
rescue => error
failure_policy.call(error)
end
def provision_host(host, failure_policy)
make_user_accounts(host, failure_policy)
end
policy = lambda { |e| puts e.message }
provision_host("192.168.1.123", policy)
Picks
JP:
https://github.com/xotahal/react-native-motion
https://github.com/fram-x/FluidTransitions
https://github.com/callstack/react-native-testing-library
John:
Slack Video Calling + Collaboration

Oct 26, 2018 • 48min
Designing for Failures
Designing for Failures
Failure flags and benign values
Sometimes responding with a nil is good enough, i.e.
def save
# some failing code
rescue
nil
end
Related to this is the concept of "benign values"
The system might replace the erroneous value with a phony value that it knows to have a benign effect on the rest of the system
When the system's success doesn't depend on the outcome of the method in question, using a benign value may be the right choice. Benign values are also helpful in making the code more testable.
Example:
begin
response = HTTP.get_response(url)
JSON.parse(response.body)
rescue Net::HTTPError
{ 'stock_quote' => '' }
end
Instead of 'puts'ing, we can usewarn`
Warning as errors
Check out this hack:
module Kernel
def warn(message)
raise message
end
end
warn 'uh oh'
Remote failure reporting
At OL we use Bugsnag
Idea of bulkheads -> a wall beyond which failures cannot have an effect on other parts of the system
you should put bulkheads between external services and processes
Circuit breaker pattern
Ending the program
Calling exit ends the whole program
Remember that time I used exit in the Whiz Tutor codebase?
Picks
John: User Onboard - https://www.useronboard.com/ by https://twitter.com/samuelhulick
JP: singlediv.com - https://twitter.com/samuelhulick

Oct 19, 2018 • 50min
Exceptional Failure
Exceptional Failure
In this short season, we are going through EXceptional Ruby by Advi Grimm
What is a failure?
Let's talk about some definitions first:
Exception - the occurrence of an abnormal condition during the execution of a software element.
Failure - the inability of a software element to satisfy its purpose
Error - the presence in the software of some element not satisfying its specification
"Failures cause exceptions which are due to errors"
Failures - methods are thought to be designed to fulfill a contract. when they don't fulfill the contract, they fail
The life-cycle of an exception
Exceptions are raised with either the raise or fail methods
In Ruby, we signal failures with exceptions
🗣 Discussion: When do you find yourself using raise?
🗣 Discussion: When do you find yourself using rescue?
The rescue clause should be a short sequence of simple instructions designed to bring the object back to a stable state and to either retry the operation or terminate with a failure
syntax
Starts with the rescue keyword, followed by one or more classes or modules to match, then a hash rocket and the variable name to which the matching exception will be assigned
Subsequent lines of code up to an end keyword will be executed if the rescue is matched
rescue IOError => e
puts "Error while writing to file: #{e.message}"
end
Moar Code
begin
raise RuntimeError, 'specific error'
rescue StandardError => error
puts "Generic error handler: #{error.inspect}"
rescue RuntimeError => error
puts "runtime error handler: #{error.inspect}"
end
Order matters when stacking multiple rescue clauses. the RuntimeError rescue block will never execute!
🗣 Discussion: Have you ever used retry?
tries = 0
begin
tries += 1
puts "trying #{tries}"
raise
rescue
retry if tries < 3
puts 'I give up'
end
Ruby gives you the power to retry
I can see how this might be useful for making API calls
Be super careful that your 'giving up' criteria will eventually be met
Retry is nice for things that are unreliable
Picks:
JP: Overcast https://overcast.fm/
John: Apple Refurbished