Building APIs That Rock - Notes - Drupalcon DC
Aquia room 9am - Building apis that rock
Congratulations, you're a nerd. We knew that.
Eaton - lullabot
worked on a lot of apis, token, voting, form, amazon, twitter.
wants to help us avoid pitfalls
No Elmo - he has not written any code worth anything. :)
Drupal 2004: Lego blocks that fit together.
Now, even more lego blocks - easy to step on and hurt.
Not a 'bad' thing,
Need modules we can combine easily and effectively. Need to be able to build in layers, and pieces need to work together properly, and that's where apis fit in. apis are like the little divits on top of lego pieces that make them fit together.
picture of tug of war, knot on rope is your module. tug of war between all the cool things that your module does and what people want, Building code that does stuff is important.
What is an API?
99% of stuff we build is based on clicking around to set things up.
Code cannot click on controls and submit forms. Can the "Code" user use your module? Is it
possible for an install profile to configure your module out of the box? Can they bypass your user interface or use a better UI?
Pointing out how Views is an api, because the UI is separate from the working bits.
The first key to an api is that if your module is a pile of money features, The ATM is an api to get your money. It is an interface with a simple set of instructions of what you can do with your pile of money. OG, for instance, provides a lot of functionality out of the box, and has an API. Other code can act as a friendly layer on top of the api. Flag module another example, it provides an api.
Just forms for a UI is bad - "Code is a user with no hands."
Want to get away from forms -> items, instead of forms -> something -> api
< Your API>
API: An abstraction that hides complexity - like a bank teller.
Image API is an abstraction - hides the available tools from the code using it.
The messaging module is another example - messaging sits on top of the details, and lets you just say 'send this message to this user'. It's an abstraction on top of telling people stuff. Cache_get and cache_set are apis in drupal - because they don't specify where the cache is and can be swapped out.
API: An agreement about how things are done.
Think of it as a credit card - value is not in the small piece of plastic, but the advantage is that everyone has agreed to do the same thing with every credit card. Not that you can do this in one place, but that everywhere you go you can be pretty sure the card will work the same way.
So, it's a solved problem, and you can go on to do the interesting things.
Eaton is good at this thing.
recap:
* Drupal is complicated
* apis let other code use your features
* apis hide complexity
* apis get everyone on the same page. Token module, for example.
Token piggybacks on pathauto, but it's v. useful.
Let's make an API!
"When two modules love each other very much"
VotingAPI 0.1
Eaton wanted people to be able to vote on stuff. All sorts of cool rating modules, but none of them worked together. This was very frustrating for him. So, decided to make VotingAPI. Chose the one with the nicest flash widget and ripped it open.
two functions: votingapi_set_vote / votingapi_get_vote
Important thing to do with API: Find the Nouns. - this is your data
then, find the verbs - these are your methods.
If you can find the nouns, these are your data, what you store. The verbs is what people want to do with the nouns, and this is your api.
If you can explain things that people want to do with your api in terms of your data/nouns and functions/verbs, and it makes sense to someone else, that's a god sign.
Evolution - are your verbs and nouns flexible enough - add/change/delete votes in addition to just setting. As people need more complexity, they can drill down to more detailed stuff.
Building in layers is important, building simple helpers on top of more detailed functions is good to help developers.
Step 3: Planning ahead - letting other modules do the unanticipated.
Supporting different kinds of votes - percentages, points, etc.
Sorting was tricky, complex sql, so recalculate results / voting results - 'results' is the new noun.
New verb - recalculate / get
The naming conventions may seem like fluff / bikeshed argument, but it helps people understand your api by looking at the functions. VotingAPI was gathering functions willy-nilly, and it started to cause problems.
First person to try a new type f vote got upset - didn't work. He numbered the different types of votes, which didn't work. and the new types people made overlapped, which caused problems. Angry puppets give you the finger.
Don't use enums or hardcoded values unless you know it won't change - Use strings. Remember css's theory of doing char(3) for data fields.
Users will abuse your module.
Use strings for stuff you can't predict! Type is now a string.
'percent', 'points', whatever.
Module is now being driven around - boldly going where no module has gone before. Enough points of expandability that users can use it oddly But still not planning head for stuff.
module_invoke_all - remember the verbs? Are you doing things other modules care about?
Fire off hook events when things happen.
The idea isn't number - more isn't better - but well placed hook invocations let other people do the hard work for you. The more your module is set up, the less you have to do, can pass responsibility to code.
9times out of 10 the goofy ui folks people want to have is an edge case, used in oneplace only.
module_invoke_all() - party invitations for code.
Recalculates cached results - Are you building data other modules want to change?
drupal_alter('votingapi_results', $results, $type, $id);
form_alter same-way. Give everyone a chance to change it. module_votingapi_results_alter() thingy.
The ampersand in the _alter(&$results) - passed in by reference, allows it to be changed. Change is made to the result. By the end, all the various changes add up and can be used.
drupal_alter() - It's like passing around the doobie of data - don't have to change it, but everyone gets a chance.
function myapi_do_something() {
$stuff = module_invoke-all('myapi_stuff');
drupal_alter('myapi_stuff', $stuff); // change stuff that other modules have sent in
$results = myapi_process_stuff($stuff);
module_invoke_all('myapi_stuffed', $stuff, $results);
return $results;
}
formapi is like this - you get to alter what another module set up
Menu very much like it - everyone contributes menu paths, and then everyone gets to change the menu paths.
Let other modules alter the flow...Template pattern -