The Pragmatic Craftsman :: Simplicity from complexity :: | Home | About Me |

You are here: The Pragmatic Craftsman > Architecture & Design

Criteria for good design March 31, 2008
What is a good software architecture? August 30, 2007
Most Valuable IT Architecture Skill November 10, 2006
The Decorator Pattern September 14, 2006
Use MVC Properly July 28, 2006
A Simple Design May 3, 2006
Architects Must Write Code April 28, 2006
Characteristics of a software architect March 24, 2006
Learning GoF Design Patterns and Refactoring May 5, 2005
Top 10 Elements of Good Software Design February 14, 2005
What Do Users Want? -- Usability Primer January 7, 2005
Holiday Party Guide to Patterns December 27, 2004

Criteria for good design

Uncle Bob listed a few Design smells -- the odors of rotting software in his book Agile Software Development. Take the inverse of that and what do you get? Criteria for good design -- that's the approach that the author of the book PHP in Action took.

Here are the characteristics of good design.


  1. Flexibility - easy to change

  2. Robustness - hard to break

  3. Mobility - easy to disentagle into reusable components

  4. Fluidity - easy to do things right

  5. Simplicity

  6. Once and only once

  7. Transparency - easy to read and understand

Very good criteria, in my opinion.


What is a good software architecture?

Constructing a good architecture is a tough task. In my developer’s career, I have not come across too many architects that really do a decent job creating good – cohesive - architectures. That just reiterates my point that architecting a system is not an easy task.

What is a good architecture, though? What are its characteristics? I found some definite answers to this question in a book I’m reading now, Object Oriented Analysis and Design with Applications, 3rd edition. These are some of the best definitions and views on software architecture I have come across.

“A system that has a sound architecture is one that has conceptual integrity. Having a “clean internal structure” is essential to constructing a system that is understandable, can be extended and reorganized, and is maintainable and testable.”

“There is no right way to craft the architecture of a given system.”

    Three Common Attributes of Good Software Architectures

  1. They are constructed in a well-defined layers of abstraction, each layer representing a coherent abstraction, provided through a well-defined and controlled interface, and built on equally well-defined and controlled facilities at lower levels of abstraction.
  2. There is a clear separation of concerns between the interface and implementation of each layer, making it possible to change the implementation of a layer without violating the assumptions made by its clients.
  3. The architecture is simple: Common behavior is achieved through common abstractions and common mechanisms.


  4. Architectures constructed in this way tend to be less complex and more robust and resilient. They also enable more effective reuse.


Most Valuable IT Architecture Skill

What is it? I don't know. I think it's communication skills, the ability to see the big picture, staying abreast of new technologies, and learning quickly. Plus, the ability to dive into new technologies and leave your comfort zone -- leave the old technologies behind.

But who am I to answer a question like this. I'm not an architect. Yet. :-) It's something I'm preparing myself for.

Anyway, this question, "what is the most valuable IT architecture skill?," was answered by some distinguished IBM architects, Grady Booch being one of them. It's a very good article.

Reference
What is the most valuable IT architecture skill and how can you learn it?,
developerWorks


The Decorator Pattern

I've been in the dark as far as the Decorator pattern is concerned. I knew, in principle, how it works, but I can see that my understanding was very incomplete. Plus, I never had a chance to use it. While reading the Head First Design Patterns book, I discovered something basic that: when you wrap an object several times and then call a method on it, it will be called as many times as it was wrapped. The trick? Keep a reference to the object -- you're creating a chain.

Let me go through this step by step. By example. This is the book's example, the Starbuzz Coffee decorator.

A simple interface.

 

public interface Beverage {

public String getDescription();

public BigDecimal getCost();

}

We have several coffee types, Dark Roast being one of them.

public class DarkRoast implements Beverage {

