iteration
Get Flexible
Episode Summary
This week we talk about defining interfaces, constructing an intention, and using messages to discover objects.
Episode Notes
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:
- 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 -