Showing posts with label design. Show all posts
Showing posts with label design. Show all posts

Monday, April 23, 2012

Anti-if workshop #4

During the last weekend I have attended an intense three days workshop lead by Francesco Cirillo on the importance of objects in Object Oriented Programming. Maybe you're reckoning it should be obvious, after all the name states it crystal clear.

Yet, too often we (at least I do) translate the concept to something we could call Class Oriented Programming. Don't get me wrong, classes are good, but only to evaluate the design after we have carefully and thouroghly worked with objects, scenario after scenario. Classes can be confusing, because they solve many different problems: they actually consolidate all the objects that solve each scenario. Then we must start from objects, which means that we should start with a single scenario.

So what is an object?

An object is not only "state and behavior", as we often hear. An object is an instance of a class, but this definition does not add anything to our knowledge (and moves the focus back on classes, where we don't want to keep it).

We used a phenomenological definition: an object is characterized by a series of operations that operate on the object itself and by a state that keeps track of the effects of the said operations (please help me to rewrite it avoiding the pun).

What did I learn? I did not learn to truly think with objects, as three days are not enough to overcome many years of bad habits (I can see clearly now the rain has gone), but I learned that I must strive to do it. And I have some more tools in my shed, even if I have to learn how to use them properly :-)

In a few words, the workshop was completely different from what I was expecting, but I suppose it's been much more effective this way. If I survive from all the homeworks Francesco gave us, I'll plan to write more about it.

I have joined Anti-IF CampaignMeanwhile, join the anti-if campaign as I did a long time ago.

Thanks again to Francesco and to all the brilliant guys I had the luck to meet there... looking forward to meeting you all soon!

Saturday, March 26, 2011

On "Working Effectively with Legacy Code"

In the last few weeks I have spent most of my time working on a legacy system which is going to be partly replaced by a new one which greatly broadens its scope. But what exactly is legacy code? Michael Feathers says that
To me, legacy code is simply code without tests.

It is as simple as that:
Code without tests is bad code. (...) With tests, we can change the behavior of our code quickly and verifiably. Without them, we really don't know if our code is getting better or worse.

Alas, too often the answer is not the one we'd like to hear.

We started out so well

Almost every system, if you have at least decent programmers working on it, starts out as a wonderful green field: defined architecture, code conventions, solid principles, patterns and practices.

After a while the gardeners get busy with other gardens, and a couple of weeds start to poke out. Then some more, then more. And more. Meanwhile seasons pass and rain falls, so our green field gets muddier and muddier. Actually it looks more like it has rained cats and dogs, day after day after day. Mud becomes quicksand, and nobody dares to even get close to it.

The (in)famous spaghetti incident

Too soon the project reaches the point in which whenever you pull a string you have an undesired and often undetected change in a completely different part of the system. When I want to sound important I refer to this as the butterfly effect, a metaphore used in chaos theory. Yes, I know that your projects are different and you have never seen it happen, so try to use your imagination and stay with me a little more, will you?

That was exactly where I was, all tangled up in obscure dependencies: the perfect spaghetti code.


As I tweeted, I love spaghetti when they are in my dish, not in my code, so I had to do something (even because deadlines are always waiting in ambush). To sharpen my tools I retrieved my copy of "Working Effectively with Legacy Code". The book covers many aspects of what we developers have to face daily: instead of the "write once, run anywhere" mantra, we have to deal with "write once, read it at least ten times", but too often our code is obscure. Yes, our code. And we don't have tests, or at least we don't have enough. Do you have a complete coverage? If you do, you have all my respect, otherwise welcome in the family.

How do we get out of this?

First of all, we have to get our code into a test harness, but it is not as easy as it sounds. The book contains a series of 24 different dependency breaking techniques, each of which presented in several almost-real situations, to minimize the impacts of changes and ensure that we are not breaking anything. It sounds like the classic catch-22 thing:

When we change code, we should have tests in place. To put tests in place, we often have to change code.


This is where the techniques come in handy. I was pleasantly surprised when I discovered that, after some years of TDD, almost every problem and solution described in the book sounded familiar, so I skimmed it more than actually reading it. I still remember when I first read it: man it was hard, not the writer's fault, but because of the reader.
One of the most important things is that you have to preserve the behavior of your system when you refactor it (and preserve the rest of the system when you introduce new features or change existing ones), so you should at least know what it does. What is better than some characterisation tests?

Cleaning it up

