Friday, October 26, 2007

Every time you're writing a piece of code and you have to deal with unknown corner cases ...Every time you're implementing some kind of logic and you don't know what to do when things go bad ...Every time you think: this can never happen, I don't have to check for it ...Every time you don't know what to do or what would happen ...Please ...

Tuesday, October 23, 2007

It wasn't easy: the standard JavaMail configuration didn't work, while Google gave me a lot of wrong and/or outdated information.Moreover, JavaMail FAQs provide a sample about sending emails via GMail, but it has some problems too.

So I think these bits of information will be helpful to someone trying to accomplish the same task ...

The problem is that GMail uses TLS and the STARTTLS command.The solution applies to JavaMail 1.4 and JDK 1.4 or higher and is just a matter of configuration.

First, and obviously, enable POP support for your GMail account.

Then, put the following configuration in your properties file:

mail.transport.protocol=smtp

mail.smtp.host=smtp.gmail.com

mail.smtp.starttls.enable=true

mail.smtp.auth=true

mail.user=<your_username>

mail.password=<your_password>

The key point is the part in bold: enabling the STARTTLS command.That's the tricky part.Once created the properties file above, just configure your JavaMail Session object and send your mail message as you'd always do:

We'll see how wrongly managing responsibilities and behaviors, while abusing getters and setters, can lead to a corrupted business domain, and how the patterns above will help you to correctly address these kind of problems.

The business domain.

Let's start our discussion by showing a simple business domain.We're implementing yet another ugly e-commerce system, so we have a shopping cart holding a number of orders, each referring to a given product.Without going further on, let's restrict our domain model to three simple entities: ShoppingCart, Order and Product.

A ShoppingCart can hold one or more Orders, and an Order refers just to a single Product.Moreover, we have some simple business rules regarding these entities:

The ShoppingCart total is the sum of all Order sub-totals.

Each Order sub-total is the Product price times the ordered Product quantity.

The ShoppingCart total cannot exceed the value of EUR 10000.

Pay particular attention to the latest point: it is an invariant, a rule that must be always kept valid.

That's all.Very simple, isn't it?

Let's implement it : the wrong way.

The entities and rules above can be straightforwardly implemented as follows:

public class Product {

private String name;

// ...

private double price;

// ...

public double getPrice() { return this.price; }

public void setPrice(double price) { this.price = price; }}

public class Order {

private Product product; private int quantity;

public Product getProduct() { return this.product; }

public void setProduct(Product p) { this.product = p; }

public int getQuantity() { return this.quantity; }

public void setQuantity(int q) { this.quantity = q; }}

public class ShoppingCart {

private List orders = new ArrayList();

public void addOrder(Order o) { this.orders.add(o); }

public List getOrders() { return this.orders; }}

As you can see, all classes have the right properties and dependencies:

A Product has a price.

An Order refers a Product and has a product quantity.

The ShoppingCart has more orders.

The ShoppingCart total can be calculated by iterating all Orders and summing up each Product price times the ordered product quantity.

However, this design (and implementation) is seriously flawed:

There's no clear assignment of responsibilities and behaviors.

Hence, it is full of getters and setters.

Hence, there's no encapsulation.

Hence, all business logic is external.

Hence, it is easy to corrupt domain state and violate business rules.

How?

Given our design and implementation, the following code is absolutely legal:

Product p1 = new Product();Product p2 = new Product();

p1.setPrice(1000);p2.setPrice(2000);

Order o1 = new Order();Order o2 = new Order();

o1.setProduct(p1);o1.setQuantity(5);

o2.setProduct(p2);o2.setQuantity(5);

ShoppingCart cart = new ShoppingCart();

cart.addOrder(o1);cart.addOrder(o2);

But hey, wait!The ShoppingCart total is now EUR 15000!That's because the business logic is computed outside of the object that holds the information; so let's solve this problem by introducing the Information Expert pattern.

Refactoring toward the Expert.

The Information Expert pattern is part of the General Responsibility Assignment Software Patterns (GRASP), and states the following:

Assign a responsibility to the information expert: the class that has the information necessary to fulfill the responsibility.

We have two responsibilities to relocate:

The shopping cart total computation: here, the information expert is the ShoppingCart class.

The order sub-total computation: here, the information expert is the Order class.

By relocating the two responsibilities we'll improve our encapsulation and make our implementation more robust, because the ShoppingCart will be able to check that the total doesn't exceed EUR 10000.

The problem is that we can always change the Order product and quantity, changing so the shopping cart total without preventing it to enter in an invalid state!

Where's the real problem?How to solve it?

Refactoring toward the Aggregate and the Value Object.

The real problem is that we are interested in keeping the ShoppingCart state always correct, that is, in keeping its invariants: however in the current design and implementation we are not able to control everything happens inside the ShoppingCart, because we can directly modify its Orders without going through it!

The solution is to apply the Aggregate and Value Object patterns, part of the Domain Driven Design.

An Aggregate is a set of related objects whose invariants must always be kept consistent, and an Aggregate Root is an object that acts like the main access point into the aggregate; all access must go through the root, and objects external to the aggregate cannot keep references to objects contained into the aggregate: they can keep a reference only to the aggregate root.

A Value Object is an object that has no identity and is immutable: it is equal to another value object of the same type if its properties are equal too, and must be discarded if its properties need to change.

How to turn this theory into practice, applying it to our domain?

First, our ShoppingCart and Order are part of an aggregate.It's easy: the "EUR 10000" invariant involves both objects, so it must be kept consistent across the two.Moreover, Orders make sense only if related to a ShoppingCart, so no one should access an Order without first going through a ShoppingCart: this means that the ShoppingCart is the root of the aggregate.

Second, the Order is a Value Object: it doesn't make sense to create an order and change its related product and quantity during its life cycle; an order always refers to the same product with the same quantity, and if something needs to be changed, it must be discarded and a new one must be created.

Saturday, October 13, 2007

I'm not going to talk about the great Pearl Jam song.I'm going to talk about me, because (very) long time has passed since my last post, and yes ... I'm still alive.

I don't want to bother you too much, just let me jumble a few bullet points about the most important things happened to me during these months:

I finished working at that big project for RAI, the Italian State Television, involving the design and development of its main portal. It was a very interesting experience and I think I'll write more about things I learned (because we always learn), in the future.

I became a committer of the Taconite Ajax Framework, improving my Javascript skills and working with CSS Selectors.

I've been at Spring One 2007 and it was nice, even if it didn't fulfill my high, maybe too high, expectations.