Book Review: 97 Things Every Software Architect Should Know

More then year ago I bought book 97 Things Every Software Architect Should Know for myself. I was expecting to get a book with some useful technical advices how to create cool software architecture,- that's what was always interesting for me.

Instead I've got the book with 97 small articles, each 2 pages long. No technical advices, no silver bullet, no advices on what and how use design patterns or modern technologies. Truly say, after reading few articles, I was upset. And leaved the book on my bookshelf and move on.

A year later, ie a month ago, I've took this book into my hands and decided that it's time to try to read it again. (Yes, I have a habit to re-read books again a year or two later, as found that it helps to understand much more and see the forest behind the trees).

I'm still reading this - few articles per week,- but decided to note my thoughts as review in this article.

In this attempt, book is very interesting. A year later my vision was changed cardinally again and now, I think, I can understand what those guys mean when they were writing their posts. These all can be said simply in one sentence:
Software Architects are bridges between business needs, software needs, technical needs and team needs.

Especially interesting were next articles for me (remember, I'm still reading):

  • Don't Put Your Resume Ahead of the Requirements

  • It Is All About The Data

  • Pattern Pathology

  • If You Design It, You Should Be Able to Code It

  • Empower Developers

  • Chances Are, You Biggest Problem Isn't Technical

  • Business Drives

  • Great Content Creates Great Systems

  • Start with a Walking Skeleton

  • Communication Is King; Clarity and Leadership, Its Humble Servants

I'm sure articles' titles are saying enough, so will not describe them. Want know more - just go and buy (as I did :)

A week ago I was reading "Business Drives" article. And especially remembered the summary of this article: "The long-term interests of the software development team are best served when business drives". And I agree with this summary. It's sad to know, that many software developers are still in the race for better skills and modern technologies if this is in damage for the project and business.

It's one of that books, that reminds that software is making by humans for humans.

So, my advise is to get and read this book; hope you're ready for it and hope I'm too :)

PS: Just found another review of this book http://dotnet.dzone.com/news/97-things-every-software

Groovy annotations

As I wrote in my last post Groovy 1.8 is still in progress. One of the new features I liked a lot is annotation support for AST transformations (i.e. @ToString, @Canonical etc.).

As I'm still acquainted with Groovy, I've decided to look what useful annotations it has already. So this post is about what was found.

There are next annotations in the groovy.lang package:

  • @Lazy
  • @Immutable
  • @Newify
  • @Singleton
  • @Mixin
  • @Category

Also want to describe them with few simple samples.

@Lazy

This annotation can be applied to class field. As result new instance for field value is created on get method call for field property. In this case Groovy generates getter method for you, that checks whether field is not initialized yet and initialize it in this case, otherwise returns its value:

@Lazy T x

generates next code:

private T $x

T getX() {
if ($x != null)
return $x
else {
$x = new T()
return $x
}
}

You also can do lazy field initialization with specified value, just assign this value for field with @Lazy annotation:

@Lazy T x = new T(code: 'S')

That will generate next code:

private T $x

T getX() {
T $x_local = $x
if ($x_local != null)
return $x_local
else {
synchronized(this) {
if ($x == null) {
$x = new T(code: 'S')
}
return $x
}
}
}

Absolutely useful thing with only a few of keypresses. That's awesome.

Read more in GroovyDoc

@Immutable

Used to mark classes and make them immutable. That's mean that your class becomes final and nobody can change value field value and you get tuple and map based constructors. Also Groovy generated toString(), hashCode() and equals() methods for you. You should also need to be sure that fields types are immutable, primitives, strings, enums or are annotated with @Immutable.

Read more in GroovyDoc

@Newify

This annotation is perfect for DSL expressions. With it you can change creating new objects expression, for example, use

def b = Book('The Best Book Ever')

instead of

def b = new Book('The Best Book Ever')

Read more in GroovyDoc

@Singleton

Well, another annotation that makes your life easier. As you maybe already understand, this annotation is for types and make them singletons.
getInstance() method is generated for you, so simply call it when you need new instance. If you set annotation lazy parameter to be true, your singleton instance will be created on first call to this method. As for this case method supports double checking locks, you may be sure that only one instance will be created. Here is some sample:

@Singleton
class Player {
def play() {}
def stop() {}
}

...

Player.instance.start()

Read more in GroovyDoc and Singleton transformation.

@Mixin

Used to mix one or few types into annotated type. As result, you can have a class that have members (fields and methods) from other classes, specified in the annotation. And here is sample:

class Book {
String name
String author

def find(text) {
....
}
}

@Mixing(Book)
class HardBookMetadata extends Metadata {
int pages
String publication
}

....
def metadata = new HardBookMetadata()
metadata.title = 'Some cool title'
metadata.author = 'Ruslan Khmelyuk'
metadata.pages = 400

println metadata.find('cool')

As you see, using variable metadata of HardBookMetadata type have access to Book members.
Yeah, this also can be used with @Category.

Read more in GroovyDoc.

Waiting for Groovy 1.8

Groovy 1.8 is going to be released in December 2010. First beta release is already open to download and second beta release will be ready in September.

Groovy developers team preparing for us a few important surprises.

They added more AST transformations, for different cases like @Canonical, @EqualAndHashCash, @ToString and many others. You may use such annotations to generate toString(), equals(), hashCode() methods on compilation. @InheritConstructors helps to generate inherit all parent constructors, and here is link to task.

Another interesting feature is Closure composition, so now it's possible to use special syntax to compose multiple closures, like:

def log = { a -> println(a); a }
def save = { a -> dao.save(a); a}
def notify = { a -> notificationService.notify(a); a }