I love NetBeans. I always have, since it was Forte4Java. Now I love it even more because it has a heap of automated refactorings that make "Refactoring" needless (ehm... that's not true, NetBeans deals with the mechanics, but you should know what you're doing, so stop reading and go buy your copy if you still don't have it. Done? OK, let's get on).

Do you need to create a new test class? nothing simpler, just a simple SHIFT + CTRL + U and a template with all the skeleton methods is ready for you. Just punch in the starting conditions and the expected results and you're done. Feathers describes all refactorings steps by steps, but a few keystrokes are all NetBeans needs to extract superclasses, methods, interfaces, pull up or push down members and methods, delegate, and so on and so forth. Nevertheless, you should know what you're doing.

While working your code could get uglier in some places. It could be temporary, or temporary in the Italian way (which means definitive). Even in the latter case, at least you would have tests in place so that you know you're not breaking anything.

In several places Feathers suggests to reduce incapsulation to put code into a test harness. Somebody might find it strange, extremists might find it insane. Yet...

Encapsulation isn't an end in itself: it is a tool for understanding.


Remember when I wrote that you write code once and read the very same code over and over? What 's the point of an encapsulated design if I spend hours for the most trivial task? Mnd you, I'm not suggesting every field must be public and collections should be directly exposed, but nobody is going die if a private method becomes protected for the sake of testing.

Where have my spaghetti gone?

After a while, one after the other, your pull spaghetti out of your dish, slowly replacing them with neat and tidy sushi.

Before you realize it, you will look at your codebase with different eyes, and chances are that you will enjoy dealing with legacy code. Don't enjoy too much though, even if you have a lot of technical debt to pay: you don't have to pay it for the sake of doing it, but because it allows you to move faster when you need it (and you know you will need it).

Let me stress this again: if I didn't have some hundreds of tests already in place, these weeks would have been months. Baby steps, nip and tuck, red and green bar. But I only introduced tests and refactored legacy code when I needed it, otherwise I would spend too much time on activities that were not a priority. See something rotten? pen it down, fix what you're doing and if you still have time you can deal with it. Look for decisions that could change, but change your code just in time (the YAGNI rule rules).

Wednesday, November 10, 2010

Is Open Session in View an AntiPattern?

A friend of mine pointed me to a willingly provocative article that describes Open Session in View as an AntiPattern. After sharing some thoughts with him, I've decided to post them here.

I agree on the N +1 queries problem, but unless (and until) you have devastating impacts on performances I would not worry about it, applying a YAGNI approach. On the other hand, if a view requires a lot of fetches maybe DTOs come in useful (and I would suggest Dozer). This also semplifies the objects exposed, thus hiding from the "high" layers of the application all the complexities that exist within the domain.

Personally, one of the reasons for which I found Struts 1 frustrating - yet much better than the proprietary framework we were using at the time - was the need for form beans, which lead to tons of duplications (no Dozer yet, a long time ago in a galaxy far far away we only had some Commons Beanutils) which is normally bad. OK, forget the "normally" part.

As a general rule I think that exposing domain objects can be accepted if and only if they are true domain objects, not beans with a bunch of setters and getters and transaction scripts in disguise, otherwise you could bypass many of the application logics and end up with an unmanageable mess.

And, talking about layers leaking, I would also like to quote a couple of sentences from the Domain-Driven Design Using Naked Objects book which I suggest as a very interesting and useful reading:

It takes real skill to ensure the correct separation of concerns between these layers, if indeed you can get an agreement to what these concerns really are. Even with the best intentions, it's all too easy for custom-written layers to blur the boundaries and put (for example) validation in the user interface layer when it should belong to the domain layer. At the other extreme, it's quite possible for custom layers to distort or completely subvert the underlying domain model.


The leaking of the persistence layer is not good per se, but if it does not become a problem you can live with it. As always, it depends on circumstances: why should a spend an incredible amount of resources (which means time and money) to obtain perfect isolation if I don't need it?

In general I think Open Session in View to be a good solution to manage database connections, but it would be even better leverage this strategy with join fetch queries for the most important relations. After all, when writing a service or a facade we know what objects will be needed: this does not mean that the domain or the controller should depend on the presentation layer (they must not!), but pretend that we don't know anything about it is just a waste of time. So, for example, if our facade has a result factory this could be a nice place to eagerly load all objects we know the presentation layer will need; if the view still needs more objects the open session can provide them on the fly: in this way we can optimize the most important parts and live with the rest.

Friday, January 30, 2009

Singletons?

...any global data is guilty until proven innocent
(Martin Fowler)

If you want to be a good software designer, don't optimize code prematurely. [...] If you use the Singleton pattern out of habit, because it "makes your code more efficient", you're prematurely optimizing. You suffer from Singletonitis
(Joshua Kerievsky)

