Wednesday, January 30, 2008

Hitting the Sweet Spot

Do you have to be a better X (for all X mainstream) to be a successful mainstream programming language ? Smalltalk lost out to C++ back in the 80s even though Smalltalk had a purer object model (Objects all the way down) with lots of powerful abstractions, espoused the virtues of garbage collection, byte codes and JIT (only later to be hijacked by Java) and provided a solid refactoring browser based IDE. On the other hand, C++ was positioned to be a better C and had played upon the familiarity cards of having the curly brace syntax, syntactic compatibility with C but with better type-safety. Even today, we find enough impact that Smalltalk, both as a language and as a platform, has in the market. Ruby is strongly influenced by Smalltalk - even many dynamic language gurus feel that Ruby should be made to run on the highly optimized Strongtalk VM rather than labour through the process of carving out its own or try to make it run on the JVM through JRuby. Gemstone's object server runs Smalltalk and provides a state-of-the-art platform for developing, deploying, and managing scalable, high-performance, multi-tier applications based on business objects. Recently announced new Web programming environment from Sun Labs, Lively Kernel was inspired in part by the success of the Squeak Smalltalk programming environment.

Why did Smalltalk lose out to C++ ?

Eventually Java hit the sweetest of spots as a better and easy-to-use C++. Java adapted the Smalltalk VM and roped in the same features that people rejected with Smalltalk in the 80s. The only difference that Java created was that the community focused on building a strong ecosystem to support the average programmer better than any of its predecessors. This included richer libraries and frameworks, great tooling, a uniform runtime environment, JITs that generated efficient code and of course a very warm and supportive community participation. Lawrence Kesteloot makes a strong point when he emphasizes that helping the average programmer creates the necessary strength and durability of the ecosystem for the language to thrive.

Enterprise projects thrive on the ecosystem.

No matter how elegant your language is, unless you have a strong ecosystem that lives up to the demand / supply economics of developing enterprise software, it will not be able to move into the ranks of BigCo projects. Even the most beautiful piece of code that you may write has an IDE life directly proportional to the skillset of the programmer who will maintain it. Of course there are plenty of good programmers working with the BigCo enterprise projects, but it is the machinery assuring a copius supply of average programmers that keeps the economics ticking.

And only one language has so far been able to create this ecosystem !

Monday, January 21, 2008

Scala can make your Java Objects look smarter

It's really a strange situation out there. On one hand, people are advocating for polyglot programming over the JVM or CLR, and on the other hand, the same set of advocates are busy protecting their own afficionados with great care, wisdom and frequent aggression, in the race for leadership as the dominant linguistic force in tomorrow's application development stack. Groovy or JRuby, Grails or Rails, Java or Scala - the blogosphere today have started a combinatorial explosion of mutual vilification programs. The most surprising part of this series is that almost everyone is talking about X or Y either in the stable layer or in the DSL layer. My question is why not X AND Y ?

Ola Bini talks about a layered architecture, with a stable, typesafe, performant kernel, providing the foundation for a malleable DSL-based end-user API. To me this makes a lot of sense, at least in the context of the large codebase of existing Java applications. Language adoption in the mainstream has traditionally been evolutionary and for quite some time we will see lots of layers and wrappers being written and exposed as flexible APIs in the newer languages, over today's mainstream codebases acting as the so-called kernel.

Java is still the most dominant of these forces in application development, particularly in the enterprise segment. And given the degree of penetration that Java, the language, has enjoyed over the last decade or so, coupled with the strong ecosystem that it has been able to create, it will possibly remain the most potent candidate for what Ola Bini calls the kernel layer.

With more and more mindset converging towards new languages on the JVM, albeit in blogs or toy applications, I am sure many of them have already started thinking about polyglot programming paradigms. In an existing application, with the basic abstractions implemented in Java, can we use one of its newer cousins to design more dynamic APIs ? With the toolsets and libraries still in nascent state of evolution, it will be quite some time (if ever at all) that some BigCo decides to develop a complete enterprise application in JRuby or Scala or Groovy. After all, the BigCos are least excited with Ruby evals, Groovy builders or Scala type inferencing. It is the ecosystem that matters to them, it is the availability of programmers that counts for them and it is the comfort factor of their IT managers that calls the shots and decides on the development platform.

Anyway, this is not an enterprise application. I tried to build a layer of Scala APIs on top of some of the utilitarian Java classes in a medium sized application. It was fun, but more importantly, it showed how better APIs evolve easily once you can work with more powerful interoperable languages on a common runtime.

Consider this simplified example Java class, which has worked so faithfully for my client over the last couple of years ..


// Account.java
public class Account {
  private List<String> names;
  private String number;
  private List<Address> addresses;
  private BigDecimal interest;
  private Status status;
  private AccountType accountType;

  public Account(String name, String number, Address address) {
    //..
  }

  //.. standard getters

  public void calculate(BigDecimal precision, Calculator c) {
    interest = c.calculate(this, precision);
  }

  public boolean isOpen() {
    return status.equals(Status.OPEN);
  }
}



