Customizing Eclipse: Setting Up Shortcuts

If you’re using Eclipse as your IDE every day, you’ve probably got certain tasks that you do regularly such as getting projects from version control or writing unit tests, as well as normal coding tasks. This tip shows how you can customize what shows up on your File/New menu for a certain perspective. Some of the commands that you use might be buried under the File/New/Other.. menu. This brings them up a level.

To do this, go to Customize Perspective from the Window menu in Eclipse, while in the perspective where you want the changes to apply.

Here, you will see a number of options that you can add to the New menu. Note that you can also customize shortcuts for the Show View and Open Perspective menus from here.

Just select the items that you want to appear. In the above example, I’ve included the JUnit shortcuts.

Now when I use the File/New menu, these options will be easily accessible:

It’s a pretty simple thing to do, but it might save you a little bit of time.

Deadlines Without Downtime: The Curse of Software Development

A common observation of the software development industry is that it’s immature. And that’s true when compared with more established professions related to construction or medicine. I’ve been thinking that this may be due, in no small way, to the way software developers are treated, which Neil McAllister outlines in his article Developer Burnout: Time To End The Disposable Geek Mentality.

Neil captures the core of the issue in the following paragraph:

Long work hours, missed vacation and sick time, and lack of recognition and advancement are endemic in the software development industry. For all the talk of a “knowledge economy,” some of the smartest and most highly specialized members of the workforce are often treated like disposable labor, easily replaced by newer, cheaper recruits. The result, predictably, is burnout, where the most seasoned team members leave the organization for greener pastures — and or vacate the field completely.

Every sofware developer with a year or two’s experience has served their fair share of crunch time. There’s always something else that needs to be done, deadlines are a constant squeeze and the result is a worn out workforce. And what’s next once the deadline is reached? More of the same.

Sure, managers can do stuff to help out here by allowing key developers to take some time out from the critical path. But usually, the key people are the ones that are always busy. Does taking an agile approach improves things? Yes, but the same demands on the software developer persist.

The thing is, I’m not sure why this is the case, or what could change things. Perhaps software development isn’t looked at as the highly skilled profession that it really is? I know, unlike doctors, we’re not saving lives (for the most of us at least), but with IT at the center of everything, surely developers should be more valued?

Maybe software development has become too cheap – everyone wants to save money, so why pay $100K for a developer if you can get one for $50K? It’s not all about the money, but salary is a big issue for software developers, the same as everyone else. If you can give a developer a salary that means they don’t need to worry about other things, such as how to pay this bill, maybe you improve productivity and the value you get from the developer. The following presentation, from Dan Park, gives some great insights into what works for motivation:

Maybe I’m wrong, but the broad consensus seems to suggest that software developers aren’t treated as well as they should be. Have you got any horror stories that support this claim?

 

Have You Found Your Project In Technical Debt?

I’ve been reading a lot about technical debt recently where people alternate between voluntary technical debt or inadvertant debt. Without doubt, every project has some level of debt, but the important thing is how much do you have, and when do you plan on paying it off.

Martin Fowler says

“Technical Debt should be reserved for cases when people have made a considered decision to adopt a design strategy that isn’t sustainable in the longer term, but yields a short term benefit, such as making a release. The point is that the debt yields value sooner, but needs to be paid off as soon as possible.”

Technical debt is an excellent way for an architect or developer to communicate the cost that a particular decision or implementation made in the short term will affect the project in the longer term.

While in words this works fine, I wonder if there is some type of formula that we can apply to illustrate and track the debt of a project. For each item in the project that causes some debt, it needs to have interest (the cost of not addressing it) and principle (the cost of refactoring the issue to make it work).
While principle could be the number of man days to fix it, I’m stuck with how to express the interest. And how do you work out how much technical debt a project can actually afford. I’m interested to hear if any of you have used the technical debt metaphor in your projects effectively?

There are different types of technical debt, which Martin Fowler describes very neatly in his quadrant diagram:

Reckless and Deliberate

The cost of racing making the deadline at all costs. Once it runs it’s ok right?

Reckless and Inadvertant

Creating a mess without noticing that they’ve done so. Without bringing in any design patterns or real knowledge/experience, debt it going to happen, without the team realising how much of a mess they’ve created.

Prudent but Inadvertant