I'm not afraid of a few globals. They provide the global context that everyone must understand. There shouldn't be many though. Too many would scare me.
(Ward Cunningham)

The real problem with Singletons is that they give you such a good excuse not to think carefully about the appropriate visibility of an object.
(Kent Beck)

I mean, it looks like we're not lacking literature on the subject, are we? I wonder why so many people are just too busy with their Singletonitis to consult it (Kent Beck gave a hint on this).

Friday, September 19, 2008

A flexibility contest

The introduction in the Hibernate documentation reports that

A relational database is more flexible than a network programming language, so it doesn't need anything like a navigation direction - data can be viewed and retrieved in any possibile way.

As this is quite a statement, I stopped to consider it a while.

In a programming language you have to consider navigability, so if you have - as in the example - a Person class and an Event class and you want to get all events associated to a person you'll have to ask the person with something like person.getEvents(), but if you also want to get all persons associated to an event you'll have to ask the event with event.getPersons(), i.e. you have to provide accessors to both classes. And both classes hold a reference to a collection of their companion class. Moreover, when you add a person to an event you have to make sure that also the event gets modified, and vice versa.

In an RDBMS you can compose all the queries you like, starting from persons or events; the only thing you'll need is a well defined relation between the tables, which tipically translates into a bridge table. You don't even need to enforce referential integrity, though this is the path to the dark side (or is it?), as long as everybody knows how the tables should be connected. So when you add a person to an event you only have to insert a row in the bridge table.

In this sense databases are more flexible than programming languages. You can write
select *
from person p
left outer join person_event pe
on p.id = pe.person_id
left outer join events e
on pe.event_id = e.id
as well as
select *
from event e
left outer join person_event pe
on e.id = pe.event_id
left outer join person p
on pe.person_id = p.id
but this comes at a cost. You need keys. And you need indexes to manage them (even if this relates to the phisical aspect rather than to the logical one). And a bridge table to manage the many-to-many relationship, which doesn't belong in the domain at all but is a pure fabrication used to represent the model. This clutters things a bit, even if we're so used to it that we don't even notice.

The Java language gives a much clearer representation of the domain (at least, the signatures of the method do):
public class Person {
// stuff
public List getEvents() {...}
public void addEvent(Event event) {...}
}

