Monday, November 26, 2012

inline-block

This is probably old hat to css veterans, but, for someone like myself who last did hardcore html work in days of tables, it was a neat trick for me to learn.  On our login page the user is asked to select their location within the hospital.  To start out with, we had a simple selection list with all of the locations.  But, for improved usability, the actual design called for the locations to be grouped into three columns. I was prepping myself for an alignment nightmare when Alex showed me that it could be done simply by setting the "display" attribute to "inline-block".  This allows you to set each element as a fixed width, and, tada, you end up with aligned columns.

To get this...



... all we had to do was this...

<div id="sessionLocation">
       <% locations.each { %>
             <span class="locationOption" value="${it.id}">${ui.format(it)}</span>
       <% } %>
</div>


and

.locationOption {
    display: inline-block;
    font-size: 1em;
    padding: 3px 15px;
    width: 250px;
}

(Then you can just use some simple javascript to mimic selection list functionality)

I found a good article that discusses inline-block in greater detail:

What’s the Deal With Display: Inline-Block?

All right, I'm going to head back to work on the API now and stay out of the web layer as much as possible... :)

Friday, November 23, 2012

OpenMRS Style Tip: standardizing our DAOs, and avoiding data-level services

We've developed a new best-practice way of organizing services and DAOs in OpenMRS, and I wanted to share that here.

1. We should have one DAO class for every domain object, and the boilerplate code should be encapsulated in an abstract base class

2. A service can contain multiple DAOs, for related domain functionality:

3. The service methods should expose higher-level functionality, rather than just CRUD

Below are (long) code samples:

Friday, November 16, 2012

Pretty pictures

For a long time at the beginning of every software project, it seems like you can only really blog about technical stuff, which I'm sure gets boring for all the non-developers out there.

And while I could keep talking about maven modules and behavior-driven development until you fall asleep, we've finally arrived at the phase of the project where we'll start having actual pretty pictures to show. :-)

Here's our first pass at the login screen. Note that we're building in the idea of a "session location," mostly so when you start filling out forms, you don't have to keep saying where you are:


And here's our first pass at the homepage: (note that the list of apps a user actually sees depends on user privileges)


Since I can't end a blog post without some technical content, I should point out that these are much easier to develop now that we've started using Sass and Compass. If you've ever written CSS and you aren't using these tools, you've got to start, stat! (If you look at our omod/pom.xml and search for "compass" you'll see how we incorporated these into the build process.)

Thursday, November 8, 2012

Premature Optimization

Last week, we had a discussion on my project about what we should test. For sure there is a boundary for test, but where does this boundary live? I'm an advocate for tests, mostly unit tests. I think by using unit tests we have documentation about our classes and also good and quick feedback on what we're doing. It is a good safety net.

Ok, but everyone knows that. What happens when takes too much time to create a test? It happens in legacy systems when classes have big methods, use a lot of static methods, no dependency injection, etc. But everyone knows those classes are working, because the system is working. It is legacy code, but it is also working code. Should we test those classes? In this discussion, one of the members of my team Fernando Freire, told me about a presentation (only in Portuguese) from Lucas Cavalcanti at Agile Brazil. This presentation is about Premature Optimization and it is about how and when clean code and good design practices can help us to deliver. In this presentation Lucas uses a pseudo-graph from a Martin Fowler post. Design Stamin Graph Well, the graph shows the delivery curve using good design and also no design. In the beginning, the team that uses no design "practices" can delivery faster than the other team that uses good design practices. But this changes after some time and the team with good practices delivers more. The problem is how long is this "some time". It is very difficult to estimate. It depends of the project, on the team and when we have to deliver.

After this discussion, I thought a lot about this graph. When is it safe keep moving with fewer tests and when do we have to use all the good practices to slow down the team. I'm pretty sure that the answer to my question above, about to testing a class that is hard to test, is that it depends. If you have a tight deadline and you're not changing this class, well, you don't need to test it. But if you know you'll have to change this class a lot, then I think it is worth spending some time to cover it with tests and to refactor it to make the class more simple and readable.

Actually, I had to to take a decision like this. I was pairing with Darius and we were changing the patient registration module to be able to add two new fields in the check-in flow. The code wasn't that good and we didn't have any unit tests testing it, after some discussion, we realized that refactor everything to able to test it won't be a good decision. It would take too much time and it won't bring much business value since we didn't have plans to change that screen in our short period of time. After 1 month, I still think that was a good decision and we saved a lot of time.

My conclusion after this discussion is: we cannot compromise our delivery because of good practices. The good practices were created to help us to deliver more, to create more value for the client. If good practices are slowing the team down, something is wrong. I know its easier said than done. Sometimes this boundary about what and when to test is hard to see. Actually, most of the time this it is VERY hard to see. But this is what Agile is about right? If we focus on delivering value, we'll learn where this boundary lives and learn how to improve the team velocity.

BDD while doing OpenMRS development, thanks to Thoughtworks

I recorded a screencast for OpenMRS University a couple days ago, which was supposed to be about using the UI Framework module. I ended up doing an extra 25-minute tangent about behavior-driven development of API functionality, inspired by the process Thoughtworks has been helping us take up.

Watch on YouTube (over an hour long)