“If I was starting again, I’d do it differently”. While things were done to the best of the teams ability, we find that there will be a better way.

Prudent and Deliberate

Voluntary debt. The team knows that it’s not quite right, but it’s better to ship and accept the technical debt that will arise because of this.

Aspect Oriented Programming For Eclipse Plug-ins

It seems to me that Aspect Oriented Programming never really took off when it was introduced. However, it’s a useful way to intercept, or analyse, methods as they happen, in an independent way.  Eclipse has a useful suite of AspectJ tools that you can download for your Eclipse installlation. Paired with the benefits of Eclipse’s plug-in system, aspects are a nice way of intercepting your RCP application.

The following instructions show how to get up and running with aspects in the Plug-in Development Environment really quickly. Once you have downloaded the Eclipse AspectJ tools, you will also want to include the Equinox Aspect jars in your plug-ins directory. The plug-ins you will need are org.eclipse.equinox.weaving.aspectj andorg.eclipse.equinox.weaving.hook

  1. Create a new OSGi plug-in:
  2. Right click on the project and choose AspectJ Tools/Convert to AspectJ Project
  3. Create a new package within the plugin eg. com.dzone.aspects.aspectTest
  4. Make a new aspectj Aspect within the package e.g. MyAspect
  5. In your manifest.mf export the package created in the previous step
    Export-Package: com.dzone.aspects
  6. A you write your AspectJ code, you will be advising another plug-in (for example org.eclipse.jdt.junit) You’ll need to do some extra setup in order to advise other plug-ins, by adding the following to your Aspect plug-in manifest.mf.
    Eclipse-SupplementBundle: org.eclipse.jdt.junit

    Note you can only supplement one bundle in an aspect. Therefore, if you want to crosscut another bundle, you’ll need to create a new AspectJ plug-in.

  7. It also helps to add the plugin that you are advising (org.eclipse.jdt.junit) to your aspect plugin’s dependencies. If you don’t do it you will get lint warnings from the AspectJ compiler
  8. In your plugins META-INF directory make a file called aop.xml, consisting of content similar to the following
    <?xml version="1.0" encoding="UTF-8"?>
    <aspectj>
        <aspects>
            <aspect
                name="com.dzone.aspects.aspectTest.MyAspect" />
        </aspects>
        <weaver options="-verbose"/>
    </aspectj>
  9. When executing use the following VM arguments in your Run Configuration
    -Dosgi.framework.extensions=org.eclipse.equinox.weaving.hook
    
    -Dorg.aspectj.osgi.verbose=true

It’s as simple as that. Have you any instructions to add to this?

Effective Debugging: Conditional Breakpoints

One of the most important developer activities is debugging. In my college days, we were forced to use simple text editors for our software development, so I started out using print statements to see where my code was going wrong. These days, we have the comfort of IDEs, but debugging remains one of those talents that you get more efficient at with experience.

The best feature I have seen in both Eclipse and NetBeans is the conditional breakpoint concept. The idea is simple, take your breakpoint, and type in a condition for the breakpoint to stop at. For example if I have the following code:

for(Employee emp: employees)
{
   if(emp.getType() == Employee.MANAGER)
   {
     addToManagers(emp);
   }
}

Let’s say that I want to see the values of all the variables when the employee’s getType value is Employee.DEVELOPER, and step through to make sure that we don’t enter the if statement block.

In Eclipse, you can set the breakpoint as normal on the if statement, right click on the breakpoint and you’ll see the following menu:

You can now set a condition for your breakpoint in the resulting dialog by selecting the Enable Condition checkbox:
As you type in the condition you get full content assist. You can also change what this condition means – whether to stop when it’s true, or when it changes since the last iteration.
In NetBeans, it’s much the same. You still get the properties on right-click of the breakpoint:
The dialog is also similar with conditions and hit count, with content assist:
Things like this can really help speed up your debugging – when you know a particular value has caused your program to fail, you can get right to the heart of the matter.

I Don’t Write Unit Tests Because…. : The Excuses

As someone who’s seen the benefits of the approach, I’m a huge believer in test driven development. It adds a level of quality and maturity to the field of software development, yet it’s still not a widespread practice across development projects. When it comes to a choice between the features, time and quality, it’s always the quality that suffers. We don’t want to add extra time for testing and we don’t want to compromise on the feature set of the delivery. If you haven’t set out to do test driven development at the start of the phase, then it’s difficult to fit in.

