08
Jan
09

How to become a better Ruby programmer

1. Buy the Pickaxe and put it on the John

Idea: Know the standard library

When I got an actual copy of Programming Ruby on paper, I found myself looking into it whenever I had spare time and no computer available – usually this was mostly on the toilet. ;)

That way I discovered so many useful methods and classes in Ruby’s standard library, you won’t believe it. Often times developers tend to reinvent some functionality, just because they don’t realize it’s already provided for them. And trust me, Ruby comes with quite some distinct features out of the box.

So my tip is to get a good book that covers the Standard Library or print it out somehow, and have it with you whenever you have to kill time, e.g. in a bus or the bathroom (or even for 10 minutes in bed).

2. Necromancer-Style: Create skeletons

Idea: When using a new tool or trying to implement a bigger feature, get started with just the boilerplate code

Often times, when I want to try out a new library, I hesitate, because of the steps necessary to get started with it. First I have to install it, and maybe some dependencies, then create a file with some boilerplate code, and sometimes also do some configuration.

Not until then can I really start with the actual functionality I want to try. And the worst thing is, weeks later I’d like to use the same library again in another project, can’t remember the procedure and have to do it all over again. And sometimes this keeps me from using that new library (e.g. RSpec) at all, because I can just resort to a good old tool I know (e.g. Test/Unit).

Another exemplification is starting a big feature, where you don’t know how to implement the actual business logic. My suggestion is, just start with something, even if it’s an empty file. And then create a test case, to tell yourself where you want to go. Remember, that you can also write empty (deferred) tests, which just exist to remind you of the behavior you want to realize.

Now when you take a break from the project, and have a Geistesblitz, you can directly open the file and start typing. Believe me, this shouldn’t be underestimated!

Rails is an ideal role model with all it’s generators. It is an important step to get a complete application skeleton
with the rails command, so can directly start with your business logic. And when you create a controller, it also creates a test case for you, to motivate you writing functional tests at all. Sometimes just creating that file and filling it with the necessary boilerplate seems to be too much for us (at least for me).

I recommend preparing the installation and initial configuration of new tools and features, and sometimes even automate this step. There are various ways to do this:

  1. You can add a snippet to TextMate (e.g. try Command+N in your test-folder, choose a filename, hit ENTER,  type tc and press TAB).
  2. Maybe it’s even enough to have a file somewhere in a directory, where you can just copy and paste the configuration.
  3. Ruby is also the perfect language for writing a small shell script to download a library or create necessary files.
  4. You could also write a complex generator for more elaborated tasks.

To sum it up: have a place where you can directly start typing your ideas without being distracted. Create file skeletons, and for more complex tasks, try to automate this step.

3. Don’t be shy

Idea: Communicate with other people on IRC to reinforce your comprehension

Chatting with fellow programmers has a number of advantages:

  1. You can ask questions to Ruby experts, which you haven’t been able to solve with the API documentation or a google search. Sometimes a question can spark really interesting discussions, you weren’t able to predict.
  2. When you help other people with a specific problem, oftentimes you increase your understanding in that area or see things from a different perspective. Many times when someone asks something I’m not sure of,  I open up IRB and just try it out. This lead to some new revelations, but also consolidated things I was already quite certain about. And don’t forget that your helping other people learning the language, which will keep the mutually assistence up.
  3. Hanging in the different channels will possibly bring new connections: maybe you find a project you’re interested in, because some people are constantly talking about it, or you just keep talking to the same guys over again. Which brings us the the next point:
  4. IRC is also a good place to meet new friends, after all everyone in #ruby-lang shares the same hobby, which is a good foundation, right?

So I suggest to just give it a try and download an IRC Client (on OS X i recommend Colloquy), connect to irc.freenode.net, and join #ruby plus #ruby-lang (there is also #rubyonrails or #shoes and many more specialized channels). But beware: it can get pretty addictive and distracting if you don’t watch it. ;)

28
Aug
08

What is REST ?

What it is not

