Friday, December 30, 2011

Rails is still cool

There are many discussions recently on things that suck in Rails. Specifically, it's about how people misuse Rails. I think we need more OOP in Rails.

Let me explain.

Disclaimer: I started using Rails in 2004, now I run a Rails consultancy and I've been more or less involved in about 30-35 Rails projects. I'm also involved in building a"social games for brands" product called GameBoxed, which proudly runs Rails 3.1 under the hood.

Rails history and background


When Rails was released in 2004, I don't remember that DHH was saying it was perfect for everything. He showed us Rails and said: "look, this solves many problems of a typical web app". He was right. Somehow, it was assumed that the Rails way is the only way. This led to some people complaining about how Rails doesn't fit well into their more complex apps - I was one of such complainers, shame on me.

Rails is awesome for starting an app


Let me repeat - Rails is great for starting an app. Do we want it or not (I want) we will see new Rails apps being created every day. The mainstream future is still before Rails, because it's really easy to start and new people will keep coming in.

Why do you complain about Rails?


It's not complaining about Rails, it's complaining about the current "best practices" and how we (me included) use Rails. In every project I worked on, choosing Rails as the platform was a good decision at the beginning. It's just that at some point we not always realized that we should find our way, not the Rails way to implement the requirements. We had a hammer, so we looked for nails everywhere. It doesn't mean that we should drop Rails. Projects evolve. What starts as a typical Rails app, evolves into something bigger, more complex at some point. Maybe it should be 5 small Rails apps cooperating together with some APIs?


Why don't you write your own framework?


Someone asked me this question recently and I realized that my Rails critics is presented in a way that put Rails in a bad light. It's not true. Rails is awesome. It has almost everything right. I don't want to create a new framework. It's too much work and there's no point in it. What I want, though, is looking for ways how to improve the apps that were misusing Rails at some point. In our company we sometimes inherit projects from other teams and that's my main area of research - how to maintain and refresh legacy Rails projects.
Another argument is that I haven't seen such an awesome community anywhere else. It's a community extremely open for new, good suggestions.


But you criticized ActiveRecord so often, what about that?


ActiveRecord is a great persistence layer. It was never my favorite part of Rails, because I never really liked the persistence part of projects. It's kind of an implementation detail to me.
Somehow, I misused Rails in this area. Instead of treating ActiveRecord as a persistence layer I started treating it as a domain layer as well. It was so tempting to do so...
Actually, at the beginning of a project it can be fine, to make AR you domain layer as well. Just for quick prototyping. But later I think that you should have a separate OOP domain model. I will come back to this point.


ActionController is the problem


There's a valid argument that Steve Klabnik and others talk about. The way Rails handles the communication between controllers and views by default is awful. I suppose you all know what I mean. Note that Rails doesn't force you to use it this way. You're free to make it better. My suggestion? Use cells and research the presenter-based gems for views.


ActionView is the problem


The problem is not ActionView itself, it's how some people misuse it. Rails community does a lot to discourage putting logic inside views and I think it goes well. We could go with Mustache or other logic-less templating systems, but it's assuming that we can't trust programmers. Welcome back to Java? BTW, stop hating Java ;)


MVC is the problem


First of all, Rails is not MVC. Second, the Rails MVC (Model2) is fine for monolithic apps that are (yay!) going to the past. The future is in viewless, API-based backends with rich clients like mobile apps and CoffeeScript apps.


Rails for bigger apps


The first thing to remember is that Rails is not your application. Rails helps you as a delivery mechanism. Once it's bigger, you should consider:

  • breaking from the monolith application into backend+frontend
  • implement a separate (from AR) domain layer

It all assumes that you have tests for your project. If not, then you're screwed anyway. There's no chance for refactoring if you don't have tests.


Future?


I see the future in separating backends from frontends. This alone makes the architectures simpler and easier to maintain.
Extract your domain layer. It's something that I'm experimenting with. It's hard, but it's not about Rails making it hard. Surprisingly it's hard because of the way we deploy Rails apps.

Domain layer


The point in separating the domain layer is that we want to implement some classes that have nothing to do with ActiveRecord classes. Yes, they may be similar. Maybe some names will be duplicated, but that's another layer. It should be framework-free, pure objects. PORO.

The deployment way leads to the question - What's the point of building an object model in memory, just to run one use-case and it all disappears? It's a waste. That's what happens when you build a domain layer based on database (ActiveRecord) data in a typical mongrel/passenger/heroku environment.

I'm experimenting with running Rails in a threaded environment (Thin allows it). It means that Rails is run in a single process and all requests come as threads. It's promising and very liberating - you can have your own Ruby objects, without being restricted by the ActiveRecord problems. I will blog more about it, soon.

There are problems, though. This approach requires a different scaling mechanism (but it also move the scaling need further to the future by speeding things up - your data is now in memory). Another problem is that you need to synchronize your domain layer with the ActiveRecord layer.

Despite the problems, I think that this approach has some potential. Contact me, if you would like to help me with this research.

Avdi also has some interesting ideas about the ActiveRecord separation in his book - "Objects on Rails".

Use cases

The synchronization part can be done using the use-cases layer. Read about it here: http://blog.firsthand.ca/2011/12/your-rails-application-is-missing.html