  public BigDecimal getCost() {

     return new BigDecimal("1.55");

  public String getDescription() {

    return "Dark Roast";

  }

}

When ordering coffee, you can pick a coffee type (Dark Roast, Latte, etc), and you can also add on to the coffee. For instance, you can add a whip cream on top, or add a shot of expresso to it. Which, of course, adds to the price. You could extend Beverage with all of the types, but that's too many classes. Here's where the decorator pattern comes into play.

Here's the solution. You define the AddOnDecorator and extend it with the different add ons.

/** It's just an empty class */

public abstract class AddOnDecorator implements Beverage { }

public class Expresso extends AddOnDecorator {

Beverage beverage;

public Expresso(Beverage beverage) {

  this.beverage = beverage;

}

public BigDecimal getCost() {

  return new BigDecimal("0.25").add(beverage.getCost());

}

public String getDescription() {

  return beverage.getDescription() + ", with Expresso";

}

public class Whip extends AddOnDecorator {

Beverage beverage;

public Whip(Beverage beverage) {

this.beverage = beverage;

 

public BigDecimal getCost() {

return new BigDecimal("0.10").add(beverage.getCost());

 

public String getDescription() {

return beverage.getDescription() + ", Whipped";

}

}

public class StarbuzzCoffee {

public static void main(String[] args) {

Beverage darkRoast = new DarkRoast();

darkRoast = new Expresso(darkRoast);

darkRoast = new Whip(darkRoast);

System.out.println(darkRoast.getDescription() + " costs "

+ darkRoast.getCost());

}

}

When I first looked at the code, I was confused. I thought that new Whip(...) would just override it, right?

This is what gets printed: Dark Roast, with Expresso, Whipped costs 1.90

You get the beverage you want (DarkRoast), you pass it to the Expresso wrapper, which in turn passes it to the Whip wrapper.

First the Expresso wrapper is called, it receives the dark roast beverage. Then the dark roast is passed again to the Whip wrapper. If you look closely (and this is a little confusing), when an Expresso is instantiated, it receives the beverage and makes a local copy (so it is never lost). Essentially, a chain is made. When the action on the final object is made, the chain is traversed and the beverage object is passed around. That's how this pattern works. (Wow, I learn something (basic) every day. :-))

The Decorator pattern is cool. It rocks. :-) It lets you keep adding functionality and still keep the objects cohesive (as you're not bloating the objects). No coupling as well. Nice.

Reference
Head First Design Patterns, the example above was taken from the book


Use MVC Properly

When building web applications, everybody seems to be using the Model View Controller (MVC) pattern. We all use it. It's a fundamental pattern. However, a lot of people use it incorrectly. Actually, in my six years of programming, I have never seen it done the proper way. From what I've seen, the majority of the MVC implementations have a major flow: too much "model" in the controller. That's a critical error and a no-no in proper usage of the pattern.

So how should it work? The critical thing is not to have any business logic in the controller, and have a separate business layer that is not aware of the view technology.

Here are fundamental characteristics of MVC:

Model: encapsulates all of the business logic. It is not aware of the view technology.

Controller: fetches the information needed from the view, puts it together and calls the appropriate models for processing. It contains no business logic.

View: displays the model that it gets from the controller.

I just thought of a good analogy for the Model. Think of it as the brain. It's the most important thing. You don't want to distribute its knowledge into other parts. What if you lose the other part, a finger let's say, do you want to be dumber as a result? I certainly would not like that.

Martin Fowler, in Patterns of Enterprise Architecture, says that the proper definition for the Controller is "input controller." He has a good explanation of MVC.

"A request comes in to an input controller, which pulls information off the request. It then forwards the business logic to an appropriate model object. The model object talks to the data source and does everything indicated by the request as well as gather information for the response. When it's done it returns control to the input controller, which looks at the results and decides which view is needed to display the response. It then passes control, together with the response data, to the view."

"Ensure that the models are completely separated from the Web presentation," says Fowler.

How can I test whether I have a good MVC? It is not always easy. Here's a good test: can I add a different view technology without duplicating any business logic?

The biggest benefit of proper implementation of the MVC pattern is that you have a separate business layer. Because it is seperate, it is easier to test -- you don't need a container to test. It is easier to understand. You don't have duplication. And you are well prepared to add a different view technology to it without a major effort.

Another great benefit is that your architecture remains simple. Your controllers are simple. The business logic might be complicated, but it is in a separate layer and encapsulated in one place.

It is tempting to put business logic into the controller or the view (we all did it). Stop. Don't do that. (I should yell here. :-)) Refactor the architecture if you have to. Putting business logic into the controller makes the application harder to maintain, it makes the business logic almost impossible to test, and it also spreads the business logic into several layers. All smells of a bad design.

The Spring framework gives you a skeleton MVC out of the box. But if you look at it, it only gives you the VC part, without the M. You have to add the M, the business logic yourself. It is very easy just to add it into the controller. I that's what a lot of people do. Then you really have a VC pattern. Make sure you add the missing M and make sure it sits in a different room than the VC.

You will benefit in a big way if you followed the MVC principles. And no exceptions. You are hurting yourself if you follow an ad-hoc approach -- a little logic here, a little there.

If you want to be a good coder, when using the MVC pattern, never break its principles.


A Simple Design

Simplicity always wins, in my opinion. The following two quotes from Programming Pearls (book I'm reading now) need no further comment: they nail it.

A designer knows he has arrived at perfection not when there is no longer anything to add, but wen there is no longer anything to take away.
--Antoine de Saint-Exupery the French writer and aircraft designer (quoted in Programming Pearls)

More programmers should judge their work by this criterion. Simple programs are usally more reliable, secure, robust and efficient than their complex cousins, and easier to build and maintain.
--Jon Bentley in Programming Pearls


Architects Must Write Code

That's an exact title from Johanna Rothman's blog post. I totally agree: architects must code. If you an architect you need feedback. You need feedback because you want to make a better architecture in the future, to make improvements, and to see what doesn't work. How do you get that feedback? You need to write code. There is no other way. There might be, of course, but most of the time it does not work.

I want to move into architecture in the next couple of years, I like to code: perfect marriage. :-) But architecture is hard, it requires a lot of knowledge in a lot of areas. Most of all, it requires a lot of experience so you know what works and does not work. That's why I'm learning a lot, keeping an eye on how to improve.

This point from Johanna says it best:


I've been a part of projects for 30 years. I've been assessing projects for 10 years. And every time I've seen an architect who doesn't participate in the code-writing part of the project, I've seen an architecture that doesn't do what it's supposed to do, never mind extend to inevitable changes in requirements that occur during the project.

Architects need feedback about their architecture. The only way to get feedback is to write the code, integrate it, and see what happens.

Related
Characteristics of a Software Architect, my previous post

Reference
Architects Must Write Code, Johanna Rothman


Characteristics of a software architect

Are you thinking of becoming an architect someday? What are your plans for future? Maybe you are just a hard-core programmer and want to stay that way? There are people in each group. I would like to become an architect, a technical leader, and a manager. What? All three? Actually, I would like to become a manager, but I think a software manager should also be a technical leader and have at least some of the architect's skills. I'd say, by the end of 2008, I would like to be a manager. Those are my goals for next couple of years. I am still not 100% on it, but more and more, that's the direction I want to pursue.

Back to architecture. Being a software architect is not easy. It is only for the select few.

But I know, now, what software architect is, and what it entails. I found out from this excellent article, Characteristics of a software architect, by Peter Eeles, a Senior IT Architect at IBM. It's an excellent read. A must read if you would like to go in that direction.

Software Architect is (I'm putting my comments for each major point; quotes are taken from the article)..

The architect is a technical leader
No question about it. You have to know your stuff. You have to be an expert in a lot of different areas.

First and foremost, the architect is a technical leader, which means that, as well as having technical skills, the architect exhibits leadership qualities.

The architect role may be fulfilled by a team
This is an interesting point. I think that's how I would like it to be: a team effort.

Given that the role of architect requires a very broad set of skills, it is often the case that the architect role is fulfilled by more than one person. This allows the skills to be spread across a number of individuals, each bringing his or her own experiences to the role. In particular, the skills required to understand both the business domain and also various aspects of technology are often best spread across a number of individuals.

The architect understands the software development process
This is a must. A software process needs to be continuously improved. You have to understand it first, to make improvements. Thus, you need to know others processes as well.

The architect has a knowledge of the business domain
Very important. One interesting point in the article, by knowing the domain you can foresee some of the problems or extension to the system.

The architect has technology knowledge
Of course.

The architect has design skills
A big part of architecting is designing flexible, easy to understand, maintainable systems.

The architect has programming skills
As an architect, you will oversee other programmers, you have to know.

The developers on the project represent one of the most important groups that the architect must interact with. After all, it is their work products that ultimately deliver the working executable software. The communication between the architect and the developers can only be effective if the architect is appreciative of the work of developers.

The architect is a good communicator
An architect has to be able to communicate with a lot of stakeholders; he has to share his vision clearly. Plus, he has to defend his decisions.

Being able to communicate effectively is a skill that is fundamental to the success of a project for many reasons. Clearly, communication with stakeholders is particularly important in order to understand their needs and also to communicate the architecture in a way that secures (and maintains) agreement with all stakeholders. Communication with the project team is particularly important, since the architect is not simply responsible for conveying information to the team, but also for motivating them. Specifically, the architect is responsible for communicating (and reinforcing the communication of) the vision for the system, so that the vision becomes shared and not something that is only understood and believed in by the architect.

The architect makes decisions
Very good point.

The architect is aware of organizational politics
You cannot avoid politics, as much as I don't like it, that's the truth.

The architect is a negotiator
You have to talk to programmers, testers, business people. You have to negotiate.

What do you think? A lot of skills and knowledge required.

Excellent article. This is the best summary I've read. Written in a clean manner. Nice, pragmatic approach.

Do you still want to be an architect?

Reference
Characteristics of a software architect, The Rational Edge Newsletter, March 2005, my recommended resource


Learning GoF Design Patterns and Refactoring

To learn design patterns is not easy. It's one thing to just read about them and think you know them. It's another thing to actually know how to use them, and to remember them as time passes by. I must admit, there is only a couple of the GoF patterns I remember. I read about them and after a while I forget them. However, that might be changing, as I have a different approach: I read several books on patterns at the same time.

A while back, I read Robert Martin's Agile Software Development, Principles, Patterns, and Practices (a great book). I also read portions of the first edition of Design Patterns Explained (ok), portions of the classic Design Patterns, and the whole Holub on Patterns (I did not like it at all). I own all of the books I mentioned (except Holub on Patterns). And I recently bought Refactoring to Patterns by Kerievski. This latest book is what prompted me to change how I study design patterns. (I also own Martin Fowler's Refactoring, which is a classic book that every developer should have by his side.)

I started reading Refactoring to Patterns. So far, about a third into the book, the book is very good. But I feel that the design patterns are starting to click. Why? As you might guess, the book tries to combine Fowler's Refactoring and the GoF's Design Patterns. So, whenever I read about a particular refactoring, I jump into Martin's book. Not only that helps me understand the text better, I also get more info about the refactoring. (Plus, you get some good advice from Fowler, which I admire as a developer.) Same with patterns, whenever he mentions a GoF pattern (almost every refactoring), I go to the Design Patterns book.

However, the GoF book is not easy, and the book by itself is not enough sometimes. That's when I turn to Robert Martin's book, which contains simple Java code for a lot of patterns he mentions. And because he doesn't mention all of them, I hit the web. This site, Design Patterns, contains code about all GoF patterns -- very good resource.

And if that was not enough, I try to write practice code in Eclipse. I created a learn patterns project, and I create a new package for each pattern. This is very useful when, down the road, you forget about the pattern and want a quick reminder (I learn by example). Design patterns are hard to learn because we don't get to use them right away. By practicing them, you see them in real world. You see them from a different angle. This is very valuable.

Have I found the ultimate solution for learning patterns. I don't think so. But it makes a big difference to me. Yesterday, I learned about a Composite pattern, today I learned about the Boulder pattern. And I think the knowledge is deeper this time. I think this is a very good way. Little more involved and time consuming, but at the end, it's what stays with you. Try it and learn. :-)


Top 10 Elements of Good Software Design

Will the team be able to implement it? Is the responsibility uniformly distributed? Is it documented? Is there duplication? High cohesion and low coupling? Is it as simple as possible?

These and the others are part of the Top 10 Elements of Good Software Design by Mr Ed. Very good list.


What Do Users Want? -- Usability Primer

How do you build a good software? In this article, What Do Users Want?, Larry Constantine explains what users want and how you build software to accomodate that. I'll give you the portions of the article that I liked the best. However, you should read the first four pages of the article: it will give the the principles of usability. A required read for all software engineers.

What users really want is good tools. They want systems that are easy to learn and easy to use, and that help them do their work. They want software that doesn't slow them down, that doesn't trick or confuse them, that doesn't make it easier to make mistakes or harder to finish the job.

How do you achieve that? Usage-Centered Design

User-centered development was not really such a bad idea but it, too, missed an important point: all software systems are just tools. Since good tools support work, making someone's job easier, faster, simpler, more flexible, or more fun, what is really important is not building software around users, but around uses. It may be nice to get software and applications developers to understand users, but what really matters is understanding what users are doing or trying to do, to understand the intended and necessary usage. Users are not the center of the universe. To design more usable software the most important issue is neither the user nor the user interface, but usage.

Ask Why

Why? Why is this needed? Why would users interact with this software? What are they trying to accomplish?

Just asking the question helps focus on fundamental issues of what would make the system more usable.


Principal Principles of Usability

First Rule: Access: "Good systems are usable -- without help or instruction -- by a user having knowledge and experience in the application domain but no experience with the system."

Second Rule: Efficacy: "Good systems do not interfere with or impede efficient use by a skilled user having substantial experience with the system."

Third Rule: Progression: "Good systems facilitate continuous advancement in knowledge, skill, and facility and accommodate progressive change in usage as the user gains experience with the system."

Fourth Rule: Support: "Good systems support the real work that users are trying to accomplish, making it easier, simpler, faster or more fun."

Fifth Rule: Context: "Good systems are suited to the conditions and environment of the actual operational context within which they are deployed."

Visibility Principle: Keep all needed options and materials for a given task visible without distracting the user with extraneous or redundant information. Instead of WYSIWYG, use WYSIWYN: What-You-See-Is-What-You-Need.

Feedback Principle: Keep users informed of actions or interpretations, changes of state or condition, and errors or exceptions using clear, concise, and unambiguous language familiar to users.

Structure Principle: Organize the user interface purposefully, in meaningful and useful ways that put related things together and separate unrelated things based on clear, consistent models that are apparent and recognizable to users.

Reuse Principle: Reduce the need for users to rethink and remember by reusing internal and external components and behaviors, maintaining consistency with purpose rather than merely arbitrary consistency.

Tolerance Principle: Be flexible and tolerant, preventing errors where possible by tolerating varied inputs and sequences and by interpreting all reasonable actions reasonably; reduce the cost of mistakes and misuse by allowing undoing and redoing.

Simplicity Principles: Make simple, common, tasks simple to to, communicating straightforwardly in the user's own language and providing good shortcuts that are meaningfully related to longer procedures.


Holiday Party Guide to Patterns

Do you know Singleton, Factory, Decorator, Adapter, Fa軋de, Strategy, State, MVC? As you might have guessed, they are all patterns from the GoF book. But if you are like me, you might know couple of them and a lot of times you are confused. If that's the case, you should read this article on java.net about those patterns. The authors prepare you for a holiday conversation on design patterns. They will help you look like a true guru. Fun and interesting article. I really liked it.


© 2001-2009

Random Quote

Topics

Architecture & Design :12
Better Coder :30
Books :50
Books I Recommend :21
Career :25
Craftsmanship :17
Java :16
Quotes :25
Recommended :11
Software Engineering :3
Uncategorized :34
Web Development :2

Archive

May 2009 (2)
April 2009 (3)
March 2009 (1)
February 2009 (3)
January 2009 (2)
December 2008 (1)
May 2008 (1)
April 2008 (3)

...since January 2002

Currently Reading

Shelfari: Book reviews on your book blog

:: The Pragmatic Craftsman recommends

:: The Pragmatic Craftsman book reviews

Info

© 2001-2009 Stanley Kubasek About me :: Contact me