Too often I have heard the term REST used in a wrong way. Sometimes people think that when they are accessing a Web Service via a simple HTTP GET and the URL, they are using REST.

For example I’ve seen stuff like this in the Axis2 documentation, where they say, that you invoke a deployed SOAP service the REST way by using your browser and navigating to a certain URL:

http://domain.com/service-name/service-method?parameter=value

This is not RESTful!

So a lot of times you can see services claiming having a REST interface, when in reality they only have a HTTP GET interface, which totally misses the point. (Don’t get me wrong here, Axis2 actually seems to have real REST support, but the above example is not part of that!)

Okay, so what is REST then?

REST uses the HTTP architecture and (usually) XML, which are basically used everywhere. It does not add a new protocol layer (like the SOAP envelope for example) on top of that. Unlike SOAP, you don’t define services with actions (methods) and arguments.

Instead it’s all about resources and representations. All resources can be listed, viewed, created, updated or deleted. And every resource has at least one representation (think of it as rendering the raw data), for example in XML, HTML or Plaintext.

It is best described using an example:

A bookstore example

Say we have a bookstore where we want to publish books and let authors upload their own books.

So what we need to do is create, read, update and delete books. (Note the 4 verbs and the noun books in there) This is basically what all RESTful web services do: basic CRUDing. That’s also what databases do by the way in addition to allowing complex search queries.

The nice thing now is that HTTP already supports keywords for exactly these use cases. I guess you all know GET and POST requests. But there are also some other verbs defined like PUT and DELETE for example.

Listing all items

Listing resources is usually the first step for a user of the REST service to get an overview of what’s available. It is similar to viewing the items, but instead it returns all resources of a certain type. To list all books of our store we simple send a GET request to the following URL:

http://domain.com/books

This will return a list of <book> elements in the HTTP response body, like this:

<books>
  <book>
    <id>1</id>
    <title>Cryptonomicon</title>
    <author>Neal Stephenson</author>
    <price>19.95</price>
  </book>
</books>

Currently there is only one book, let’s upload a new one.

Creating resources

To upload a book, we POST to the very same URL. The nice thing about REST is, that we reuse URLs (resources) all over again, we just change the verb to tell the service what we want to do with it. So just send a POST request to the books resource:

http://domain.com/books

As you can see there are no parameters supplied in the URL, the actual payload is in the HTTP request body, like this:

<book>
  <title>World War Z</title>
  <author>Max Brooks</author>
  <price>14.95</price>
</book>

Note that there’s no id-parameter supplied yet, as this is not needed, because the web service will create one when it actually stores the book in its database backend. (You as the web service author are responsible for doing this, Rails does it automatically)

Now what do we do if we want to update the price of a book? Let’s use 2 steps for that, to see a real world use case, and also learn some theory and vocabulary.

Representations

Your data is usually saved in a (relational) database. But your users need a certain view (a.k.a. representation) of this raw data. And you can represent your data not only as XML, but also as HTML, JSON, CSV or whatever format you need. If you want you can also support multiple formats, and let your users decide which representation of the data they want to see.

For this HTTP has the content-type header, which you would set to application/xml to get your book in XML as we need to do in our examples. (Note: We needed to send this content-type for every request so far, but I haven’t mentioned it yet, to keep it simple at the beginning.)
 

Show me a resource

To get a book with the ID 2, we send a GET request with the content-type header of application/xml to the following URL:

http://domain.com/books/2

Note: We could also identify our books via something more descriptive, e.g. their title, but then we have to make sure that a) each title is unique and b) the id-part of the URL is all lowercase and uses dashes instead of spaces (this is not absolutely needed, but makes the URLs much easier to read – it’s really confusing to use mixed case in URLs for the end user). An example URL for the above book would be:

http://domain.com/books/world-war-z

Modifying the Show view

In any way we get the following XML back, which is basically the same we uploaded before, but with an additional ID field, which was inserted by our backend. (Note: If we would use the title as our ID, then obviously this field is not present)