Nothing complex, usual verbose stuff, encapsulating the domain model that our client has been using for years ..

I thought it may be time for a facelift with some smarter APIs for the clients of this class, keeping the core logic untouched.

Let us have a Scala class which will act as an adapter to the existing Java class. Later we will find out how some of the magic of Scala *implicits* enables us to use the adaptee seamlessly with the adaptor.

// scala class: RichAccount.scala
// takes the Java object to construct the rich Scala object
class RichAccount(value: Account) {
  //..
}


Scala collections are much richer than Java ones - hence it makes sense to expose the collection members as Scala Lists. Later we will find out how the client can use these richer data structures to cook up some more dynamic functionalities.


class RichAccount(value: Account) {
  //..
  def names =
    (new BufferWrapper[String] {
      def underlying = value.getNames()
    }).toList

  def addresses =
    (new BufferWrapper[Address] {
      def underlying = value.getAddresses()
    }).toList

  def interests =
    (new BufferWrapper[java.math.BigDecimal] {
      def underlying = value.getInterests()
    }).toList
}



Now with the properties exposed as Scala lists, we can cook up some more elegant APIs, using the added power of Scala collections and comprehensions.


class RichAccount(value: Account) {
  //..as above

  // check if the account belongs to a particular name
  def belongsTo(name: String): boolean = {
    names exists (=> s == name)
  }
}



Then the client code can use these APIs as higher order functions ..


// filter out all accounts belonging to debasish
accounts filter(_ belongsTo "debasish") foreach(=> println(a.getName()))



or for a functional variant of computing the sum of all non-zero accrued interest over all accounts ..


accounts.filter(_ belongsTo "debasish")
        .map(_.calculateInterest(java.math.BigDecimal.valueOf(0.25)))
        .filter(!= 0)
        .foldLeft(java.math.BigDecimal.ZERO)(_.add(_))



This style of programming, despite having chaining of function calls are very much intuitive to the reader (expression oriented programming), since it represents the way we think about the computation within our mind. I am sure your clients will love it and the best part is that, you still have your tried-and-tested Java objects doing all the heavy-lifting at the backend.

Similarly, we can write some friendly methods in the Scala class that act as builder APIs ..


class RichAccount(value: Account) {
  //..as above

  def <<(address: Address) = {
    value.addAddress(address)
    this
  }

  def <<(name: String) = {
    value.addName(name)
    this
  }
}



and which allows client code of the following form to build up the name and address list of an account ..

acc << "shubhasis"
    << new Address(13, "street_1n", "700098")
    << "ashis"


Scala Implicits for more concise API

Now that we have some of the above APIs, how can we ensure that the Scala class really serves as a seamless extension (or adaptation) of the Java class. The answer is the *implicit* feature of Scala language. Implicits offer seamless conversions between types and makes it easy to extend third party libraries and frameworks. Martin Oderskey has a nice writeup on this feature in his blog. In this example we use the same feature to provide an implicit conversion function from the Java class to the Scala class ..

implicit def enrichAccount(acc: Account): RichAccount =
    new RichAccount(acc)


This defines the implicit conversion function which the complier transparently uses to convert Account to RichAccount. So the client can now write ..


// instantiate using Java class
val myAccount = new Account("debasish", "100", new Address(12, "street_1", "700097"))



and watch (or feel) the compiler transparently converting the Java instance to a Scala instance. He can now use all the rich APIs that the Scala class has cooked up for him ..

// use the functional API of Scala on this object
myAccount.names.reverse foreach(println)


We can also use Scala implicits more effectively and more idiomatically to make our APIs smarter and extensible. Have a look at the Java API for calculation of interest in the Java class Account :

public void calculate(BigDecimal precision, Calculator c) {
  interest = c.calculate(this, precision);
}


Here Calculator is a Java interface, whose implementation will possibly be injected by a DI container like Spring or Guice. We can make this a smarter API in Scala and possibly do away with the requirement of using a DI container.


class RichAccount(value: Account) {
  //..as above

  def calculateInterest(precision: java.math.BigDecimal)
           (implicit calc: Calculator): java.math.BigDecimal = {
    value.calculate(precision, calc)
    value.getInterest()
  }
}



Here we use the nice curry syntax of Scala, so that the client code can look nice, concise and intuitive ..


val accounts = List[Account](..)
accounts filter(_ belongsTo "debasish")
    foreach(=> println(a.calculateInterest(java.math.BigDecimal.valueOf(0.25))))



Note that the Calculator parameter in calculateInterest() has been declared implicit. Hence we can optionally do away specifying it explicitly so long we have an implicit definition provided. The client code has to mention the following declaration, some place accessible to his APIs ..

implicit val calc = new DefaultCalculator


and we need no DI magic for this. It's all part of the language.

Spice up the class with some control abstractions

Finally we can use higher order functions of Scala to define some nice control abstractions for your Java objects ..


class RichAccount(value: Account) {
  //..as above

