February 23 - Keynote titled OSGi in the Enterprise: Agility, Modularity, and Architecture’s Paradox
March 22 - 25 - Tutorial on Modular Architecture
June 14 - 17 - Sessions titled Turtles and Architecture and Patterns of Modular Architecture
July 26 - 30 - Two sessions on rich mobile applications and one on agile development. Half day tutorial on software process improvement.
Right on. I just won a Best Buy drawing worth $1000. Either that or I won a shiny new virus by clicking the link. Hmm...what to do. 2012-08-29
The opinions expressed on this site are my own, and not necessarily those of my employer.
We all like metrics, statistics, and measurements that let us know how we’re doing. Released about a week ago, the 2009 Standish CHAOS Report should have plenty of numbers. Jim Johnson, the guy behind it all, cites some numbers pulled from the report. It appears failure is on the rise. In fact, it’s the highest failure rate in over a decade.
I’ve always liked the Standish report. It’s packed full of interesting and high impact statistics that can really help drive a point home - especially when you’re on stage presenting. But you also have to be careful about reading too deeply into those number. It’s very easy to metriculate, and some have challenged the accuracy of the numbers within prior reports.
I was browsing through some older directories and stumbled across a Ruby programming kata I had done a couple of years ago. This is a simple kata where I calculate the payment for a loan based on interest rate, number of months, and loan value. I typically practice this code exercise for new languages that I’m learning, and I go through a progression of steps that help me understand the language sytanx and semantics first, before moving onto improving my design, using other features and frameworks of the language, and making it accessible via the web.
I was actually pretty surprised that the exercises still worked, save for a few scripts I had to change. The code hasn’t been touched for about two years, and I was very shocked I didn’t experience the phenomena where code that goes untouched for prolonged periods of time tends to somehow break. Strange, isn’t it? Anyway, I’ll walk you through the four versions. You can find the code for each of the versions in my Google code repository. To checkout all versions of the kata, simply do the following:
svn co http://kcode.googlecode.com/svn/trunk/kata/ruby
It doesn’t get much simpler than Version 1. Just two files. Input.rb manages the command line interaction, and prompts for the rate, months, and value. Loan.rb performs the calculations. To run this sample, just type
and enter values, such as 6, 60, and 15000. There is also a testcase, named LoanTest.rb.
The second version has some minor enhancements over the first.
To accommodate printing the payment schedule, I modified Input.rb to prompt the user to choose to print either the payment schedule or monthly payment. I also added a new method to Loan.rb called calculatePaymentSchedule. To address the running total that I need to keep track of when calculating the full payment schedule, I also added PaymentSchedule.rb to represent the complete payment schedule. Within the PaymentSchedule instance is a collection of Payment.rb instances - one for each monthly payment.
You can run the sample in the same manner as before. Just be sure you’re in the V2 directory when executing.
require 'rake/testtask' task :default => [:unit_test] Rake::TestTask.new(:unit_test) do | tsk | tsk.libs << "./app:./test" tsk.test_files = "AllTests.rb" end
There is a pretty lengthy discussion of my initial struggles with rake in the trouble.txt file included with this version. Suffice it to say that at the time I performed this kata, I had trouble finding good documentation that showed me how to do what I wanted. The only real change I’ve made recently to the rakefile was to use the PATH_SEPARATOR constant in lieu of hardcoding the separator (”:” or “;”), which I struggled with for a while when I got my Mac.
Here, I wanted to take the code and transform it into a REST service. I wound up making it work by replacing Input.rb with Server.rb. It didn’t really wind up all that RESTful, but oh well…it works. I also added something else I’m pretty fond of, which is test coverage using RCov. My trials and tribulations with making this accessible via the web can be found in V4.txt.
To run the sample, just type the following in the terminal from within the V4 directory.
You’ll see the server startup, then you can access the sample at http://localhost:8181/loan. In doing this, you’ll get back a response that shows you the URL parameters you’ll need to add. You can also click right here to the fully customized URL with sample parameters. Pretty simply really.
I also suggest you take a look at the rakefile.rb included with V4 because it uses rcov. As you can see from the rake tasks that have been commented out, at one time I had this working with CruiseControl.rb, though I no longer do because that bit of funtionality did succumb to the phenoma of code that isn’t exercised eventually breaks. Invoking the build with CruiseControl.rb would be a good exercise, as would the numerous other improvements that could be made to the code. But I’ve been done with this Ruby kata for about two years, and don’t intend to do anything else with it. I’m only sharing it as an example of what I like to do when learning a new language. Time for a Scala kata, Clojure kata, Fan kata, and more.
A while back, I posted about Jar Design over Class Design, which summarizes the responses I’ve gotten over the years when asking developers where they devote the majority of their design activity. The responses I get are always consistent - time is spent on class design, not JAR design. In fact, few teams spend time on JAR design.
For several years, I’ve always felt that JAR design is equally, if not more important, than class design. In fact, the majority of postings on this blog talk about modularity, OSGi, managing dependencies, and a lot of other design stuff that’s specifically focused on JAR design. But that doesn’t appear to be mainstream thinking, and I’m very curious, and would appreciate your help. Why do you spend more time on class design, and less time on JAR design? Please let me know.
In Rotting Design, I spoke of how software tends to rot over time. When you establish your initial vision for the software’s design and architecture, you imagine a system that is easy to modify, extend, and maintain. Unfortunately, as time passes, changes trickle in that exercise your design in unexpected ways. Each change begins to resemble nothing more than another hack, until finally the system becomes a tangled web of code that few developers care to venture through. The most common cause of rotting software is tightly coupled code with excessive dependencies.
Dependencies hinder the maintenance effort. When you’re working on a system with heavy dependencies, you typically find that changes in one area of the application trickle to many other areas of the application. In some cases, this cannot be avoided. For instance, when you add a column to a database table that must be displayed on a page, you’ll be forced to modify at least the data access and user interface layers. Such a scenario is mostly inevitable. However, applications with a well thought dependency structure should embrace this change instead of resist the change. Applications with complex dependencies do not accommodate change well. Instead, with change, the system breaks in unexpected ways and in unexpected places. For this to happen, the module you unexpectedly broke must be dependent on the module that changed.
Dependencies prevent extensibility. The goal of object-oriented systems is to create software that is open for extension but closed to modification. This idea is known as the Open-Closed Principle. The desire is to add new functionality to the system by extending existing abstractions, and plugging these extensions into the existing system without making rampant modifications. One reason for heavy dependencies is the improper use of abstraction, and those cases where abstractions are not present are areas that are difficult to extend.
Dependencies inhibit reusability. Reuse is often touted as a fundamental advantage of well-designed object oriented software. Unfortunately, few applications realize this benefit. Too often, we emphasize class level reuse. To achieve higher levels of reuse, careful consideration must also be given to the package structure and deployable unit structure. Software with complex package and physical dependencies minimize the likelihood of achieving higher degrees of reuse.
Dependencies restrict testability. Tight coupling between classes eliminates the ability to test classes independently. Unit testing is a fundamental principle that should be employed by all developers. Tests provide you the courage to improve your designs, knowing flaws will be caught by unit tests. They also help you design proactively and discourage undesirable dependencies. Heavy dependencies do not allow you to test software modules independently.
Dependencies limit understanding. When you work on a software system, it’s important that you understand the system’s structural architecture and design constructs. A structure with complex dependencies is inherently more difficult to understand.
Excessive dependencies are bad. But cyclic dependencies are especially bad. Cyclic dependencies are manifest in various ways at different levels within a system. It’s also possible that acyclic relationships at one level cause cycles at another.
Cycles exist across a variety of entities; notably class, package and JAR. Class cycles exist when two classes, such as Customer and Bill shown here, each reference the other (assume Customer has a list of Bill instances, and Bill references the Customer to calculate a discount amount). This is also known as a bi-directional assocation. It’s a maintenance and testing issue, since you can’t do anything to either class without affecting the other.
Class cycles can be broken a few different ways, one of which is to introduce an abstraction that breaks the cycle, as shown here. Now you can test Bill with a mock DiscountCalculator. Testing Customer, of course, still requires the presence of Bill. This is not a cyclic issue, it’s a different type of coupling issue as Bill is a concrete class, and is fodder for a separate discussion. Introducing DiscountCalculator has broken the cycle between Customer and Bill…but has it broken all cycles?
We don’t intentionally create cyclic dependencies. Instead, they tend to creep into our design. They commonly surface when cyclic or acyclic relationships at one level cause cycles at another. For instance, if Customer and DiscountCalculator are placed in a cust package, and Bill is placed in a billing package, a cyclic dependency between cust and billing exists even though the class structure is acyclic, as shown here. Allocating the cust and billing packages to cust.jar and bill.jar also causes a cycle between the .jars.
To break the cycle, we should move DiscountCalculator to its own package, or the billing package. Simple heh? Well sure…but now toss in a few thousand classes, a few hundred packages, and numerous JAR files, and it’s not so simple to manage anymore.
Fortunately, there are many ways (some easier than others) to manage dependencies and eliminate cycles. Test Driven Development is a great way to manage class cycles assuming we strive to test classes in isolation. JDepend allows you to manage package cycles, either by writing package constraint tests or including JDepend reports within your Ant build script. Jar cycles can be managed using a Levelized Build, where individual jars are built, including only necessary components in the build class path. JarAnalyzer can also be included in your build script, generating a component diagram illustrating the relationship between JAR files, or a dependency report similar to that of JDepend. Maven and Ivy also provide ways to help manage dependencies. And of course, looming on the horizon is OSGi, which may not be ready for widespread enterprise use today, but hopefully will be soon.
Generally speaking, cycles are always bad! But some cycles are worse than others. Cycles among classes are tolerable, assuming they don’t cause cycles among the packages or JAR files containing them (ie. the classes must be in the same package, essentially encapsulating the design). Cycles among packages may also be tolerable, assuming they don’t cause cycles among the JAR files containing them (again, packages are in the same JAR file). Most important is that we are aware of the relationships existing between the JAR files. In so many cases, we aren’t.
In browsing through some of the articles I’ve written, I stumbled across Benefits of the Build, which was published in the March 2005 issue of Software Development Magazine. SD Magazine was rolled into Dr. Dobb’s a while back, but I found the article is still on-line, and still very relevant. That article also forms the foundation of a very successful talk I’ve given at various conferences.
I’m continually amazed by the number of development teams that don’t practice continuous integration. IMHO, it’s the most important technical practice you can employ, assuming you leverage the fact that you’ve got a functional product. I’d highly recommend that any team start today.
Since the time I wrote that article, I’ve learned a lot and developed a stronger sense of what it takes to employ a successful continuous integration strategy. Here are a few guiding principles and rules that help maximize the benefits of the build.
The image is a wordle of the text in Benefits of the Build.