Using Aspects you can safe-guard that the code will keep in a good state after refactoring

How do we safe guard that new features will comply with the new design? A refactoring needs to be looked after.

A refactoring aims to leave the code in a better state than before. But what happens after the dust is settled and it is time for some new development that must adhere to the new architecture. What can we do in order to avoid degeneration of the software architecture?

 

Documentation & training

All relevant documentation needs to be updated like, SAD, design documents etc. Also developers need to get hands on training to understand the refactoring.

Code-documentation. Adding of comments describing what an interface is doing so we know what to do when implementing.

This and other things are all done in order to keep code not deteriorating. But is it really enough? What happens for example if new developers join? How do we guarantee that they will acquire the knowledge needed?

More often developers code first and read documentation later. So what we need is a way of enforce our architectural refactoring (or any architecture for that matter) and convey that to the developer. Our answer is Aspects! First some background regarding Aspects.

Aspects is used to separate cross-cutting concerns, thus separating business logic from secondary functions like caching, logging etc. Aspects is defined in separate modules specifying what it should do and when it should be trigger at what point in the program. Using this approach you don’t have to concern yourself with coding logging or caching in every business object, the aspect will handle this.

For further reading regarding Aspects:

https://en.wikipedia.org/wiki/Aspect-oriented_software_development

Even though Aspects is great doing this, how does this relate to future-proof our architecture? Of course when defining our Aspects correct we will always have logging, caching, etc not worrying about if the programmer remembered to add it. But it will not check that that design patterns are followed correctly. We want to use it where it hurts for a programmer: at compilation time!

Daniel Svedberg

Senior Consultant
Daniel has extensive technical experience as a developer and software architect for large mission critical systems. He is responsible for designing and developing applications in multi-layered architecture. The solutions put high demands on scalability to handle large volumes of user and usability.

This can be done using the framework AspectJ. This is a extension used in the java programming language implementing the aspect model. It has all of the functionality mentioned above plus that you can use the point-cuts to add compiler time warnings and errors with the “declare:” statement. This can be a very efficient way of reinforcing architectural rule.

Further reading of AspectJ:

https://www.eclipse.org/aspectj/

Using the declare statements of AspectJ you can control that:

  • certain calls from specified classes are forbidden
  • Methods follows requested signatures
  • certain calls from specified
  • classes are mandatory
  • and more…

For example:

declare error : call(* org.xyz.model.*.*(..)) &&
!@within(Trusted)
: "Untrusted code should not call the model classes directly";

This means that the aspect will generate an compiler error when any this pattern is encountered (the trusted condition can be whatever you can define using Aspects).

You can also declare exception to the rules that certain classes/methods shall be excluded from the compile-time check etc. It is a powerful tool and you can almost specify any compilation rule you want to enforce.

Using Aspects you can safe-guard that the code will keep in a good state after refactoring. Separating concerns helps, with the addition of compiler time check we can take a step further. It is hard to ignore compilation errors.

Please feel free to share