Showing posts with label Design Patterns. Show all posts
Showing posts with label Design Patterns. Show all posts

Wednesday, August 28, 2013

Agility demands good Software Design

From what i have seen, Agile Software Development is widely misinterpreted nowadays. Many people think to be agile, they just need a process like scrum to define a framework of sprints and iterations. They will sprint until they exhaust and change until they stagnate. But when you'd ask them what principles of objectoriented design are, they'd answer: "Aww yes, we use classes". And when you'd asked them if they did test driven development, they'd reply: "Ahh, this is the thing where you write tests first, isn't it?". Bottom line, people think to be agile without caring about good software design. But in the end, the most important thing is what nobody cares about. It is the agility of the software that they are producing. So if you want to be agile, a process and a mindset is not enough. You need to keep your software agile. By that i mean, you need to keep the design of the software as clean and flexible as possible, to be able to apply any future changes at minimal cost. Software design of course includes your source code. In the end, you are only as agile as your software is.

Why Agile?

A customer does not know what he wants in the first place. He might have a rough idea, but thats it. We cant even blame him for that, because the actual problem that we are supposed to solve is influenced by so many factors and opinions that it is almost impossible to define the best solution right away. Other than that, miscommunication will most likely make things worse. To solve these issues we start small, and deliver fast. Seeing the first result, the customer can verify if we are on track or not. He can check if we have understood, or if he himself made a bad call. He might recognize things that he hasnt thought of before. Delivering repeatedly and iteratively like that, our software will more likely be useful and accepted by the customer in the end. It will more likely lead our project to success. Of course we will have to deal with changes more often, which is why we have to make the software itself agile. In the end it is the software which needs to be changeable, not us.

What it takes

Not only does an agile development process put our software under frequent change, it also demands progress at a fast and steady pace. These facts can quickly cause our software to rot if we don't watch out. And when it does, we get slowed down even more and changes suddenly become impossible. So we'd better not forget about the most important part in agile software development: Keeping our software design as agile as possible, from high-level architecture to the very code itself. Sadly, this gets ignored way too often, and many agile projects fail because of it. They fail because they chose to go faster by neglecting quality, and they quickly rush into a deadend of code rot leading to stagnation. So please remember: It is the Software you are building that needs to be agile in order to adapt to change defined by the customer. It is the software that needs to be agile in order to react to change with minimal effort. Rushing is not gonna make your software agile. Rushing is not gonna make YOU agile. Agility comes hand in hand with quality. And high quality is not even slow, hell no. Good quality done right makes you go even faster.

So what is Agile Software Design?

Agile Software Design is what makes your software as clean and flexible as you need it to be. It demands deliberate adoption of discovered and well established design patterns and principles of objectoriented programming. This is not easy. In fact it's hard, it's very hard. Even if you are really good and experienced at it, you might fail at some point, having to rethink many of your previous design decisions. Agile Software Design is not something that you can rush. It needs time and deliberateness. But it will pay off in the long term by making you progress at a more constant pace, which will in fact be much faster than it would be without agile design. The graphic below should clarify how quick ignorant rushing can slow you down tremendously. The graphic is not based on statistics, but on experience.

Agile Software Design does not end at high-level architecture. It goes on with coding. Bad code can quickly make your project more clumsy than a bad high-level design could. So the devil is in the details.

What can you do to make your Software Design more Agile?

From a Managers perspective? Trust your Developers, don't push them. Invest in experience and expertise.

From a developers perspective? First of all, learn the principles and patterns of objectoriented programming - not just in theory. Being good at those needs lots of practice. There are plenty of books for this:
and many more.

Keep your code clean - don't underestimate this! When you are programming, you spend more time reading code, than writing code. Thus you want to minimize the time you have to read code by making it more readable. It's not a secret how clean code looks like. Take a look at Clean Code.
Other than that, use the right practices like

Test Driven Development  

Just do it already. And if you don't know how, go on and start learning. I have heard numerous opinions of TDD where people said
  • "Unittests are too expensive. The Customer wont pay for that."
  • "Unittests slow us down, we needed to write more code in that time."
  • "I don't know. I'm pretty good at programming, Test-First feels needlessly hard and awkward."