  def withAccount(accountType: AccountType)(operation: => Unit) = {
    if (!value.isOpen())
      throw new Exception("account not open")

    // other validations

    if (value.getAccountType().equals(accountType))
      operation
    }
  }
}



The method is an equivalent of the Template Method pattern of OO languages. But using functional Scala, we have been able to templatize the variable part of the algorithm as a higher order function without the additional complexity of creating one more subclass. The client code can be as intuitive as ..


a1.withAccount(AccountType.SAVINGS) {
  println(a1.calculateInterest(java.math.BigDecimal.valueOf(0.25)))
}



As I mentioned in the beginning, I think this layering approach is going to be the normal course of evolution in mainstream adoption of other JVM languages. Java is so dominant today, not without reason. Java commands the most dominant ecosystem today - the toolsets, libraries, IDEs and the much familiar curly brace syntax has contributed to the terrific growth of Java as a language. And this domination of the Java language has also led to the evolution of Java as a platform. Smalltalk may have been a great platform, but it lost out mainly because developers didn't accept Smalltalk as a mainstream programming language. Now that we have seen the evolution of so many JVM languages, it is about time we experiment with polyglot paradigms and find our way to the next big language set (yes, it need not be a single language) of application development. So long we have been using Java as the be-all and end-all language in application development. Now that we have options, we can think about using the better features of other JVM languages to offer a smarter interface to our clients.

Monday, January 14, 2008

Better Application Configuration using Spring Meta-Annotations

One of the common allegations against Spring is that it promotes XML abuse. Since 2.0, Spring has started putting in features in the DI container that provide developers options to minimize XML configuration and promote use of Java 5 annotations. Configuration parameters that are truly external and needs to change across deployments viz. driver pathname, URL base, file names etc. are definite candidates for property files or XML. While those mappings which deal with wiring of application components are better handled through a mechanism that enforces more type-safety than string literals in XML. With the recent releases of Spring, we are getting more and more options towards better configuration of the DI container.

This post talks about my experience in evolution of better configuration options with Spring 2.5 in one of the real life applications. Spring folks have now realized that programmatic configuration options through proper type-safety of the Java language has definite advantages in encouraging code modularity, unit testability and refactorability. Modularization is one of the key focal areas in application construction and integration today, and modules based on a type safe programming language yield better end result than one based on XML files.

In one of my applications, I have the following implementation of a Strategy pattern that models the interest calculation algorithm for various types of accounts. The algorithm varies depending upon some of the attributes of the account. Here is a simplified view of things ..


public interface InterestCalculation {
  BigDecimal calculate(final Account account);
}

public class NormalCheckingInterestCalculation
    implements InterestCalculation {
  //..
}

public class PriorityCheckingInterestCalculation
    implements InterestCalculation {
  //..
}

public class NormalSavingsInterestCalculation
    implements InterestCalculation {
  //..
}

public class PrioritySavingsInterestCalculation
    implements InterestCalculation {
  //..
}



One of the issues with earlier versions of Spring was that the best (or the most recommended) practices espoused writing XML code not only for declaring the beans for every concrete implementation, but also for every collaboration that it takes part in. Hence my XML code also goes on increasing in addition to the Java code. One available option to reduce the growing chunks of XML is to use autowiring, which, being implemented at a very coarse level of granularity in earlier versions of Spring seemed too magical to me to use in production code.

Spring offers options for modularizing XML configurations and implementing hierarchical application contexts. But still I think the recent thoughts towards modularization using typesafe metadata holds more promise. It is good that initiatives like Spring JavaConfig are gaining in importance. When we speak of modularization of application components, one of the very important aspects in it is composition of modules. And XML cannot be a viable option towards scalable module composition. Guice has been doing some promising stuff with modules and composition, but that is another story for another post.

Meanwhile in the Spring land ..

Spring 2.5 implements autowiring at a much finer level of granularity that allows developers to provide explicit controls on the matching closure. Using annotations like @Qualifier, I can control the selection of candidates amongst the multiple matches. However, the default usage of @Qualifier allows only specification of bean names, which once again is in the form of string literals and hence susceptible to typos, usual type-unsafety kludges and refactoring unfriendliness. The real treat, however, is the feature that enables you to use @Qualifier as a meta annotation to implement your own custom qualifiers.

Consider how the new autowiring features in Spring 2.5 improve upon the above example and allow explicit declarative configuration by using fully type-safe annotations in place of XML.

Autowiring based on Annotations

Spring 2.5 allows you to define your own annotations that can act as classifiers for matching candidates in autowiring. For the example above, the various strategies for interest calculation are based on 2 axes of variation - the account type and the customer type. With the earlier variant of using XML as the configuration metadata, these business rules were buried deep within the implementing classes only, and dependency injection was done using explicit bean names as string literals. Here is an annotation that defines the classifiers in Spring 2.5 ..


@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface AccountQualifier {
  AccountType accountType() default AccountType.CHECKING;
  CustomerType customerType() default CustomerType.NORMAL;
}



Note the usage of @Qualifier as the meta-annotation to define custom domain specific annotations.

