Tuesday, April 29, 2014

Remote team tools

I've been speaking today at a local IT entrepreneur meetup about remote work and about the ways a company can transition towards being more remote.

The part of the talk that seemed to be most interesting was the toolset that we're using at the moment. I thought I'd share this list here, as well.

Remember, that tools should just support your process and not replace it. If your goals are clear to you and your team, then the tools are just implementation details.

  • Internal (written) Communication - IRC
  • Requirements/Tickets - Trello
  • Documentation - Hackpad
  • Voice communication - Mumble
  • Code reviews - Github
  • Continuous Integration - Jenkins
  • Remote pairing - tmux
  • Video calls - Google Hangouts


Internal (written) Communication - IRC

For most of the internal communication in the team, we've been using IRC. It's a kind of a old-school tool. It served us well for about 7 years now, but meanwhile we've been experimenting with alternatives, like Slack (just recently).

The tool itself is not that important, it's the goal it serves that is interesting.

We have one channel per project and several generic channels, like #lol, #arkency, #links, #coffee, #products, #blog.

The project channels are often integrated with other tools and receive notifications from Trello, Github, Jenkins. This is like the headquarters.

In some projects we also use Slack or Flowdock for the same goal.

Requirements/Tickets - Trello

This is our default project management tool. It works as a backlog. It contains many tickets/stories, prioritised and described. It helps detailing the requirements and seeing what's the status.

The tickets are also refactored - we extract new tickets, rename them, group them - whatever is needed.

In some projects we use Pivotal, Redmine or Asana for the same goal.

Documentation  - Hackpad

Hackpad - this is my favourite one. If you're not familiar with it already, it works similarly to Google Docs. In my opinion, it's a bit more interactive.

It's basically a wiki on steroids. It has support for collections, it notifies about changes via email. You clearly see who wrote what. You can comment sections of code and checkboxes.

Whatever interesting happens in our company, it gets an URL on Hackpad. Do I have an idea for a bigger refactoring in one project? I create a hackpad, paste some code and describe the plan. Others can join whenever they want (async!) and add their comments.

Voice communication - Mumble

Mumble is probably unknown to you. It's a tool very popular among gamers. They use it to communicate in a team, during a game. We started using it, as it was much more reliable than Skype. It's a very minimalistic tool. It has the concept of channels, so we designed it similarly to our communication tool (IRC). It also allows recording the conversations, so that people who were not able to attend (async!) can later listen to the most important fragments.

Code reviews - Github

We use Github for hosting code and for making the micro-code reviews. I call it micro, as they only let us comment the deltas - commits or pull request. They don't let us comment the existing code base, which is a limitation many similar tools share.
If there's one place, I'd like to see improvement for remote teams it would be a proper code review tool.

Continuous Integration - Jenkins

We host the Jenkins instances to build our projects. I'm very far from liking it - it has many quirks, but overall we didn't find a good alternative to switch, yet.

Remote pairing - tmux

I blogged about remote pair programming 6 years ago. At that time, I was using screen + vim and I still think it's a good combo (together with Skype or Mumble). Nowadays, we don't pair program too often, but when people in my team do that, they often use tmux to connect to each other (terminal-based). Another tool is tmate.io, which is also tmux-based.

On a good connection you can also use Google Hangouts and their Desktop Sharing feature.

Video calls - Google Hangouts

We use video calls very rarely and mostly, when external teams are involved who prefer it. In that case, we use Google Hangouts.

Summary

It's important to understand that those are only tools. They can change. I'm pretty sure, next year, we'll use a different toolset. What's important is the process around it - how you collaborate on projects, how you split stories, how you discuss, how you collaborate on the code.


If you'd like to learn more about the techniques that we use in our remote and async collaboration (not only about the tools), then let me recommend the Robert Pankowecki book about it (I also wrote one chapter): Developer Oriented Project Management.

What tools are you using? What would you recommend?

Sunday, April 27, 2014

TDD and Rails - what makes a good Unit?

There is an ongoing discussion about TDD and Rails. It was recently heated by some some of the DHH statements in his RailsConf keynote and in the blog post: http://david.heinemeierhansson.com/2014/tdd-is-dead-long-live-testing.html

One aspect of this discussion is the confusion about - What makes a good Unit?

In the Rails community, I've seen people overusing mocks and stubs - you can detect it by looking at all the "should_receive" calls in the codebase. They're not always bad, but they might be potential code smells.

