Hackers Hiring Hackers | Gun.io
an interesting job site
an interesting job site
Writing Fabrication has given me a lot of insight into the world of object generation. It has forced me to reflect a lot on how we are doing it and how we can do it better. The reason I wrote Fabrication to begin with was to try out the idea of lazy generation of associations, meaning that a defined association wouldn’t actually be generated unless it was actually referenced. That would allow you to specify the entire object graph in a single set of fabricators but not worry about generating them all every time.
After implementing that and working extensively with the library, I have settled on what I consider to be a few best practices for defining fabricators. Whether you are using Factory Girl, Machinist, Object Daddy, Fabrication, or some other library, these principals all still apply.
In the spirit of the upcoming bike week, let’s say we have the following class, representing a motorcycle model.
class Model < ActiveRecord::Base belongs_to :manufacturer has_many :motorcycles validates :name, presence: true, uniqueness: true endThe primary fabricator should only have the fields necessary to create a valid object.
In many cases, a table has quite a few fields on it. Most of them are not necessary for the object to be valid in the database and so don’t need to be generated every time you create an object.
This particular class probably has a whole lot of fields on it specifying the engine displacement, drive type, tire sizes, etc. Our system may not care about any of those fields the majority of the time though. The only thing the model actually validates is the presence of the name.
The primary fabricator should always create belongs_to associations, but never has_many.
A good object model will typically require objects going up the tree to exist, but never objects going down. Any time there is an id field on your model, as in the case of a belongs to, then that other object is very likely necessary for your object to exist. In the case of our Model, it has_many motorcycles but you don’t actually need to make a production run for the model to exist. The manufacturer does need to exist for the model to make sense, so we should be creating that every time.
Use a sequence when uniqueness is required.
Our Model has a uniqueness validation on name. There are a number of ways to ensure that, but the easiest one is to use a sequence.
Let’s put it all together.
Now that we have the basics down our fabricator should look like this.
Fabricator(:model) do manufacturer! name { Fabricate.sequence(:model_name) { |i| "Model #{i}" } } endWe skipped all the fields we didn’t absolutely need, didn’t mention the has_many relationship, forced the manufacturer, and used a sequence for the name. It is lean and clean, but flexible enough for the vast majority of your specs.
Fabricator looks very interesting — like Machinist with looser coupling, useable in standalone apps.
I recently received an email from someone who was getting into programming, and was asking for advice on how to proceed. He had a project in mind, and had started on it, but had run into areas where his current knowledge was insufficient to puzzle out the solution.
First of all, I was very impressed that he had actually started work. Ideas are a dime-a-dozen, and one of my least favorite things are “idea people” who feel like their work is done when they come up with an idea, and all that’s left is to find a programmer who is willing to fill in the blanks. That this person came to me after first trying to solve it himself was a huge mark in his favor.
Apple’s famously guarded about their upcoming product releases. It’s a good strategy that gets them lotsa free press.
There’s more to the story. My theory is that Apple stays mum because any particular plan isn’t concrete until the trigger is pulled. It’s better to under-promise and over-deliver.
I imagine that Apple is constantly refining, experimenting, developing each of their products. What we ultimately see is just a snapshot of that product during its evolution. I recall a quote from Pixar (Tim Cook?):
“Our movies are never ‘done’, what gets released is just a snapshot in time.”
That philosophy certainly carried over to Apple.
Consider the rumored upcoming MacBook Pro refresh. Apple hadn’t announced anything. Because I don’t think they knew themselves. The next MBP was expected 2012-ish, to leverage some new Intel chipset. Alas, Intel’s late. Waiting 18 months to refresh is too long. So Apple pulled the trigger on what they have in the pipe.
A better example is the iPad 3. Why refresh when the iPad 2 continues to stomp? The longer Apple waits, the better the iPad 3 will be. Whenever a new challenger appears, or demand for the iPad 2 starts to dip, Apple can just pull the trigger.
Steve Jobs once admitted (at D8?) that their tablet was a work in progress, but they decided to release their phone first. By not announcing either, Apple didn’t precommit and was able to deliver whatever made the most sense.
Releases as snapshots is very “agile”, something us software developers aspire to do. By always having a product that is shippable, a team can pull the trigger when it makes most sense. Much less risky than the traditional Big Bang, waterfall, Hail Mary Pass product management strategy.
Sep 16, 2011
I’ll always remember this as the night that Michael Jordan and I combined for 70 points. Said after Michael Jordan scored a career high 69 points and Stacey King scored 1 point against the Cavaliers….
If you want to build a ship, don’t drum up the men to gather wood, divide the work and give orders. Instead, teach them to yearn for the vast and endless sea. Antoine de Saint-Exupery, Citadelle
It’s actually the real account. Awesome.
Wow @dianakimball is awesome. Took idea http://t.co/NFK1q8I and in 20 mins composed, recorded, posted http://t.co/DYiSMM5 to SoundCloud
I think I shared some earlier version of this. It’s an interesting talk about the future of curation, Authority records, and geography in the face of Open Street Map and similar.