<book>
  <id>2</id>
  <title>World War Z</title>
  <author>Max Brooks</author>
  <price>14.95</price>
</book>

So lets say, we want to increase the price of the book, because it’s so good. We just set the text of the <price> element (with our XML library of choice or a simple String-replace) to our new value.

Updating a resource

Now that we have the updated XML representation of the book, we are ready to upload it to the server. REST uses the HTTP method PUT for updating.

Just send a PUT request (with the XML payload in the http-body) to the URL of this resource:

http://domain.com/books/2

If everything went well, the server should send a HTTP status code of 200 (OK) or 201 (Created). The nice thing is that HTTP already defines all the status codes you need, so no need to reinvent the wheel. And you can always send additional status messages in the body of the response.

Delete with DELETE

So you think this was easy? (I hope so) Then wait till you see how we remove resources. There is a HTTP method for exactly this use case, which was not really used before REST. Just send a DELETE request to the target resource:

http://domain.com/books/2

There you have it, same URL again, different method.

Summary

That is the basic architecture of a REST based web service. Basically you send one of the four HTTP request methods to a URL and put any payload directly in the HTTP body. The server sends a response with an appropriate HTTP status code and also puts any content in the body.

Advanced uses

Let’s say you also want to view certain chapters of a book. Usually you would think of something like this:

http://domain.com/books/2?chapter=1

This is also the way Axis2 handles arguments to a service’s method. But doesn’t it look way better the following way:

http://domain.com/books/2/chapters/1

This is the concept of nested resources. You have a full URL (without any URL parameters) that identifies a given resource. It gets even clearer when you have an even deeper nesting than two. Let’s say we also want to view certain pages of a chapter. Compare the following:

http://domain.com/books/2?chapter=1&page=2

This doesn’t make clear if we mean the 2nd page of the book or the 2nd page of a chapter. With nested resources it’s unambiguous:

http://domain.com/books/2/chapters/1/pages/2

It should be clear, that this returns the 2nd page of the 1st chapter of the 2nd book. Note that we always used the plural version of a resource. This allows us to GET a list of all chapters using the URL:

http://domain.com/books/2/chapters

And it also allows us to POST new chapters to the very same URL!

Advantages of the REST approach

First of all I think it’s really simple (you need to have a basic understanding of HTTP though – which every web developer should have anyways). And you are reusing existing technology, instead of adding even more to the already crowded IT world. For example you can use HTTPS in combination with HTTP basic authentication for security.

Because SOAs often forward messages and act as middleware, you can make use of the lightweight HTTP redirection and referrer mechanisms.

All REST services have a uniform interface. Unlike SOAP you don’t really need a WSDL to see what methods are available for your service: if you know which resources are available, you know that you can GET, POST, PUT or DELETE them.

REST services can be invoked by the browser. When you have HTML representations, you can GET them with the browser, and you can also POST resources (e.g. as JSON). Unfortunately current browsers do not support PUT and DELETE requests from HTML forms (maybe Firefox3 does, not sure?), but I’m sure we will see these in the future.

Disadvantages

As REST uses the CRUD approach, it is sometimes not easy to implement certain service designs. For example a calculator in SOAP style would have add() and multiply() methods with 2 (or more) arguments.

In REST you have to rely on the GET, POST, PUT and DELETE methods, so at first this problem might seem untackable. But with a different way of thinking, it could be realized like this: You have sum and product resource, which you will GET for different arguments, for example:

http://domain.com/calculator/sum/1/2

Which simply return 3 in the body. You could always use dynamic number of arguments like the following:

http://domain.com/calculator/product/1/2/3/4

And this would return 24 and a status code of 200 (ok).

Additional Reading

There’s a lot more to REST than I could cover in one mere article (for example caching). Whole books can be written about RESTful design (somehow I know only one). To get started here are some links I found helpful:




November 2014
M T W T F S S
« Jan    
 12
3456789
10111213141516
17181920212223
24252627282930

Follow

Get every new post delivered to your Inbox.