The reason we use should_receive is in a way to draw the boundary between what's important to test right now and what's outside of the test scope.

Unit example

Let's take an example - you've got an Order, which can have many OrderLines, a ShippingAddress and a Customer.

Do we have 4 units here, representing each class? It depends, but most likely it may be easier to treat the whole thing as a Unit. You can write a test which test the whole thing through the Order object. The test is never aware of the existence of the ShippingAddress. It's an internal implementation detail of the Order unit.

A class doesn't usually make a good Unit, it's usually a collection of classes that is interesting.

This way of defining a Unit gives you tests, that don't need to change whenever the internals change - that's a good thing. You don't want to change tests on every refactoring - in fact it's a smell.

Unit-based architectures

Some time ago, I wrote a surprisingly popular post: The four architectures that will inspire your programming in which I listed:


  • Hexagonal Architecture
  • Clean Architecture
  • DDD
  • DCI

In a way, all of them are focused on defining what a good Unit is and how to separate it from other Units. 

DDD has the concept of an aggregate, quote: "A DDD aggregate is a cluster of domain objects that can be treated as a single unit."

Clean Architecture has the concept of use-cases which touch the topic slightly differently (by operations, not units), but overall it's very similar: http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html

Hexagonal Architecture is all about a Unit surrounded by adapters, in my interpretation. They often call it the Middle Hex. http://alistair.cockburn.us/Hexagonal+architecture

Last, but not least - DCI. This architecture deserves a special mention here. DHH quoted James Coplien in his TDD talk. James has been famous not only from his strong opinions on TDD, but more from his activity in the DCI world. He's one of the fathers of this movement. DCI is the most inspiring architecture here. Ruby and DCI makes a fantastic combination, however not all can work as in the DCI theory. DCI gives good tools for defining what a Unit can be. In short, their approach to what a Context is, may be used to defining Units. A Unit is this paradigm is a collaboration of objects. Read more here: http://fulloo.info/

Have fun in researching more!

If you want to follow more of my work - I'm writing a book on Refactoring Rails apps, which is already available. At the moment, I'm writing new chapters on how to write tests that support refactoring of Rails apps.

Tuesday, April 15, 2014

Be careful with "the Rails way"

The "the Rails way" expression is becoming popular in the Rails community. Depending on the people who use it, it means either something good or something bad. 

(btw, this blog post has nothing to do with a book with a similar title)


This post is about why I think that "the Rails way" is not always so positive. 

Let me start with the DHH ping pong story, which is happening now as it has a good code example to focus on.

The history

The code ping pong with DHH has already started and my submission was chosen by DHH as the first one.
For those of you who are not familiar with the code ping pong action - there was an interesting discussion on HackerNews triggered by the “Rails - the Missing Parts” post.

At some point DHH wrote:

"If this is a poor example, pick a good example. I'll be happy to code ping pong you whatever example you choose.”

The idea was picked up by Marcin "the awesome" Stecki from Netguru, who created http://www.dhh-ping-pong.com/ and announced it at the http://wrocloverb.com/ conference.

As I’m writing a book on this exact topic (how to turn Rails controllers into service objects) I decided to submit my example. I took the code from my recent blog post on refactoring: http://blog.arkency.com/2014/02/rails-refactoring-the-aha-moments/

DHH picked up the example and here we are, having different solutions to the same Rails problem.

This is the actuall Pong page: http://www.dhh-ping-pong.com/pongs/13 (you can vote there).

Why I’m participating in this?

It wasn't an easy decision. Going public with some piece of code is not unusual in the age of open source. Here, however, it's going to be compared. It's going to be pointed out. There's some voting going on. I'm an easy target now ;) 

It's not about voting, though.

The Rails community is huge nowadays. It's not the same small group of people, as it was in 2004-2005. We have hundreds of thousands Rails programmers in the world. Every day, new people are joining our community.

Rails is no longer used only for small apps. 

It's used in enterprise. People rely on Rails codebases to make money for living. I'm sure, that somewhere out there, there is a Rails codebase, on which people lives depend on.

Let's talk about responsibility.

Are we responsible for all Rails codebases out there? For sure, not. But there's a lot we can do to help our community and thus help the people who rely on Rails codebases.

Can we do something about those codebases being better? Not directly. 

A small thing, that we can do is to trigger discussions. It's not for the sake of discussions. It's for the sake of learning. For the sake of improving. 

It's easy to go too abstract with discussions. This is where DHH is totally right. 

Let's focus on the code. 

