Thursday, March 12, 2009

Principles of Architecture - Anticipate Reality

My title at work is System Architect. Actually, it's something like System Architect / Engineering Lead, but I have my suspicions that it was suggested by our business card printing company who may, or may not, get paid by the letter. That's a story for another time.

What I'm driving at is that many times, architects are thought of as different from developers. It's true that the path to software architecture is either rooted in, or tightly entwined with, software development, but it tends to be some kind of a specialization. The reason I bring this up is because, as architects, we run the risk of separation from actual, real world, implementation concerns. By removing ourselves from the nitty gritty implementation details (a phrase I've been lazy enough to toss around in certain circumstances, admittedly) we have the potential to forget or otherwise disregard the venerable minefield that is the production environment and even the real world.

Using tools like diagrams, white boards with the nice non-smelly dry erase markers, pens and paper, and even more direct methods such as defining interfaces, we're still far removed from the underbelly. We're removed from reality both conceptually and (almost) physically; the implementation - the realization of a given architecture, big or small - is not our own. In other words, we're not subject to our own dog food. And, if you're not careful, you might end up designing for the utopian world of your favorite modeling tools. The professional term for that is screwed.

By not pushing yourself back into the role of implementor either by contributing to code directly or working closely with those dealing with your precious architecture, you are robbing yourself as well as sabotaging the rest of the team, not to mention the project. If you work in an organization where this isn't feasible you can still place yourself in the shoes of the developer, the testers, tech writers, product managers, all the way up to the end users. The impact of your design decisions are greater than just the common set of technical concerns. You are bound by the goals of the project. Your design must not only be simple, elegant, and technically correct, but it must deal with the idiosyncracies of the business, production woes, maintenance and operation teams, and so on. In fact, I'm a little sad I even used the word elegant.

I spend quite a bit of time writing code at work. I do this for a few reasons. For starters, we're just in need of extra hands; we're working on some very cool projects on tight time lines and I'm always a developer regardless of title. Possibly even more important than simply generating code, though, is the need to get things right, in terms of design. By working with the rest of the team, dealing with implementation questions and concerns, all day, every day, I'm forced to constantly reconsider what is working and what isn't. Developers are the first to trip over corner cases in the design or find awkward situations that are difficult to detect in a pure design phase. In an agile environment, the constant attention to high quality and correctness means - in terms of design - following a design through to the end, through all its transformations and anticipating real world situations.

Wednesday, March 4, 2009

Declarative Concurrency In Java - A follow up

It's put up or shut up, right? I don't know if this is something I can do by myself, but I'm happy to try and get the ball rolling.

Some time ago, I wrote about declarative concurrency in Java. It seemed to get a good reaction from many people from different sections of the community. I wound up receiving a lot of email about how people were interested and how the idea of being able to define concurrency semantics in such a manner was appealing for a number of reasons. Well, I went ahead and stubbed out a project which I've pushed to github[1] for the world to pick at! It's minimal and there's very little there right now, but I wanted to solidify my intent to actually produce a prototype by physically creating the project and pushing it out there.

Everyone is welcome and encouraged to participate. The goal of the project will be to create a simple, open source, library in Java that will do the following.

  1. Allow developers to annotate methods, indicating that they may be executed in parallel.
  2. Provide a simple library that will, based on configuration and hints from the annotations, intercept invocations of the annotated methods and execute them concurrently.

I hope to get additional feedback on the concepts as well as the implementation as it evolves over time. Thanks to all who have provided feedback and encouragement thus far!

http://wiki.github.com/esammer/decothread

[1] - github.com - decothread project @ github

Tuesday, February 24, 2009

Principles of Architecture - Reduce and Simplify

Just a few days ago, I had a weekly one on one meeting with my boss. It's times like that where work becomes kind of like a game of Can I go a full hour without putting my foot in my mouth? Turns out, I came out unscathed this time.

Recently, around the office, we've been talking a lot about the principles behind the agile manifesto. Pav (aka John Pavley, CTO) mentioned that I probably had a similar list of principles of software architecture I operate by. He pointed out that I hadn't really vocalized what those are in any obvious way and that doing so would probably be beneficial or at least interesting. Thinking about what those principles are and needing to actually enumerate them also helps me think about what's really important and why.

Before we get into the first principle I want to discuss, I want to clarify why I'm using the term principle rather than, well, anything else. During our discussions of the principles of the agile manifesto, we used this word because, like what I hope to describe in software architecture, those items are considered intrinsic properties of software development. As Pav would say, they're discovered, not invented. I tend to think he's right and that the choice of the word principle is deliberate and intentional. This is also my intention here.

One of the first two principles that came to mind was the idea of reduction and simplicity. When designing software, we strive to reduce or eliminate complexity wherever possible. There are times where a task is inherently complicated, but the design of the system need not necessarily be complicated. If that sounds counter-intuitive, consider the separation between designing the system's architecture - the way it behaves, the layering, the major objects in play, the way it interacts with constituent systems or resources, its fault semantics, and so on - from its implementation. In many cases, what you'll find is that the implementation may have some inherent level of complexity to meet the business requirements, but that a well designed system is almost obvious and easily fits in your brain without confusing you. Let's consider something concrete.

If you were to design an SQL query execution engine... I don't even need to finish that sentence for it to sound scary. Take a few minutes to think about how you might design a query execution engine. In five or ten minutes you might actually be able to work out a simple model that makes sense (within reason). The details of how to implement that design is where one gets into the shady details of how to make the magic happen. Even the design of a compiler is simple enough, in most cases, where as the implementation is where the complexity lies. A compiler will have a grammar, a lexer, a parser, probably an AST, a chain of optimization strategies, maybe a number of output generation strategies. Within each of those major components, you could break things down further and come up with an easily understood design for a modular compiler. I'm not trying to trivialize building a compiler (try implementing a C++ compiler some day) but I do think that with some thought, the design process would effect a reasonable, intuitive result.

The point I'm trying to make is that a well designed system should be intuitive to the person or team implementing the system as well as the architect. If you find it difficult to communicate a design, there's a high chance that the implementation of that design will not make things any simpler. In fact, it's probably impossible. To be clear, some things have an inherent degree of complexity, but we should always strive for the simplest, but still most complete, design possible.

These are all relative terms; simple, complex, intuitive, complete. You'll always have to rely on your judgement, experience, and best practices of the trade. By properly deconstructing an application, its components, their components, and so on, even the most complex system can be easily understood and digested.

Some techniques I find useful for making this happen are:

  • Apply Divide and Conquer. Break down components recursively until you get to easy to understand units of functionality.
  • Never work alone. Statistically, you're more than likely to be surrounded by people who can contribute experiences and ideas during the design process that will yield a better result. The added benefit here is that you're constantly having to explain your thought process and ideas to other humans; the degree of complexity is probably proportional to the number of times a junior developer says Huh?
  • Follow patterns and best practices. Silly questions like Does your class do one thing and do it well? have saved me from my own cleverness more than once (but admittedly not always).
  • Trust your gut. If it sounds too complicated, it probably is. Take a break, look at similar problems, ask around, and try a different approach.

There's no complexity blasting ray gun of designly awesomeness. There's no third party library that you can just drop in to make it simple. Sometimes, the business requirements are as tough as they sound. Most of the time though, you can reduce and simplify.

Tuesday, February 10, 2009

Class Categories in Java

Class categories have existed in a few incarnations over the years. My personal knowledge of comp sci history is thin, at best, but my small amount of research into the material is that it came from Smalltalk-80. Certainly, my first exposure to class categories came from working with Objective-C on NeXTSTEP and later Mac OS X.

What a category does is relatively simple to understand. Basically, the idea is that a developer may take an existing class and, effectively, append methods to it without having access to the source code or subclassing it. This is best illustrated in code.

// A normal, and terribly boring class.
public class Foo {

  public void displayMessage(String message) {
    System.out.println("A useless message:" + message);
  }

}

// Extending the class by creating a category on it.
public class Foo (MyExtensions) {

  public String getDefaultMessage() {
    return "Hello world.";
  }

}

// ...and finally, what one would expect.
Foo f = new Foo();

f.displayMessage(f.getDefaultMessage());

Normally, when I explain class categories to Java developers, I barely get the words out before I'm hit with what you might expect. People question whether this is breaking encapsulation, if this bloats code, if it creates tight coupling, if it breaks access rules, and so on. Some of the more dynamic languages like Ruby and Perl will happily let you do things like this (albeit, sometimes safer than others), but that happens at runtime.

I'm proposing we bring categories to Java. Yep. I said it. I'm going to focus more on how this might work rather than why I think it's a good idea, although I'll try and briefly address that too. Here's how I think it could work and why.

The Basics

The syntax would work like Objective-C's syntax. Creating a category would be done by specifying the same package and class definition, in the interest of simplicity, with the addition of a category name enclosed in parenthesis (see the above example). It would not be legal to specify inheritance when creating a category; inheritance would always be defined by the original definition (i.e. the uncategorized class declaration), although there's no reason to prohibit the implementation of additional interfaces in a category. This would allow those creating categories on a class to extend an existing class to implement a new interface without modifying source code.

Access, Security, and Visibility

In many ways, the access and visibility rules of subclassing applies to categories as the result is very similar from the perspective of the original class; the new functionality is unknown and untrusted.

It would only be legal to access public or protected members of a class when creating a category. This would respect access and visibility restrictions on code developed prior to the existence of categories. Overriding a method in a category would not be permitted, although method overloading is fine. Private members within a category would not be visible outside of the category.

Category Availability

The biggest differentiation between categories in Java and class reopening in Ruby, for instance, is that the contributions made to a class via a category would be known and could be checked for at compile time. This would allow developers to see and avoid cases of competing categories or member addition during development, which is usually not possible with languages that allow for this kind of functionality.

It would not be legal to create a category on a class declared as final. This extends the meaning of declaring a class to be final, but only slightly as creating a category is similar in intention to subclassing (in theory). This rightly implies that there is no way to prevent the creation of categories, but allow subclassing as there's no obvious reason to draw a distinction as categories can only access public and protected members of an existing class, just as a subclass would.

External classes including unrelated as well as subclasses of a class with categories would see all members including those defined in categories as usual. The category information of a member should be made available via the standard reflection classes and methods. Given the above example Foo class, the following would work as expected.

/* Includes both methods from the original class declaration
 * as well as methods from categories.
 */

Methods[] methods = Foo.class.getMethods();

/* Additionally, category information should be made available
 * via reflection.
 */

Category[] categories = Foo.class.getCategories();

for (Category category : categories) {
  System.out.println("Methods in category:" + category.getName());

  for (Method method : category.getMethods()) {
    System.out.println("method name:" + method.getName());
  }
}

Some Quick Reasons Why

There are a few nice advantages to having categories available in a language, especially at compile time. There are the obvious advantages such as simple code organization. What I tend to think is more interesting, though, is creating categories to apply specialized functionality to core classes. For instance, one may want to add methods to collections to glue validation logic to core components. In cases where Spring is used, it's not uncommon to see many adapter type objects that simply exist to make an object more amenable to participate in DI. I believe that a lot of code and class structures could be greatly simplified by being able to make minor alterations to existing classes rather than resorting to multiple objects to mediate or adapt existing code to new systems and frameworks.

Like anything else, there is the obvious ability to abuse something like categories. I think there are times when more traditional approaches are the best option, and there's no replacement for good design and education, but to remove a valuable tool because some subset of the population may misuse it only serves to hurt those that could make proper use.

My plan is to attempt to draft this as a JSR and submit it for review. I don't know if I have the ability to chew through the politics (I'm assuming are) attached to that, but it might be fun to try. Clearly there's more to work out (I haven't looked deeply into what this does to the compiler and runtime at a low level, for instance), but I'm interested in what people think about categories in Java.