We’ve all heard excuses for not taking the test driven approach, but nowhere compiles them better than “Pragmatic Unit Testing in Java With JUnit“, from the Pragmatic Bookshelf.  I read the book a few years ago, and afterward I thought there was no way that any responsible developer could read the book without truly believing that unit tests were one of the most important aspects of the development activity.

The most worrying excuse I’ve heard is that it’s too difficult to test my code. This can be for one of two reasons. One is that your code is mainly UI related, and automating the UI tests is too difficult. I’ll concede that UI automation is a tricky area (but not impossible, as we’ll see in a later article), but every effort should be made to automate it if possible: think about regression tests. If you have a fully automated test suite, including the UI behaviour, you can make a change to your code, and have full confidence that you haven’t broken anything if you have tests to re-run.

The second reason that your code is too difficult to test is that you’ve messed up your design. Maybe your logic and UI code are too tightly coupled, and without that automated UI layer existing, the dependency between the logic and the UI will cause a problem. This is where test driven development helps to ensure a clean design, following best practices. Using JUnit is simple, so if I can just point my test at a clean logic layer, I can test all logic that the UI will ever touch.  What’s that? You’re missing your data model? Well then just use mock objects – there are many frameworks for that!

For those who haven’t read the book yet, I’ll give a quick summary of the excuses for not testing as outlined in the introduction chapter:

  • It takes too much time to write tests
    As the number one reason that developers give, and thinking back on my own education, I think this is down to the way computer science is taught. For the most part, we’re lead to believe that testing happens at the end of the process, not all the way through. 

    Pragmatic Unit Testing encourage the “pay as you go” model, where having tests written as you are developing means that you don’t have that crunch time at the end where you try to cram all your unit tests in.

    Anyway, if you’re not writing tests as you go along, how are you checking if the code behaves as you expect? You run it manually? Wouldn’t it make sense to invest some of that manual testing time into writing a JUnit test for it? I mean you’ll have to run that piece of code again sometime – it’s not going to remain untouched for the lifetime of the product.

    In fact, there are many more time penalties that happen if you don’t write unit tests. You’ll have to spend time debugging code trying to work out why something doesn’t work. Or you’ll refactor the code, and then find that nothing works as it used to after the refactor. If you had the unit tests written, you have a base of confidence.

  • It takes too long to run the tests
    I’ll admit, there can be a good amount of time taken running tests that involve external entities, or the user interface. But you’re supposed to have more than one level of test. The unit level tests should run quickly, and there may be a level of integration tests that can run without a big time impact. If there are higher level integration tests that are taking time, just run them less frequently – maybe even in a nightly build. That’s not to say you should ignore the lower level unit tests. These should always run fast enough that it becomes a natural part of your own development process.
  • It’s not my job to test code
    I don’t know at what stage a software developer decides that he can just throw code over the wall. If your job title was simple Coder than maybe there’s an excuse. But as your job is to develop working software, you need to be able to say that your code is functional.  The book makes a good point that if the QA development finds it difficult to find bugs in your code, it will do wonders for your reputation.
  • I don’t really know how the code is supposed to behave so I can’t test it
    This is a difficult one to react to without incredulity. If you don’t know how the code is supposed to behave, you shouldn’t have started writing it. You need to understand the requirements first.

There are a few more excuses listed in the book, but these are the main ones. What are the excuses that you’ve heard for not writing tests.

Write Your Good Code First

Writing good code first is a pretty obvious statement, but I’m not sure if people do this. In fact, I think that we make excuses all the time so that we don’t have to.

While catching up on Twitter recently, I checked what@UncleBob (Robert Martin, author of Clean Code) has been saying. Obviously he’s a smart guy, as pragamatic as they get, and always has useful insightful things to say. Here’s the tweet that caught my attention:

I’m sure most developers would say that they write good code, always. Think about it? Do you? I know I’ve definitely compromised my quality standards in the past, deciding that it’s better to “fix that later” rather than to get it right first time. The minute you do that, you’ve broken a window.

While on this topic of writing good code first, you might wonder where refactoring fits (but I hope that you’re not wondering!). Refactoring is inevitable, but what really gets me is when refactoring needs to be put down as a separate task in a project schedule. Looks like UncleBob would agree:

