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

Sunday, August 19, 2012

Little robot (II): Java version

As I wrote in a previous post, I was asked to design a software managing a robot inside a board of 5x5 cells. The typical commands were

PLACE X,Y,F ->Places the robot in the x,y position facing F
MOVE ->Move the robot 1 cell in the facing direction
LEFT ->Changes the facing counter-clockwise
RIGHT ->Changes the facing clockwise
REPORT ->Shows the current position and facing

and the main requirement was that the robot didn't fall outside the board. The assignment allowed to read commands from the console (standard input/output) or from a file. You can read the assignment here, but that's not my code.

Initially I didn't want to focus on the input/output, so I decided to test only the engine. Without writing a line of functional code, I developed a JUnit test class just from translating the requirements into code. It wasn't pure TDD, because there weren't tests for individual methods. But it gave me the security net I needed to play a bit with the design.

It was obvious for me that the there was going to be a class between the user and the engine, mediating input and output. For me that class was the UI of the engine. I could think of a console UI, a file UI, or even a graphical UI. The implementation I decided was a console UI (read from standard input and standard output), but I decided not to make tests for that class. Probably I should have done the tests, and I don't love the code in the method parseLine().

Following that, I focused on the engine class. Should the engine class have everything in it? Should it manage variables independently? I did different implementations, refactoring the code, peaceful, knowing my tests were saving the bacon. In the end I decided to manage whole objects with the whole status (both position x,y and facing f). That way I was thread safe: either the new position is good, (and it becomes the current position), or bad (and I kept the previous). I played a lot with the names of these entities, not deciding between Status, and Position. I didn't love either of them, but chose Position. I also played a lot with the facing. Should I use constants in Position class, or an enum? I thought about creating a service implementing the commands, doing it in the Robot engine, in the position, or in the enum?

The bad thing about an assignment like this is that you have too many options. The code in Java wasn't perfect, but I guess it was good enough.


Friday, August 17, 2012

Little robot (I)

While applying to a position a few days ago, I received an assignment trying to test my coding style.