The use-case object can synchronize the two parts together, but you need to remember about keeping it consistent (either by transactioning it or by having a synchronizg thread).

Use cases alone are an awesome idea. Imagine that all the changes to your system that are triggered by a user or another actor come through a use-case object. This way, you're nicely exposing all the actors playing together and you can expose your real architecture.

ActiveRecord is changing in Rails 4


Look at this commit: https://github.com/rails/rails/commit/00318e9bdfc346a57cab34b2ec3724f3e9605ac1
It seems to be a small change, but it will allow extending your objects with the persistence responsibility runtime with DCI. Wouldn't that be cool?

DCI


You knew that I would mention DCI, didn't you? :) Yeah, I'm a big fan of DCI, just for the use-cases alone. They call it contexts, but it's the same meaning. The idea of DCI spreads nicely in the Rails world, but what worries me it's only the idea of extending objects runtime that is being spread. Runtime extending can easily bring you to a mess if you're not controlling who can extend any object. It's the context. If you're extending model objects inside other model objects, then you're doing it wrong, I'm sorry. Lessons learnt, trust me.

Read more about DCI on my blog posts:
http://andrzejonsoftware.blogspot.com/2011/12/dci-for-dummies.html
http://andrzejonsoftware.blogspot.com/2011/02/dci-and-rails.html

You should also read "Lean architecture" book which is a deep introduction to the DCI way of thinking.