But these are just subjective opinions of people who are not experienced in TDD.
TDD should in fact boost your longterm development speed if you are doing it right. I have not seen a single project in my life that has been as small and simple as that it would not have taken a significant profit from a TDD approach. And i have in fact seen very simple ones. The thing is, you have to test it anyways. What else would speed up your testing more than to automate it? Also, TDD significantly reduces the amount of time you have to spend debugging which already eats up lots of your time - at least more than you'd think. Other than that those tests
  • become a reliable documentation of your code,
  • allow you to fearlessly clean up your code,
  • force you to think of the problem before thinking of the actual solution, which will improve your initial draft,
  • enforce decoupling of components, which will make your design more agile.

Pair Programming

It's not only that 4 eyes will see more defects than 2 eyes do, but also that the transfer of knowledge is taking place. You want all developers to learn from each other to become equally valuable. And you always want more than one person to know a specific module to improve the truck factor. Heck yeah, some people even do mobprogramming - Seriously.

Collective Code Ownership

Don't allow one guy to own that modules code. All code on the project must belong to everybody. Everyone is allowed and invited to view, question and improve everyones code. This might be hard for some people, and might provoke conflicts, but it is absolutely mandatory to make the code better.

Code Reviews

Constantly review code changes. It is the only way to stay up to date, and it will reveal code smell. You need to reveal code smell, because if you don't, you will get stuck.

Refactoring

Refactor often. Everytime you see something that could be refactored, you need to do it right on the spot. The earlier you do it, the more time you save. So if you do it right then, you save the most possible amount of time.


tl;dr: You are just as agile as your software design, which of course includes code. High speed does not demand low quality. It doesn't work like that. In fact high quality is needed to allow high speed. Agile design evolves high quality.

Tuesday, May 21, 2013

The Art of Naming


1
2
3
4
5
6
7
8
public class Handler {
    
    private String data;
    private String temp;

