Friday, July 22, 2011

Stop hating Java

I noticed that in the Ruby community “Java” is a synonym of pure evilness. It’s often used as an argument against some techniques.

“It’s Java all the way”


“If you drop static methods, then welcome to Java and its billions of useless factories.”


“Your mention of ‘factories’ gives me nightmares about Java-style over/premature abstraction where you need to interact with (and therefore understand) WAY too many different classes to get anything done.”

Those are some quotes that come from only one discussion triggered by Nick, me and Michal only because our ideas sounded a bit Java-like.

History

Part of the Java-hate comes from the historical reasons. When Rails appeared lots of Java people switched to it as it solved some of the problems with Java. I was one of them.

Rails was simpler than the existing Java frameworks. It let us solve most of the problems much faster than with Java. Ruby as a language was and still is a big advantage. Its syntax is more concise. Even though I still prefer Rails than Java based frameworks I don’t get why so many Rails people simply hate Java.

Java and XML

I always disliked the XML impact on the Java frameworks. It didn’t come from nowhere, though, let’s be fair. Java as a languages is not as readable as Ruby, so it wasn’t perfect for configuration. Yaml wasn’t popular and JSON was still not really mature back in 2000. Something had to be chosen and that was XML. What would you do better back then?

It doesn’t mean that whenever some Java-like idea is presented then somehow you have to be scared that you’d have to use XML again. Let’s try not to be biased and look at Java ideas without the XML bias.

Java and over-abstraction

Yes, often Java frameworks were very abstract and overgeneralized. Again, it was a result of Java lack of dynamic features. Whenever you needed a pluggable system in your code you had to abstract away some concepts in order to make it work. Ruby lets us do it much easier and that’s cool.

Java and good things

There is lots of good things that came from Java to the Rails world. Most of the TDD/BDD stuff comes from Java. Refactoring came to us from Java [UPDATE: What I mean is that those techniques came to the Rails world *through* the Java world, they're not originally from Java]. They became popular in the Rails world. That’s cool. There are other techniques that are great, but somehow didn’t get so popular:

Dependency Injection and Inversion of Control

These two techniques are great for many reasons. They suggest that you should expose your dependencies in the constructor or through setters. It reduces the usage of globals and static methods and simplifies testing. In my opinion they result in much better object oriented design.

POJO - Plain Old Java Objects

This is one of the places where I felt I made a step back when entered Rails from Java. In Java there was a clear trend that your business classes should be clear from any framework dirtiness. Persistence was configured and injected from outside (or through annotations). When your business classes are not polluted with framework stuff it’s much easier to test them in isolation. In Rails there are many tries but no good solution on how to test models without a database.

Aspect Oriented Programming

I was involved in the AOP movement in my Java life. AOP was the tool that let you intercept method calls and run some crosscutting code from one place. If you needed logging of method calls and params, it was just 3 lines of code in an aspect and all of your method calls were traced. Similarly, it was possible to handle persistence with AOP. Another part of AOP was composing classes from smaller pieces. Fortunately, this part now appears in the Ruby world in form of the DCI architecture. The dynamic part (interception of methods) didn’t get very popular. We have some limited AOP with filters in Rails controllers and callbacks in Rails models, but we could go further and use it for persistence or for logging.

Let’s stop the hate

It’s cool that we, as a community, strongly identify with some techniques. What I’d love to see is more tolerance for other technologies.

There are smart things in the Java world but we have to be open to reuse what’s most cool and replace the bad parts with Ruby awesomeness. When someone starts his talk with “In Java this problem is solved by …” don’t laugh and interrupt with quotes like “OMG, XML and factories again”. It didn’t happen only to me. I have seen this behavior at Ruby conferences very often. It's childish.

Many good things came from the Java world - we should love them for that.


There are more large Java systems than Ruby ones. They abstract for reasons. They use IoC and DI for good reasons. AOP is awesome when used in a good way. Let's learn more from Java - it will help us once we work more with larger systems and codebases. They already learnt their lessons.

[Discussion on Hacker News: http://news.ycombinator.com/item?id=2793227 ]

If you read this far you should Follow andrzejkrzywda on Twitter and subscribe to my RSS. You can also buy me a beer at the wroc_love.rb conference. I'm one of the organizers.

Wednesday, July 20, 2011

Yes, Nick - class methods are evil

My friend Nick has just posted an interesting article about the usage of class methods. The article is really good, go read it first and then come back.

Are class methods evil?

In my opinion class methods are almost always a wrong approach to a problem. It’s not wrong as in “it doesn’t work” but wrong as “we can make it better”.

ActiveRecord and Rails

I blame the ActiveRecord pattern for the current class methods problem. Every Rails application I see is full of globals which are often results or causes of class methods. The problem with ActiveRecord is that it forces you to think in terms of sql tables. Almost every table exists as a class with lots of class methods that let you access the data from this table.

I mean methods like:
User.find(id)
User.all
etc.

Can we do better?

One of the things Nick suggested is using user_factory. Overall he’s right, but I don’t think user_factory is a good name for that. We’re not producing users in our app, right? The users live in the context of our app. Is it a shop or a game or maybe a portal? Then create a class for that. This is your “factory”. Once you have it, always access users through this object. Not only users, you can do the same with products, prizes etc.

Instead of User.find(4) you now have game.users.find(4) or better game.find_user(4). You still gain from the ActiveRecord methods, without using the class methods, though.

How to implement the app class?

There are two ways that I’m aware of. Both are not ideal, mostly due to the way ActiveRecord works, but in my opinion they improve the code quality.

1. Create an ActiveRecord model for that.

If your app is a game then create a model called Game with the associated table (games). Yes, it will possibly have only one record and yes it may add some overhead to the queries that are generated by the ActiveRecord framework. Thanks to that however you may have only one “singleton/global” in your app.

class Game
  has_many :users
  has_many :prizes
  ....
end
I usually put the implementation in the ApplicationController and have something like:

def game
  Game.find_by_name(“Music Challenge”)
end

Then, in every other controller I can access the game object and find all the data I need through its scope.

2. Non-ActiveRecord class

The other way assumes that you hide the globals in this class. It can be done in many different ways. One of them is:

class Shop

  def products
    Product.all
  end

  def find_product(id)
    Product.find(id)
  end
end
What’s my choice?

Overall, I prefer the first way. It has a nice side-effect that once you have the game/shop model you can easily turn your application from a single game to a platform of games (which we actually did in one project, but that's another story).

I also try hard to find the way out of the ActiveRecord and sql/nosql dependencies and go into a pure OOP direction with madeleine/prevayler-like tools.

What’s your choice? Do you see the problem with class methods?


If you read this far you should Follow andrzejkrzywda on Twitter and subscribe to my RSS

Friday, May 27, 2011

Madeleine with Rails

I've been recently researching a topic that I was lucky to use 10 years ago - prevalence. Back then I used it with Java. The system still works fine with Prevayler (the prevalence tool for Java).

Nowadays I use Ruby on Rails and whenever I deal with ActiveRecord (which overall is fine...) I miss the old days of Prevayler, where you can use pure objects.

Three years ago I did some initial research at the RailsCamp UK. You can some of the results at this presentation:
http://www.slideshare.net/andrzejkrzywda/madeleine-on-rails-presentation


The results were not positive, mainly due to the one process limitation of madeleine and because of the problems with integrating the madeleine object with the Rails ecosystem.

Now, 3 years later, a few things have improved. There are solid Rails servers which can run with threads (Thin) and Ruby 1.9 solves the threading problems that Ruby 1.8 has. Also, Rails now provides ActiveModel which makes integrating non-AR objects much easier.

I decided that it may be the time to try it again. First results are promising, I was able to rewrite a small part of my side project (search) with the madeleine approach and it seems to work fine (even with the AR objects coexisting in the same app).

I published the madeleine source code to Github (copied from RubyForge) and I applied some small changes to make it work with Ruby 1.9
https://github.com/andrzejkrzywda/madeleine

You can also read more about the prevalence concept at the Prevayler website, most of the things should apply to madeleine:
http://prevayler.org/

Below you will find "slides" from my talk at Poznan Ruby User Group which describe the approach. Let me know if this topic sounds interesting to you. Soon I'm going to post more about it along with some code examples.



Madeleine - Prevayler for Ruby

  • Objects in memory, no db
  • Science-fiction
  • It probably doesn't work, I don't know the reason yet.


Instiki

  • The first public Rails project used Madeleine.
  • DHH almost made it the default persistence for Rails (back in 2004)



Java with Prevayler, 2001 - 2011


  • Work Service - big recruitment agency in Poland
  • main system
  • ORM nightmare
  • 10 years ago and still running
  • Missing the good things...
  • No db.



Objects in memory

  • Snapshots every x minutes (serialization)
  • Changes are serialized



Happy scenario:

  • System works
  • Snapshot is taken when server is stopped
  • Server starts - objects are 
  • deserialized from the snapshot



Unhappy scenario

  • System works
  • Power goes down
  • Server starts - objects are deserialized 
  • from the last snapshot
  • Commands objecs are deserialized and applied
  • We have the system in the same state as before



What is good about it?

  • No ORM, sql, nosql
  • Pure objects
  • No queries - ask objects, methods
  • Very fast - everything in memory
  • Fast development.



What is bad about it?

  • No one uses it.
  • New way of thinking...
  • No data access outside of your application
  • unless you create an API


Single process with threads

  • (Thin)
  • ruby 1.9 only (thread-safe)
  • hard to scale



Lots of default Rails things won't work

  • gems (will_paginate) EDIT: will_paginate can work with arrays, so everything should be fine.
  • everything that depends 
  • on ActiveRecord won't work.
  • ActiveModel helps a lot 
  • (views, validations etc)



One process. Only one command at a time.

  • DateTime.now problem
  • Clock object provided



Migrations mean something different now

  • (pure Ruby code)
  • Refactoring - remember about snapshots.


Thanks for reading!

If you read this far you should Follow andrzejkrzywda on Twitter and subscribe to my RSS

Monday, May 16, 2011

Tracking bugs in external code

If you're using any external code (open source, closed source or external web service) then you probably had situations that the code had a bug and you had to find a workaround for this bug.

Usually this kind of workaround is ugly and results in a piece of code of bad quality.

Chances are that one day the author of the code will fix it. (Obviously you can help if it's an open-source library). It would be great to improve the ugly code when a new versions of the library fixes the bug.

When I was working with the Resolver team I have learnt a useful technique for tracking whether the bug was fixed and for improving the "bad code".

Let's imagine a simple example -  we use an external library called OpenSourceMath which (among other things that we use) provides:

OpenSourceMath::Calculator.complicated_stuff(x, y)

We then find out that this method doesn't work correctly for some arguments. It means we have to write some of our own logic in order to finish the task.

We do the following steps:

1. Write a unit test that exposes the bug, it fails

assert_equal 10, Calculator.complicated_stuff(5, 5)

2. Change the assertion so that the test passes only when the bug exists.

assert_not_equal 10, Calculator.complicated_stuff(5, 5)

3. Write a comment to this test explaining which part of the production code is a workaround for this bug.

assert_not_equal 10, Calculator.complicated_stuff(5, 5)
# fix the code in app/models/order.rb:50-55

(later)
4. Try out a new version of the library.
5. If the bug has been fixed the test should fail.
6. Read the comment.
7. Fix the production code so that it now uses the library without workarounds.
8. Change the "bug test" so that it now fails when the bug exists. (optionally remove the test)

This way it's quite easy to track the bug fixes in any external code and be able to remove the workarounds.

Thursday, May 12, 2011

Teaching Rails at University of Wrocław

Between October 2010 and February 2011 I had the pleasure to teach Ruby on Rails at the University of Wrocław (Poland).

The course was 30 hours of lectures and 30 hours of labs - 15 weeks, 4 hours every Wednesday. There were about 30 students. The University of Wrocław is known of its quality and when I met the students I wasn't disappointed.

My goal for this course was to prepare the students to working with Rails. The second goal was to teach them how it is to work on a Rails project within a team in a company. I also managed to sneak some agile techniques (testing, refactoring, continuous deployment) into the program.

Every exercise required the result as a repo on Github and as a working app at Heroku. Many thanks to Github for giving us free private repos! Thanks to Heroku just for being awesome for this kind of needs.

Here is the list of lessons and exercises:

Exercise 1

Hello world app on github and heroku.

Exercise 2

2-models UI (articles + comments), has_many

Exercise 3

validations, deleting, editing the article, partials, callbacks, belongs_to

Exercise 4

Authentication, devise, authlogic

Exercise 5

searching, pagination, model specs, controller specs

Exercise 6

integration tests, capybara, more rspecs

Exercise 7

Groups app, inviting, declining, memberships
Big project - first release

Exercise 8

e-commerce app
admin can add products, cart, order confirmation
Big project - second release

Exercise 9

jQuery with Rails

Exercise 10

Facebook application
Big project - third release

Exercise 11

Rails engine (with Rails 3.1)

Big project

As you see, additionally to the exercises I required a Big Project from each student. There were many interesting projects - e-commerce app, surveys app, a really nice app for teaching Japanese, a tool which supports work of a non-profit organization, radio website, tenis tournament website and many other cool apps.

The result


I'm really happy with the result of this course. It was a great feeling watching the final presentation of a cool app being shown by a person who wrote the first Ruby line of code at my course. The level was very high and I learnt a lot from these young people. Some of the students got quickly hired by Wroclaw companies after the end of the course so this goal was at least partially achieved.

Wrocław and Ruby


BTW, Wroclaw is really strong when it comes to Ruby. Apart from my company (Arkency) there are many other awesome teams. We have regular monthly meetups (DRUGs) with more and more people every time. Additionally to the meetups we organize monthly hackathons where we work together on gems like exceptioner and bbq (yep, the famous replacement for Cucumber).

Thanks

Firstly, thanks to dr Ewa Gurbiel who not only encouraged me to run this course but who is also responsible for me being interested in programming and software engineering.

The University of Wroclaw supported the course very professionally, we hade a big room available with all the equipment needed. Special thanks to the guest speakers: Jan Filipowski (talk about facebook apps), Robert Pankowecki (ActiveModel), Piotr Sarnecki (Rails engines).

Thanks to all the students for the hard work you put into the exercises and for a good time spent together!



I'm always very happy to teach Rails or speak about Rails related technologies. Contact me by email if you're interested.

Tuesday, April 26, 2011

Events in acceptance tests

I've been recently experimenting with the idea of events in the acceptance tests.

With the current approach based on Cucumber-like tools I see the following problems:


  • Short scenarios share the same state but they prepare the state every time.
  • Long scenarios are hard to follow
  • Fixtures/Factories are in use, which makes the tests dependent on the implementation
  • Slow builds


The idea is to solve some of the problems by using events.

As "events" I mean the following concept:


  • Split tests into base scenarios and side scenarios
  • Base scenarios can trigger certain events
  • Side scenarios can declare which events they're interested in
  • When the base scenario triggers an event all the side scenarios are executed


In practice it means that some tests depend on other tests. However scary it sounds I believe the reward is worth the risk.

This is going to require more discipline than "normal" tests, you need to find out what are the best base scenarios and which are fine as side scenarios. In my opinion it comes down to better understanding the business domain - which is always critical to the success of the project.

It's important to note that the side scenarios have to leave the application state unchanged, they may create some new content, but it needs to be destroyed at the end of the tests or it must be a content that doesn't influence other tests.

Let's look at an example. In an e-commerce app I think this would be a base scenario.

admin.create_new_product("a book")
user. visit_main_page
user. add_to_cart("a book")
user. confirm_order
admin.should_see_new_order("a book")
admin.confirm_the_last_order
This is the core scenario without looking at any side effects/side scenarios. The shop exists so that admin can sell products.
What are the possible side scenarios here? Several of them come to my mind:


  • user can find the product using the search box
  • google bot can find the product page
  • admin can edit the product data
  • user can recommend the product to his friend
  • the product is in the "recently added" box


As you see, all of the above require that the product is already created.

Here are some tests that require an order to be created by the user:

  • admins receive an email
  • the user data exist in the admin panel
  • the user receives an email


One way to look at it is that the requirements are implemented as events, so that:

admin.create_new_product("a book")
trigger("product:created", "a book")

user. visit_main_page
user. add_to_cart("a book")
user. confirm_order
trigger("order:created")

admin.should_see_new_order("a book")
admin.confirm_the_last_order
How can we implement an example side scenario?

With my current implementation it looks like this.

class SearchProductScenario

  def initialize(test_framework)
    test_framework.subscribe("product:created", self)
  end

  def execute(options)
    product_name = options[:product_name]
    user         = options[:user]

    user.visit_main_page
    user.fills_in "query", :with => product_name
    user.clicks("Search")
    user.should_see(product_name)
  end
end
I've got a simple TestFramework class that is responsible for instantiating all of the scenarios. It's not fully automated yet. It works with RSpec now, but it's framework independent.

We use this approach in one of our projects. It's too early to say if it works well in development. In my opinion it will help with most of the problems stated at the beginning of this post. Scenarios should be shorter and focused on the core of the feature in test. Tests should run quicker as they can share the state with their base scenarios. Fixtures or factories are no longer needed. It's all at the cost of being disciplined in writing scenarios in a certain way.

What do you think about this approach?

Some good news for people interested in this concept! We've been discussing the ideas with other DRUG (Wroclaw Ruby User Group) people and we're going to release a gem which will include this idea. The gem will contain the best things from Cucumber and Steak, so the name is natural: bbq :)

Thanks for reading!

If you read this far you should Follow andrzejkrzywda on Twitter and subscribe to my RSS

Thursday, April 7, 2011

Object oriented acceptance testing

In my last blog post I highlighted the two problems that I have with Cucumber for acceptance testing:

  1. It's difficult to get the customer to write/read Cucumber scenarios
  2. Cucumber scenarios most of the time are procedural programming.

The story

Being aware of the problems mentioned above I started experimenting with my side project to find a better way. I prefer trying out new ways on my side project instead of on the client work. The project is a social network app for board game geeks. As with every social app the interaction between users is quite high. People can vote for good games, comment on other people votes, write game reviews etc. I started writing tests in the following format:

user = TestUser.new
user.visit_main_page
user.click "Login"
user.fills_in :login, :with ="andrzej"

As you see it's a fairly normal Ruby code with API similar to what Capybara/Webrat offers out of the box. In fact, I use Steak with Capybara.

Ruby code

When you compare it to the Cucumber style, the main difference is that it's Ruby code. If it's so hard to convince the customers to write scenarios then I see no point in inventing and using a new language. We all love Ruby.

Programmer-friendly


If it's mostly programmers who read the scenarios, then Ruby is the best choice. It's programmer-friendly and I think many programmers would parse the Ruby code above more easily than the Cucumber way:
Given a new user
When he visits the main page
And he follows "Login"
And he fills in "Login" with "Andrzej"
..

User object

In most apps the concept of User is very important. Why not making it an object? It simplifies a lot and you can hide some implementation details in the (Test)User class. You can create methods and reuse the implementation in an easier (IMO) way than reusing step definitions in Cucumber.

Everything is an object

In fact when you start working this way, you quickly realize that there are more objects appearing in your test world. You will probably have a Website object which can keep some implementation details, like the path to admin panel or methods responsible for setting up the application state.

You can also have objects encapsulating certain pages, if it's useful, or objects for some of your website widgets - sidebar, search_box etc.

Object oriented programming


As you see it's all about the good old OOP that we use in our production code. This solves my problem with Cucumber being too procedural. I can write code like:
user.should_see("Popular games", :inside => sidebar)
Whatever OOP style you like, you can use in your tests. Sounds good to have all pages being subclasses of Page? Write it so.


Human readable

I complain about the fact that it's hard to get customers read/write the scenarios. Cucumber is human readable, no doubts about it. However, if you look at the OOP code - is it not human readable? It takes discipline to have all your methods well named, but it's so worth it. 

I claim that this kind of code is still readable to our non-programmers stakeholders.

Documentation

If you agree that it's readable, then you can actually think of your scenarios as the documentation. Nothing different here, as compared to Cucumber. If you organize your test objects nicely then you not only have a scenario view but also you can see what are the widgets responsible for or what is possible for the Guest user and what is possible for the logged-in User.

Interaction

I found it hard to implement interaction between users in a Cucumber style of testing. I mean things like this:
andrzej = TestUser("andrzej", "password")
john = TestUser("john", "password")
andrzej.logs_in
andrzej.writes_a_review("Agricola", "content")
andrzej.logs_out
john.logs_in
john.visits_reviews_page
john.should_see "content"
john.comments("nice review!")
john.logs_out
andrzej.should_receive_email("nice review!",  "john")

I think it's readable and if you hide the details in methods then the scenario reads very well. You can easily introduce new users into the interaction.

Personas

Personas is a concept in which you find the different types of users who interact with your app. You can give them names, describe what they do, what matters to them etc. This concept can help you think about new features in terms of which persona would use the feature in what way.

In your scenarios you can then use the persona to highlight which aspect of the feature you test. If you worry about security of the new feature then have a user in mind who can hack into your website and write scenarios to ensure it's not possible.
little_bobby_tables.visits_main_page
little_bobby_tables.fills_in :login, :with => "Robert'); DROP TABLE Users;--")
db.should_have_table("users")

Common.rb

When I started with this kind of acceptance testing I didn't think it was so useful at first. When I showed it to my colleagues they quickly started using it as well. Special thanks to Paweł Pacana, who used it in our Ruby User Group website and published it to Github. Since then we started using this approach in our client projects and it works really well. I think it brings back the joy of writing acceptance tests.

I call this approach "object oriented acceptance testing" but my friends started calling it "common.rb" as the main test file that I used. Here is an excerpt from the first version of my common.rb file:
class TestUser
  attr_accessor :steak
  attr_accessor :email
  attr_accessor :password
  attr_accessor :login
  

  def initialize(steak)
    @steak = steak
    yield if block_given?
    self
  end


  def click(*args);     steak.click_link_or_button(*args) end
  def choose(*args);    steak.choose(*args) end
  def select(*args);    steak.select(*args) end
  def fill_in(*args);   steak.fill_in(*args) end
  def visit(path);      steak.visit(path) end
  def attach_file(*args);      steak.attach_file(*args) end
  def should_see(text); steak.page.body.include?(text).should == true end
  def should_not_see(text); steak.page.should_not(steak.have_content(text)) end
  def should_receive_email(text) 
    steak.find_email(@email, :with_text => text).should_not == nil
  end
If you want to see more, look here:


All of the scenarios are kept in spec/acceptance, so look around how it works.

Not a gem, an approach


I was asked to release it as a gem. After some thinking I decided not to do that, as this would make it limiting. I prefer to think about it as an approach, not a specific technology. It all comes down to: Use object in your acceptance tests

The technology I choose is Capybara + Steak. Steak is a very simple DSL around RSpec. Since I started Capybara already provided a replacement for Steak, so it's no longer needed.

This approach is not web specific. In fact, we have a project which consists of a server written in Ruby with EventMachine which has no views but just exposes an API. We write test scenarios using objects that simulate clients connecting to the API. It works very well with typical acceptance tests but also with load testing.

Summary


As you see the approach is not revolutionary and I know that I'm not the first developer who uses it. There are not so many articles about it and I hope it can become more popular. Obviously, it doesn't solve all of the problems that exist in acceptance testing.

We still need to think how to make acceptance tests run quickly or solve the problem of preparing the application state for testing. I think we can do better than using Factories or Fixtures in acceptance tests and I have some ideas for simplifying it. I will present how it works in my next blog posts. Stay tuned. Thanks for reading.

If you read this far you should Follow andrzejkrzywda on Twitter and subscribe to my RSS