Code Crafter

Exit the Cruft, Enter the Craft

Thursday, March 1, 2012

Some OO Design

"The critical design tool for software development is a mind well educated in design principles. It is not the UML or any other technology." - Craig Larman

I've recently found the following interview question on stackoverflow:

Basic sales tax is applicable at a rate of 10% on all goods, except books, food, and medical products that are exempt. Import duty is an additional sales tax applicable on all imported goods at a rate of 5%, with no exemptions. When I purchase items I receive a receipt which lists the name of all the items and their price (including tax), finishing with the total cost of the items, and the total amounts of sales taxes paid. The rounding rules for sales tax are that for a tax rate of n%, a shelf price of p contains (np/100 rounded up to the nearest 0.05) amount of sales tax.

This is a very familiar example that can be used as a really good gauge of various software development skills. There are many different ways to solve this problem. I'll use object-oriented techniques and the Java language to show one such possibility. I'll not show a step-by-step process, just some ideas on how I got to the end result.

Introduction

Before writing any line of code (even tests), I like to think about the main entities involved and broadly how they're connected. This can be seen as a very high level Domain Model that will support the described scenario and serve as the foundation for any subsequent requirement.

At a high level, there are Products, Taxes and Orders. I can put Products into Orders, where Taxes will be applied; and I can get a detailed Receipt for all Entries in the Order.

Then, I'll create the first automated acceptance test, what will drive my design choices. For that, I'll create a couple of Taxes, Products, and an Order.

Products

I'll start with the Products. From the requirements, Products have a Name, a Type (or Category), an indication of whether they're Imported, and a Price. This is how I'd like to create one:

Product ddd = Product.create("Domain Driven Design", ProductType.BOOK, ProductOrigin.LOCAL, dollars("69.99"));

There are many assumptions and simplifications here. First, I'm representing ProductType as a simple enumeration:

public enum ProductType {
  BOOK,
  FOOD,
  MEDICAL,
  MOVIE
}

This fixes the types of product in the code. It's more sensible to think that new types can be created at runtime, and that ProductType deserves a class of its own. But, since I want to focus on the sample scenario and finish my acceptance test, I'll just live with fixed types for now. Also, different types of products could have different properties; Movies can have Length and Cast, Books can have Authors and NumberOfPages. For fixed types this could be modeled with Product subclasses; for dynamic types more complicated DynamicProperties (pdf) could be used, with an effort to find the least amount of property "bags" that would describe most product types. These property bags could also be created as subclasses of some ProductProperties class.

The ProductOrigin enum indicates if a product is imported or not:

public enum ProductOrigin {
  LOCAL,
  IMPORTED
}

I could have used a simple boolean, but the enum makes the code readily understandable.

For the price, I'll use a simple Money class, which is a ValueObject that stores an amount as a BigDecimal. Money is a valuable abstraction; it's more work than using raw BigDecimals, but it improves the intention of the code. It's the simpler thing, not the faster thing. Since all my values will be in dollars, I don't even include a Currency, and leave the constructor private to control instantiation through the dollars factory method, which I statically imported to write the Product creation statement. Also, I set the number of decimal places to 2 (the usual for dollars) rounding up.

public class Money {

  public static Money dollars(String amount) {
    return new Money(new BigDecimal(amount));
  }

  private final BigDecimal amount;

  private Money(BigDecimal amount) { 
    this.amount = amount.setScale(2, RoundingMode.UP);
  }

  ...

}

Prices are one of the most volatile Product properties. They can change with time, with store or market; they can have discounts, different values in different currencies and many other variations. The price associated with a product can be seen as its BasePrice, which at a minimum should be a TemporalProperty. But, for the time being, I don't need to address these concerns, but it's still good to keep them in mind.

Taxes

Now I can tackle taxes:

Basic sales tax is applicable at a rate of 10% on all goods, except books, food, and medical products that are exempt.

The first part is easy. Taxes have a Name and a Rate:

Tax basicSalesTax = Tax.create("Basic sales tax", "0.10");

The Rate is stored as a BigDecimal. Doubles and Floats are never suitable for financial calculations, even when used as rates.