Summary

  • Rails is cool, if combined with classical OOP. 
  • Remember about TDD and testing. 
  • Separate backend from a frontend. 
  • ActiveRecord is not your domain layer. 
  • Learn DCI. 
  • Think in use cases. 
  • Attend the wroc_love.rb conference in Wrocław, Poland. There will be many Rails OOP related talks. 
  • Send us your ideas for talks (you have my vote if it's Rails OOP related :) ) - I'm one of the organizers.

Bonus


Uncle Bob talk from RubyMidwest
http://confreaks.net/videos/759-rubymidwest2011-keynote-architecture-the-lost-years


It's one of the most important talks I have seen recently. You must watch it. It will change the way you think about Rails apps.

Thanks!


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

Small, deployable commits

We've had an interesting discussion at our stand-up today. The discussion was triggered by Jan Filipowski post on "early commiting in TDD".

The main questions are:

  • Should I refactor before every commit?
  • Should a commit pass all tests?
  • What units of code should be code-reviewed?
It got me thinking about my current approach and about my "ideal world" approach.
I'm a big fan of the idea of continuous deployment. It means that every commit, after passing all tests, can be automatically deployed. 

I'm not there yet. I try to work with very short commits, often it's only 2-line changes. However, I still miss an infrastructure which could automatically push this commit, test it and deploy. It's not that it's difficult to prepare, it's just some kind of a psychological bareer. It's definitely something I want to improve as soon as possible.

Sometimes it's hard to have deployable commits. Recently we've been upgrading our app to Rails 3.1 and it's not something that can be done in one commit. 

Going back to questions:

Should I refactor before every commit?

Refactoring is part of a workflow, but I wouldn't say it should part of every commit. Sometimes a commit can be just the red-green part, and it's the next commit that does the "refactor" part.

Should a commit pass all tests?

This is a tricky one. In my ideal world - yes, because it should be deployable. Is it hard to achieve in practice? I'm wondering if there's a conflict between a deployable commit and one that fails on some tests.  Maybe it's fine to have some tests failing, if they are not part of the code that is being used in production?

 What units of code should be code-reviewed?

We tend to make code reviews using GitHub commit comments. They're fine, but sometimes I comment on something that was changed 3 commits later, which makes my comment irrelevant. 

Obviously it all depends on a project. In most cases I think we shouldn't be too serious with the code reviews comments. In my opinion code reviews should help us triggering some coding/architecture discussions, they shouldn't be too formal. I don't like proceses which require code reviews before the code goes into production - we should trust each other that nothing stupid gets deployed. If we treat a code review as a tool for better communication then it's not that important if a comment is about a code that changed later or not.

How about you? How often do you commit?

Sunday, December 18, 2011

args, opts, params

It's quite popular, especially in Ruby code, to see methods like this (note the method arguments):
def show(args)
  some_other_object(args)
end
or
def show(opts)
  .. lots of code
  bar = opts[:foo]
  opts[:bar]
end
and also:
def show(name, params)
  some_other_object(name, params[:foo])
end
I see some problems with such code:

1. It's hard to tell, when you call the method, what is really required/expected to pass in.

It's less of a problem, when you can see in the method body what is used. But it's not always the case. Often the params are passed further, so you have to look around and think hard how the params are used.


2. (args, opts, params) as names sound very generic, they don't tell me too much.

I understand that hashes are quire useful sometimes. But it's a similar situation like the one where we would call a variable a var_1.
Why don't we, at least, give them good names, like address_hash or html_options or maybe game_configuration?

3. It's a missing object smell.

Very often, to me, the examples above are code smells. There's a missing object somewhere. Especially when this data is passed further. Maybe it's Address object, maybe PopupContent, whatever sounds good in your domain.

What's your opinion?

Friday, December 16, 2011

DCI for dummies


The metaphor of DCI is a theatre. The context is the director. Chooses who plays what, instruct them how to do it and then let them play.

Theory:
  1. Expose use-cases (context) as first-class citizens of your code. 
  2. Each use-case selects which objects are needed for this use-case. 
  3. Extend the objects only with the roles that are needed in this use-case. 
  4. Start the interaction. 
Example:

Buying a product.
  1. UserBuysAProduct object, that can be executed. 
  2. Objects/actors needed: user, shop 
  3. Extend user with a Buyer role and shop with ProductCatalogue and OrderManager. 
  4. call shop.buy_product(user, product) 

Tuesday, December 6, 2011

Continuous integration - some tips

Continuous integration server is a must for every non-basic project.

Here are some of my tips for working with CI servers.

Notifications


IRC, email, campfire - use what fits best for you. Ideally, the notification should come with some info about the code changes that triggered the build. We use IRC - we've got an IRC channel for every project we work on, so the notifications go to the correct channel.

Build time

It's a huge topic. It's so difficult to keep the build time short for every project. I have to admit we've got projects where build time takes 20 minutes. My goal is to get down to below 10 minutes for existing projects and try to keep the new projects below 3 minutes. Slow builds have a very bad impact on so many things. The feedback is late. People tend not to run builds on local machines.

Local builds


It's great that you have a CI server, but the goal is also that all tests can be run on every developer machine in a decent time.

Architecture decisions


That's the most surprising effect of using tests and CI. Once we got to the point where many of our projects have the slow build problem we investigated our technology choices. In many cases the slowness came from using Selenium. Selenium is the only "right" tool when you have an app that is a mix of server-side logic and client-side code (JS). It seems, surprisingly, that many of our projects could be turned into one-page CoffeeScript apps. Obviously it's not an easy goal (and not always possible). It's changing the way we architecture our apps. If the split is achieved you can test the CS code in isolation from the server-side and then test the server-side API, also in separation, but without Selenium.
Selenium is cool, but it has the drawbacks of being slow and unreliable.

Unreliable tests


If you're using Selenium, then you already know what I mean. I hate this fact but sometimes we've got build failures which shouldn't appear, they're most of the time timing issues. It's a hard situation to have. The important thing to remember is that we (the team) are all in it. Every team member should investigate the problem and try to fix them - sometimes adding a sleep (a hack, I know) solves the problem.

Who's responsible for failures?


I like the idea that the last person who triggered a failing build is responsible for fixing it. It's hard to get to this point, especially if your build is unreliable. This leads to:

Never leave a broken build


This is the biggest sin when working with CI servers. If I want to start coding and I see that a build is broken and no one seem to care then it's very depressing to me. In practice, it means that you should commit your changes some time before you finish your work, so that the CI can run it and get you the result back. If it's broken, try to fix that as much as you can. It's less of a sin when the failure comes from unreliability, but leaving a broken build caused by your changes is unforgettable :)

Summary


A green, fast build run frequently on the CI server is a sign of a healthy project. If there's anything broken with the build process, look at it. It's often a smell showing you that something can be wrong in your process. Don't ignore that.

Any tips from your experience?

Sunday, December 4, 2011

CoffeeScript is the fresh air

When I started using Ruby and Rails in 2004 I immediately knew that Rails is going to be huge. At that time I was working mostly with Java.

Ruby and Rails brought so much joy to my programming world that it was kind of a revolution in my programming passion. This revolution is still going on, I'm still happy with Ruby and Rails even if I sometimes criticize some aspects of it.

There is however a new thing that triggered a new (r)evolution in my programming world.

This thing is called CoffeeScript.

I know that Coffee is only a "patch" to JavaScript, but for me this slight change is huge. The syntax is the prettiest combination of Ruby and Python that I have ever seen.

The code written in Coffee is so pretty that it almost allows you to think at new levels of abstraction. Yes, it's that huge to me.

I never especially liked working with JavaScript on the front-end. I preferred to focus on Ruby backends. Now it's harder to me to switch from frontend code to server Ruby code.

I still love Ruby, but CoffeeScript is officially becoming my new passion, equal to Ruby. If you haven't given it a try, then you should. It's so worth it.

Sunday, September 25, 2011

Rails is not MVC

There is a terminology problem in the Rails community.

Everyone promotes Rails as a MVC framework. I did that as well. However, the truth is that Rails represents the Model2 architecture. It's not MVC. 

I know it's just a definition issue. Maybe we shouldn't care. It wasn't really a problem until recently. We see the rise of the JavaScript MVC topic, which is an awesome thing. The browser clients with its JS engines can have a real MVC, as opposed to Model2.

OK, so what's the difference?

In short, we're talking about MVC when a model can notify (through the Observer pattern) the views about the changes. It's not possible in a classical Rails app (it's possible when you use WebSockets, Pusher or a similar technology, but it's not so popular yet.). MVC was popular in desktop apps.

On the other hand, Model2 is exactly what we do with Rails. We don't notify the views from the model, the controller simply passes the model data to the views and handles the html generation which is then sent to the browser.

There's an interesting pattern evolving recently that a Rails app simply serves as a backend for a mobile app and all it does is exposing a JSON/REST API. It's similar to Model2, but instead of generating HTML it generates JSON. Still, it's not MVC.

You can read more about UI architectures in this article by Martin Fowler

Why is it important?

It's becoming an issue now, because we start talking more about the JavaScript MVC. The JavaScript MVC is a real MVC. The models can easily notify the views. Often, when you talk to people being introduced to the JS MVC they seem to be confused and try to implement the Model2 pattern on the client side, which in my opinion is ridiculous.

What shall we do about the Model2 and MVC confusion?

I see three choices.

The first one is to say that MVC changed its original meaning and Model2 can also be called MVC. In that case we can start using terms like "classic MVC" or "real MVC" for the old MVC. This is what is happening now, but I don't think that changing definitions is a good idea. It brings even more confusion.

The second way is to promote the fact that Rails represents a Model2 architecture and MVC is reserved to, well, MVC. It's going to be hard, but we will keep the definitions stable.

The third way is to just ignore the confusion. Who cares?

I decided to go with the second option. What's the best way in your opinion?

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

Saturday, September 24, 2011

3 steps to MVC in JavaScript


  1. Read this article MVC Architecture for JavaScript Applications by Peter Michaux. It's a must-read and it nicely explains how the observer pattern works in the classic MVC. (Keep in mind that the MVC that you know from Rails/Django is a limited MVC, that's a topic for another post).
  2. Use Backbone and Underscore to handle events or roll your own observer mechanism (as described in Peter's article).
  3. (optional) Use CoffeeScript to make your code prettier.
Let me quote Peter Michaux:

In a nutshell the classic MVC architecture work like this. There is a model that is at the heart of the whole thing. If the model changes, it notifies its observers that a change occurred. The view is the stuff you can see and the view observes the model. When the view is notified that the model has changed, the view changes its appearance. The user can interact with the view (e.g. clicking stuff) but the view doesn’t know what to do. So the view tells the controller what the user did and assumes the controller knows what to do. The controller appropriately changes the model. And around and around it goes.

In the GameBoxed platform, we have a Monopoly-like Facebook game. There's a concept of a player (this is the model). A player, after rolling a dice, can receive points and when he does we need to update the player-details box.



When the page is loaded (our games are one-page apps, no full reloads), the Monopoly object is initialized. It's a facade object responsible for initializing models, views and controllers and wiring them together.

At some point thanks to some users actions the player.addPoints method is called which triggers the "player:updated" event with some arguments. Thanks to the controller (the bind method), the PlayerView object is notified that something interesting happened and the view updates the html (with some jquery helpers).

This pattern is very useful and can be used in most of the typical UI scenarios. Let me know what you think about it.
 If you read this far you should Follow andrzejkrzywda on Twitter and subscribe to my RSS.

Monday, August 22, 2011

DCI in short - Can you fly that helicopter?

Trinity is the object, Matrix is the Context, HelicopterPilot is the role (injected runtime in Matrix).


It's obviously a simplification but overall I think this metaphor expresses the idea of DCI very well. Trinity represents the D (Data), Matrix represents the C (Context) and HelicopterPilot role along with the Helicopter itself (and other objects) represent the I (Interaction).

This example is good as it shows how your software can evolve. Your objects don't need to know upfront that they will play some roles, it's all runtime (as with Trinity and the helicopter).

Can you fly that helicopter?

Wednesday, August 17, 2011

Tracing aspect for a Rails application

Aspects are modules for crosscutting concerns. Typical crosscutting concerns are: persistence, tracing changes (history), permissions and logging.

Aspect Oriented Programming is not a popular topic in the Ruby community. Partially, it's because Ruby gives us some AOP constructs out-of-the-box (open classes) but also due to some built-in mechanisms in Rails - like filters and callbacks which serve as the dynamic part of AOP.

I think that there are scenarios in which traditional AOP can be very useful. Today, I'm going to show you how to implement logging of chosen method calls, without touching the methods itself.

Aquarium seems to be the best AOP framework with Ruby.

Installation

#the first part is only needed if you want to use ruby 1.9
#otherwise just put gem "aquarium" into the Gemfile and run "bundle install"

cd vendor/gems
git clone https://github.com/deanwampler/Aquarium.git
cd Aquarium
git checkout 1.9.1-port

# edit Gemfile and add:
gem 'aquarium', "0.0.0", :path => 'vendor/gems/Aquarium/aquarium'
bundle install

Creating an aspect


Create config/initializers/tracing_aspect.rb and paste:
require 'aquarium'
include Aquarium::Aspects
Aspect.new :around, :calls_to => :all_methods, 
    :for_types => [User],
    :method_options => :exclude_ancestor_methods do |jp, obj, *args|
  begin
    names = "#{jp.target_type.name}##{jp.method_name}"
    p "Entering: #{names}: args = #{args.inspect}"
    jp.proceed
  ensure
    p "Leaving:  #{names}: args = #{args.inspect}"
  end 
end

If you now run the tests or just use your app, you should see all the method calls on User objects being logged to the output.

I hope it works fine for you, let me know in case of problems.

Sunday, August 14, 2011

DCI patterns - how to write DCI contexts in Ruby

After my previous post about DCI and Rails some people contacted me regarding best DCI patterns. As the topic of DCI is still new I didn't want to engage into creating patterns - I think they should emerge from existing projects. The idea of DCI seems to propagate in the Ruby/Rails circles - there was a RailsConf talk on this topic and more DCI blog posts appear. If you haven't heard about DCI yet, please read my last post first: DCI and Rails.

Recently I got an email from Pavel Mitin in which he describes his pattern for creating DCI contexts in Ruby. As this pattern matches exactly with my approach I think it's worth sharing and recommending as a pattern.

This example consists of two base classes - Human and Address. Objects of the Human class can play two roles: Policeman and Thief, while the Address can sometime play the role of FakeAddress.

Splitting classes into roles and injecting roles runtime is only a small part of DCI. The bigger thing is the idea of Contexts, which you can also think like a User Story or a Use Case (as a big simplification). In Pavel's example we have the context of the Policeman arresting the Thief. In this case the thief object has the address object extended with a FakeAddress.

This example shows some interesting concepts. As you see we're not replacing the thief's address - as in this world we think that humans have one address. What we're doing is extending the address object and "overwrite" the to_s method runtime in the context of arresting. I assume here the to_s method abstracts the thing that the thief is "saying" to the policeman.

The most important part, however is the way the context class is written. ArrestContext is a class with a constructor and the execute method. It's the constructor job to wire all the relevant roles to the actors. Once the roles are injected the execute method can start the "procedure".


There are still questions remaining regarding the contexts. Who should access the context classes? Let's assume that we have an application object in our project which represents the whole system and that it's a web Rails app. Should the application object (a model) know about the contexts?

Here are some options:

1. the application object has access to all the possible contexts. The controller just calls methods like: application.register_new_user(..) and it's the application that initializes the context.

2. controller has the knowledge about the specific "global" context it handles: NewUserContext.new(..).execute

3. controllers as we know them (Rails) disappear, the wiring between actions and context takes place in a configuration file.

All of the Ruby DCI examples so far seem a little bit verbose. It's because they are direct translation from languages that are not as dynamic as Ruby. It's not my goal at the moment to create a nicer API but I'm pretty sure we can come up with nicer syntax. Can you help? Especially, I think that the context classes can become some kind of configuration files - what role to inject to which objects, then which method starts the "procedure".

I'd love to know your opinion on this topic. Does it make sense to you? Is the DCI concept clear to you?

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

Wednesday, March 30, 2011

2 problems with Cucumber

The most popular technology for acceptance testing in Rails applications is Cucumber.

I used to be a big fan of Cucumber. We've been using it in every project for our customers.

From my point of view Cucumber delivers 2 important features:
  • A special language readable to non-programmers (Gherkin)
  • Acceptance tests - embedded browser driver - Webrat/Capybara etc
When I started using Cucumber (and prior to that I used Rspec Stories) it was mostly because of the acceptance tests part. Cucumber offered the whole philosophy in the framework, a philosophy based on the importance of communication with customers through the scenarios. The communication was based on a language called Gherkin.

Cucumber became a whole framework for managing requirements. The implementation is based on step definitions which we could implement in Ruby. Cucumber also gives us tools for running the acceptance tests, tools like tagging, features like documentation etc.

Thanks to tags we could run only the tests that are responsible for a specific part of the system. Another use case is to tag new scenarios with @wip and those are not run.

The biggest Cucumber project we have at the moment contains almost 600 scenarios. The biggest project I'm aware of has 2000 scenarios. It's a lot of "code".

With every new project I hoped that Cucumber can become one of the communication tools between our team and the customer. Only once I managed to get the customer write the scenarios, however the quality wasn't good and they had to be rewritten by a developer.

Every now and then we could send the scenario to the customer to get their approval that they are correct. In this cases the customer was able to read them easily. However, it was difficult to convince the customer to review the scenarios on a daily basis. They preferred writing a document or using a ticketing system like Redmine. The result is that we have requirements in 2 places - tickets and scenarios. It's not perfect, but it works well enough.

My conclusion for now is:

1. It's difficult to get the customer to write/read Cucumber scenarios

We gain a lot from the acceptance tests feature of Cucumber. Every functionality is covered by scenarios and it creates a nice regression weapon in cases where we need to change something in the application. Upgrading from Rails 2 to Rails 3 was one of such occasions. Unit tests would not be enough.

Recently I noticed that it's getting harder to manage the scenarios written the Cucumber way. There are many patterns how to keep the steps definitions, how to split the scenario etc.

I realized that it's the same kind of problem when you write a procedural code with no objects.

2. Cucumber scenarios most of the time are procedural programming. 

With procedural programming it's hard to keep data and behaviour together. For simpler apps procedural programming is fine but for a bigger codebase I personally prefer object-oriented programing. I suppose it would be possible to include some object-orientation into Cucumber but I'm not sure if it would feel right and if it's worth the effort.

Summary

I see two problems with Cucumber and its usage in our projects:
It's hard to get customer working with scenarios and it's hard for developers to work with a bigger Cucumber codebase.

If you have customers working with Cucumber - congratulations! If you manage to deal with the procedural style of Cucumber - congratulations!

Is there any solution? 


I started experimenting with a new way of acceptance testing based on Capybara and an object-oriented approach. It spread very quickly among the Wrocław Rails developers so it seems to be an idea worth investigating. I will present how it works in my next blog post. Stay tuned.

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

Friday, March 25, 2011

MVC and OOP, are we doing our best? - talk proposal

Here's my Euruko 2011 talk proposal which was rejected by the organizers. Let me know if the topic sounds interesting to you, I'd be happy to present it at some other conference.

Euruko 2011 talk proposal

It's a result of many years of my research/practice in OOP and MVC. The recent discovery of DCI can change a lot about the way we create MVC applications and Ruby is the best fit for DCI, in my opinion.


"MVC and OOP, are we doing our best?"

Ruby is one of the best OOP languages - are we using it the best way in our MVC applications? My observations show that there are common places where Ruby developers break the traditional OOP rules like the Law of Demeter or SOLID. It results in code of worse quality than it could be.

Early on, we agreed that we should move the logic from controllers into models. It's all fine, but most often it results in fat model classes. How to deal with the complexity?

We put everything into classes. DCI claims it's not OOP, it's class-oriented programming.

DCI (Data Context Interactions), a new architecture paradigm focuses more on object behavior and fits very well with Ruby MVC frameworks like Rails or Sinatra. I will talk about DCI and present some examples. DCI was invented by Trygve Reenskaug, the same scientists who formulated MVC. One of its main ideas is to inject roles to objects runtime (using mixins), thus making the base classes much thiner.

DCI brings some fresh air into the MVC architecture and solves many of the existing problems, like:
- fat model classes
- difficult reusability
- testing problems
- instead of one big object-oriented design we can deal with many small ones

This talk is based on several of my blog posts. Some of the ideas were already presented at SRUG and DRUG (Silesia and Lower Silesia Ruby User Groups) meetups. The blog posts and the talks triggered many interesting discussions.

http://andrzejonsoftware.blogspot.com/2008/07/mvc-how-to-write-controllers.html
http://andrzejonsoftware.blogspot.com/2010/05/rails-mvc-how-to-deal-with-fat-models.html
http://andrzejonsoftware.blogspot.com/2011/01/code-reuse-in-ruby-why-composition-is.html
http://andrzejonsoftware.blogspot.com/2011/02/dci-and-rails.html
http://andrzejonsoftware.blogspot.com/2011/02/application-or-set-of-resources.html

http://srug.pl/assets/andrzej-krzywda-rails-and-dci.txt



BIO

Andrzej Krzywda is the founder of Arkency, a Ruby on Rails shop (6 developers) based in Wroclaw, Poland. He also teaches Ruby on Rails at the University of Wroclaw. Andrzej has 11 years of IT experience. He has been involved in many different projects, including big telco, small startups, consulting companies etc. He worked with Java, .Net, Python, PHP but since 2004 he feels most comfortable with Ruby. Andrzej has presented at conferences like RuPy 2007, RuPy 2008, PyCon 2008, SFI 2006, SFI 2008, KKIO 2004 and lots of smaller meetups like DRUG or SRUG.
andrzejkrzywda@gmail.com

Sunday, February 27, 2011

Rails: Many classes in one file

Some time ago I asked if there is any way of having many classes in one file and being able to work normally in the development environment (reloading classes between requests).

Luckily, Jan Dudek (thanks!) came up with some nice solutions. The best of them uses ActionDispatch::Callbacks in combination with require_dependency. Here is an example:

config/initializers/load_classes.rb
ActionDispatch::Callbacks.before do
  require_dependency "app/models/events.rb"
end

I have tried it in one project and it works pretty well in all environments.

Why would I want to keep many classes in one file?


I agree that this technique breaks the Rails convention of keeping one class per file. Possibly, it can confuse some developers on where to find classes definitions. In this case it's important to communicate with the team whether it's worth trying and explaining how it works before using it.

For me this technique is useful when I have many Rails models, all very short, related to the same feature. The example above (app/models/events.rb) keeps definitions of Event, Attendee, Attendance, AttendanceType, EventBoard. All of them are short and instead of jumping between many files I've got one file which keeps it all in one place. It's hard to measure whether it's good or bad, works well for me so far.

Monday, February 14, 2011

An application or a set of resources?

My last post about DCI and Rails triggered many interesting discussions. One of the topics that came up very often can be summarized to this question:

Do you think of your web application as an application or as a set of resources?


My answer is clear: it's an application.

I noticed that not everyone agrees with it.

In the Rails world a resource is a very popular word. Mostly because of the REST architecture that we follow in our apps. Whenever I can I use the REST approach, but I think of it as a way of using URL's and accessing the application. I find it a nice way of structuring my controllers. REST is just an interface. From outside and for my users it's an application, not a set of resources. They use resources but they access them through an application which to me is an important distinction.

This topic caused that I decided to publish the assumptions that are needed for a DCI architecture, at least how I understand it:

1. As developers we model the real/business world.
2. If a concept appears in the model we reflect it in the code.
3. Most of the web apps scenarios has the pattern of "a user does something with the app"
4. If user and app are so important in the domain then we make them classes/objects.
5. It results in big user/app classes.
6. The problem of big classes can be solved by using the idea of "injecting roles" runtime.

Usually point 5. discouraged people from reflecting the user/app importance in the code. The alternative is chosen which is things like this in the controller:

@discounted_products = Product.discounted

whereas I prefer this:

@discounted_products = shop.discounted_products 
# shop is like the application object here

Anyway, point 5 can be now solved by the idea of injecting roles and DCI as described in my last blog post and in my opinion we can start using the user and application objects more often. Once you start using them, many of the OOP decisions you need to make become easier, because you just reflect the domain in the code.

Friday, February 11, 2011

DCI and Rails

I got really excited about DCI recently.  I'm still not sure if I get it right, but let me try to describe the way it works and how it can improve our Rails applications.

Here is the short version of this blog post:

#controller action 


current_user.extend Buyer 
current_user.add_to_cart(product_id, quantity)


DCI stands for Data Context Interaction. It was invented by Trygve Reenskaug, the same scientists who formulated MVC. It's a new paradigm, but it's very similar to OOP and fits especially well with the MVC architecture that we use in Rails applications.


Let me start with the evolution of Rails applications, so that I can explain current problems with the Rails model layer (in my opinion).

Very early we (the Rails community) agreed that it's better to move the logic down to models and keep controller very thin. I also wrote a blog post on how to write Rails controllers which is still my opinion on this topic.

As a result we had to cope with so called "fat models". This topic was an area of my research for years. It resulted in some techniques that I described in the "How to deal with fat models" blog post.

One of the things that I personally dislike is the overuse of Global State and Class Methods in Rails controllers. I have seen it everywhere and it my opinion in bigger apps it can result in maintenance problems. You can read why it's bad in this article by Hevery Misko. I must admit that with ActiveRecord it's very hard not to use Class Methods, but at least we can minimize it.

I was researching more OOP techniques that can be used to keep a nice OOP design in Rails model classes. I found the composite pattern (resulting in delegation) to be the closest to what I want to have. I asked the Ruby community why we don't use composition so often. The answers confirmed my observations that Ruby mixins (modules) are much more popular.

Anyway, it doesn't really matter - the result of "traditional usage" of mixins and composition in Ruby is very similar - you end up with a class which has lots of responsibilities. It doesn't matter that most of the responsibilities are delegated to other objects, actually it leads to a problem called self schizofrenia. This is especially visible in classes like User (in a social network app) or Article (in portal apps), which are very often a central place of application logic.

There are two techniques that I found useful during my research.

1. Current user pattern

This pattern was just reflecting the fact from a real life - a user interacts with our website so whenever a user does something there is a method in the User class responsible for that. Some methods can be grouped into "roles" and extracted to another class or a module, but they're declared in the User class.

2. Website pattern

This is the other side of the current user pattern. The user is interacting with a website, so it sounds like a good idea to have some kind of Website (or Application) class. This class encapsulates all the data and behaviour that is accessible from the website.


As you are probably seeing it now, it results in huge User and Website classes.

Just to be clear - both the current_user (in the Devise/Authlogic meaning) object and the website object are accessible from ApplicationController, so any controller could have access to them. The advantage here is that you don't need to introduce Global State and with the website pattern you can eliminate calls to class methods.

It was always kind of a smell to me that any controller takes the whole user object just to interact with a very small subset of the user interface. Let's say that you have a PostsController which needs to display all the posts. It takes the website object just to call website.posts, but theoretically it can call any other unrelated method. Static languages deal with it by communication using interfaces. It is a solution but it's still not perfect.

Here is where DCI comes in.

One of the things DCI claims is that most of the time we don't do object oriented programming but we do class oriented programming. It's more visible in the Java/.Net world but I think the same applies to most of us - Rails programmers. We put our declarations in classes and then instantiate objects with lots of unnecessary stuff.

DCI suggests that we keep our core model classes very thin. Zero logic, only data, if anything.


The logic/behaviour should be kept in roles. In Ruby we can nicely use mixins for that.


In an e-commerce app you would have User class but the buying/cart logic would be in the Buyer module. The User class knows nothing about cart, buying.

In a social network app you can create a GroupUser role and keep all the group related logic inside.

You can also extract some roles from the Website class. Some candidates in an e-commerce could be ProductRepository, OrderDepartment, NewsletterManager, Blog etc.

This logic is then injected runtime, at the object level, in the context of a specific use case.  In my opinion contexts or use case fits very well with the rails thin controllers rule.

Usually, one controller action is a specific use case. One example may be adding some product to a cart. The action could look like this:

current_user.extend Buyer
current_user.add_to_cart(product_id, quantity)

Another example, with a website:

class EventsController
  def index
    website.extend EventsBoard
    @events = website.recent_events
  end
end

As you see we use .extend method here which allows extending an object with a module. It all happens at the object level.

To me, this technique is most crucial for DCI (from a Rails perspective). Extending the object with a role at the controller level simply solves all of the OOP problems I had to deal with. The class doesn't know about all the roles, there's no problem with huge classes or object schizofrenia. You just create roles which are usually small modules and that's it.

DCI suggests that we keep use cases as classes. If my understanding is correct the place for creating use cases would be at the controller level. Notice that usually a single request is some kind of a use case. However, usually the code is so small in this area that I'm not sure it deserves a class. I can see the advantage of seeing all the interaction in one place so I just need to get used to this kind of thinking.

Terminology

In order to fit DCI into the Rails terminology I assume that we can call our thin model classes the Data layer. Our controllers actions can be wrapped into a class and called Contexts. Those actions take the Data, inject the roles (as Ruby modules) and run some Interactions.

Problems


I have already tried this approach in one small application. It worked pretty well. One of the problems that appeared was a situation when I actually want the object playing almost all of the available roles. This kind of situation often takes place at main pages or in some kind of dashboards.
I solved it by using the Cells framework. In short, Cells let you create mini-controllers (cells) that can be responsible for one part of the view. It can access the controller and execute a "mini-action". In my case I used in a way that every cell extends the website with the role that is associated with this view. It worked pretty well and I'm quite happy with the result.

Summary


In my opinion DCI fits very well with the way we create Rails apps. It simplifies the Model layer a lot. If you're happy with your current OOP design then you will probably not gain too much from DCI. If not, wikipedia entry is a good start for getting familiar with this concept at a more theoretical level. The whole concept is actually very simple and intuitive. It brings the user perspective to your code, which in my opinion is a good thing. We're here to model the real world/business etc.



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

Saturday, January 22, 2011

Dear Lazyweb: How can I put many classes in one file in a Rails app?

Since yesterday, I asked many of my Rails friends the same question:

How can I put many classes in one file in a Rails app?

Unfortunately, I haven't got any answer that would work.

I try to solve this problem every 6 months or so. It's not a thing that I can't live without, but it would help my workflow a lot.

One use case is to put 4-5 model classes in one file. If each class is only 15 lines and they're all conceptually related then why not to put them together?

Another use case is to keep related controllers in one file.

So far I tried a combination of require, require_dependency and autoload and I tried to put them in config/initializers, environment.rb or in application_controller. Each resulted in some kind of error. Either  one of the class was not found, or Rails complained with "A copy of ApplicationController has been removed from the module tree but is still active!".

I tried all of it with Rails 2.3.5 in development mode, however a solution that works with Rails 3 would also be great!

Can anyone help?

Monday, January 17, 2011

Code reuse in Ruby, why composition is so rare?

I've been researching topics related to code reuse and object oriented design in Ruby apps recently.

There are three popular ways of reusing code in the Ruby community:

  1. Inheritance
  2. Modules/mixins
  3. Composition
1. Inheritance

class User < ActiveRecord::Base
  def change_login(new_login)
    login = new_login
    save
  end
end
It's very popular, mostly because this is the default way you can use ActiveRecord in Rails applications. To be honest, I don't like inheritance. It doesn't fit into my model of thinking about object oriented design. That's a topic for another post, though.
Inheritance let's us access methods available in the base class. The limitation is that a class can only inherit from one base class. Python is better here, allowing multiple inheritance. I don't like inheritance, both from a theoretical and practical point of view.
2. Modules/mixins
module Buyer
  def add_to_cart(product_id, quantity)
    cart.add(find_product(product_id), quantity))
  end