// so now instead of calling notify(save(log(user)))
// you may call it like
def action = log >> save >> notify
action(user)

// or even like
notify << save << log << user // is that awesome or awful?!

Also they prepared few performance improvements: avoiding calling methods when it's not necessary and processing operations on integers as primary type values but not objects (like, incrementing or adding). As result Groovy can be used for mathematical calculations without performance issues. In this presentation you can read much more about this. And here are related jira tasks so anyone can watch the progress.

This issue is fixed so they can't say that "Ruby is right, Groovy is wrong" anymore :)

Annotations now can accept closure as argument:

@Validator { password.size() > 6 }
String password

This task contains more information and links.

Closure currying is a powerful thing. And now it's possible to curry right and 2nd (of three) parameter. Moreover no need to wait Groovy 1.8 to try this, because it's available right now and right here, starting from version 1.7.2 of course ;)

Well, that's all about this for now. Waiting for Groovy 1.8 and for more interesting things to be released this December.

SpringWS and Jaxb

Well, truly say this small post is not about how to use SpringWS and Jaxb together. It's more about potential power of this combination. I know, that combination is in release for few years alredy and used by thousands of developers. But this article is more for guys in doubt if they really need SpringWS rather than for experienced Spring WS developers.

First of all, I want to say that Spring WS is very powerful framework. I've noticed it when version 1.0 beta was released. As everything in Spring it has good API, simple implementation model and as result it was very flexible. And this mean that you can easily introduce need changes and extensions without changing Spring WS source code.

From the beginning, the Spring WS team was saying that SpringWS should support not only low-level request processing, when you have some object that represents input XML document or build output XML document, but can use different mapping and translation libraries to make it for you. And here is a place for Jaxb.

To enable marshaling you need just to do few simple changes:

  1. Add marshaller bean of org.springframework.oxm.jaxb.Jaxb2Marshaller type:
    <bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
    <property name="classesToBeBound">
    <list>
    <value>GetImageRequest</value>
    <value>GetImageResponse</value>
    <value>AddImageRequest</value>
    <value>AddImageResponse</value>
    </list>
    </property>
    </bean>

  2. Add Marshaling Method Endpoint Adapter to yours spring.xml:
    <bean class="org.springframework.ws.server.endpoint.adapter.GenericMarshallingMethodEndpointAdapter">
    <property name="marshaller" ref="marshaller"/>
    <property name="unmarshaller" ref="marshaller"/>
    </bean>

  3. Well, that's all :)

And then, after some testing, I found that it would be nice to trim input text fields and do other post-marshalling operations. And I was sure there was a normal way to do that with rather Spring WS or Jaxb. After a few minutes of searching, I have found the way and had completely working code that was doing what I was needed.

The catch is that Jaxb Unmarshaller supports listeners and Spring's Jaxb2Marshaller has a property unmarshallerListener, that points your listener to Unmarshaller's listeners.
With only 3 lines of configuration we have own listener called on each unmarshalling:
<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
....
<property name="unmarshallerListener">
<bean class="TargetHandlerUnmarshallerListener"/>
</property>
</bean>

Here is TargetHandlerUnmarshallerListener code:
import javax.xml.bind.Unmarshaller;

public class TargetHandlerUnmarshallerListener extends Unmarshaller.Listener {

@Override public void afterUnmarshal(Object target, Object parent) {
super.afterUnmarshal(target, parent);

if (target instanceof PostPopulatedHandler) {
((PostPopulatedHandler) target).postPopulated();
}
}
}

In this class I override only afterUnmarshal() method, that is called after XML is transformed to the Java object. You can also override beforeUnmarshal() method if you need.

PostPopulatedHandler is my own interface that expose only postPopulated() method. Each class knows what to do after unmarshalling, and declares it in the postPopulated() method. Of course, there can be used some annotation, but interface option is the most simple, easier and obvious way.

So, some summary is next: Spring libraries are awesome, because they always provide very good API and you always can do what you need without changing library source code. Jaxb is awesome as well. I'm noticing this, because it's always hard to write good API, especially in multifunctional libraries.

Migrate from SVN repository to Git

As I was saying in my previous post it is easy to migrate you project from Subversion to Git.

Really, you will need just a few commands to run.

First of all you need to make a clone of Subversion repository using git-svn tool:

$ git svn clone --authors-file=authors.txt https://example/svn/MyRepo/trunk/project project

On this command git will go through the history of the project and fetch it into local git repository. If your subversion repository is using standard layout (i.e. trunk, branches and tags paths are present in the SVN repository root tree) than you may be interesting in --stdlayout option. You may also specify custom path for trunk or branches or tags using -T or -t or -b option respectively.

Option --authors-file contains the path to the file with committers mapping.
This file contains SVN committer mapping to git user per line.
For example:

ruslan = Ruslan <ruslan@example.com>
john = John Smith <john@smith.com>

So now you have local working copy that is managed by Git and also you have all project history in your local repository. It's easy to check what branches and tags you have using next commands:

$ cd project
$ git branches
$ git tag -l

If you have remote Git repository (maybe in GitHub), than you may want to push source code with all history to that repository. And it is not a problem, as you have already everything you need.

1. So add remote repository:

$ git remote add origin git@github.com:myname/myproject.git

2. And push to the remote repository:

$ git push origin master

3. and be happy - now you have migrated to the git repository.

Remove directory with SVN repository clone and make another clone but from git repository and continue using it:

$ cd ..
$ rm -rf project
$ mkdir project
$ cd project
$ git init
$ git remote add origin git@github.com:myname/myproject.git
$ git pull origin master


Thats how it worked for me 2 months ago.