    public int c(int a, int a2){
        int result = a+a2;
        //...


Why is Naming so important?

Because its a matter of Quality.
Naming = Readability = Understandability = Maintainability = Quality.
Good Names make your code readable, which is an essential feature for every person that has to work on it, including yourself. Soon after written, you'll forget about the details. Getting into it and understanding again can be tough and frustrating. The right Names will redeem yourself and others from those barriers. You'll might think for yourself: "No!!! I don't have the time to make this all clean and perfect. I just have to get the thing done as fast as possible, and it's no problem because i won't have to deal with it after its finished anyways..." - That's just wishful thinking. Software never ever becomes completed. Thats part of its nature. In fact, the opposite is the truth: By choosing the right names carefully, you save a lot of time from the very first day on. You keep your mind free of needless noise that slows your progression down.

How to choose the right Names?

According to "Clean Code", Names should:
  • Be intention revealing
  • Avoid disinformation
  • Make meaningful distinctions
  • Be pronounceable
  • Be searchable
But i'll add one point
  • be unmistakable (which might already be part of avoiding disinformation)

Be skeptical about a name in the first place, and dont accept it until every bit of skepticism has been eliminated. Complete Words are usually better than Acronyms, AND .... avoid redundancy!!

1
2
3
class Book{

  public String[] bookPage; // Don't repeat book since its given in the classname!

The art is to combine good names so that your code becomes a meaningful, selfdocumenting story.

1
if(plant.needsWater()) gardener.water(plant)

Classes, Interfaces and Abstracts

Stay away from 'Manager', 'Handler' and the such. 'SomethingManager' doesn't mean anything specific and is clearly not unmistakable. Use Design Patterns in your Names. They are common knowledge and give a good information about what a Class is doing. Eg.: ShadowedBorderDecorator. Name Interfaces as what they are, and don't add Pre- / Suffixes to them (IFoo, BarInterface). Client-classes don't care if they work on Interfaces or Implementations. And it's not the Names job to indicate it's Type. You dont name a Variable intNumber either, do you? It's a violation of the DRY principle. Using Abstract in a Classname is debatable. While it's pretty common, it still violates the DRY principle. Decide for yourself.

Common Errors in Variablenaming


Repeating Type in Variablenames:

1
2
3
4
Timestamp creationTime;
Date date;
String[] bookArray;
SomeType somethingObject

Adding "is" as a Prefix to booleans:
isActive. So the getter becomes isIsActive() or what?

Consecutive numbers.
There is nothing harder to read than a calculation using a1, a2 and a3 multiple times.

Generic names:
temp, data, other, object, result, value and so on

Inconsistency:
Mixing multiple Naming Strategies, or choosing one without 100% sticking to it.
E.g.: Mixing camelCase with under_scored

Saturday, March 9, 2013

Wanna Cache? Decorate!!

The Decorator Pattern

Class Diagram:

Decorator Pattern is one of the most powerful Design Patterns, and its important to understand why. It allows you to add functionality to a Class without changing it. You use delegation instead of inheritance by just wrapping the existing Class in a "Suite" of your choice while the Interface stays the same. This way, you can even wrap a Class into multiple layers of Decorators where every Layer has its own and different purpose, and the Original Class even stays the same. Other than that the Layers are completely interchangeable and removable, because they all have the same Interface.
You can use your naked Object in the same manner as a decorated one with multiple Layers, and the rest of the Application wont even notice. Other components dont need to know whether a Class is decorated or not, because the only thing they care about is the Interface. The following Graphic should clear things up:
Just follow the Steps:
In the first example there is no Decorator. So SomeClass directly speaks to BookService
In the second example there is a single Decorator. Therefore the following steps apply
  1. SomeClass calls SomeDecoratorA.
  2. SomeDecoratorA delegates the call to the real BookService. The Decorator could even manipulate the call in this step.
  3. BookService returns a result. SomeDecoratorA now holds the result, and may manipulate it.
  4. Finally, SomeDecoratorA hands the result over to the original caller SomeClass.
In the third example, there are even 2 Nested Decorators. Since every Decorator speaks the Interface of the BookService Class you can wrap an infinite amount of Decorators upon.

Usage Examples

Most examples in Books and online Guides describe the Decorator Pattern used by some Graphic related stuff. You would have a normal line, and a line decorated with a shadow. Another example would be a Window in a GUI where you vary Decorators that add different kinds of styles (e.g. different Colors).

But its important to understand, that Decorators are not intended to just make Styling more dynamic. It is just one way to use them. Instead, there are many more great use cases for Decorators and i will show you an example applying cache functionality.

Applying Cache with Decorator Pattern

Class Diagram:

As you can see i am adding a BookServiceCacheDecorator that holds a Cache Component which temporarily stores a List of Books. The BookServiceCacheDecorator in the first place asks the Cache if there is a result available. If thats true, the decorator will use the cached result. Otherwise it will fetch the Result of the BookService itself, and store the Result in the Cache for later use.

I start with the BookService Interface,

1
2
3
public interface BookService {
    public List<Book> findAll();
}

and its prime implementation.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public class BookServiceImpl implements BookService {

    @Override
    public List<Book> findAll() {
        System.out.println("load new data");
        List<Book> books = new ArrayList<Book>();
        books.add(new Book("BookA"));
        books.add(new Book("BookB"));
        books.add(new Book("BookC"));
        return books;
    }
}

Here is the Code of the Cache Class. In this example it's caching forever, but thats alright.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
public class Cache {

    private List<Book> storage;

    public void save(List<Book> books){
        this.storage = books;
    }

    public boolean hasResult(){
        if(storage != null){
            return true;
        }

        return false;
    }

    public List<Book> load(){
        System.out.println("load from cache");
        return storage;
    }
}

Now lets continue with the Decorator Base Class. It has a preemtive Constructor to hand over the decorated Object.

1
2
3
4
5
6
7
8
abstract public class BookServiceDecorator implements BookService{

    protected BookService decorated;

    public BookServiceDecorator(BookService decorated){
        this.decorated = decorated;
    }
}

And finally the CacheDecorator. It Checks the Cache before calling BookServiceImpl.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class BookServiceCacheDecorator extends BookServiceDecorator {

    private Cache cache;

    public BookServiceCacheDecorator(BookService decorated) {
        super(decorated);
    }

    public BookServiceCacheDecorator(BookService decorated, Cache cache) {
        super(decorated);
        this.cache = cache;
    }

    @Override
    public List<Book> findAll() {
        if(cache.hasResult()){
            return cache.load();
        }
        List<Book> books = decorated.findAll();
        cache.save(books);
        return books;
    }
}

Now two different use cases. One without Decorator, and one with the Cache Decorator:

1
2
3
4
5
6
7
8
9
BookService bookService = new BookServiceImpl();
bookService.findAll(); // prints: load new data
bookService.findAll(); // prints: load new data
bookService.findAll(); // prints: load new data

BookService cachedBookService = new BookServiceCacheDecorator(new BookServiceImpl(), new Cache());
cachedBookService.findAll(); // prints: load new data
cachedBookService.findAll(); // prints: load from cache
cachedBookService.findAll(); // prints: load from cache

Thats basically it. Just read the Code carefully. The final use cases should make clear how the Decorator applies functionality. Decorator pattern really helps you create a very modular Code in many circumstances. You should not be afraid of the additional Classes the Pattern depends on, since they are really not a big deal. The modularity gained easily outweighs them.

Wednesday, March 6, 2013

Avoid too many Parameters using the Builder Pattern

Today i want to show you another way to use the Builder Pattern. From what i've seen there are tons of examples of the Builder Pattern online. But they do all have one thing in common: They are used to create an Instance of an Object and "replace" its constructor. This way you can create a complex Object in a very clean and readable fashion using a Fluent Interface.

Other than that, there is also a slightly different way you can benefit of the Builder Pattern. Think of a Method with like 10 Parameters. Thats not quite nice, and should not ever happen. Robert C. Martin recommends a maximum amount of 3 Parameters in his book: Clean Code. You should rather use some kind of a Config Object holding those 10 parameters, to clean it up. But lets say, you have a BookService Class with a find(..) method, that allows to search by 10 different parameters, and every single one of them is optional. You could use the Builder Pattern with some kind of Query Object to solve the problem.

As we should always program against Interfaces to keep things modular, ill start with the Interface:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public interface BookService {

    public Book create(Book book);

    public void delete(String isbn);

    public Query query();

    public interface Query {

        public Query isName(String name);

        public Query hasAuthor(String author);

        public Query isCheaperThan(Float price);

        public Query isIsbn(String isbn);

        public Query hasMorePagesThan(Long pages);

        public Query isAvailable();

        public List<Book> find();

    }
}

So the Interface looks pretty neat. It allows you to write something like:

bookService.query().hasAuthor("Bob").isCheaperThan(20.9).isAvailable().find();

While the Query could be considered as an implementation of the Query Object pattern it is not tied to any Database related stuff, which is very important. You dont want to be tied to Criteria Queries or SQL in this Layer. It should be independent of any implementation (e.g. Database or Filesystem).

To clear things up, i want to show you an implementation example using Spring-Data. I am a big fan of Spring-Data, since it allows you to create full featured DAOs with little to no Programming effort for many different Persistence Providers. If you havent used it yet, you should definitely give it a try.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
@Transactional
public class BookServiceImpl implements BookService {

    @Autowired
    private BookRepository bookRepository;

    // ...

    @Override
    @Transactional(readOnly=true)
    public Query query() {
        return new QueryImpl(this.bookRepository);
    }

    public class QueryImpl implements Query{

        private BookRepository bookRepository;
        private Specifications<Book> filters = null;

        public QueryImpl(BookRepository bookRepository) {
            this.bookRepository = bookRepository;
        }

        private void addFilter(Specification<FlowMessage> filter) {
            filters = (filters == null) ? where(filter) : filters.and(filter);
        }

        public Query isName(String name) {
            if (name == null) return this;
            addFilter(BookSpecifications.isName(name));
            return this;
        }

        public Query hasAuthor(String author) {
            if (author == null) return this;
            addFilter(BookSpecifications.hasAuthor(author));
            return this;
        }

        // other criterias ...

        public List<Book> find() {
            return this.bookRepository.findAll(filters);
        }
    }
}

As you can see i am just joining filter Criterias together, and thats it. The implementation is really simple but also expandable. These filter Criterias are supported by my BookRepository (=DAO). I just have to define them in a helper class first. Check out this and that for a deeper understanding how to combine spring-data with criteria queries.