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.