end

class User
  include Buyer
end

#usage
User.new.add_to_cart(params[:product_id, params[:quantity])
A module is basically a set of methods. You can't instantiate a module and that's the main reason I'm not a big fan of modules. 
You can include as many modules as you want into one class. That's kind of a work around for the lack of multiple inheritance. Modules are extremely popular in the Ruby community - just look at the Rails source code.
One problem with modules is that in order to unit test them you either test every single method or you need to create a dummy class that includes the module and then you test an object of this class. 
Another problem (in my opinion) is that modules introduce hidden dependencies. You can't easily create an object and replace the module with a mock in order to test the collaboration.
The good thing about modules is that it's very easy to use. When you see a common set of methods in two classes, you extract it to a module and the duplication disappears.
My biggest concern with modules is that they break the concept of "Everything is an object", so the theory doesn't fit well with my understanding of object orientation. The practical usage however is very useful, you just extract methods to a module and then you can include it in many classes.
3. Composition
class User
  attr_accessor :buyer
  
  def add_to_cart(product_id, quantity)
    buyer.add_to_cart(product_id, quantity)
  end
end
Composition feels most right to me.
You can compose many objects in one place and delegate the work that you specify. Composition uses classes/objects so you can easily test all the classes separately.
When you want to test a class that uses composition you can easily replace one of the collaborators with a mock and just test the communication.
Composition is perfect for a good OO design, but it's very rare to see it in Ruby/Rails projects and here is my question: Is composition so rare because it's hard to use or is there any other reason?

Update: Added code examples, changed modules to modules/mixins

Tuesday, January 4, 2011

Testing emails with Rails, Steak and email_spec

We've started experimenting with switching from Cucumber to Steak.
Here is how you can use email_spec inside Steak scenarios:

Gemfile
gem 'email_spec', "1.1.1"

spec/acceptance/acceptance_helper.rb
require "email_spec"

spec/acceptance/commenting_spec.rb
feature "Commenting" do
  include EmailSpec::Helpers
  
  scenario "email notification about a comment" do
    find_email(email, :with_text => text).should_not == nil
  end
end