Now annotate all injected instances of the strategy interface with the annotation @AccountQualifier. The wiring will be done by Spring based on the matching qualifiers.


public class InterestCalculator {
  @Autowired
  @AccountQualifier(
      accountType=AccountType.CHECKING,
      customerType=CustomerType.NORMAL
  )
  private InterestCalculation normalChecking;

  @Autowired
  @AccountQualifier(
      accountType=AccountType.SAVINGS,
      customerType=CustomerType.PRIORITY
  )
  private InterestCalculation prioritySavings;

  //..
}



In the above snippet, the instance normalChecking will be wired with an instance of NormalCheckingInterestCalculation, while prioritySavings will get an instance of PrioritySavingsInterestCalculation. Implement fine grained autowiring with Spring 2.5 and get explicit declarative business rule based configuration as aprt of metadata free!

Now the configuration XML does not have to specify the collaborators. The size goes down, though still we need to specify each of the custom qualifiers associated with the concrete implementation classes of the strategy.


<beans>
    <context:annotation-config/>

    <bean class="org.dg.biz.NormalCheckingInterestCalculation">
        <qualifier type="AccountQualifier">
            <attribute key="accountType" value="CHECKING"/>
            <attribute key="customerType" value="NORMAL"/>
        </qualifier>
    </bean>

    <bean class="org.dg.biz.NormalSavingsInterestCalculation">
        <qualifier type="AccountQualifier">
            <attribute key="accountType" value="SAVINGS"/>
            <attribute key="customerType" value="NORMAL"/>
        </qualifier>
    </bean>

    <bean class="org.dg.biz.PriorityCheckingInterestCalculation">
        <qualifier type="AccountQualifier">
            <attribute key="accountType" value="CHECKING"/>
            <attribute key="customerType" value="PRIORITY"/>
        </qualifier>
    </bean>

    <bean class="org.dg.biz.PrioritySavingsInterestCalculation">
        <qualifier type="AccountQualifier">
            <attribute key="accountType" value="SAVINGS"/>
            <attribute key="customerType" value="PRIORITY"/>
        </qualifier>
    </bean>
    
    <bean id="interestCalculator" class="org.dg.biz.InterestCalculator" />
</beans>



Classpath AutoScan for Managed Components - Even less XML

Spring 2.5 makes it possible to do away with explicit declarations of the concrete implementation classes in the XML file by using the auto-scan feature. This allows the DI container to auto-scan the classpath and detect all wiring candidates based on user specified filters. In our case, we already have the metadata as the selection criteria - hence we can use the same annotation @AccountQualifier as the basis for autoscanning of managed components. So annotate the implementation classes with the appropriate metadata ..


@AccountQualifier(accountType=AccountType.CHECKING, customerType=CustomerType.NORMAL)
public class NormalCheckingInterestCalculation
    implements InterestCalculation {
  //..
}

@AccountQualifier(accountType=AccountType.CHECKING, customerType=CustomerType.PRIORITY)
public class PriorityCheckingInterestCalculation
    implements InterestCalculation {
  //..
}

// similarly the other classes



and include the final snippet in XML that does the last bit of trick to auto-scan the classpath to find out matching entries based on the annotations. The entire erstwhile blob of XML turns into the following snippet of a few lines ..


<context:annotation-config/>

<bean id="interestCalculator" 
      class="org.dg.biz.InterestCalculator"/>

<context:component-scan base-package="org.dg.biz" use-default-filters="false">
  <context:include-filter type="annotation" expression="org.dg.biz.AccountQualifier"/>
</context:component-scan>



That's it! We do not need to declare any of the above beans explicitly for autowiring.

One last point .. in the above example we have used @Qualifier as a meta-annotation. Hence our custom domain specific annotation @AccountQualifier class still has a Spring import of @Qualifier. In keeping with Spring's usual promise of non-intrusiveness, there is a way out of it. If you do not want a Spring dependency in your custom annotation @AccountQualifier, you can do that as well, by adding the following snippet to the above 5 lines of XML ..


<bean id="customAutowireConfigurer" 
      class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
  <property name="customQualifierTypes">
    <set>
      <value>org.dg.biz.AccountQualifier</value>
    </set>
  </property>
</bean>






P.S. Using the same annotation for autowiring and autodetection of managed components does not work in Spring 2.5 because of a bug. Mark Fisher of SpringSource pointed this out to me and verified that it works in Spring 2.5.1. I upgraded my application and things worked fine.

Monday, January 07, 2008

Language Explorations on the JVM - An Application Developer's perspective

Sometime ago I had reported on our first experience of using Rhino scripting in a Java EE application for a large client. It was exactly what Ola Bini suggests in his post on language explorations. Some of the modules of the application needed the dynamism, were required to be hot swappable and customizable by the domain users. And the compilation cycle was getting in the way in trying to meet up these requirements through the standard server side language. We went for Rhino scripting for all such controllers using the new scripting engine available for executing Javascript within the JVM.

Since that application has been successfully deployed, we have been fiddling around with some more options towards polyglotism. This post is a brief summary of some of the languages / language bridges we explored in the process. All of what we did so far has been on the JVM as the underlying Polyglot platform - we have not yet explored anything on the .NET world.