public class Event {
//stuff
public List getPersons() {...}
public void addPerson(Person person) {...}
}
The language shields you from how the model is represented (that's where the rigidity is hidden), and it is more natural to use.

Databases can use views to simplify data retrieval, but they don't work for inserts and updates. That's where stored procedures come in handy, but... aren't they written in a programming language? Should the latter be considered part if the database or as an external means to get a higher abstraction over SQL (which in turn is a language of its own)? How far should we push this?

My conclusion? Everyone should get their act together to make sure that the quality of what they build is the highest that they can get, either when designing a good database schema or when implementing a bidirectional association. The problem is that "the highest they can get" can sometimes be a low standard, so everyone should always try to improve, no matter how high the standard. I think this rule applies not only to programmers in their own field of competence, but to men in the broader sense.

Wednesday, August 6, 2008

Hello, World!

<sarcastic>Ever came within an ace of understanding those damned patterns, but never really got them? Here's your solution: the classic and boring Hello World refactored to patterns - the ultimate experience!</sarcastic>

public interface MessageStrategy {
public void sendMessage();
}

public abstract class AbstractStrategyFactory {
public abstract MessageStrategy createStrategy(MessageBody mb);

}

public class MessageBody {

Object payload;

public Object getPayload() {
return payload;
}

public void configure(Object obj) {
payload = obj;
}

public void send(MessageStrategy ms) {
ms.sendMessage();
}
}

public class DefaultFactory extends AbstractStrategyFactory {

private DefaultFactory() {
;
}

static DefaultFactory instance;

public static AbstractStrategyFactory getInstance() {
if (instance == null) {
instance = new DefaultFactory();
}
return instance;
}

public MessageStrategy createStrategy(final MessageBody mb) {
return new MessageStrategy() {
MessageBody body = mb;

public void sendMessage() {
Object obj = body.getPayload();
System.out.println((String) obj);
}
};
}
}

public class HelloWorld {

public static void main(String[] args) {
MessageBody mb = new MessageBody();
mb.configure("Hello World!");
AbstractStrategyFactory asf = DefaultFactory.getInstance();
MessageStrategy strategy = asf.createStrategy(mb);
mb.send(strategy);
}
}

The original post is here. Let me add a disclaimer for the overexcited with their eyes rolling, thrilled about the whole thing and eager to refactor all their codebase: don't try this at home.

Tuesday, July 8, 2008

Divide et impera

Following this ancient rule (and Uncle Bob's suggestions) we recently separated our new development effort into four subproject, each of which focuses on a particular aspect of the whole project. The separation is also based on the techniques for splitting the different domain aspects explained in DDD.

Everything has been integrated in Hudson, with the Cobertura, Open Tasks and Violations (with PMD) plugins.

We still have to reintroduce JDepend, but we'll do it in a short while.

Thursday, June 19, 2008

No bump, no set, a spike

Yesterday we ended our second iteration on a brand new project, in which we are trying new technologies and some adjustments to our process. We choose a story which touches almost every layer of the application and made an architectural spike: more a proof of facts than a real application, as we oversimplified domain objects and processes, but it gave us some good insights.

Unit testing is great (and TDD even more), as it forces you to carefully think of the design of your collaborations. And I'm not talking about "Design", rather I'm focusing on simple objects with clear behaviours. After all, tests are the first clients of the objects that make up our applications, and if they're difficult to test it means that they are also difficult to use. As we're totally on a green field, we agreed to not to write any line of code without having a corresponding test first, and it gave us great results. That was very difficult in some legacy applications, due to a very long list of factors (e.g. the persistence mechanism is embedded in every domain object and you can't test anything if you don't have the whole system up and running. Please don't ask, it's already frustrating enough).

Continuous integration is a huge boost for quality, much more than simple unit testing, as it has a broader impact and checks for defects against the work of all the team. Besides, no one wants to break a build and let everybody else know, so you also get improved committments for free. We also configured the PMD plugin for Hudson to report hints for cleaning and refactoring.

Paper cards for story and tasks helped us to easily visualize how the iteration proceeded; keeping the tasks small increased the effect of cards moving from the "open" column to the "closed" one.

We also tried a very simplified variation of CRC cards, based on outdated visiting cards; maybe I'll post something about it, sooner or later.

We tried some technologies that were unknown to some members of the team, but we faced the risk and resolved the problem pairing the untrained members with (more or less) expert ones, who enriched the sessions with many explanations about the basic concepts.

Due to several external incidents which required the help of the team, we didn't have enough time to deliver everything we had planned, but, as we previously agreed on which tasks were droppable, there were no problems in reaching the iteration goals nevertheless.

All the team is now looking forward to the next iteration, which is a very positive achievement.

Tuesday, April 29, 2008

KISS more

Keep - It - Simple - Stupid. We never remember it enough. Too often we overengineer. It's also true that for every complex problem there is a very straightforward solution, which is wrong. But we should really strive to follow this simple rule.

Wednesday, March 26, 2008

A bad citizen in Javaland

I just read this wonderful post on the use of setters and getters in Java classes... that's a very good metaphore which explains why they really break encapsulation, as they actually expose the internal structure of a bean this leading to, er, "interesting" results.

Do I hear someone say "How can I then build an object if I don't have all the mandatory informations I need from the start?"? Well, to begin with that's what Builders are for. If you feel this is an issue you're probabily storing the data in the wrong class.

OOD is about collaborations, not about structures. If you stick with structures, there's some procedural programming lurking under your OO language: you're not asking services, you're instructing slaves. Slaves of which you know everything. Doesn't it smell? You have "sad" objects, as Francesco Cirillo calls them, mere value objects in disguise. That doesn't mean "Transaction Script is evil", but surely means "Transaction Script can be really evil"; it all depends on the domain and on the application you're working on.

That can sometimes lead to another common objection: "data survive applications, so that's the focal point around which everything must revolve". Curiously enough, the way data is persisted is just an implementation detail - and I'm not saying it's easy, as a matter of fact there are a lot of issues and patterns about how to deal with them on the subject. But it's not the main concern in OOD, even if generates a lot of boilerplate code.

Thursday, February 28, 2008

Domain-Driven Design? now you can have it quickly

Eric Evans is the author of Domain Driven Design, a text which explains the importance of having a software closely related to the real domain it models; the book presents best practices, principles and techniques based on real experience.

I found it challenging but very interesting, but one friend of mine found it thick as a brick. Luckily for M. (and I'm sure for many other people out there) InfoQ has released Domain Driven Design Quickly, which does not introduce new concepts but summarizes the essence of what DDD is, drawing mostly on Evans' book as well as other sources.

You can download a free online version, but you are invited to support the work and buy a print copy.