I'm glad that DHH picked my example. It's based on a real Redmine code. Such code is written everyday by many programmers. The problem is small enough to be presented in one page. It's big enough to show different approaches.

Can my code be better? For sure! My code wasn't meant to be perfect. The main focus of the research and practice for my book is how to let people get out of the messy Rails codebases on a step-by-step basis. You can't risk rewriting the whole part. Every line of code can be hiding some potential user path. You have to make safe steps. 

I believe in gradual improvement. I prefer evolution over revolution in the code.

That's why my example is not perfect. It's just a snapshot from a refactoring session that I took one evening. However, it's good enough to show some concepts. 

It's showing the concept of a Service object. Even, if at the current shape it's using the "hack" of SimpleDelegator, it's worth to have it extracted.

I'm not proud of this code, neither I'm ashamed.

It's hard to discuss code refactorings without taking the time cost into account. It's not impossible to rewrite Redmine to a better code. It's a function of time. 

If you look at the DHH code, the shape of the code (yes, code has a shape!) is better. Overall, the example is shorter than mine. I think not all the cases are covered, but that's not the point. DHH focused on using some of the Rails features to make the code shorter. The code is good. I'd take it over the existing Redmine code, without any doubt (assuming all the paths were covered!).

It's nice to see both the pieces of code, side by side.

We both agree that the existing code was bad

First of all - that's probably most important here - we both agree that the existing code was bad. That's a good starting point.

Where do we differ?

I didn't actually talk to DHH about it. I hope I'm not misinterpreting his intents here.

The main difference seems to be the fact, that I tried to escape the framework as early as possible. I avoided controller filters. I avoided model callbacks. Those are the things that I teach how to get rid of, if possible. DHH went the opposite way, he's using filters, he's using callbacks.

I'm not here to judge which approach is better.

Let me explain my refactorings here. I want to isolate my code from the framework. I didn't go that far, but I also want to isolate the 'logic' from persistence in the next steps (by using the repository pattern). The goal here is to have your logic framework-independent. To be able to run tests quickly, without hitting the database. To be able to split your app into smaller pieces - gems or microservices. To be able to control the whole application easier, this way.

In a way, it's an unusual approach in the Rails world. It's not so unusual if you look at other communities - Java, .Net, Scala, Clojure, Haskell, even PHP (with the fantastic Symfony2 framework).

Wasn't that the reason that we use Rails not to need to escape from it?

Yes and no.

It's a longer story, for another blog post, probably. In short, I believe that Rails is good for the start (as long, as you're not efficient with other approaches yet), however it's bad for a longer run. 

Rails gives you a nice start, very quickly. This usually helps with the costs and the business side of the project. In the longer run, though - you have a much bigger codebase ( think > 100 database tables, if that means anything useful) and you want to split into smaller pieces. The more you're using Rails-specific features, the harder it is to split. It's a hard, ongoing transformation that can take months or years. That's why it's so important to realise it quickly and start sooner.

I've seen many projects that are stagnating with a typical Rails codebase. It's so hard to escape from the Rails monolith at some point.

You can say, that it's about programmers having low skills and that's the problem, not Rails. It's right to some extent. However, when you're stuck with a Rails codebase, you rely on a lot of magic. The Rails framework code is in fact becoming your code. Whatever happens inside, it's your problem now. It's hard to be a good programmer in the legacy Rails environment.

At the beginning the pain is not so visible. It's hard later, when new requirements are coming. The ones, that are not shown on all Rails tutorials. The ones that require you to actually do some domain modelling, to secure the business logic, to hide some data from different roles. This is the place, where Rails is not helping you - it's going into your way. This is the moment, when you realise that mixing logic and persistence is not really the best idea. This is the moment, when your build already takes 20 minutes and you'd actually prefer to add even more tests. This is the moment, when you're better with a modular design instead of the connected design, as Kent Beck rightly points out.



I'm showing a way that makes it possible to deal with bigger Rails codebases in the longer run. I'm not saying this is the only way to stay alive. It's just one way.

DHH and his team are very successful with "the Rails way". Business-wise I can't even compare my "successes" with their huge success. 

Why choose the way I'm suggesting over "the Rails way"? I believe it's easier. It's based more on the overall programming rules, than on relying on some specific Rails features. You can look at the projects created in other communities and apply the lessons in your project. When you rely on Rails, you're in the ActiveRecord-based programming land. A place that lives somewhere between a relational database and OOP. It's a world on its own. You can be successful here, but it's a one-way ticket.