Web controllers are areas which may need lots of dynamic nature, since they deal with user interactions, page flows, stateful storage across requests and many other control flow structures for realizing one complex use case. Spring Web Flow provides one viable option for modeling this. Another option from the scripting world is Rhino in Spring, which integrates Mozilla Rhino JavaScript interpreter with Spring Framework. The value add is to offer to the user the flexibility of a dynamic language to model the dynamic parts of the application on the Java platform, while integrating with the dependency injection principles of the Spring framework. Spring also offers nice support of plugging in managed script based controllers in multiple languages - this will surely provide more options towards evolution of polyglot programming in today's applications.

Another area where we explored the possible usage of an expressive language is the configuration of an application. Applications today mostly use XML based configurations, which feels too noisy for human consumption. SISC offers a lightweight Scheme scripting engine atop the JVM and comes bundled with a small footprint of around 230 KB. I had blogged before on using Scheme as an executable XML :
In SISC bridging is accomplished by a Java API for executing Scheme code and evaluating Scheme expressions, and a module that provides Scheme-level access to Java objects and implementation of Java interfaces in Scheme.

Talking about what Ola Bini calls the "stable layer", I fully agree that static type safety helps here, since the entire application infrastructure will be built upon this layer. Till today Java is my #1 choice as the language and Spring is my only choice as the framework for this layer. I have talked on this a number of times before, but I guess it is worth repeating that I love the non-intrusiveness of Spring as far as declarative programming on the JVM is concerned. As it stands now, I will not forego Spring if I am developing on the JVM platform.

It will be really interesting to see how Scala shapes up its future as a potential candidate for this layer. Scala is a feature rich language with an advanced type system, nice syntax, less verbosity and more elegance than Java. Where Scala lacks are tooling, documentation and industry patronage, all of which can improve with more and more users joining the community.

In the domain layer, most applications rely on pure Java to model business rules. As Ola has mentioned, this layer is a strong candidate for DSL based implementation. Irrespective of what language(s) you use to implement your DSL, the business application rules should always be based on the DSL only. My feeling is that in today's scenario, Java is not really an ideal language to design a DSL. Hence we tend to find almost all applications implementing the domain layer at lower levels of abstraction. This makes the domain layer of today more verbose and less maintainable.

Powerful and expressive languages with conciseness of syntax are better fit for designing DSLs. While JRuby and Scala make suitable candidates for designing DSLs for the domain layer, I think the static typing of Scala makes it a better fit here. I may be biased, but when I am thinking of reusable API design to be used by big teams, somehow static typing (possibly done better than Java) makes me more comfortable. However, considering the state of enterprise software development today, there is a significant entry barrier for average programmers to both Scala and JRuby. Idiomatic Scala or Ruby is primarily based on functional paradigms, something which is still not intuitive to a Java programmer today. With most of today's new generation languages embracing FP, this may be the single most deciding factor that will determine the amount of acceptability that polyglot programming will find within the behemoth called enterprise software development. But there is no doubt that a well designed DSL using languages like Scala or JRuby will find tomorrow's domain model at a much higher level of abstraction than what it is today.

Tuesday, January 01, 2008

Hello 2008! Will Java Strike Back ?

Wish I could start the new year blogging on a more positive note!

Two of these recent articles by InfoWorld don't look inspiring if you are a Java programmer. Particularly if you are one of the Java only programmers constructing enterprise software for one of the BigCos, these lines do not sound like music.

Notwithstanding the fact that Java is syntactically verbose, lacks the elegance of Ruby or conciseness of Haskell, Java has so far delivered the promises in developing performant enterprise applications, where you look for a statically typed, fast, stable language with a strong community contributing to the zillions of open source libraries and frameworks.

But since the release of Java 6, the issue of language design in Java clearly lacks strong leadership - whiteboards and community voting help in getting the watermark, but you need a strong leader to dictate the best features into the future versions of the language.

Developers who seek joy in programming have been moving away from Java to the rails of Ruby, Erlang and Haskell. The bottomline is that we need to make Java more productive, and the only way to do so is to add features that reduce the verbosity of Java code and encourage developers to design more powerful abstractions using the language. On the contrary, the recent trend in the Java development ecosystem has been towards adding frameworks in the development stack to make the round peg fit the square hole.

Some of the experts of the Java language suggest moving to other languages on the JVM (ala Scala, JRuby) if you like to have more powerful control abstractions. In that case what will happen to the tonnes of Java code ruling today's enterprise ?

Will Java be the new COBOL ?

Sunday, December 23, 2007

The Yegge Effect

So Steve Yegge has come up with another big post, and, as usual, the blogosphere is up on their heels. For mere mortal bloggers, it is like planning a movie release for not-so-big producers - your blog post is likely to be swamped in the Yegge Effect if the timing of your post happens to clash with that of Mr. Yegge. This post is a reaction to the Yegge Effect. Irrespective of whether you agree to all of his rants or not, a Yegge post has an impact, which you cannot ignore. You may call it the Yegge Impact as well.

