Class vs. aspect oriented source code organization
Posted by Peter Vanbroekhoven on Sep 24, 2007
Organizing the source code of your library or application well is extremely important. Well laid-out source code helps maintainability and readability, both very important aspects of software that is to last. Class oriented source organization was made popular by Java and adopted by Ruby on Rails, and is an accepted industry standard. Ruby code organization is file oriented. This allows most any code organization a programmer could want, opening the road to—god forbid—even better organizations. This article focuses on aspect oriented code organization.
Class oriented organization
The source code organization popularized by Java is to put a single class in a single file. The name of the class contained in a file can be derived directly from the file name; the package in which the class is located can be derived from the path to the file. This makes it easy to locate the full definition of a class, both for someone reading the source code and for tools such as “javac”, the java compiler.
This is a convention that in Java’s early days was actually enforced. With the advent of build tools for Java that are better than plain “javac”, this convention was no longer necessary. Several classes can be defined in a source file whose name bears no relation to the classes defined in it; the path to a source file needs no longer coincide with the package name. If “javac” is used as build tool (though not recommended), one should still use class oriented organization to allow it to find source files automatically. The Java specification still requires a class be fully defined in a single source file. Likely, the reason is conceptual simplicity of the compilation process, for instance to avoid having to work with partial class definitions and such.
File oriented organization
In Ruby, source code is organized in files. Files can contain partial class definitions and executable code (as far as these two are actually disjunct in Ruby), and files are “required” explicitly. This means that class definitions can be spread over several files, and that a single file can contain several class definitions. As such, there is not necessarily a direct relation between the name and path of a file, and the class defined in it. Class oriented organization can be implemented on top of file oriented organization; this is what Rails does and it allows it to locate class definitions automatically. Many other organizations are possible, opening up many possibilities.
Object oriented design vs. aspect oriented design
The premise of object oriented design is that data structures and the code working with them belong together in one class. This assumes that your design is driven by the data structures, and a good design consists of distributing the code as well as possible over these data structures. For large applications, this means that single classes will acquire much domain knowledge, often of several aspects of your application. This is bad as it leads to bloated classes that decrease maintainability and reusability. While these different aspects can usually be factored out in separate classes, this is tedious and time consuming, and makes the design very heavy.
The premise of aspect oriented design is that, rather than being composed of classes, an application is composed of aspects. Aspects roughly correspond to features or groups of features of the application. The boundaries of the features are usually very different from the boundaries of the classes and they cross all the time; that is why aspect oriented design is said to deal with cross-cutting concerns. Because changes are often confined within one aspect or feature of the application, and reusability really is at the level of aspects or features, it makes more sense to use aspects as the building blocks rather than classes.
Aspect oriented organization
An aspect of an application consists of a number of methods that together perform certain functions and that are usually scattered over several classes. This means that when programming a particular aspect, one is constantly switching files. Your favorite editor or IDE will happily perform that operation for you, but even with the best IDEs, this becomes annoying when the list of files no longer fits the screen. A larger problem, though, is that you cannot see the code for one aspect on one screen. It is hard to see the complete picture when all you can see at once are small portions of the picture. Hence, it makes sense to put code related to the same aspect of the application in a single file. We call this aspect oriented source code organization.
This kind of organization has distinct advantages because developers normally work on one aspect at the time.
- It eliminates constant switching between files and searching for related code.
- All code related to a single aspect can be seen in one glance.
- A change to an aspect is confined to a single file, minimizing the danger of forgetting to apply the change everywhere.
- It provides clues for when to refactor. If you start switching files too often when working on an aspect of the application, it is time to refactor.
- It allows easy enabling and disabling of features by requiring or not requiring the file corresponding to that feature or aspect.
- Aspects can more easily be reused by copying one or a few files. With a class oriented organization, an aspect often needs to be factored out at the cost of code complexity and a heavier design that makes reuse more costly in terms of the amount of code needed to glue the aspects together. The alternative is to include much unneeded code that can interfere with your own code. Aspect oriented organization has none of these problems.
- File sizes are more balanced. Some classes tend to accumulate many methods without a good way to change this without creating a heavy design. An aspect does not tend to grow that much, and if they do you know that it is time to refactor it in several smaller aspects.
Aspect oriented organization has its disadvantages as well, which are inherited from file based organization.
- It is hard for tools to locate full class definitions. This is testified by the still limited amount of automatic code analysis tools that exist for Ruby. Analysis usually resorts to gathering information by running the application, for instance RubyScript2Exe for gathering a list of required files, or to inspecting the run time code representation using libraries like ParseTree.
- IDEs still have quite some trouble navigating Ruby source code. This really coincides with the previous item as an IDE is a tool, but it is an important tool that many Rubyists have got used to having at their disposal, and as such it is worth a separate mention.
Conclusion
Class based source code organization seems to be mostly for the benefit of tools. Because tools are for the benefit of programmers, through transitivity, class based organization is indirectly also for the benefit of programmers. Aspect oriented source code organization, on the other hand, is often more natural as it makes an application fall apart in its aspects instead of its classes. This too is for the benefit of the programmer because it opens the way to many new and better design technologies that increase maintainability and reusability—things that tools cannot provide.
While the existence of good tools should not be underestimated, in software development, it will always be the programmer that is the bottleneck. New, better tools will emerge in time and will fully support file based source code organization, or even aspect oriented organization, but tools can never replace a good software designer. Hence, the most important aspect of software design is to cater to the designer’s needs with decent design technologies.
So maybe it is time to put class based code organization to rest, and move on to better things. Let us know what you think!