IMO, assignments are quite a good way to get a peek on the coding style of someone. They are easy programming tasks that show if somebody is able to code (it seems many of us can't), and what's his/her style.

Another similar tool would be online testing web applications such as codility. My opinion of codility is mixed. I think it's a good way to test, but some of the assignments are already on the Internet, and doing a bit of research you can find some of them. Besides, focusing on a fixed time frame (one hour), it's more prone to errors on the assignee.

Anyway, no method is perfect, and I've discovered the assignment I was given was already solved on the Internet. For the record, with due respect, I think googled solution is overkill. But you can see there the specific assignment.

When I received the test, first thing I thought was about the programming language. I was allowed to code in any language, but the position I had applied was Ruby based. I was more comfortable doing it in Java, but wanted to do it in Ruby. What if I wasn't able to do it right in Ruby? Better to do it right first, and then to try to show the point I am at in Ruby.

So I did it both in Java and in Ruby.




Wednesday, August 15, 2012

Savon.rb and sequences

As I wrote in my last post, I've recently learned it is important to be able to show what you've been doing. So I'm trying to increase the posts on a number of small problems I find in my daily job, and in my hobby projects. This one appeared in my daily job.

I was developing a small interface between two applications via a SOAP web service. Actually, we are using Redmine for development, and Remedy for the whole organization, and we didn't want to fill the information twice.

I was using Savon.rb for creating a client in Redmine that would invoke a SOAP web service in Remedy. The code was something like this:

          response=client.request "Resolver" do
            soap.header={:AuthenticationInfo=>{
                 :userName=>ws_user,
                 :password=>ws_pwd,
            }
            soap.body = {
                "Status"=>"Resolved",
                "Resolution"=> message ,
                "Status_Reason"=>"Client Action Required",
                "Incident_Number"=>code,
                "Status_Reason2"=>"Client Action Required",
                "AssigneeLoginID"=>user,
            }
          end


However, I was getting a SOAP error

ARERR [8962] Unexpected element encountered in the input XML document

The problem lies in Ruby hashes not preserving the order and Savon sending XML sequences in incorrect order. I just updated the call to something like this

          response=client.request "Resolver" do
            soap.header={:AuthenticationInfo=>{
                 :userName=>ws_user,
                 :password=>ws_pwd,
                 :order! => [:userName, :password]}             }
            soap.body = {
                "Status"=>"Resolved",
                "Resolution"=>message,
                "Status_Reason"=>"Client Action Required",
                "Incident_Number"=>code,
                "Status_Reason2"=>"Client Action Required",
                "AssigneeLoginID"=>user,
                :order! => ["Status", "Resolution", "Status_Reason","Incident_Number", "Status_Reason2", "AssigneeLoginID"]             }
          end


and it solved the issue. I expected Savon to take care of this, but anyway, I understand this is solved in Ruby 1.9x.

Tuesday, August 14, 2012

A great experience applying to a position (II)

In my previous post I explained a great experience applying for a position. In this post I wanted to share what lessons I've learnt from that experience.

  1. Selection: Be very selective about what you apply for. For me this means no recruiters, making a pre-research of the company, and reading carefully the description to get a sense of what the company is asking. It's pretty obvious, but essential for the following lesson.
  2. Visa: When applying for a foreign country, make some research about Visa requirements. For example, unless you are a guru, don't apply to an US listing. It's quite difficult to get an sponsorship for the US, but no so for Australia. Are you an European citizen? Doors open in Europe. And so on.
  3. Target: Carefully target the ad and the company with the cover letter. In my experience this is more important than the CV. CVs doesn't work. I'm in the process of completing a 35 pages CV (no kidding) and I can tell you it won't describe me. 
  4. Try to target the cover letter but be honest and open. There was a great post on 3degrees blog, unfortunately deleted. See this cache copy.
  5. Test, code, refactor: Yes, you know about TDD and BDD. In fact you are expected to send the tests along with the code. But at least in my previous assignments, I had tested, then coded, but I had forgot to refactor to get a nice design. And I had sent code not adequately designed. This time, I set a good set of tests, then hacked something quick, then refactored lots of times.
  6. Research: For the interview do a great research. Be prepared. Who would be your mates? Nasty comments about the company? Source code of the pages?. And if the interview seems in a loop, (not the case this time), be open but drive it to a point. 
  7. Build a presence online. Most asked request: show us your code. Yes, I have a github account (actually two). And I also have a blog (this one ;D) But at work I don't have the time to build the presence. And doing it at home is quite difficult. But it's essential
I think fifth and sixth really made a difference, but I'm really starting to learn how to apply to a position.And I'm trying to complete the seventh point. This blog posts are part of that effort.


Monday, August 13, 2012

A great experience applying to a position (I)

I wrote in my last post about lessons I've got from bad experiences looking for a job. In this post I'm going to tell you about a good experience I had last week, how much I learnt from it, and the lessons I got from it. Make no mistakes: I didn't get offered the position in the end.

For me, the outcome is not the most important thing in such a process, but the feeling you're not losing your time, and the lessons learned. In this post I'll try to point why I felt I wasn't losing my time, and in the following I'll post the lessons learned. Experiences

  1. The job listing was in a specialized place for software job listings, but the tone of the listing was not a yet-another-ad-looking-for-a-guru. I think there is some kind of kind of wrong game between companies and candidates. Companies asks for lots of things from candidates. From my recruiting experience (yes I've been on the other side too) candidates usually fall in three categories: candidates good at everything asked, candidates that consider themselves an expert in a topic for an article they read about the topic, and candidates that try to tell beforehand why they think they match the position. My impression is that the first group does not apply and companies tend to ask for an interview to people on the second group. However this company was asking for people "good enough". It was something like "hey, we are looking for good programmers. But mere mortals. If you can think you can match, please apply". They made a funny listing with what they were looking for, they got a lot of attention and they were proud of their listing, not giving a damn for the comments. Good for the listing.
  2. I applied a Wednesday, I had a first reply on Thursday, and we wrote each one back an forth (despite 8 hours and 17200 km of distance) several times until Friday. On Friday I got a basic assignment. I sent it back on Sunday, and on Monday morning (his Monday afternoon) he had revised the assignment and was planning an interview on Skype. We did the interview on Thursday, and on Friday we wrote me back telling me I wasn't going to be offered the job. Yes, 10 days total.
  3. Regarding the mails previous to the assignment, he made interesting questions. In retrospect, there were wonderful questions to know if somebody is what it seems, but from reading them at the beginning, they seemed pretty innocent. Good for the previous
  4. With respect the assignment, I did both in Java (for now I feel more comfortable), and in Ruby (the main language of the position). He evaluated both, and even if Ruby's one was not good (in retrospect I would say clearly wrong), he was interested in talking with me. Both he (CEO of the startup) and the developers' manager. So the assignment was part of the process, but not the whole process. I had told him I wasn't perfect rubyist, so he only wanted to know if I was a good developer (and it seemed my Java was good enough), and my level of Ruby.
  5. On the interview we were talking about lots of topics for an hour. Despite my sometimes rough spoken English, they were very patient, and they didn't seemed bored or in run to cut the interview. I had done a research of the company, but they point it and were grateful.
  6. And the following day I got an email telling me I was no longer in the process. I think this was the part less clear for me because the rejection seems to point to a "there were better candidates", but there were something in the tone (like a polite "contact us if your circumstances change")  that could point to "you seem good but you need to learn Ruby better". I know enough from girls rejections that "I like you as a friend" is not what it sounds but it is what everybody knows. :D 
Anyway, overall I got a really nice experience, I felt valued, and I learnt a lot. Lessons in the following post.

Sunday, August 12, 2012

Bad experiences

For some time I've been applying to different positions. I have two daughters and I want for them (and for me) to live in a different culture and language. After a few experiences, I'm tempted to say something about bad experiences:
  1. Forget about recruiters. They have different alignments than yours. In my experience (it could be biased), 90% of them are just form fillers. They ask you things (CV, tests, questions), in order to fill a form in a random web site. When they send you the position, look for the most weird sentence, and put it on Google. You'll probably get the company hit, because they don't bother to change it (sometimes I've been tempted to apply directly). Usually they don't know about the IT bussiness (I've been offered Javascript position because my CV had lots of Java in it). And for me, the more important problem with recruiters is that they won't ever (EVER), contact back for a position. They can ask again new things for a new position but they won't tell you anything about the previous one. So recruiters are a lot of effort but with very low response.
  2. Forget about public/international employment unless there is a competitive examination. Here my personal sample is smaller (just two cases). But from what I've heard, it's quite representative and unbiased. Usually behind a public offer there's some procedure forcing to publish a public profile to hire somebody already known. In my personal experience(an embassy on 2008 and an EU position in 2011) it was like this.
I'm still in contact with a recruiter because I have some type of personal commitment with him. But this is what I've learned and I share just in case it's useful. However, I have good experiences to tell you about. You'll have to wait next post for it.