Anyway, on a more serious note, it was a great post from Steve Yegge. It has brought to the forefront a number of software engineering issues - both technical and cultural. My greatest take from the post has been the preaching to select the engineering tools (read the language of development) based only on the job at hand. In fact, in one of the responses to the comments, Steve mentions that his selection of a dynamically typed language for rewriting Wyvern has been driven by the fact that the system he is trying to model is an extremely dynamic beast and in the earlier Java based system he needed all sorts of twisting and subversion of the type system to achieve the level of dynamism that the software demanded. And he chose Rhino over Groovy and Scala simply because the latter have not yet been mature enough and he was looking for something that has been enough time tested.

Yet Another Java Bashing ?

Expectedly enough, many of the bloggers have interpreted Yegge's post as another of those Java bashings. Admittedly there has been some unfair criticism of Java and design patterns in his post. We cannot ignore the fact that Java is verbose, and lacks the expressiveness of many of today's programming languages. And design patterns, very often, do not help in making your code succinct or concise, irrespective of the language in which you implement them. The biggest contribution of design patterns in statically typed implementations is the uniformity of vocabulary that they espouse - the moment you talk about factories, people understand creational semantics, the moment you talk about strategies, developers understand granular variations of algorithims within a larger context. Many of today's languages, especially the dynamically typed functional ones, have most of the 23 GOF patterns built-in the language themselves. To them, evolution of these patterns may sound like ways to get around the deficiencies of languages like Java and C++.

I feel Java has been able to successfully position itself as a much better C++. Accidental complexities of memmory management and pointer manipulations have been successfully abstracted away in Java - a definite step forward in expressiveness. And this is possibly the single most important reason that Java is ruling the enterprise even today. Java maintained the curly braces look and feel of C++ - yet another reason it could successfully launch itself within the cultural embodiment of C++ programmers. Raganwald is correct when he talks about Yegge's post as addressing more of cultural issues than technical ones. It is the Java culture that dominates the enterprise today. It does not require to be a strong elitist to program at a higher level of abstraction in Java - only you need to embrace the implementation of these features in the future versions of the language. Unfortunately many people are still against the empowerment of Java programmers with the new tools to write better programs. Steve Yegge mentions about copy-paste in Java causing code bloats. Many of the bloats are due to the fact that Java lacks the expressiveness of languages like Scala, but many of them are also due to an averagist mentality towards designing programs in Java. People have grown to develop a cultural apathy towards embracing new paradigms, incorporating functional features within the language, in the fear that it will make Java too complicated for the average Wall Street programmer. Until we come out of this vicious circle of apprehension, Java programs will continue to be great big machines that can move the dirt this way and that.

The question is .. Is Java too broken to support such empowerment ?

Tools of the Trade

Responding to a user comment, Steve says :
If I were writing a compiler, I'd use an H-M language (probably Scala). This game is a different beast; it's one of the most "living" systems in the world (notwithstanding its 1-year hibernation). You could do it in an H-M system, but it would be nearly as big as the Java system.

Select your programming language based on the task at hand. If you need well defined contracts that will be used by a large programmer base, then static typing is the answer. And Scala is one of the most advanced and expressive statically typed languages on the JVM today. In case Java decides not to implement any of the features that have been proposed by so many experts, then possibly Scala will enter into the same footsteps to displace Java that Java could successfully do to C++ a decade ago. Natural evolution !

