Showing posts with label developer. Show all posts
Showing posts with label developer. Show all posts

Friday, January 2, 2015

Developers are from Mars, users from Venus

From 2008 to 2012, I was the project manager of a project with very special users. The kind of project was in the field of digital signature for the Spanish Government. I was in charge not only of acting as a Product Owner (determine features and priorities), but also provided telephone support (second point of contact, that in fact used to be first). The main group of users where well-educated, high-ranked with lots of responsibility in their own field, but non-technical. There were also personal assistants for the previous group, but it wasn't a different group in terms of behavior towards technology.
I remember that apparently trivial questions could pose a challenge. Many people didn't know what a browser is, let alone there were different ones. 
I remember that digital signature at that time was a challenge (install Java, install a certificate, provide appropriate permissions for an applet). Something would fail, and you didn't know what. You would have to debug the process. The other problem for the users would be speed. 
However, as developers it was difficult not to focus in a different set of features, and not try to improve the existing issues.
At that time I started to perceive the radically different world-views between developers and users. I started to understand when my mom would get angry of me for keeping 10 open tabs while navigating, or to perceive that the AND/OR boolean logic can be quite tricky for non-techies. But I also became aware that maybe when in 2006 I was acting as part of the client team for an outsourced project, it was not a bad provider what time after time would deliver a different thing from what we (technical guys) where expecting.
Nowadays, I think communication between users and developers is of great importance. The "I'll tell you want I want when I see it" is not something to be dismissed. 
The agile approach is not a "quick and dirty hack" but a "let's understand what the user is looking for". Apart from helping managing risk.

Saturday, October 4, 2014

Agile is about managing risk

It is not easy to explain what is agile or the need of agile practices in software development. Agile is not only about releasing early a valuable product even if it is the highest priority.

Anyway, a few days ago I found this tweet:

I showed the picture to my wife, and I tried to explain it to her. It was funny because she couldn't understand what's wrong with the first part of the picture and why the second one is the proper way to build software. She insisted that if you want to build a car, you should do the a wheel the proper way, then the other wheel, then the body and finally you deliver the car.

So why many people in the software development world are trying to deliver a skateboard, and then a bike, and then a scooter, and finally a car?

I think it is about managing risk.

It is not about following the coolest paradigm or techniques. But about identifying what usually goes wrong when developing software, and providing solutions.

Users complain that what they receive is not what they asked for, it is delivered late, and it costs too much. Software developers say users don't know what they want, and they keep changing the vision throughout the project. As a result, many software projects end as a failure

To avoid it, the typical solution is to increase the requirements analysis phase (not a straw-man, see previous link). You set in stone what the user wants and if the user changes his/her opinion (or he/she doesn't understand what appears on the requirements document), bad for him/her. Then, the software is designed, properly built, tested and deployed. And finally (or at least later in the process) you put a wrap and show it to the user. I call it a waterfall mindset.

Traditional software development

From a pure risk perspective that is a lot of uncertainty. We don't know if that is what the user wants. We don't know if we'll deliver on time. Any change could have catastrophic consequences. Your product is not ready to look until very late in the process.

Agile is almost the opposite. It's about delivering early, something that can be used right from the start, and slowly enhance it. It is about talking with the user throughout the process. It is about developing software WITH the user. Problems tend to appear early in the process, and you tackle them as they appear. Sometimes problems are the result of a growth without a blueprint, and you need to rebuild things you've already built. But that's OK, because Agile is about facing risks.

I've been part of teams with daily stand-ups, with sprints, with code reviews, but with a waterfall mindset. Agile shouldn't be a warm feeling of this is right, or cool. Agile should be a way to minimize risk. 

Saturday, July 12, 2014

Jetty

Lately I've had three different issues with Jetty. Two of them were those kind of issues that are not directly related to the problem. The third proved to be a bit more tricky.

The first one was the typical example of "correlation does not equal causation". I started getting a weird error trying to run a Scala based web application in Jetty. And I kept received the following error "Could not create symlink /tmp". I thought it could be related to some kind of permissions issue. In the end the problem was more basic: I'd exhausted all the free space and nothing could be written to disk (and jetty couldn't create a symlink).

