Jun 15, 2010

Designing Distributed Systems with SCALA and DDS

In the past few months I've been experimenting with Scala a relatively new programming language targeting the JVM (and .NET). Differently from some of the latest programming languages targeting the JVM such as Groovy or Clojure, Scala is statically typed and features a very powerful type system with sophisticated type inference -- meaning that the compiler will infer types for you whenever possible thus limiting the need for typing them explicitly.

Scala provides a well balanced blend of imperative and functional programming mechanism which, I have to admit, seem to always give you the right tool to address a programming challenge in the most elegant manner.

Another very interesting aspect of the language, especially for those that have to deal with large systems, is that it has been designed ground up to be scalable, meaning that Scala supports equally well the development of small applications as well as big systems and system of systems.

Last but not the least, Scala is fully interoperable with Java, meaning that you can reuse Java Classes in Scala applications and viceversa. In summary, if you are a Java programmer, I think, you should definitively take a look at Scala and seriously consider moving to it.

Performance... Right, you might be wondering about Scala's overhead. In my experience in using Scala for distributed applications I've not seen any difference w.r.t. Java. This is consistent with what reported by other Scala users -- Scala matches Java in terms of performance.

Assuming that now you are agreeing that Scala is a great language for developing your next application, and be aware that companies like Twitter, SIEMENS, SONY and many others have taken that route, let's explore why Scala and DDS is a great combination.

There are several reasons why the combination of Scala and DDS is very natural, so let's explore two of those. First, DDS, differently from many other Pub/Sub technologies allows you to preserve the user-defined-types end-to-end. What do I mean with this? If you think about an application in abstract terms, you can think of it as a computation applying operators (or operations) on types. Some of these types might be native to your programming environment, such as Int, String, List, etc., other might be user-defined such as FinancialInstrument, RadarTrack, FlightDataPlan, etc. Programming languages usually give you abstraction to build user defined types and operate over them. DDS, provides you abstractions to distributed user defined types, without loosing type information, across applications in a distributed system. This means, that your application does not have to deal problem of representing user-defined-types into some other type that can be handled by the distribution technology (e.g. a specific JMS Message, or a sequence of bytes) . Applications using DDS always and only deal with user-defined-types. This has some important implications in terms of simplicity, code clarity, efficiency and safety.

As a result when combining Scala and DDS you have a statically typed programming language and distributed middleware that allow you to preserve your type invariants end-to-end.
At this point some people will raise the issue that types get you into troubles when you are trying to extend your system. This is true for inflexible type systems, however both Scala and DDS (with the newly adopted specification on Extensible and Dynamic Topic Types) provide you with structural type system that while preserving all the good properties of a sound type system nicely support type extensibility and evolution.

The second reason why I think that Scala and DDS are a very good combination is that it provides an actor model for building concurrent and distributed applications. The actor model matches very nicely with DDS and provides you an elegant and effective abstraction for building distributed systems.

There are several other reasons that I could list for choosing Scala and DDS for distributed applications. One of the other may is the native support for dependency injection supported by Scala, the other will probably be explored in some future post.


No comments: