Code Less: A Language Keystroke Expirement 3

Posted by Paul Pagel Sun, 08 Jun 2008 18:06:00 GMT

When I first started writing code in ruby, it was a breath of fresh air after writing C# code for a year. Ruby had a thesis, a clear purpose, rather than a hodgepodge of features strung together. It was a language obviously written by someone who cared about what the code looked like. So I jumped into it and loved writing ruby code (still do!). Recently I had to write a project in Java using IntelliJ, and the powerful IDE was also a breath of fresh air after using text editors to write ruby code. The IDE helps me in the same way ruby helped me. I write less code that does the same thing, without loosing expressiveness or transparency of intent. Less code in this case meaning less keystrokes.

So, I am going to do a little experiment using two editors and languages: ruby with textmate and java with IntelliJ. I want to see how many lines of code I have to write. The application I am going to start is a simple baseball at bat scorer. First lets see the ruby version.



We have about 27 lines of code written, and other than the describe method, which I have a macro for, I typed them all by hand. Lets look at the java code. This is just the JUnit test I wrote, there is no production code yet.



It is about 16 lines of code, which I wrote all of but the import statement. By doing a few alt-enters on the squiggly lines, I can get a stub of a class looking like this.



That is 13 more lines of code, without really typing, just hitting enter a few times. Now, lets start to make the method pass. I am going to write the algorithm without worrying about all the type definition java wants. Here is what it looks like.



So the code written is around 4 lines of code. Lets use the IntelliJ autocomplete features to help us make a passing test, which looks like.



So roughly, the ruby version was 23 lines of written code and the java version was about 20 lines of written code. There is an expense to doing all of the alt-enters to auto-generate the method and variable stubs, but IntelliJ is pretty smart about what it generates. Also, I understand a single test doesn’t tell the whole story, but it is a good indication. I found as I wrote more tests for this application, a smaller amount of keystrokes was needed for the java version, and the same amount was needed for ruby. This is due to the refactoring tools, and intellisense. As applications get larger, I find the IntelliJ refactorings become more useful. Inversely, ruby refactorings become more painful, as they are mostly done by hand.

So, in the end the constraints on a static language allows the IDE to make the refactoring tools better. Specifically, when writing java code, I can lean on the IDE to generate all the uninteresting stubs for me. All I do is fill in the algorithms: the fun part. When I start to see places where my code can be cleaned up a bit, I can lean on the IDE again to do those refactorings for me once I recognize the need for them. Removing and optimizing the code is something which is easily deducible in static languages, as it is mostly pattern matching, with no monkey patches, meta-programming, and evals to worry about. This is a limitation which frustrates me as a developer who wants to have a large set of tools in my bag, but is helpful when it comes to developing a powerful IDE.

The number of lines of code I need to type isn’t the reason I choose a language over another. In fact, it would be pretty low on the list of deciding factors. However, it is interesting to see what each language and its sets of tools do best. Hopefully the ruby community can take some notes from them. I would rather solve the other end of the equation, get a powerful ruby IDE. I know Eclipse and Net Beans have some preliminary refactoring tools, but they are still aways from being as seamless as their java counterparts.

Announcing Limelight 1

Posted by Micah Mon, 02 Jun 2008 20:42:00 GMT

I’m pleased to announce the open source Limelight project: A thin client and application framework written in Ruby (JRuby).

Erlang and the OCP

Posted by Eric Sat, 24 May 2008 17:39:00 GMT

OCP was defined in 1988 in Bertrand Meyer’s book “Object Oriented Software Construction” as follows:

Modules should be both open (for extension and adaptation) and closed (to avoid modification that affect clients)

Recently we had an issue in my office with our system which uses Rinda (a Ruby implentation of Linda) as a blackboard architecture. The architecture looks a little like this crude drawing.

Rindapic

This hides the OCP violation. The “rindlet,” our informal name for these subprocesses, actually removes the message from the blackboard. So if you send a message that looked like this [1, 2, 3] and one rindlet took it then no other rindlets can receive it. To repeat myself, this meant all messages had to have as their first data member the name of the rindlet they were sending the message too. This is bad. Adding another rindlet meant changing the client sending the message. Now to quote Agile Software Development: Principles, Patterns, and Practices [Martin 2003] An axis of change is an axis of change only if the changes actually occur. That is to say if only one rindlet cared about a message than this wouldn’t be an issue. When this became a problem was when more than one rindlet wanted the same message. Suddenly we have to send many otherwise identical messages to different rindlets. This is the heart of the OCP, the Server (in this case the one sending the messages), should be closed for implementation, but is not. In our case we changed the architecture to shield the server from those changes, and fixed the issue.

This brings me to Erlang and its message passing system. Last year I began playing with it, but lost interest as the difficulty of the syntax simply ruined the fun for me. I do know enough about it that when this issue came up in our ruby system, I was immediately reminded of Erlang’s message passing system. Specifically it has three methods [Armstrong 2007 pg. 134]:

spawn - Create a new concurrent process that evaluates a passed in Fun. The new process runs in parallel with the creating process.

Pid ! Message - Send a message to a Pid - returned by the previous spawn.

receive…end Receives a message that has been sent to a process.

On a cursory glance it appears we have the same issue since you must know the Pid of the process. Aha, but the command sending a message to the process actually created the process, and therein lies the difference. The blackboard architecture deliberately decouples the constantly running processes from messages, the messages are sent to the blackboard. The sender has no right to know about the constantly running process, and should not need to change to add another one. Erlang on the other hand spawns processes as if they were objects, and sends them messages. Sending messages, heck that’s what you do with an object too isn’t it? I don’t think creating an object and sending it messages is a violation of OCP, and neither is this. The sender can be extended without effecting clients. It turns out that Erlang does not intrinsically violate the OPC like I’d originally surmised, although like any other system I could easily create an architecture that did.

Older posts: 1 2 3 4 5 ... 25