The second one was one of those Doh! moments. My web application didn't respond to any request. But it didn't show any error in the logs. I'm quite ashamed of putting this in writing but the issue was that the web application was paused in a breakpoint while debugging.

The third one was a bit strange. The web application obviously has static files. Some of the Javascript files were served correctly, other Javascript files weren't. The files not served were always the same. I didn't detect any specific pattern. But the fact was that Chrome would receive net::ERR_EMPTY_RESPONSE, and the Jetty was logging an exception NoSuchMethodError in javax.servlet.http.HttpServletRequest.isAsyncStarted  

The typical answer relates the problem to having several versions of the servlet api. But I somehow didn't pay too much attention because [sarcasm on] everybody knows servlet-api.2.5 and javax.servlet-api-3.1.0 are not different versions of the same API [sarcasm off] (indeed they ARE different versions of the servlet API)

Sunday, June 8, 2014

Scala: First impressions

A couple of months ago I started working for a different company. I'm quite happy there for many reasons. But one of them is having the opportunity to learn a new language: Scala. It's uncommon to get a programming job when you don't know the syntax of the programming language used. But if you really think about it, it's much better to hire somebody passionate about technology and that really loves to learn (and commit) than somebody that knows the language but doesn't give a d***mn.

Anyway, after a couple of months, I thought it would be good to write my experience about the language.

First. What is Scala? Scala is a programming language that allows to develop both Object Oriented Programming and Functional programming. Functional programming is a new paradigm of developing that is opposed to Imperative programming. In a nutshell, imagine SQL, the language for querying databases. When writing a query you don't write code like "Take the first row, check if satisfies the WHERE clause, if it does, append to the list of results, take the following row...". You simply specify the criteria for the results and that's it.

But that way of querying with SQL that it's inside of almost every developer's brain, involves a new way of thinking about problems for things that are not database queries. And, believe me, it takes time to learn. To the point that today, a couple of months later, and halfway a course devoted to it, I keep writing imperative instead of Functional code.

One could ask "if it is that complicated, why bother?". Multithreading is tricky, but CPUs have stopped increasing speed and they are increasing number of cores, which implies concurrency. Functional programming promises to help in that process. And in fact, one the emerging libraries in the Java field, the akka library, comes from the Scala world. The famous lambda in Java 8 is functional programming.

Regarding the specific language (not the functional paradigm), I have mixed feelings. I find it brilliant sometimes. And others I see it weird. As an example, I love the tuple concept (the ability for a function to return a couple of values at the same time without defining a class for that). But I almost scream each time I have to refer to the first element of the tuple with an _1 (as opposed to the typical _0).

I remember loving Ruby and Rails almost in any line of code. Everything felt natural and although in retrospective there were weird things, my general feeling was that code flows. With Scala I'm just starting to feel productive. With Scala love appears, but it tends to be in "this is freaking awesome" moments from time to time. [OMG, love and code. I'm really a nerd, isn't it?]

Don't get me wrong. Once you get the hang of Scala, it is much much much better than Java. It has a strong typing system like java, but with type inference that allows to skip types in some declarations. It tends to be concise (sometimes to the extreme). In its origin, Scala allowed to generate code both for the JVM and .NET runtime environments. I suspect that's no longer the case and nobody develops in Scala using the .NET.

One thing I find mind blowing (for bad and for good) is implicits. Implicits allow a type to be considered as a different one, upgrading the type to a different one. That is very powerful because the implicit mechanism relies in transforming functions (instead of inheritance or casting). Believe me when I say it is brilliant. But sometimes it leaves you scratching your head thinking why your code does not work until you remember to import the proper implicit conversion function.

The editor would need a post on its own. There is an Eclipse version for Scala. But until last Monday, I wasn't able to do automatic indentation without risking to mangle my code. Refactoring is for brave. And I'm living in nightly updates for Scala-IDE. I've been told that IntelliJ is much better, but I'm trying to avoid it.

Finally, learning a new language is not only the language itself, but a whole array of technologies around. OK. You learn Scala, and then you need to learn a web framework. Play would be the equivalent to the latest versions of Spring MVC or even Rails. But I'm in a love-hate relationship with lift (which I find absolutely different to anything else except for Meteor).  And you also need an ORM. The typical one would be hibernate in the Java world or ActiveRecord for ruby. Slick is not the more used, but it is really promising.

And that's it.

I'm REALLY happy of being able to learn Scala. And I think it has transformed my programming habits for years to come (and it will do more if I leave behind the beginner level).

To the point that I read val instead of let.

I'm not entirely sure I would use Scala for all kind of projects. But certainly I would do for backend mission-critical code.

Thursday, March 13, 2014

Optimizing

A few days ago I went to a meeting and we were discussing (among lots of different topics) various optimizing mechanisms for a web application.

After the meeting had ended, I came to the conclusion that, implicit in all the conversation, I was not fully aware of the most obvious step previous to any optimization:

Measure

You cannot optimize if you don't know what do you need to optimize. Is it a database problem? A web problem?

The guy interviewing had tried to push me further.  What to measure? Memory, CPU and request time I vaguely remember replying. What tools to use? At that point I probably screwed up the meeting, but that worth a post on its own.

I was thinking along these terms while preparing for a different interview. And I suddenly realized that "what to measure" is also important and the answer I provided can be valid but is not the only one. Yes, I knew it from courses. But now I've learnt it.

Good thing about selection processes is that you learn a lot from the processes themselves.

Wednesday, March 12, 2014

Tipping point

I'm happy. 

I was developing a feature that allows to export from my showcase project Whendoigo to TripIt

I was using a gem from TripIt. A gem is kind of a library for Ruby (sort of jar for Java). The gem simply encapsulated the API from TripIt. But it was failing and apparently everything on my project was correct. So this time it didn't took me too long to start debugging the actual gem's code.

The exception had traces with ActiveRecord references. ActiveRecord is an ORM, (think Hibernate or iBatis for Java). It's part of Rails. And the gem shouldn't have any dealing with ActiveRecord

The code that was failing was a bit difficult to understand. It uses one of the more powerful features in Ruby called meta-programming, but not with the more typical ways. Trying to put into words, it was creating a class with a dynamic name on the fly, and then instantiating an object of that class. 

What happens when the name it is trying to use is already being used in a different part of the application? To avoid that issue, the gem was creating the names with a namespace. 

And that should have been all.

But it wasn't. Lots of debugging and some restructuring later I found the problem. 

The names were being cached and when asking for the names it was asking for the names with the namespace... or without it. 

Two lines of code. A pull request. It took me a while. 

Not many people would appreciate the reason. 

But I'm really happy.


Thursday, February 27, 2014

I was sure it was my fault...

... but it wasn't.