The post also has a healthy bias towards dynamically typed systems, with all the code compression benefits that they offer through succinct abstractions. No complaints on that, though given today's constraints in executing large enterprise projects, I am still inclined to use the safety net that powerful static typing has to offer. One of the masters and researchers of programming languages, Matthias Felleisen makes the following observation in the comments to Yegge's post, while talking about evolutionary programming and gradual typing in ES4:
As a co-creator of gradual transformations from dynamically typed to statically typed languages (see DLS 2006), I am perfectly aware of this idea. The problem is that Ecmascript's implementation of the idea is broken, unsound. So whatever advantages you would get from a sound system, such as ML's or even Java's, you won't get from ES 4. (The most you get is C's notion of types.)


X Programmer (for all X)
But you should take anything a "Java programmer" tells you with a hefty grain of salt, because an "X programmer", for any value of X, is a weak player. You have to cross-train to be a decent athlete these days. Programmers need to be fluent in multiple languages with fundamentally different "character" before they can make truly informed design decisions.

A single language programmer always suffers from a myopic view of designing things. Unless you are exposed to other paradigms of programming, anonymous inner classes will always appear to be the most suitable idiom for the problem at hand. Many powerful programming techniques offered by the next door programming language may be more suited to solving your problem. Explore them, learn a new language and learn to think in that new language. This is a great message from Steve Yegge. Sometime back I was looking at an interview with Joe Armstrong, the inventor of Erlang. He believes that the combination of OCamL, Erlang and Haskell has the power to solve most of the problems of today's enterprise. OCamL, with all the static typing can be the C of tomorrow, the zen language for building the virtual machines, Erlang, with its dynamic typing, can support distributed applications with changing code on-the-fly, not really a cup of tea for constant type analyses, while Haskell can be great for building business applications. The only teaching that is required is to appease the user community of the unwarranted apprehensions of functional programming. Functional programming is based on the lambda calculus - it is the sheer intellectual weight of this very basic dictum that drives today's Java programmers away from the paradigm. Joe believes that functional programming experts should come forward more and write easy-to-read books to dispel this demon out of programmer's mind. Joe's book on Programming Erlang is a great piece - go grab a copy and do yourself a favor of learning a new functional language. You may not use FP in your next enterprise project, but you will surely be enriched with powerful idioms that higher order functions, pattern matching and hylomorphisms have to offer.

and then the central thesis ..

Refactoring makes the codebase larger that the IDEs of today are simply not capable of handling. Steve mentions that his codebase of 500K LOC could not be managed by Eclipse. I do not know for sure about the organization of the codebase of Wyvern, but I have seen Eclipse handle huge codebases. Only catch is that you need to manage them as multiple separate individual projects / artifacts with clean dependencies specified between them. And you need not have all of them open and active at the same time. Refactoring may increase the physical size of your codebase - refactoring away creational statements with pluggable factories through a Dependency Injection framework will cost some megabytes in terms of the ear size. But, I think the intellectual size of the codebase reduces - you now no longer need to worry about the creation processes and lifecycle management of your objects. Steve, however, feels that DI is also a bloat enhancer in a project. If I am using a statically typed language like Java, I think DI is a useful technique for implementing separation of concerns and modularization of your codebase. But I agree with Steve that platforms like Javascript, Ruby and Python do not need DI. They are too dynamic and offers enough flexibility to do away with the overhead of a DI framework. And regarding size bloat being reduced by dynamically typed languages, don't you think that it also increases the intellectual size of the codebase ?

So, that, in short was the Yegge Impact on me ..

Tuesday, December 18, 2007

Domain Modeling - What exactly is a Rich Model ?

It is possibly an understatement to emphasize the usefulness of making your domain model rich. It has been reiterated many times that a rich domain model is the cornerstone of building a scalable application. It places business rules in proper perspective to wherever they belong, instead of piling stuffs in the form of a fat service layer. But domain services are also part of the domain model - hence when we talk about the richness of a domain model, we need to ensure that the richness is distributed in a balanced way between all the artifacts of the domain model, like entities, value objects, services and factories. In course of designing a rich domain model, enough care should be taken to avoid the much dreaded bloat in your class design. Richer is not necessarily fatter and a class should only have the responsibilities that encapsulates its interaction in the domain with other related entities. By related, I mean, related by the Law of Demeter. I have seen instances of developers trying to overdo the richness thing and ultimately land up with bloated class structures in the domain entities. People tend to think of a domain entity as the sole embodiment of all the richness and often end up with an entity design that locks itself up in the context of its execution at the expense of reusability and unit testability. One very important perspective of architecting reusable domain models is to appreciate the philosophical difference in design forces amongst the various types of domain artifacts. Designing an entity is different from designing a domain service, you need to focus on reusability and a clean POJO based model while designing a domain entity. OTOH a domain service has to interact a lot with the context of execution - hence it is very likely that a domain service needs to have wiring with infrastructure services and other third party functionalities. A value object has different lifecycle considerations than entities and we need not worry about its identity. Hence when we talk of richness, it should always be dealt with the perspective of application. This post discusses some of the common pitfalls in entity design that developers face while trying to achieve rich domain models.

Entities are the most reusable artifacts of a domain model. Hence an entity should be extremely minimalistic in design and should encapsulate only the state that is required to support the persistence model in the Aggregate to which it belongs. Regarding the abstraction of the entity's behavior, it should contain only business logic and rules that model its own behavior and interaction with its collaborating entities.

Have a look at this simple domain entity ..


class Account {
    private String accountNo;
    private Customer customer;
    private Set<Address> addresses;
    private BigDecimal currentBalance;
    private Date date;

    //.. other attributes

    //.. constructors etc.

    public Account addAddress(final Address address) {
        addresses.add(address);
        return this;
    }

    public Collection<Address> getAddresses() {
        return Collections.unmodifiableSet(addresses);
    }

    public void debit(final BigDecimal amount) {
        //..
    }

    public void credit(final BigDecimal amount) {
        //..
    }

    //.. other methods
}



Looks ok ? It has a minimalistic behavior and encapsulates the business functionalities that it does in the domain.

Question : Suppose I want to do a transfer of funds from one account to another. Will transfer() be a behavior of Account ? Let's find out ..


class Account {
    //..
    //.. as above

    // transfer from this account to another
    public void transfer(Account to, BigDecimal amount) {
        this.debit(amount);
        to.credit(amount);
    }
    //.. other methods
}



Looks cool for now. We have supposedly made the domain entity richer by adding more behaviors. But at the same time we need to worry about transactional semantics for transfer() use case. Do we implant transactional behavior also within the entity model ? Hold on to that thought for a moment, while we have some fresh requirements from the domain expert.

In the meantime the domain expert tells us that every transfer needs an authorization and logging process through corporate authorization service. This is part of the statutory regulations and need to be enforced as part of the business rules. How does that impact our model ? Let us continue adding to the richness of the entity in the same spirit as above ..


class Account {
    //.. as above

    // dependency injected
    private AuthorizationService auth;
    //..

    public void transfer(Account to, BigDecimal amount) {
        auth.authorize(this, to, amount);
        this.debit(amount);
        to.credit(amount);
    }
    //.. other methods
}



Aha! .. so now we start loading up our entity with services that needs to be injected from outside. If we use third party dependency injection for this, we can make use of @Configurable of Spring and have DI in entities which are not instantiated by Spring.


import org.springframework.beans.factory.annotation.Configurable;
class Account {
    //.. as above

    // dependency injected
    @Configurable
    private AuthorizationService auth;

    //..
}



How rich is my entity now ?

Is the above Account model still a POJO ? There have already been lots of flamebaits over this, I am not going into this debate. But immediately certain issues crop up with the above injection :

  • The class Account becomes compile-time dependent on a third party jar. That import lying out there is a red herring.

  • The class loses some degree of unit-testability. Of course, you can inject mocks through Spring DI and do unit testing without going into wiring the hoops of an actual authorization service. But still, the moment you make your class depend on a third party framework, both reusability and unit testability get compromised.

  • Using @Configurable makes you introduce aspect weaving - load time or compile time. The former has performance implications, the latter is messy.



Does this really make my domain model richer ?

The first question you should ask yourself is whether you followed the minimalistic principle of class design. A class should contain *only* what it requires to encapsulate its own behavior and nothing else. Often it is said that making an abstraction design better depends on how much code you can remove from it, rather than how much code you add to it.

In the above case, transfer() is not an innate behavior of the Account entity per se, it is a use case which involves multiple accounts and maybe, usage of external services like authorization, logging and various operational semantics like transaction behavior. transfer() should not be part of the entity Account. It should be designed as a domain service that uses the relationship with the entity Account.


class AccountTransferService {
    // dependency injected
    private AuthorizationService auth;

    void transfer(Account from, Account to, BigDecimal amount) {
        auth.authorize(from, to, amount);
        from.debit(amount);
        to.credit(amount);
    }
    //..
}



Another important benefit that you get out of making transfer() a service is that you have a much cleaner transactional semantics. Now you can make the service method transactional by adding an annotation to it. There are enough reasons to justify that transactions should always be handled at the service layer, and not at the entity layer.

So, this takes some meat out of your entity Account but once again gives it back the POJO semantics. Taking out transfer() from Account, also makes Account decoupled from third party services and dependency injection issues.

What about Account.debit() and Account.credit() ?

In case debit() and credit() need to be designed as independent use cases under separate transaction cover, then it definitely makes sense to have service wrappers on these methods. Here they are ..


class AccountManagementService {
    // dependency injected
    private AuthorizationService auth;

    @Transactional
    public void debit(Account from, BigDecimal amount) {
        from.debit(amount);
    }
    @Transactional
    public void credit(Account to, BigDecimal amount) {
        to.credit(amount);
    }
    @Transactional
    public void transfer(Account from, Account to, BigDecimal amount) {
        //..
    }
    //..
}



Now the Account entity is minimalistic and just rich enough ..

Injection into Entities - Is it a good idea ?

I don't think there is a definite yes/no answer, just like there is no definite good or bad about a particular design. A design is a compromise of all the constraints in the best possible manner and the goodness of a design depends very much on the context in which it is used. However, with my experience of JPA based modeling of rich domain models, I prefer to consider this as my last resort. I try to approach modeling an entity with a clean POJO based approach, because this provides me the holy grail of complete unit-testability that I consider to be one of the most important trademarks of good design. In most of the cases where I initially considered using @Configurable, I could come up with alternate designs to make the entity decoupled from the gymnastics of third party weaving and wiring. In your specific design there may be cases where possibly you need to use @Configurable to make rich POJOs, but make a judgement call by considering other options as well before jumping on to the conclusion. Some of the other options to consider are :

  • using Hibernate interceptors that does not compromise with the POJO model

  • instead of injection, use the service as an argument to the entity method. This way you keep the entity still a pure POJO, yet open up an option to inject mocks during unit testing of the entity


Another point to consider is that @Configurable makes a constructor interception, which means that construction of every instance of that particular entity will be intercepted for injection. I do not have any figures, but that can be a performance overhead for entities which are created in huge numbers. A useful compromise in such cases may be to use a getter injection on the service, which means that the service will be injected only when it is accessed within the entity.

Having said all these, @Configurable has some advantages over Hibernate interceptors regarding handling of serialization and automatic reconstruction of the service object during de-serialization.

For more on domain modeling using JPA, have a look at the mini series which I wrote sometime back. And don't miss the comments too, there are some interesting feedbacks and suggestions ..