Wednesday, January 21, 2009

Another Night with GridGain

Earlier this evening, I had a chance to attend a presentation on GridGain at this month's NYC JavaSIG at the Google Engineering building here in New York City, NY, US. I've written about GridGain before, but if you haven't read my thoughts on it, I'll sum it up; I'm a fan.

I got a chance to talk to Nikita Ivanov, if only briefly. Nice enough guy. What I like about his presentation most is the lack of - and there's probably no other way to really say it - bullshit. Sure, he uses words like grid and cloud which is always suspect, but in this case, he provides an actual, single slide, definition of what it means to him and GridGain.

Grid Computing = Compute Grid + Data Grid

Makes sense if the terms compute grid and data grid mean something to you. Nikita seems to stick to (what I think is) the standard definition of a data grid - a network of data storage machines containing partitioned or distributed storage. I'm paraphrasing a bit here, but mostly because I don't recall his exact wording. The compute grid portion of that should be obvious. I'm not providing any hints on that one.

Cloud computing is defined by Ivanov as follows.

Cloud Computing = Grid Computing + Data Center Automation

This is also simple and concise. So we get grid computing; at least in the context of GridGain. Data center automation, in this case (and Ivanov's opinion) covers not just the normal stuff, but specifically the creation and shutdown of instances of machines. This is generally stuck behind an API such as Amazon's EC2 and related services with the goal that one can have a greater degree of flexibility. While I'm not really in love with EC2 as some others may be (not referring to Ivanov, specifically, just the sometimes expressed idea that EC2 is solution to all woes) it is a readily available cloud environment that one can play with. I'm glad it exists.

A panacea? Of course not. Honestly, what could be, short of a super code-monkey falling from the sky to do your evil bidding? Ok, maybe an intern.

The point, I think, is that this kind of functionality - the ability to perform massive, distributed, parallelized computing without six-plus figures worth of hardware and software - is both simple and significant.

As usual, no grand epiphany here on my part... just some commentary on one of the areas where we can push performance in real world applications. That, of course, being something we should always be looking to do. Thanks to GridGain, Ivanov, NY JavaSIG, Google, the JavaSIG sponsors, and my employers for not getting annoyed that I suckered my team into cutting out early to go to the event.

Friday, January 9, 2009

Of Maven Dependencies and Repositories

I think of Maven the same way I tend to think of Git; excellent features, but just a little more complicated and obtuse than is really reasonable for the task. I know that's insanely unpopular to say about Git, but luckily this isn't about Git.

Recently, I was converting a project at work to Maven (from Ant) as an experiment. This is a relatively standard, mid-sized, Java project that makes heavy use of a number of what I would consider common Java libraries. In our case, we use Spring very heavily, along with other staples like Hibernate. One of Maven's killer features is the ability to resolve dependencies and pull the correct versions from the Maven Repository, but we already know that.

I found the selection of dependencies from the central repository to be one of the worst things I've had to do in recent days. I was spending more time setting up different repositories and wading through the duplicate packages than I was enjoying the benefits of such features. It's almost more of a headache than doing it all by hand.

In OSGI bundles, which have some similarities in dependency specification, at least, with Maven, one has the ability to express dependencies in a few ways. The obvious unit of dependency is specifying another bundle. This is, effectively, the same as Maven. OSGI bundles, though, may also opt to specify only what Java packages the bundle imports and let the runtime figure out what bundle to take those packages from. This is similar to how many Linux package managers operate when more than one package can fulfill a dependency and it's traditionally referred to as a virtual dependency.

Maybe what we need from Maven is the notion of the virtual dependency. A Maven POM could specify virtual packages as dependencies that could be filled by any one of a number of providers. Java lends itself to this very well because the majority of standards define the APIs with service providers being distributed separately. Think of things like JPA (provided by Hibernate EM), JAXP (Xerces and friends), and so on. I suppose it's a little different because Java developers want to pick an implementation for a specific reason, but having virtual dependencies would eliminate many of the overly specific dependency graphs created when dealing with complex packages such as Spring, for instance.

It's worth noting that the most significant issue I have with Maven is the quality of the metadata. It is just plain awful. Some of the things I ran into were:

  • Packages that weren't updated with bug fixes or recent versions
  • Many copies of the same package with different names and odd descrepancies in versions
  • Missing (or unavailable) dependencies
  • When using Spring's Maven repositories, duplicates of the dependencies are pulled in because Spring depends on versions not in the central rep.
  • Because Spring came from Spring's repository, packages like GridGain which depend on Spring, grab the version from the central repository, but Spring Integration which is only available from Spring's rep has a dependency on the version of Spring from Spring's rep... AARRRRRRRRRRRRGGGGGGGGGGHHHHH!

I get that this is hard and it requires a lot of coordination. I get that I could repackage things in my local repository or a corporate shared repository. Should I have to? A lot of the advantage of Maven is lost when one has to manually follow dependencies to figure out why there are two (full) versions of Spring Core in the project. It's annoying, wasteful, and prone to error.

Maven, I want to like you. Really I do. But like a real, live, flesh and blood human, you make it so difficult sometimes, just like your sister (Git).

Wednesday, January 7, 2009

Declarative Concurrency in Java

Good, solid, safe, effective concurrent programming is hard. Modern languages and paradigms make it easier, but for most, it's still a challenge to get right, right away. Many people have predicted the end of the great Ghz race. They're probably right. I don't have any great insight into the CPU design community. Honestly, it just doesn't hold my attention. Multi-core systems are all the rage these days, though, and that's pretty damn cool. None of this is new; plenty of smarter people than myself have pointed it out.

One of the purported benefits of functional programming is how it lends itself to concurrent programming. Luckily, I work with a smart guy who's both patient and polite enough to talk to me about FP without serving kool-aid (thanks Adam). Many of those conversations entail discussion about state, immutability, and side effects in software implementation. This, of course, leads me to think about how some of these things apply to one of our weapons of choice where we work - Java.

Java accomplishes concurrency via thread objects. Big deal; nothing new here. Most of the confusion comes into play not when deciding what should run concurrently - that's usually obvious - but when figuring out how to protect shared state. Again, in Java-land, we do this with different types of locks, either implicitly with synchronized blocks or explicitly with the grab bag of fun from the java.util.concurrent.locks package. Many of the Sun docs talk about how we use locks to establish happens before relationships between points in code. What's interesting is that this language seems so natural and simple. So why is lock management such a pain?

Maybe imperative locking isn't the right approach. Maybe, there's a more natural way to establish a happens before relationship. It sounds like dependency declaration. I'm wondering if we can't find a way to declare dependencies within source code. Maybe there's a way to declare dependencies, with something like annotations, where instrumentation can infer what we're looking for. This, of course, is sugar for what we have now, but I don't think sugar is always bad.

 public class MyClass {

   private int counter = 0;

   @Concurrent( stateful = true )
   public void execute() {
     /* Do something that might touch shared state. */
     this.counter++;
   }

   @Concurrent( unitName = "otherExecute", stateful = false )
   public void otherExecute(String someArg) {
     /* Do something that promises not to alter ourselves. */
   }

   @Concurrent(
     unitName      = "somethingElse",
     stateful      = true,
     happensBefore = "otherExecute"
   )
   public void somethingElse() {
     /* This can be run concurrently, could touch state, but
      * must happen before "otherExecute" is called.
      */
   }

   static public void main(String[] args) {
     ConcurrentController controller;
     ConcurrentUnit       unit1;
     ConcurrentUnit       unit2;

     controller = ConcurrencyController.forClass(MyClass.class);

     unit1 = controller.getUnit("somethingElse").setThreadPoolSize(10);
     unit2 = controller.getUnit("otherExecute").setThreadPoolSize(5);

     unit1.start();
     unit2.start();
   }
 }

The @Concurrent annotations would instruct an instrumentation library to perform an operation in parallel. The hints stateful and happensBefore could be used to perform additional automatic member variable monitor acquisition or something equally snazzy. The unitNames could be used to grab a handle, of sorts, to a concurrent unit of work and be used to establish relationships or to report on concurrency plans (which could be similar to an RDBMS query execution plan). Who knows... I'm tossing ideas around.

I don't think it covers every situation. In fact, I'm sure it doesn't cover everything. It's beyond flawed and probably not possible. I'm just trying to get some wheels turning. The goal is to have simpler, coarse-grained, declarative concurrency definition that can be externalized.

I'm intrigued by the idea of simple concurrency models that don't remove the fine-grained control given to us by the language and APIs. If concurrency isn't going away, it has to get easier for the majority of people to do it correctly.

I'm especially interested in feedback on this.