In the last week or so, I've been hitting against a wall because of two different bugs. I was sure that both bugs were my fault. It took me ages (of a scarce spare time) trying different things, searching for similar problems, until in both cases I finally came to an issue in different tools. As I haven't found too much information, I've decided to put it in writing.


  • First, trying to use Boostrap (a framework for presentation: sort of a CSS template), and using the grid system (a way to organize things in columns, rows and cells), I wasn't able to get things in the same row and they appeared stacked. The issue turned out to be I was using an old Bootstrap version (3.0.0rc1). Upgrading to a newer version (3.1.1) solved the problem
  • Second, again using Bootstrap and its icons (glyphs as they call it), I couldn't help but notice that the icons didn't load properly until the mouse was over the icon (hover). The usual answer on the internet for not loading icons in Bootstrap is "check the class" (it doesn't help that class name for glyphs have changed from Bootstrap 2 to Bootstrap 3). The second most typical answer is related to Firefox (I was using Chrome). Finally I managed to remember that the icons in Bootstrap 3 are fonts. Which led me to know there is a nasty bug hitting Chrome stable with the following title "External Font not rendering until forced repaint". Ouch.


By the way. "It must be my fault" is much better than "it's not my fault". But biases are not good, whether one way or another.

Tuesday, January 21, 2014

Multithreading: Warning lights

A few days ago I went to an interview which included a pair programming session. The session was a great experience, but the result wasn't quite as good as it should have been, because of some difficulties understanding on what was being asked. It didn't help it was my first experience working with a Mac.

At one point we agreed on creating a new constructor so that we could pass a service in the constructor instead of getting directly in the method under test.

So I had something like (fictitious code)

  class GreatObject {
    public void calculateAndAddAmount(int length,
          boolean cheapService) {
      int cost;
      if (cheapService) {
        cost=length*3;
      } else {
        cost=length*8;
      }
   
      Service supaService= MegaFactory.getService();
   
      supaService.addCost(cost);
    }
  }

and we had agreed on doing something like

  class GreatObject {
    private Service supaService;
    public GreatObject () {
      this.supaService= MegaFactory.getService();
    }
    public GreatObject (Service supaService) {
      this.supaService=supaService;
    }
   
    public void calculateAndAddAmount(int length,
          boolean cheapService) {
      int cost;
      if (cheapService) {
        cost=length*3;
      } else {
        cost=length*8;
      }
   
      supaService.addCost(cost);
    }
  }

When I was going to do it, something in the back of my mind started to blink. It was a bit subtle and it took me a while to be able to express it. So as an exercise for the future, I'm going to try and express it in writing.

The problem with the change is that we have transformed a local variable into an instance variable. Local variables are local to the thread. Instance variables are shared between threads. So until now we had a thread safe class, but now the class is not thread safe. As an example: What if each instance of the service can only be invoked once and we have two threads running?

I was asked to tell what to do to be protected. I replied I didn't know. The typical answer involves the reserved word synchronized. But as I've told in the past, that is not usually a good answer and almost never the best answer.

Sunday, January 12, 2014

It's great when your idea is a good one. But...

Since I came to London, more than a year ago, I've been travelling a lot back to Spain. I used to schedule trips in advance, and once I discovered I had two different reserves for the same trip (fortunately I was able to change one of them). Soon I realized I needed some tool to manage the trips.

I did a quick search and I couldn't find anything.

Then my wife and daughters finally came here. And I had even more trips to schedule. We needed to plan well in advance, because trips where more than three times more expensive (when travelling with children I cannot afford to wait queues hoping to get a good seat nor fly to a distant airport to save some pounds). Also, people in Spain started to come and visit us, and we also needed to plan that.

So I had my own itch to scratch, which is the better way to commit to something. 

But my own requirements could be expanded to accommodate similar requirements from businesses. And businesses pay. I had a business plan. Not for the next social network, but for a small web application. I also wanted to practice Rails. 

So I started to build it. In my own free time. I built a quick and dirty prototype. And I started to build something more serious

Today I discovered that there is indeed something similar. A quick sign up told me most of the things I envisioned (including emailing confirmations to ease the pain in managing trip status) are already there. 

And it is made by one of the big grands in expense and travel management.

Three lessons learned:
  • Do a proper research.
  • Commit. Commit. Commit.
  • It's great when your idea is a good one. You're no longer a freak who prefers the cloud to a notebook.
And yes. I have other ideas. But ideas are just a multiplier. The question is if I'll be able to commit.

Monday, October 1, 2012

Crash course on Spring MVC, transactions and persistence (I)

A couple of weeks ago I was asked to do an assignment for a selection process. The task was trivial for expected 2-3 hours, and mentioned that the final project would end as a Web Application based on Spring and Hibernate. So I decided to do it as a full application. I didn't want to copy code from work as a template, but I wanted to do it as a fresh project.

If you are busy, go for the code here. But for those moving from JEE to Spring and wanting a more in-depth explanation, here comes the long (as in two LOOOOOOOOONG posts) detail.

One of the main difficulties was managing the transactions. In particular I had lots of problems with transactions not being persisted, errors like "No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here", and NonUniqueObjectException. I wanted to develop with @Transactional. Despite reading the documentation and lots of posts out there, I wasn't able to find explicit end to end functional code that helped me solve my own problems.

Finally I managed to understand what was going on. And I've decided to write my personal crash course on Spring MVC, transactions and persistence. If you arrived here out of the blue, comments are very much appreciated.


Project creation

OK. So you want a Spring Web application. Then first thing you should do is create a new web project. There are several alternatives for doing this. In Eclipse the two more obvious are 1.-you can create a Dynamic Web Project, or 2.-create a Maven Project. If you choose the former, you'll have to download and add lots of libraries to the Java Build Path, but you'll have a better understanding about the code. I started from a Maven Web Project. I think I chose a Maven Archetype from codehaus for spring and jboss but I don't really remember because later I tuned it.
Anyway here comes a list of dependencies I have in my project. Some of them come from the maven archetype I chose, so maybe not all are needed:
  • org.springframework.spring-asm
  • org.springframework.spring-aop
  • org.springframework.spring-expression
  • org.springframework.spring-beans
  • org.springframework.spring-context
  • org.springframework.spring-context-support
  • org.springframework.spring-tx
  • org.springframework.spring-core
  • org.springframework.spring-jdbc
  • org.springframework.spring-web
  • org.springframework.spring-orm
  • org.springframework.spring-webmvc
  • aopalliance.aopalliance
  • taglibs.standard
  • commons-logging.commons-logging
  • log4j.log4j
  • org.springframework.spring-asm
  • org.springframework.spring-aop
  • org.springframework.spring-expression
  • org.springframework.spring-beans
  • org.springframework.spring-context
  • org.springframework.spring-context-support
  • org.springframework.spring-tx
  • org.springframework.spring-core
  • org.springframework.spring-jdbc
  • org.springframework.spring-web
  • org.springframework.spring-orm
  • org.springframework.spring-webmvc
  • aopalliance.aopalliance
  • taglibs.standard
  • commons-logging.commons-logging
  • com.h2database.h2
  • junit.junit
  • org.springframework.spring-hibernate3
  • org.hibernate.javax.persistence.hibernate-jpa-2.0-api
  • commons-dbcp.commons-dbcp
  • commons-pool.commons-pool
  • org.hibernate.hibernate-annotations
  • jstl.jstl
  • org.springframework.spring-test
  • javax.transaction.jta


The web.xml

As you well know, the file web.xml is essential for every web application as it maps URL patterns to Servlets, among many other things. This is my web.xml file


Things to note. Starting at the end of the file I declare a mapping between one servlet called "Spring MVC Servlet". The servlet, defined in lines 11-17, is of type org.springframework.web.servlet.DispatcherServlet and it takes one parameter named contextConfigLocation. That parameter points to a spring context file named spring-mvc-context.xml (we'll talk about it later).
One point interesting to note is that Spring Web application tend to have two spring-context file. One context-file is related to web (e.g. controllers) and is loaded from the servlet. This is spring-mvc-context.xml.
The other is loaded from a listener. A (servlet) listener acts on container events. In this case we load a  listener called ContextLoaderListener (line 9). This listener is in charge of loading the other Spring context. It takes it route from a parameter called contextConfigLocation (lines 5-6).
Warning. You have two context-files BUT ONLY ONE CONTEXT. The so called "web context" and "root context" are both part of the same context. You define servlet related things in the "web context" and the rest in the "root context". The web (servlet) context inherits form the "root" context.
So two contextConfigLocation. One for the listener, points in this case to spring-business-context.xml. The other for the servlet, points in this case to spring-mvc-context.xml.
What else? From lines 19-30 we load a filter. A filter, as you well know, is an artifact that sits in between the web and servlet and does something. In this case it is going to do something about transactions, but we'll talk about it later.


The web-scoped context: spring-mvc-context.xml

My web context in this case is quite short:

As you can see there are 3 main groups:

  1. context:component-scan looks at the specified package for annotations to fill.
  2. mvc:annotation-driven fills some magic relating validation, json and so on.
  3. InternalResourceViewResolver is a pretty standard way to point to where the JSP reside and the way they are named.
Nothing very fancy, you see.


The root context: spring-business-context.xml, part I

Ahh. This is quite longer than the web context. Let's see.

Here you are. In this post the easy part. Next post database, transactions and so on.

First, again, (line 13) a component-scan for annotations in business objects. Beware. If you scan the same package/class in the root context and in the web context, you are screwed and will get some nasty errors.

Second. Line 15. We are going to look for a file called spring.properties (anywhere in the classpath) and we are going to load it. It will help us to separate specific properties from the configuration.

Third. Two bean definitions. Lines 51-56 for one bean, and lines 66-67 for other. The first one needs some properties we just loaded on line 15. The second bean I'm not absolutely sure I need. I think it needs to be here because I have two different beans that could match (one in src and one in test), and here I wanted to load one of them.

That's it. The rest is persistence and transaction related. We'll leave it to the following post.



Monday, September 24, 2012

OptionalDataException while reading JMS message

We've been dealing with another bug in JMS code. The symptom was blocked queues and the following exception:

javax.jms.JMSException: getObject
          [...] 
Caused by: java.io.OptionalDataException
      at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1325)
      at java.io.ObjectInputStream.readObject(ObjectInputStream.java:348)
      at java.util.HashMap.readObject(HashMap.java:1066)

In trying to reproduce people in the team introduced a non-serializable object, but he got an exception at sending the message (Caused by: javax.jms.JMSException: setObject [...] java.io.NotSerializableException). In a similar way, trying to send an int, he got a NotSerializableException. And trying to send some class and then changing the serialVersionUID, he got an error at receiving, but a different error (java.io.InvalidClassException).

Everything in Internet pointed to a thread-unsafe error, so we looked at the code and found this


        mensaje = receptorMensaje.receive(timeOut*1000);
        [...]
        mensaje.acknowledge();


with several lines of code between the receive and the acknowledge, and without synchronization

Under very heavy load, it was easy to have a thread execute the receive, a different thread execute the receive and then the first thread acknowledge. But by then both threads have the same object and if the first thread changed its copy, the Exception would be triggered.

We extract a method this code and synchronized.

Saturday, September 22, 2012

Weird IE9 bug

This last two weeks I have dealt with a weird bug in IE9.

  • The problem appeared in a legacy web application. 
  • The issue reported by the user was a combo that didn't drop down. 
  • The problem appeared in different pages, but only for some combination of values.
  • The issue appeared after installing IE9 from IE7 in a Windows Vista. 
  • The user could reproduce the issue (for a certain combination of values).
  • We (both devs and ops) couldn't reproduce in a standard machine even tough at work final users deal with a very standard machine (machine setups are pretty standarized at work). 
  • When we finally were able to reproduce in a standard machine, it only failed the first time a user logged in (second time, or even IE close rendered the bug irreproducible).
  • We finally were able to pinpoint the problem to a very large option (as in 400 characters).
  • And now I've been able to reproduce it with a reduced version of the page even in my setup (Vista64+IE9). See the gist. Save to a file, launch it with IE9 and try to change the option.

We trimmed down to 200 chars (I guess even 150 chars wouldn't be viewable).

UPDATE (2012-09-30): Tested on IE10 in Windows8 and seems to work fine.

Friday, September 14, 2012

My first Chrome extension(II)

In last post I wrote why. In this post I want to explain how I wrote my first chrome extension.

First. The Chrome Extensions developer's documentation is quite good.

Second. A chrome extension is a zip of a folder with an crx extension instead. The folder has to have a particular file called manifest.json. It tells the extension name and the permissions asked. It also points to the main file. Pretty standard in my case.

The main file, in my case was called background.js. You should read the documentation to know more about background pages and so on.

In my case, I attach an event listener to the click of the extension button (browserAction.onclick). The listener gets the url of the current tab, process that url, encode it, get a Google url redirection from it, and ask for it.

chrome.browserAction.onClicked.addListener(function(tab) {
  var currentTab=tab.url;
  var processedURL=processURL(currentTab);
  var encodedURL=encodeURIComponent(processedURL);
  var newUrl="http://www.google.es/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&sqi=2&url="+encodedURL;
  chrome.tabs.update(tab.id, {url:newUrl});

});


The processing of the URL do a bit of tweaking for some specific servers. Pretty uninteresting.

My first Chrome extension(I)

This afternoon I was preparing an interview I expect to have next week, and came to an interesting page with information about job selection process and companies inside information. However, after surfing a bit, the inevitable, "become a registered member" started to bug me.

And I got tired.

And I remembered FT similar "become a registered" and WSJ "first-paragraph-only". Lots of sites show you the page when you come from Google, but ask you to register if you start to surf (or just come from a different page). Completely understandable, but not very pleasant.

So I asked myself if it would be too complicated to build an extension for Google Chrome, that when you are at a page and asks to register, you ask google to get redirected to that page. It seems it's not. I started poking at 19:00 (local development folder creation time was 19:07) and ended building it at 20:30 (icon included). It's pretty basic, but it makes a bit of tweaking with FT and WSJ URLs because just coming from Google was not enough. And now it works, with glassdoor, FT, and WSJ.

Great. I learnt and I have something interesting to show.

In the future.

Maybe showing I'm willing to "hack" a paywall is not something I should be publishing when interviewing for a financial information company. Or maybe yes. Anyway: this is me.

Next post. How I did it.

Monday, September 10, 2012

Tuesday, September 4, 2012

Calisthenics

I didn't know about object calisthenics. They are a set of rules to help develop better:

1. One level of indentation per method
2. Don’t use the ELSE keyword 
3. Wrap all primitives and Strings4. First class collections
5. One dot per line
6. Don’t abbreviate
7. Keep all entities small
8. No classes with more than two instance variables
9. No getters/setters/properties
Some of them are a must, with some others I have some doubts. But the point 2 is so intriguing I have to test it.

Sunday, August 26, 2012

Little robot (IV): Ruby version

Besides the console faking and the dependency inversion issue, my code in Ruby was pretty rough. You can see here the version I sent.

One obvious problem is the use of string instead of symbols. It was a bad bad mistake. So big if I had been the person testing, I would have thought very bad of myself.

Anyway it was clear that Java version was considerably more verbose.

So one obvious improvement is using symbols instead of string. But during the interview, I asked what other improvements people have done on the assignment. One tip I received is the use of Array.rotate. I don't like that improvement, because it makes the code less understandable. But I didn't like the verbosity of the case, and I tested a different approach. This is the code I left in the end:

class Robot
  VALID_X = 0..4
  VALID_Y = 0..4
  VALID_F = [:NORTH,:SOUTH,:EAST,:WEST]
  TURN_RIGHT = {:SOUTH=>:WEST,:NORTH=>:EAST,:EAST=>:SOUTH,:WEST=>:NORTH}
  TURN_LEFT = {:SOUTH=>:EAST,:NORTH=>:WEST,:EAST=>:NORTH,:WEST=>:SOUTH}
  MOVE = {:SOUTH=>[0,-1],:NORTH=>[0,1],:EAST=>[1,0],:WEST=>[-1,0]}

  def initialize
    @accepting=false
  end

  def place(cols,rows,facing)
    x=cols.to_i
    y=rows.to_i
    f=facing.to_sym
    if is_valid?(x,y,f)
      @x=x
      @y=y
      @f=f
      @accepting=true
    end
  end

  def left
      return unless @accepting
      @f=TURN_LEFT[@f]
  end

  def right
      return unless @accepting
      @f=TURN_RIGHT[@f]
  end

  def move
      return unless @accepting
      delta=MOVE[@f]
      x = @x + delta[0]
      y = @y + delta[1]
      if is_valid?(x,y)
        @x=x
        @y=y
      end
  end

  def report
    return nil unless @accepting
    "#{@x.to_s},#{@y.to_s},#{@f}"
  end

protected
  def is_valid?(x,y,f=@f)
      VALID_X.include?(x) && VALID_Y.include?(y) && VALID_F.include?(f)
  end
end

Saturday, August 25, 2012

Little robot (III): Dependency inversion

As I wrote some posts ago, I received an assignment, and I decided to do both in Java and in Ruby. When doing in Ruby I wanted to make sure I was able to test the UI, and not only the engine. For doing that, I chose to fake the console interaction (both stdin and stdout). I didn't consider dependy inversion.

Sometimes a higher level class A has to invoke methods in a lower level class. Let's say this lower level class tends to be class B. Typical approach (non DI) is to make class A depend on class B. Dependency inversion is to make class B implement some contract associated with class A (the dependency is inverted).

I think I'm still in the process of converting from Java(where DI and interfaces is compulsory) to Ruby. With Ruby is much easier to fake classes B and don't even think about inversion while developing class A.  Maybe I should have done my class more testable. But I didn't realize it until in a different selection process I was asked when to use Dependency Inversion in Ruby.

Thursday, August 23, 2012

Rails in Ubuntu

I'm planning to make a newbie post about rvm, bundler and the rest. But just in case you're starting with ubuntu, here comes a piece of advice.

There is some controversy about editor to use for ruby. Some people prefer Vim+tmux, which seems the more standard. Other people prefer TextMate on MacOSX and Redcar on Ubuntu. I must say that I prefer vi to emacs, but for the time being I prefer Redcar to vim. In the future this may change, but not at the moment. Anyway, one of typical topics when migrating from Linux Mint is "how the h*ll do I anchor an application to the Unity bar?". Well, in the case of Redcar, here is the answer.

Side question: "Why the h*ll are you leaving Linux Mint?"

Anyway, back to more interesting topics. If you are a Rails developer, you should be using RVM. How do you use RVM in Ubuntu. Two tips:

First. Forget about apt-get install rvm, and if you are reading this too late, go here.
Second. If you are using gnome terminal, read this.


Monday, August 20, 2012

Faking the console in Ruby

A few days ago, I was preparing an assignment for a job process both in Java and in Ruby. While doing in Java, I decided to test the engine. But in Ruby I wanted to test the whole application, including the communication via standard input/output on the console.

And how do you mock standard input/output in Ruby?. Well. It turns out it is quite easy to do it with Rspec. But I wanted to do it without any additional requirement. How do you mock STDIN and STDOUT in plain Ruby.

It turns out it isn't difficult. Based on this gist, I prepared my own solution. First the input faker:
class InputFaker
  def feedStrings(strings)
    @strings = strings
  end
  def gets
    next_string = @strings.shift
    next_string #TODO: I guess next_string is superflous
  end
end
Second the output faker
class OutputFaker
  def initialize
    @result=[]
  end
  def write(str)
    @result << str.chomp
  end
  def clear
    @result=[]
  end
  def result
    @result.join
  end
end
Third, setup and teardown methods
  def setup
    $stdin = InputFaker.new
    $stdout = OutputFaker.new
    @robotUI=RobotUI.new unless @robotUI
  end
  def teardown
    $stdin = STDIN
    $stdout = STDOUT
  end
And fourth, the actual use (in this case a test)

  def actual_test(array_of_inputs,expected_output)
   $stdin.feedStrings(array_of_inputs)
    array_of_inputs.size.times{@robotUI.parse()}
    assert_equal(expected_output,$stdout.result)
  end