But Taxes are not universally applicable, and there needs to be some kind of TaxEligibilityCheck to find out if a Tax should be applied to a Product (actually, it's better to check if it should be applied to an Entry, as eligibility could be based on factors other than Product properties).

One way to do this is to have an abstract method boolean isEligible(OrderEntry entry) (I'm calling Entry an OrderEntry in the code) in Tax, and have a subclass for each different eligibility criteria. The basic sales tax could then be created like this:

Tax basicSalesTax = TaxWithExemptionsOnProductType.
  create(
    "Basic sales tax", "0.10", 
    ProductType.BOOK, ProductType.FOOD, ProductType.MEDICAL);

Here, I'm assuming there's a Tax subclass named TaxWithExemptionsOnProductType that overrides isEligible to check the product type against the given exempt types. I'd also have a subclass named TaxForImportedProducts that's only applicable to imported products. But, if I wanted a tax that's applicable to imported products with certain product type exemptions, it would be awkward. I'd have to start mixing the logic of both classes and possibly create a third one that combines them. No, I'd like to keep each eligibility check Strategy separate, with the possibility of combining them for Composite criteria. Maybe I'll never need criteria different than the ones in the example, and maybe I'll never need to combine them. But, clearly delineating the responsibilities in the design makes it simpler, easier to understand and easier to evolve. Again, the simpler thing is not the faster thing. And so, I need a new abstraction:

public interface TaxEligibilityCheck {
  boolean isEligible(OrderEntry entry);
}

And Tax will now have a TaxEligibilityCheck instance.

I can already imagine using the Specification pattern to create Composite criteria based on logical operators:

Tax basicSalesTax = Tax.
  create(
    "Basic sales tax", "0.10", 
    and(exempt(ProductType.BOOK), exempt(ProductType.FOOD), not(imported())));

This very flexible approach is a possibility with the TaxEligibilityCheck interface. I couldn't get there easily with subclasses. Finding the right balance between current needs and possible future needs is always difficult, and you should never create superfluous or speculative elements. But it's a win-win situation when a more flexible design is even simpler than the obvious, direct design. Following that advice again, I don't need the full Composite Specification pattern right now, so simple one-off implementations will do.

Besides checking for eligibility, the Tax has a Money calculate(Money amount) method that applies its rate to the given amount (I'm also renaming the class to TaxMethod, not to be confused with a calculated tax amount):

public class TaxMethod {

  public static TaxMethod create(String name, String rate, TaxEligibilityCheck eligibilityCheck) {
    return new TaxMethod(name, new BigDecimal(rate), eligibilityCheck);
  }

  private final String name;
  private final BigDecimal rate;
  private final TaxEligibilityCheck eligibilityCheck;

  private TaxMethod(String name, BigDecimal rate, TaxEligibilityCheck eligibilityCheck) {
    this.name = name;
    this.rate = rate;
    this.eligibilityCheck = eligibilityCheck;
  }

  public boolean isEligible(OrderEntry entry) {
    return eligibilityCheck.isEligible(entry);
  }

  public Money calculate(Money amount) {
    return amount.multiply(rate);
  }

  ...

}

Order

With Products and TaxMethods, it's time to create an Order:

Order order = Order.create();
order.addTaxMethod(baseSalesTax);
order.addTaxMethod(importDuty);
order.addProduct(ddd, 1);

I'm adding the tax methods that the Order should use when calculating the tax for products. This could create a kind of temporal coupling, if taxes are calculated at the time products are added, I should first add all tax methods, and then start adding products. Let's eliminate that coupling:

Order order = Order.createWithTaxMethods(baseSalesTax, importDuty);
order.addProduct(ddd, 1);

That's better. Now I'm passing the tax methods to the constructor (ahem, factory method); which must be done before adding any products. Still, it's a little awkward that Orders have to keep a list of TaxMethods. I need some kind of TaxMethod container, something that will let me reuse the same taxes in different orders; a TaxingPractice that will encapsulate the tax methods in use:

TaxingPractice taxingPractice = TaxingPractice.create();
taxingPractice.add(basicSalesTax);
taxingPractice.add(importDuty);

Order order = Order.create(taxingPractice);
order.addProduct(ddd, 1);

Order Entries

The Order needs to store two types of entries: ProductEntries and the derived TaxEntries. Again, there are many ways to do it, and I've chosen to have a common interface for both entries:

public interface OrderEntry {
  Product getProduct();
  Money getAmount();
}

But still I've chosen to keep them in separate collections inside the Order:

private final List<ProductEntry> entries = new ArrayList<ProductEntry>();
private final List<TaxEntry> taxEntries = new ArrayList<TaxEntry>();

This implementation will simplify the calculation of the various totals that I need (SubTotal, TaxTotal and Total); but it's completely encapsulated in Order, and I'd like to be able to change it in the future without impacting any other class. The other possibilities that I see are having a single List<OrderEntry> for both kinds of entries or having a composite Order encapsulating the internal leaf orders ProductOrder and TaxOrder.

When adding products to an order, I calculate taxes right away:

public void add(Product product, int quantity) {
  ProductEntry entry = ProductEntry.create(product, product.getPrice(), quantity);
  entries.add(entry);
  taxEntries.addAll(taxingPractice.apply(entry));
}

The TaxEntries are derived from the created ProductEntry using the TaxingPractice tax methods and put into the taxEntries collection. It's good to keep a link between the product entry and its derived tax entries, so we better know the origin of the calculations and can more easily manipulate the objects, for example: removing a product from an order should also remove its derived tax entries (a "feature" I have not yet implemented).

This is what the TaxingPractice apply method looks like:

public Collection<TaxEntry> apply(ProductEntry entry) {
  List<TaxEntry> entries = new ArrayList<TaxEntry>();
  for (TaxMethod tax : taxes) {
    if (tax.isEligible(entry)) {
      TaxEntry taxEntry = apply(tax, entry);
      entries.add(taxEntry);
    }
  }
  return entries;
}

private TaxEntry apply(TaxMethod tax, ProductEntry entry) {
  Money taxAmount = tax.calculate(entry.getAmount());
  return TaxEntry.create(entry, tax, taxAmount);
}

To calculate totals, then, the Order just needs to sum its entries' amounts:

public Money getSubTotal() {
  return getTotal(entries);
}

public Money getTaxTotal() {
  return getTotal(taxEntries);
}

public Money getTotal() {
  return getSubTotal().add(getTaxTotal());
}

private Money getTotal(Iterable<? extends OrderEntry> entries) {
  Money total = dollars("0.00");
  for (OrderEntry entry : entries) {
    total = total.add(entry.getAmount());
  }
  return total;    
}

Receipt

The information that's in the Order will be used to create a Receipt. But how should that happen? A Receipt features a visual representation of the information contained in the Order, what conceptually could have many different formats. I can think of two ways to do it: let the Receipt derive its information from the Order or let the Order provide its information to the Receipt. I chose to let Order present its information to the Receipt, which will work like a Builder object. To allow for different receipt implementations, I created a Receipt interface:

public interface Receipt {
  void start();
  void printProduct(ProductEntry entry);
  void printTax(TaxEntry entry);
  void printSubTotal(Money subTotal);
  void printTaxTotal(Money taxTotal);
  void printTotal(Money total);
  void end();
}

The Order just provides all the necessary information to the receipt:

public void print(Receipt receipt) {
  receipt.start();
  for (ProductEntry entry : entries) receipt.printProduct(entry);
  for (TaxEntry entry : taxEntries) receipt.printTax(entry);
  receipt.printSubTotal(getSubTotal());
  receipt.printTaxTotal(getTaxTotal());
  receipt.printTotal(getTotal());
  receipt.end();
}

This way, receipts are really independent from orders. I created a very simple receipt that I can use like this to print to the console:

SimpleReceipt receipt = SimpleReceipt.create(System.out);
order.print(receipt);

Putting it all together

An example usage is this:

// configure the system
Product ddd = Product.create("Domain Driven Design", BOOK, LOCAL, dollars("69.99"));
Product goos = Product.create("Growing Object Oriented Software", BOOK, IMPORTED, dollars("49.99"));
Product house1 = Product.create("House M.D. Season 1", MOVIE, LOCAL, dollars("29.99"));
Product house7 = Product.create("House M.D. Season 7", MOVIE, IMPORTED, dollars("34.50"));

TaxMethod basicSalesTax = TaxMethod.create("BST", "0.10", exempt(BOOK, FOOD, MEDICAL));
TaxMethod importDuty = TaxMethod.create("IMD", "0.05", imported());

TaxingPractice taxes = TaxingPractice.create();
taxes.add(basicSalesTax);
taxes.add(importDuty);

// purchase some items
Order order = Order.create(taxes);
order.add(ddd, 1);
order.add(goos, 1);
order.add(house1, 1);
order.add(house7, 1);

// print the receipt
SimpleReceipt receipt = SimpleReceipt.create(System.out);
order.print(receipt);

Which will print this to the console:

------------------ THIS IS YOUR ORDER ------------------
(001)                Domain Driven Design -----   $69.99
(001)    Growing Object Oriented Software -----   $49.99
(001)                 House M.D. Season 1 -----   $29.99
(001)                 House M.D. Season 7 -----   $34.50
(IMD)    Growing Object Oriented Software -----    $2.50
(BST)                 House M.D. Season 1 -----    $3.00
(BST)                 House M.D. Season 7 -----    $3.45
(IMD)                 House M.D. Season 7 -----    $1.73
                                SUB-TOTAL -----  $184.47
                                TAX TOTAL -----   $10.68
                                    TOTAL -----  $195.15
---------------- THANKS FOR CHOOSING US ----------------

Tests

I've also created a couple of acceptance tests while implementing the solution. The tests helped me iterate and refine the design. I didn't create granular unit tests for the classes because the acceptance tests were sufficient to drive the design to this point. It's still a very incomplete solution, and going forward I'd definitely create separate unit tests to evolve some classes independently.

What's left

As I've already mentioned, the solution is still very incomplete. It exercises a happy path scenario; but it already lays a good foundation to build on. A couple things to tackle next would be:

  • Rounding - Event though I'm rounding up all monetary amounts with 2 decimal places, I haven't verified if this suffices for the rounding specified in the requirements.
  • Remove products from an order - the derived taxes should also be removed.
  • Add the same product twice to an order - the existing product entry should be updated to reflect the new quantity for the product; no two product entries should point to the same product.
  • Validation, boundary conditions, design by contract - many values should be checked for null or whether they fall in a predetermined range. For example, quantities should be greater than zero and probably have an upper limit.

Also, further ideas worth exploring might be:

  • Persistence - how would a database to persist all entities change the design?
  • UI - an interactive UI to create orders would be interesting for Customers; same for an administrative UI for the Administrators (to maintain products, taxes, and review orders)

I'm sure you can think of many other possibilities.

Da Code

My solution can be found on github. Take a look and send me your comments and suggestions!

Wednesday, August 17, 2011

Why is composition harder than inheritance?

(just some random thoughts...)

Let's take this Java example:

class Base {
  public void method() {}
}
class Derived extends Base {}

See how easy it is for Derived to "reuse" code from Base? Derived is a subclass of Base, and in its constructor it calls Base's constructor, constructing a Base before constructing a Derived:

class Derived extends Base {

  // this is what gets generated by the compiler:
  public Derived() { super(); }

  // this doesn't exist, but illustrates what happens when we call Derived.method:
  public void method() { super.method(); } 

}

Also, Derived instances have a "forwarding" method, that, when called, will delegate to the corresponding base method (this is not technically what happens, but I'm looking at the "concept" here). Isn't that convenient?

Why isn't the same capability available to compose classes? Composition is always a better strategy than inheritance in "reuse" scenarios. To compose, the delegating methods have to be manually written:

class Composed {
  private Base _base;
  public Composed(Base base) { _base = base; }
  public void method() { _base.method(); }
}

Conceptually, Composed looks a lot like Derived. The differences are obvious to OO-mongers. Inheritance is an is-a (better still, a behaves-like) relationship, and Derived instances can be subtituted whenever Base is needed. Composition is a has-a relationship, and instances of Composed cannot stand in for Base. Composition is more flexible because changes in Base do not force changes in Composed's interface, and we can choose which methods of Base to expose through Composed.

There's a degenerate version of composition called a wrapper, that wraps a class, exposes all its public methods as its own, and delegates all calls (and it can also adjusts some calls, like a proxy). But, as the Composed example shows, it's painful to write compared to the ease of inheritance. So it's not by chance that people use inheritance for the wrong reasons, it's convenience.

What if we had a wrapping "operator", much like the inheritance one?

class Wrapper wraps Base {}

Compare this to:

class Derived extends Base {}

The following constructor would be generated by the compiler (note that it takes a parameter):

class Wrapper wraps Base {
  // "wrap", like "super", does compiler magic:
  public Wrapper(Base wrappedBase) { wrap(wrappedBase); }
}

Wouldn't that bring composition (rather, wrapping) to the same level as inheritance in terms of language support? Would this be worthwhile? I think it would, and it also makes sense to allow multiple-wrapping (as opposed to multiple-inheritance), with some kind of conflict resolution strategy.

Should we be able to substitute a Wrapper for a Base? Maybe. This looks like a stronger form of duck typing, one that's actually verifiable by the compiler. Only within a class derived from Base (or in Base itself) we would be in trouble, if it accesses private or protected members of other instances of the same type. Maybe then a class should only be allowed to access its own private or protected members, and not the ones of other instances, because we don't know whether those instances will be wrappers or not. Scala has this kind of access control (by marking a member as private[this] or protected[this]). We could also declare any interfaces that Base implements in Wrapper, and work with these interfaces. And, wrappers shouldn't break the semantic contract of the wrapped class (and thus adhere to the Liskov Substitution Principle - pdf).

From another angle, traits try to solve exactly the same problem, by creating a new language-level construct (the trait, duh) that composes nicely into classes. Scala has traits. Maybe then, wrappers could be used to work with old code, and new code should be designed with traits.

Friday, June 3, 2011

DCI Example with NRoles

The DCI (Data, Context, Interactions) architecture is a style that proposes an interesting separation of concerns between the domain model of a system (what the system is) and its behavior (what the system does), normally associated with its use cases. The rationale is that, since these parts incur change at different rates, isolating them from each other results in a system that's easier to understand, evolve and maintain.

In order to enact a specific use case, a specialized context instantiates the necessary data objects assigned to the needed roles to run the required "algorithm".

A very common example is that of a bank transfer operation. This example has already been described in C# with the C# quasi-mixins pattern. With NRoles the code for a role lives in a single abstraction, which results in a more compelling implementation. I'll change the example a little bit, to introduce a stateful role; something that's harder to achieve with pure C#.

The stateful role represents a log of events, from a generic type T:

public class RJournal<T> : Role {
  private List<T> _entries = new List<T>();
  public IEnumerable<T> Entries { get { return _entries; } }
  public void Log(T entry) {
    _entries.Add(entry);
  }
}

The next roles are the debitor and the creditor in a transfer operation, a source and a target:

public abstract class RTransferSource : Does<RJournal<string>>, Role {
  public abstract void Withdraw(int amount);
  public void TransferTo(RTransferTarget target, int amount) {
    Withdraw(amount);
    target.Deposit(amount);
    LogWithdraw(amount);
    target.LogDeposit(amount);
  }
  internal void LogWithdraw(int amount) {
    this.As<RJournal<string>>().Log("Withdrew: " + amount);
  }
}

public abstract class RTransferTarget : Does<RJournal<string>>, Role {
  public abstract void Deposit(int amount);
  public void TransferFrom(RTransferSource source, int amount) {
    source.TransferTo(this, amount);
  }
  internal void LogDeposit(int amount) {
    this.As<RJournal<string>>().Log("Deposited: " + amount);
  }
}

They define abstract methods that have to be provided by composing classes. They also compose the Journal<string> role. The Account class composes all preceding roles, which means that it can be a debitor or a creditor in an operation. It provides the required abstract methods:

public class Account : Does<RJournal<string>> 
  Does<RTransferSource>, Does<RTransferTarget> 
{
  public string Id { get; private set; }
  public int Balance { get; private set; }
  public Account(string id, int balance) {
    Id = id;
    Balance = balance;
  }
  public void Withdraw(int amount) {
    Balance -= amount;
  }
  public void Deposit(int amount) {
    Balance += amount;
  }
}

This diagram describes the above constructs:

DCI

Since roles are about composition, and not inheritance, all roles included in a class are flattened. In particular, RJournal<T> ends up only once in Account.

The TransferContext class executes the use case to transfer money from a source to a target:

public class TransferContext {
  public RTransferSource Source { get; private set; }
  public RTransferTarget Target { get; private set; }
  public int Amount { get; private set; }

  public TransferContext(RTransferSource source, RTransferTarget target, int amount) {
    Source = source;
    Target = target;
    Amount = amount;
  }

  public void Execute() {
    Source.TransferTo(Target, Amount);
  }
}

The following sample code invokes the scenario:

var savingsStartBalance = 10000;
var checkingStartBalance = 500;

var savings = new Account("Savings", savingsStartBalance);
var checking = new Account("Checking", checkingStartBalance);

var context = new TransferContext(
  checking.As<RTransferSource>(), 
  savings.As<RTransferTarget>(), 
  100);
context.Execute();

PrintAccount(savingsStartBalance, savings);
Console.WriteLine();
PrintAccount(checkingStartBalance, checking);

Where PrintAccount is simply:

private static void PrintAccount(int startBalance, Account account) {
  Console.WriteLine("{0}:", account.Id);
  Console.WriteLine("Start: " + startBalance);
  account.As<RJournal<string>>().Entries.ToList().ForEach(Console.WriteLine);
  Console.WriteLine("Balance: " + account.Balance);
}

Running it yields this output:

Savings:
Start: 9000
Deposited: 100
Balance: 9100

Checking:
Start: 500
Withdrew: 100
Balance: 400

To know more and download NRoles, take a look here.

Sunday, May 29, 2011

NRoles: An experiment with roles in C#

In the last months, I've been developing in my spare time a proof-of-concept post-compiler with Mono.Cecil to enable roles in C#: NRoles. Roles are high level constructs that enable better code reuse through easier composition. They are very similar to traits as described in the traits paper (pdf).

Set up

NRoles is hosted on google code. You can get the latest source code with this mercurial command:

hg clone https://code.google.com/p/nroles/ nroles

You can also download the latest binary package from the downloads page.

To set up a Visual Studio project to use NRoles, unzip the binary package (or compile from source) in a folder accessible to the project. I normally have a project root folder, with folders for the project code (src) and for any used libraries (lib). For example:

  src\
    project files ...
  lib\
    nroles-v0.1.2-bin\
      NRoles.dll
      nutate.exe
      other NRoles binaries ...

In the project, add a reference to the NRoles.dll assembly. This is a very minimal assembly used to annotate the code to enable the post-compiler to create roles and compositions. Then, add a post-build event to the project to run the post-compiler (nutate.exe):

"$(SolutionDir)..\lib\nroles-v0.1.2-bin\nutate.exe" "$(TargetPath)"

Now nutate.exe runs whenever the project is built, and any errors or warnings are reported in the Visual Studio error list view.

Roles and compositions

Let's take a look at some code based on the examples in the traits paper. Roles are classes marked with the interface NRoles.Role. This is a simple role that implements IEquatable<T> and provides a Differs method:

public abstract class REquatable<T> : IEquatable<T>, Role {
  public abstract bool Equals(T other);
  public bool Differs(T other) {
    return !Equals(other);
  }
}

To distinguish roles from normal classes or interfaces, I prefix them with the letter R. REquatable<T> provides the Differs method, but still requires classes that compose it to implement Equals, since it's abstract.

To compose a role, a class uses the NRoles.Does<TRole> marker interface, with the desired role as a type parameter. A role can also compose other roles. This is a role that implements IComparable<T> and composes REquatable<T>:

public abstract class RComparable<T> : IComparable<T>, Does<REquatable<T>>, Role {
  public bool Equals(T other) {
    return CompareTo(other) == 0;
  }
  public abstract int CompareTo(T other);
  public bool LessThan(T other) {
    return CompareTo(other) < 0;
  }
  public bool GreaterThan(T other) {
    return CompareTo(other) > 0;
  }
  public bool LessThanOrEqualTo(T other) {
    return CompareTo(other) <= 0;
  }
  public bool GreaterThanOrEqualTo(T other) {
    return CompareTo(other) >= 0;
  }
  public bool IsBetween(T min, T max) {
    return GreaterThan(min) && LessThan(max);
  }
}

Classes that compose RComparable<T> will also compose REquatable<T> and gain the implementations of the corresponding IComparable<T> and IEquatable<T> interfaces. RComparable<T> "implements" REquatable<T>.Equals in terms of CompareTo. CompareTo is left abstract and needs to be implemented by further composing classes.

RComparable

The following role represents a circle and composes REquatable<T> and RComparable<T>:

public class RCircle : Does<REquatable<RCircle>>, Does<RComparable<RCircle>>, Role {
  public int Radius { get; set; }
  public double Area { get { return Math.PI * Radius * Radius; } }
  public int CompareTo(RCircle other) {
    if (other == null) throw new ArgumentNullException("other");
    return Radius.CompareTo(other.Radius);
  }
}

All roles in a composition have the same priority. This includes all roles declared in the composition itself and also these roles' roles, and so on. Any role will only appear once in a composition, even if it was composed multiple times through different "paths". This way, it's very different from multiple inheritance, which requires you to consider the whole hierarchy and places different priorities in each class. As a result, conflicting members from multiple roles must be resolved by the composition (more on this here), which is also different from the way that mixin inheritance normally works, where the composition order defines the relative priorities of the mixins.

This simple composition represents the RGB (red, green and blue) values for a color:

public class Rgb : Does<REquatable<Rgb>> {
  public int R { get; set; }
  public int G { get; set; }
  public int B { get; set; }
  public bool Equals(Rgb other) {
    return R == other.R && G == other.G && B == other.B;
  }
}

And this role uses the Rgb composition and represents a color:

public class RColor : Does<REquatable<RColor>>, Role {
  public Rgb Rgb { get; set; }
  public bool Equals(RColor other) {
    return Rgb.Equals(other.Rgb);
  }
}

The next composition is a circle, and uses RCircle, RColor and REquatable<T>:

public class Circle : Does<RCircle>, Does<RColor>, Does<REquatable<Circle>> {
  public bool Equals(Circle other) {
    if (other == null) throw new ArgumentNullException("other");
    return
      this.As<RCircle>().Equals(other.As<RCircle>()) &&
      this.As<RColor>().Equals(other.As<RColor>());
  }
}

Circle has an Equals method that reuses the implementations from RCircle and RColor. Since NRoles works as a post-compiler, to use compositions in the same assembly that they're defined, the As<TRole>() extension method casts the composition type to one of its composed roles. This operation is always safe (provided that you post-compile the assembly). You don't need to use this trick in other assemblies, since the compositions are implicitly convertible to the roles that they compose. The roles become interfaces that the compositions implement (look here for the conceptual idea).

The Circle class ends up composing many behaviors from different roles, hopefully giving a taste of how roles improve the overall separation of concerns of the design.

Circle

NRoles is an experiment in a very early stage. Ideally, roles would be available in the language itself. But, I hope it can already be useful to create better designs; and maybe to show language designers that this is an important concept. So please, download and play with it, and comment on any issues and possibilities. And of course: contribute!

Friday, April 22, 2011

More Macros in Nemerle

After a very brief introduction to Nemerle metaprogramming, what follows is some motivation and better expression macros examples.

Historically in C#, the using statement has been abused (guilty!) to provide a more convenient syntax to operations that have natural wrap up code which should be executed at the end of a logical scope. To enable a class to be usable like this, it just needs to implement the System.IDisposable interface. The problem is that these elements were designed with a very specific and important goal in mind: the deterministic disposal of unmanaged resources. That's why using wraps the call to IDisposable.Dispose() in a finally block: it has to run no matter what.

A finally block is a very strong statement. It runs in the presence of exceptions, and it can't be interrupted by a ThreadAbortException, what can delay a whole application domain shutdown. That's justified for releasing resources, but it is too strong a statement for simple wrap up code. If an exception happens, the state of the whole operation is compromised, what might mean that it doesn't make sense to run the wrap up code at all.

What's desired, and not possible in C#, is to have a new statement that has a different expansion as the using block and that integrates seamlessly and consistently into the language. Closures can be used to simulate this; but Nemerle goes one step further, and so it doesn't lock the developer with the original design of the language, enabling more expressive code that doesn't abuse the existing language constructs.

This is just one example of abuse. Other interesting examples are the mixin pattern that I've written about before and the code contracts feature, which requires unnatural syntax and an external assembly rewriter to enable design by contract in C#.

So, following the steps of IDisposable and using, I'll create the IScopable (I know, it's a bad name) interface and the scope macro in Nemerle.

IScopable will live in its own assembly, Scopable.dll:

namespace Scopable {
  public interface IScopable {
    EndScope(): void;
  }
}

It's just a simple interface where an implementing class' constructor implies the beginning of a scope and the EndScope method must be called to signal the end of the scope. It shares the simplicity of IDisposable but with different semantics, where the call to EndScope should not be wrapped in a finally block.

The scope macro is created in another assembly, Scopable.Macros.dll, which references Scopable.dll:

namespace Scopable.Macros {
  using Nemerle.Compiler;
  using Scopable;

  macro __Scope(expr, body) 
  syntax ("scope", "(", expr, ")", body) {

    def getStart(symbol) {
      <[ def $(symbol : name) = $expr ]>
    };

    def getEnd(symbol) {
      <[
        def scopable: IScopable = $(symbol : name);
        when (scopable != null) scopable.EndScope();
      ]>
    };

    def (start, end) = match (expr) {
      | <[ mutable $(symbol : name) = $_ ]>
      | <[ def $(symbol : name) = $_ ]> =>
        ( expr, getEnd(symbol) )
      | _ =>
        def symbol = Macros.NewSymbol();
        ( getStart(symbol), getEnd(symbol) )
    }

    <[ 
      $start; 
      $body; 
      $end; 
    ]>
  }

}

The scope macro introduces a new scope for an IScopable instance, where its EndScope method will be called at the end of a block. It takes two parameters: expr, which represents the expression that should result in an IScopable instance, and body, which is the block of code that must execute within the scope. Both parameters are nodes in the compiler's abstract syntax tree (AST), and are implicitly typed as Nemerle.Compiler.Parsetree.PExpr (a parsed expression).

The first two declarations inside the macro are the local functions getStart and getEnd, followed by a pattern matching expression that results in a tuple of two pieces of code to emit: one at the start of the scope and one at its end. Pattern matching is used to identify the format of the expr parameter, which then drives the format of the resulting code.

In Nemerle, there are two ways to declare a variable, with def for an immutable variable, and mutable for a mutable one. The first two clauses in the match expression check for these two forms. What's interesting about the code is that quasi-quotation is used in the pattern matching expressions, instead of the cumbersome code that would result if we were forced to use the AST expansions they generate. In effect, we write the code we want to match, and it's transformed in its AST representation. The $(symbol : name) in the quotation commands the pattern matching to capture the name of the declared variable and assign it to the autovivified symbol variable. $_ is just a shortcut to match anything and not capture any variables, since we don't really care what the rest of the expression looks like. In a successful match for either form, the tuple that results holds the input expression (it's already in the needed format) and the result of calling the getEnd function with the captured symbol name.

The third pattern captures all other forms, with the _ identifier. It then creates a new symbol with the Macros.NewSymbol() call. This new symbol is used to call both previously declared functions. getStart uses this symbol to create an assignment expression where the input expression is assigned to the symbol.

The getEnd function generates the code to end the scope. It declares a variable of type IScopable and assigns the given symbol to it. It then calls IScopable.EndScope() on it if it's not null. If the expression that that symbol represents is not of type IScopable, this assignment will fail compilation, and issue an error message back to the user. This is how the type of the input expression is implicitly enforced to be of type IScopable.

After resolving the code to start and end the scope, it's just a matter of emitting the resulting code in the right order, which is done as the last statement in the macro:

<[ 
  $start; 
  $body; 
  $end; 
]>

This last statement is also the return value of the macro, and it's the code that the compiler inserts in the program.

Now let's create a scopable class (some interesting Nemerle features are explained in the code):

namespace Scopable {
  using System.Diagnostics;
  using System.Diagnostics.Trace; // import the static members of a class

  public class Tracer : IScopable {
    private stopwatch = Stopwatch(); // creating an object doesn't use "new"
    private title: string;

    public this(title: string = "Execution") { // a constructor
      this.title = title;
      Start();
    }
    
    private Start(): void {
      WriteLine($"$title start"); // string interpolation
      stopwatch.Start();
    }

    private Finish(): void 
    implements IScopable.EndScope // aliased interface member implementation
    { 
      stopwatch.Stop();
      WriteLine($"$title end, took $(stopwatch.ElapsedMilliseconds / 1000f)s");
    }
  }
}

And use it in a program:

using System;
using System.Diagnostics;
using System.Threading;
using Scopable;
// Scopable.Macros.dll must be referenced as a macro reference, 
// its macro will be expanded in this code, 
// and it won't be part of the final assembly. 
using Scopable.Macros; 

module Program { // just like a C# static class, but without the cruft

  Main() : void {

    _ = Trace.Listeners.Add( // explicitly ignore the return value
      TextWriterTraceListener(Console.Out)); 

    scope(Tracer("The answer")) {
      Thread.Sleep(42);
    }

    _ = Console.ReadLine()

  }

}

The output was not quite the answer I was looking for:

The answer start
The answer end, took 0.044s

Tracer can also be encapsulated in its own macro, in a separate assembly from scope (macros can only be used - even by other macros - if they're referenced from an already compiled assembly):

namespace Tracer.Macros {
  using Scopable;
  using Scopable.Macros;

  macro __Tracer(title, body) 
  syntax ("trace", Optional("(", title, ")"), body) {
    def message = title ?? <[ "Execution" ]>;
    <[
      scope(Tracer($message)) $body;
    ]>
  }
}

The trace macro reuses the scope macro and just creates a scope with a Tracer instance. It also shows how to declare optional arguments in its syntax. It's usage is simple:

trace("The answer") {
  Thread.Sleep(42);
}

Nemerle also has a bunch of useful macros in its standard library. Some examples are macros for design by contract, lazy evaluation and XML literals.

There's no need to stick with what the language designers give you with such a powerful tool as macros for metaprogramming. Compiler and extension developers themselves profit a lot with such a foundation. There're certainly other ways to achieve this level of language customization, but the Nemerle compiler shows a very powerful and synergistic model, where algebraic data types (for the AST), pattern matching and quasi-quotation come together to make metaprogramming easy and declarative in a statically typed, C#-like language.

Thursday, April 14, 2011

Metaprogramming in Nemerle

Nemerle is a generally unknown .NET language that nevertheless has many impressive features. Its syntax is close to C#, but it has many functional programming constructs, like algebraic data types and pattern matching, that are not found in the Redmond language. It also has a very powerful metaprogramming system, where special constructs can participate in the compiler's execution pipeline and generate or manipulate code in the target program.

Metaprogramming can be very useful to cut on duplication, to apply consistent policies throughout a codebase and to raise the overall expressiveness of the code. It's one of the things that makes Ruby on Rails such a compelling and successful web application framework. Unlike Ruby, Nemerle is a compiled, statically typed language, where metaprogramming is possible already in the compilation step.

For a very simple (and unrealistic) example, imagine that we use lots of infinite loops in our code. In some parts we use while(true) ..., in other parts for(;;) ..., and still in others, do ... while(true);. None of these constructs reveal the true intent of our code, which is to loop forever (well, not really for this example, but I'm sure you can extrapolate this to some real obscure code pattern). In C#, we could create a method to encapsulate our intent:

public static class Forever {
  public static void Run(Func<Loop> action) {
    Loop control;
    do control = action(); while (control == Loop.Continue);
  }
}
public enum Loop { 
  Continue,
  Break
}

And use it like this:

int i = 0;
Forever.Run(() => {
  ++i;
  Console.WriteLine(i);
  if (i == 10) return Loop.Break;
  return Loop.Continue;
});

To simulate the statements break and continue, the Forever.Run method takes a function that returns an enumeration that indicates if the iteration should continue (Loop.Continue) or break (Loop.Break). Very cumbersome, isn't it? What's missing in C# is the ability to extend the language to create a more consistent experience. In Nemerle, you can use a macro to create code like this:

using System.Console; // WriteLine
using Nemerle.Imperative; // break
using MyMacros; // forever

...

mutable i = 0;
forever {
  ++i;
  WriteLine(i);
  when (i == 10) break;
}

The "keyword" forever is not part of the language. It's created by the following macro (which is compiled in a separate assembly):

namespace MyMacros {

  macro __Forever(body)
  syntax("forever", body) {
    <[
      while (true) $body;
    ]>
  }

}

This macro takes a body as a parameter (which can be any series of statements), introduces new syntax into the language (the "keyword" forever followed by the given body), and then simply issues an infinite loop using while(true) .... Code within <[ and ]> is transformed into an abstract syntax tree (AST) representation that the compiler then inserts into the program tree, at the place where the macro is invoked. This is called quasi-quotation, and also supports interpolation of values known at compile time, like $body, which is used to include the body parameter into the generated code.

Interestingly enough, most control statements in Nemerle are implemented as macros, like for, foreach, while, break, continue and using.

Nemerle macros are effectively compiler plugins, that work on the same structure (the AST) that the compiler uses. This is much more powerful than the simple text substitution macros in C/C++. It's equivalent to Lisp macros. They can also operate on more high level constructs, such as classes, and add or change members or introduce new types into the compilation unit.

More importantly, they can be an effective tool for a developer to create more expressive, clearer code.

Thursday, March 24, 2011

C# Mixins With State

With the C# quasi-mixin pattern, one of the biggest limitations is that the mixins can't introduce state to a class. An alternative was for the mixin interface to require the composing classes to implement a property that the mixin would use as its own, as demonstrated in this example.

In the .NET Framework 4.0, the ConditionalWeakTable<TKey, TValue> class can be used to associate arbitrary state to any instance. It's thread safe and it keeps a dictionary of weak references from the target instance to its associated state. If a target instance has no references outside the conditional weak table, then it can be reclaimed by the garbage collector. When that happens, its entry in the table is removed.

This makes it possible for a mixin-like class to maintain state for the instances it extends. Let's look at a mixin for a message container:

public enum MessageType { 
  Error, 
  Warning, 
  Info 
}

public class Message {
  public readonly MessageType Type;
  public readonly string Text;
  public Message(MessageType type, string text) {
    Text = text;
    Type = type;
  }
  public static Message Error(string text) {
    return new Message(MessageType.Error, text);
  }
  // other factory methods...
}

// this is the mixin
public interface MMessageContainer { } public static class MessageContainerCode {
  private static readonly ConditionalWeakTable<MMessageContainer, List<Message>> 
    _messagesTable = new ConditionalWeakTable<MMessageContainer, List<Message>>();

  public static IEnumerable<Message> RetrieveMessages(this MMessageContainer self) {
    return _messagesTable.GetOrCreateValue(self);
  }

  public static void AddMessage(this MMessageContainer self, Message message) {
    _messagesTable.GetOrCreateValue(self).Add(message);
  }

  public static void ClearMessages(this MMessageContainer self) {
    _messagesTable.GetOrCreateValue(self).Clear();
  }
}

The MMessageContainer mixin (actually, its code class) declares a ConditionalWeakTable field to hold the list of messages for each extended class. The GetOrCreateValue method takes the target instance as a key and retrieves the associated list of messages, or creates a new one by calling the default constructor for List<Message>. The mixin can be used like this:

public class Person : MarshalByRefObject, MMessageContainer {
  public string Name { get; set; }
  public int Age { get; set; }

  public void Validate() {
    // needs to use "this" to access extensions to this class
    this.ClearMessages();
    if (Age < 0 || Age > 120) {
      this.AddMessage(Message.Error("Invalid age"));
    }
    if (string.IsNullOrWhiteSpace(Name)) {
      this.AddMessage(Message.Error("Invalid name"));
    }
  }
}

The class Person extends MarshalByRefObject to support remoting, and also uses the message container mixin to maintain a list of validation messages. Let's use this class now:

class Program {
  static void Main(string[] args) {
    var jeanne = new Person { Name = "Jeanne Calment", Age = 122 };
    jeanne.Validate();
    PrintMessages(jeanne);
  }

  private static void PrintMessages(MMessageContainer container) {
    foreach (var message in container.RetrieveMessages()) {
      Console.WriteLine("{0}: {1}", message.Type, message.Text);
    }
  }
}

By running it we find out that Jeanne Calment actually had an invalid age when she passed away. Or is it the program that's invalid?

Error: Invalid age

To associate a number of different values for a class, the mixin can declare a nested state class and use it as a value for the ConditionalWeakTable. So, here's the pattern to use:

public interface MMixin { 
  // required members go here
}
public static class MixinCode {
  // provided methods go here, as extension methods to MMixin

  // to maintain state:
  class State { 
    // public fields or properties for the desired state, e.g.:
    public string Name;
  }
  private static readonly ConditionalWeakTable<MMixin, State>
    _stateTable = new ConditionalWeakTable<MMixin, State>();

  // to access the state:
  public static string GetName(this MMixin self) {
    return _stateTable.GetOrCreateValue(self).Name;
  }
  public static void SetName(this MMixin self, string value) {
    _stateTable.GetOrCreateValue(self).Name = value;
  }
}

There're still limitations to this approach, but most of them are only related to syntax. For example, the mixin still has to be declared with two constructs, an interface and a static class; and it's weird to provide explicit getter and setter methods to create "extension properties", when the language has a nice property syntax. Also, any code that uses the mixin composition classes must also import the mixin namespace in order to access its introduced extensions.