So why does it happen?  To me, seeing refactoring in the schedule is an admission that “you’re not going to get it right first time, so we’ll add in this extra time to fix it later”. Surely if there is a concern that the time allocated to a task doesn’t cover a complete, clean implementation, the task needs more time. Refactoring is a good thing, but you have to refactor as you go. Don’t commit too much code littered with //TODO comments, do it now.

Having refactor seen as a different task is the same as breaking down each feature into a list of tasks like design, unit test, code, refactor, test. Software developers should know what they need to do in order to produce quality software. The “task” is not just the coding part – it’s everything around it.

 

 

Creating Better Presentations

Creating presentations is a skill that is often overlooked by software developers, but it can be one of the most important parts of a developers toolbox. Getting a clear message across to your colleagues or management is vital. Of course, if you plan on presenting at a conference, writing a good presentation is even more important. The following set of slides from @jessedee, give a great set of tips to presenters:

STEAL THIS PRESENTATION!
View more presentations from @JESSEDEE

One of the tips highlighted here is that Powerpoint, or at least the templates that you get from Powerpoint, forces your presentation into a boring format. It’s something that we’ve all seen – too many bullet points and too much text. This leads to the audience doing more reading than listening. When it gets to this stage, you wonder why not just send around a document.

Another great resource for aspiring presenters is Presentation Zen. Steve Jobs is always quoted as an example of a great presenter.

Everything mentioned so far is fine more marketting or high level presentations. A lot of developers think that a technical presentation can’t conform to the above rules. But why not? You should still get the point across with an impressive visual presentation – the idea is to inspire people, or to convince them that you know what you’re talking about. Supporting documentation can be provided to the audience after the presentation.

What tips have you got for creating brilliant presentations? Are there any examples you’d like to share to highlight the very good (and the very bad!).

Design Patterns Uncovered: The Abstract Factory Pattern

Having gone through the Factory Method pattern in the last article in this series, today we’ll take a look at Abstract Factory, the other factory pattern.

Factories in the Real World

It’s easy to think of factories in the real world – a factory is just somewhere that items gets produced such as cars, computers or TVs. Wikipedia’s definition of a real world factory is:

A factory (previously manufactory) or manufacturing plant is an industrial building where workers manufacture goods or supervise machines processing one product into another.

It’s pretty clear what a factory does, so how does the pattern work?

Design Patterns Refcard
For a great overview of the most popular design patterns, DZone’s Design Patterns Refcard is the best place to start.

The Abstract Factory Pattern

The Abstract Factory is known as a creational pattern – it’s used to construct objects such that they can be decoupled from the implementing system. The definition of Abstract Factory provided in the original Gang of Four book on Design Patterns states:

Provides an interface for creating families of related or dependent objects without specifying their concrete classes.

Now, let’s take a look at the diagram definition of the Abstract Factory pattern.

Although the concept is fairly simple, there’s a lot going on in this diagram. I’ve used red to note the different between what ConcreteFactory2 is responsible for.

The AbstractFactory defines the interface that all of the concrete factories will need to implement in order to product Products. ConcreteFactoryA and ConcreteFactoryB have both implemented this interface here, creating two seperate families of product. Meanwhile, AbstractProductA and AbstractProductB are interfaces for the different types of product. Each factory will create one of each of these AbstractProducts.

The Client deals with AbstractFactory, AbstractProductA and AbstractProductB. It doesn’t know anything about the implementations. The actual implementation of AbstractFactory that the Client uses is determined at runtime.

As you can see, one of the main benefits of this pattern is that the client is totally decoupled from the concrete products. Also, new product families can be easily added into the system, by just adding in a new type of ConcreteFactory that implements AbstractFactory, and creating the specific Product implementations.

For completeness, let’s model the Clients interactions in a sequence diagram:

While the class diagram looked a bit busy, the sequence diagram shows how simple this pattern is from the Clients point of view. The client has no need to worry about what implementations are lying behind the interfaces, protecting them from change further down the line.

Where Would I Use This Pattern?

The pattern is best utilised when your system has to create multiple families of products or you want to provide a library of products without exposing the implementation details. As you’ll have noticed, a key characteristic is that the pattern will decouple the concrete classes from the client.

An example of an Abstract Factory in use could be UI toolkits. Across Windows, Mac and Linux, UI composites such as windows, buttons and textfields are all provided in a widget API like SWT. However, the implementation of these widgets vary across platforms. You could write a platform independent client thanks to the Abstract Factory implementation.

So How Does It Work In Java?

Let’s take the UI toolkit concept on to our Java code example. We’ll create a client application that needs to create a window.

First, we’ll need to create our Window interface. Window is our AbstractProduct.

//Our AbstractProduct
public interface Window
{

    public void setTitle(String text);

    public void repaint();
}

Let’s create two implementations of the Window, as our ConcreteProducts. One for Microsoft Windows:

//ConcreteProductA1
public class MSWindow implements Window
{
   public void setTitle()
  {
     //MS Windows specific behaviour
  }

   public void repaint()
  {
     //MS Windows specific behaviour
  }
}

And one for Mac OSX

//ConcreteProductA2
public class MacOSXWindow implements Window
{
   public void setTitle()
  {
     //Mac OSX specific behaviour
  }

   public void repaint()
  {
     //Mac OSX specific behaviour
  }
}

Now we need to provide our factories. First we’ll define our AbstractFactory. For this example, let’s say they just create Windows:

//AbstractFactory
public interface AbstractWidgetFactory
{
   public Window createWindow();
}

Next we need to provide ConcreteFactory implementations of these factories for our two operating systems. First for MS Windows:

//ConcreteFactory1
public class MsWindowsWidgetFactory
{
   //create an MSWindow
   public Window createWindow()
   {
      MSWindow window = new MSWindow();
      return window;
   }
}

And for MacOSX:

//ConcreteFactory2
public class MacOSXWidgetFactory
{
   //create a MacOSXWindow
   public Window createWindow()
   {
      MacOSXWindow window = new MacOSXWindow();
      return window;
   }
}

Finally we need a client to take advantage of all this functionality.

//Client
public class GUIBuilder
{
   public void buildWindow(AbstractWidgetFactory widgetFactory)
   {
      Window window = widgetFactory.createWindow();
      window.setTitle("New Window");
   }
}

Of course, we need some way to specify which type of AbstractWidgetFactory to our GUIBuilder. This is usually done with a switch statement similar to the code below:

public class Main{
   public static void main(String[] args)
   {
     GUIBuilder builder = new GUIBuilder();
     AbstractWidgetFactory widgetFactory = null;
     //check what platform we're on
     if(Platform.currentPlatform()=="MACOSX")
     {
        widgetFactory  = new MacOSXWidgetFactory();
     }
     else
     {
           widgetFactory  = new MsWindowsWidgetFactory();
     }
     builder.buildWindow(widgetFactory);
    }
}

Just to give a clear idea of how this implementation relates to the Abstract Factory pattern, here’s a class diagram representing what we’ve just done:

Watch Out for the Downsides

While the pattern does a great job of hiding implementation details from the client, there is always a chance that the underlying system will need to change. We may have new attributes to our AbstractProduct, or AbstractFactory, which would mean a change to the interface that the client was relying on, thus breaking the API.

With both the Factory Method and today’s pattern, the Abstract Factory, there’s one thing that annoys me – someone has to determine what type of factory the client is dealing with at runtime. As you see above, this is usually done with some type of switch statement.

Find Out More


The classic Design Patterns: Elements of Reusable Object Oriented Software
For more practical Java examples: Head First Design Patterns.

Design Patterns Uncovered: The Factory Method Pattern

This article will focus on the Factory Method pattern, a variation on the simple factory. The Factory, as it’s name suggests, is a pattern used to facilitate the creation of other objects. In a later article we’ll be looking at the AbstractFactory.

Factories in the Real World

It’s easy to think of factories in the real world – a factory is just somewhere that items gets produced such as cars, computers or TVs. Wikipedia’s definition of a real world factory is:

A factory (previously manufactory) or manufacturing plant is an industrial building where workers manufacture goods or supervise machines processing one product into another.

It’s pretty clear what a factory does, so how does the pattern work?

Design Patterns Refcard
For a great overview of the most popular design patterns, DZone’s Design Patterns Refcard is the best place to start.

The Factory Method Pattern

Factory Method is known as a creational pattern – it’s used to construct objects such that they can be decoupled from the implementing system. The definition of Factory Method provided in the original Gang of Four book on Design Patterns states:

Define an interface for creating an object, but let the subclasses decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses

Now, let’s take a look at the diagram definition of the Factory Method  pattern. The Creator hides the creation and instantiation of the Product from the client. This is a benefit to the client as they are now insulated from any future changes – the Creator will look after all of their creation needs, allowing to decoupling. Furthermore, once the Creator and the Product conform to an interface that the client knows, the client doesn’t need to know about the concrete implementations of either. The factory method pattern really encourages coding to an interface in order to deal with future change.

Factory Method Pattern

Here the Creator provides an interface for the creation of objects, known as the factory method. All other methods in our abstract Creator are written only to operate on the Products created in the ConcreteCreator. The Creator doesn’t create the products – that work is done by it’s subclasses, such as ConcreateCreator.

Now let’s take a look at a sequence diagram to see how this pattern behaves:

Factory Sequence Diagram

Here we see the client making a call to the abstract Creator, which then uses the factoryMethod() to get a new instance of the ConcreteProduct, complete’s the anOperation() method and completes.

Where Would I Use This Pattern?

The idea behind the Factory Method pattern is that it allows for the case where a client doesn’t know what concrete classes it will be required to create at runtime, but just wants to get a class that will do the job. The FactoryMethod builds on the concept of a simple Factory, but lets the subclasses decide which implementation of the concrete class to use.  You’ll see factories used in logging frameworks, and in a lot of scenarios where the client doesn’t need to know about the concrete implementations. It’s a good approach to encapsulation.

So How Does It Work In Java?

This example will use the concept of a logger to illustrate the factory method. First, let’s create our Product interface, in this case Logger:

//interface (Product)
public interface Logger {

	public void log(String message);
}

Next we’ll create one ConcreteProduct named XMLLogger. Obviously, we would have many different loggers

//concrete implementation of the Logger (Product)
public class XMLLogger implements Logger {

	public void log(String message) {
		//log to xml
		System.err.println("logging");
	}

}

Next, we’ll create our Creator, as a class with an abstract method that the concrete creator subclasses need to implement:

//the abstract Creator
public abstract class AbstractLoggerCreator
{
	//the factory method
	public abstract Logger createLogger();

	//the operations that are implemented for all LoggerCreators
	//like anOperation() in our diagram
	public Logger getLogger()
	{
		//depending on the subclass, we'll get a particular logger.
		Logger logger = createLogger();

		//could do other operations on the logger here

		return logger;
	}

}

The XMLLoggerCreator is our ConcreteCreator

//ConcreteCreator
public class XMLLoggerCreator extends AbstractLoggerCreator{

	@Override
	public Logger createLogger() {
		XMLLogger logger = new XMLLogger();
		return logger;
	}

}

Here’s the client code to test drive our implementation of the pattern:

public class Client {
	private void someMethodThatLogs(AbstractLoggerCreator logCreator)
	{
		Logger logger = logCreator.createLogger();
		logger.log("message");

	}

	public static void main(String[] args)
	{
		//for the purposes of this example, create an XMLLoggerCreator directly,
		//but this would normally be passed to constructor for use.
		AbstractLoggerCreator creator = new XMLLoggerCreator();

		Client client = new Client();
		client.someMethodThatLogs(creator);
	}

}

As you can see, someMethodThatLogs, takes any AbstractLoggerCreator depending on who calls the method. So, if we wanted to log to a file, or the console, we would pass through the appropriate AbstractLoggerCreator implementations.

One thing that I have left out here is the possibility to pass a paramater through to the creator in order to choose which type of concrete class to create. For example, we could have made FileLoggerCreator that could take a string parameter, allowing us to choose between XML and flat files.

Watch Out for the Downsides

One thing I would note about this approach to the Factory is that it might be overcomplicated. Perhaps the Abstract Factory is a better approach for creating objects in a decoupled manner. We’ll be discussing the Abstract Factory pattern next in the series, and will compare the two approaches then. If you want to create your own particular type of “Product” you would probably need to subclass a Creator. As with all design patterns, use it with caution, and make sure you need it.

In a lot of cases, a simple factory pattern will work fine. The FactoryMethod  just allows further decoupling, leaving it to the subclasses of the Creator to decide which type of concrete Product to create.

Find Out More


The classic Design Patterns: Elements of Reusable Object Oriented Software
For more practical Java examples: Head First Design Patterns.