Monday, July 19, 2010
Here is an example for following hierarchy
The INodeElement might look like this:
and the IHeadElement linke this
Later on, in your implementation code you can use the visitor to lookup the concrete type
As you can see there is no typecast needed, so you never get a ClassCastException. However if you look at the example, one major drawback of the visitor pattern is that if the hierarchy is not matching exactly, you have a bunch of empty methods. These methods can lead to confusion and doing nothing or throwing an exception isn't much better than a ClassCastException.
If you have the control over the source, you can easily introduce a new more specific type in your hierarchy to workaround this.
Now you can tag the child elements (in this case we have only one)
and the return type of the list can be changed to a more specific one
Using the new more specific visitor, there are no more unnecessary methods
Problem solved? Yes, if you have the freedom to modify each element for tagging it, when ever you create a child list. Otherwise you should look for a better solution.
Think a short time about, what you really want to do. You want to restrict the list to adding elements only of specific types and allow to query them later, while making sure that no type is forgotten when the code changes. Another possibility to add a visitor is to wrap the list element. To do so, remove the IHeadElementChild interface and the corresponding accept-method from the ITitelElement. Now add an implemention for the IHeadElementChild interface. Create factory method for each element allow in the childlist.
In the implementation of the IHeadElement always add the wrapper to the list, everything else can be left as it is. Now you are completely independent of the class hierarchy. Note that this solution will also work with classes provided by foreign frameworks.
If you already used actifsource to describe and generate your class hierarchy, you can leave the whole work to the generator and gain the advantage of more type-safety and less casts.
Monday, July 5, 2010
A complex system is divided in layers/tiers and packages to manage code artifacts. This technical architecture provides an overview on the implementation.
On the other hand we find the business architecture where packages, areas, functionality, epics, etc. are used to structure domain objects.
On the semantics of projects and packages
Both the technical and the business architecture have one thing in common: they are structured not only with packages but also with projects. Modern IDE's as Eclipse, MS Visual Studio or InteliJ's Idea animate developers to separate different concerns in different projects.
All artifacts of a software system are structured using projects and packages.But architecture lays above projects. Architecture describes how a system is divided into projects. This fact leads to the problem, that architecture can never be described by its projects alone.
It seems that describing architecture needs kind of an Über-Project which contains the overview how projects are interrelated. This overview shows packages and their dependencies as shown in my blog before.
There has to be an overview how projects are interrelated. This overview is the most important artifact to understand the technical architecture or business architecture.The tricky thing: The overview provides an entry point whereat the details are managed in the projects. But nevertheless this architectural project should contain all the information to get a complete overview. This includes also detail information contained in the particular projects.
Let's assume that all green packages are modeled in the architecture overview while the red packages are realized as projects.
- The architectural overview seems to define packages which contain other packages
- At a certain level the architectural overview seems to reference packages from other projects to illustrate the dependencies
Packages as resources
In the current version of actifsource packages are reflected as file system folders. But it seems obvious that packages are much more then folders.
- Package-structures have a project-specific meta model
- Packages declare dependencies to other packages (according the meta model)
- Package structures may be distributed over several projects (package references)
- Packages can be mapped to file system folders
In one of my next articles I try to examine the technicalities.
Saturday, July 3, 2010
Component interdependencies might appear deeply nested in the component. Remember that component comes from the Latin word "componere" which means being composed. The following example shows a use-relation between A.B and X.Y.
Just looking at the components without knowing the internals we can say that there is an implicit dependency between the two components A and X.
If we could make this dependency relation explicit there would be a way to constrain the A.B-X.Y relations on higher level.
This possibility would allow you to control the component-interdependencies - even if they are nested deeply in the component structure.
You may argue that component are not complex enough to control their use-relation by an explicit dependency. But imagine a software architecture which is based on layers and packages:
All packages and subpackages are somehow related to each other. Since the above diagram shows the technical architecture of our system the artifacts placed in the packages are templates (when generating) or simply code.
Just imagine you could explicitly define the dependencies between the packages. And now imagine that every template inter-dependency (one generic class using other generic classes) is checked immediately by the actifsource real-time validator.
Providing such a system your technical architecture would be documented soundly. And moreover actifsource would ensure that your code follows perfectly along the architecture.
Another very interesting application of dependency relations is found when designing the business architecture. Coping with a complex business domain the relating business objects have to be structured to keep the overview.
Grouping domain-objects in packages and defining dependencies between the packages allows you to control use-relations between components from a higher level.
Providing such a system would allow you to group domain objects together for a perfect overview. Moreover actifsource would ensure that any relationship between components follows the well defined business architecture.Conclusion
Modeling explicit dependencies allows you to control use-relations from a higher view. This view is what we usually call the architecture overview. actifsource could not only provide sound documentation of the architecture (technical and business) but also ensure at real-time that no artifact breaks the dependency rules.
The secret to this functionality lies in typed folders as Micha described in his blog Grouping Is Domain Specific Too. In one of my next blogs I try to workout the tricky details.
Friday, July 2, 2010
- nant - which is used to build the c# projects
- mono or Microsoft .NET Framwork - providing the tools and resources to run and build c#-projects
After you have installed them you need to setup emonic:
I only installed the "Eclipse Mono Integration", the debugger doesn't want to install at the moment and the other features are not required for this demo. When you have finished the installation, you first need to setup .NET preferences. Select the nant-binary-file:
and afterwards add a .NET-Framework Implementation. For example I used mono and chose the following settings:
Now create an actifsource projects for your meta model and the actifsource templates. I used the actifsource core model as meta model and wrote a simple data class template. The template is nothing special, but instead of writing java code, I wrote c# code:
Note that I have created a separate actifsource project for the actifsource template and generation specific resources. With our multi model concept, there is no need to modify your meta model project, just create an extension project. Since the actifsource project containing the template is a Java Project and mixing Java Code with C# Code is not recommended, switch to .NET-Perspective and create a separate .NET-Project.
I used "Mono 2.0" as target, you may use another target framework. This setting is important, since generics for example are not available in "Mono 1.0".
For generating the data classes I first need some actifsource classes. I just reused one of my last examples and put it into a newly created asrc folder in the dotNet project.
Now there are only a few steps to do, add a project dependency to the template-project and define the target folder.
The c# files will be generated immediately after pressing "ok". In emonic to make them compile, you have to right click on them and add each file to the build.
When doing this the first time, you need to set a build target:
Finally I added a small demo application which creates two instances of the class "Person", fills them and queries the data for writing it to the console.
To run the application one needs to right-click on the exe-file and select run .NET-Application.
That's it. If you don't want to add each file, you need to edit the build script and make use of wildcards. One drawback using wildcards is that the emonic builder doesn't seem to detect file changes for these resources.
The idea remain the same. Some use-relations are important for the overall component structure and some are not. Let's have a look at some examples.
First of all, let's have a look at the following structure. Component owns Command owns Argument. But the Argument itself has a use-Relations to type. Imagine a function declaration f(int a, float b) where the argument a has a type int and b has type float. The relation of a method argument to its type is simply functional an will never appear as a relation in an UML diagram.
The second example show a meta-model which declares that components may extend/subclass other components. This relationship is clearly structural because it's important from the component's view. Just imagine the specialization relation in a UML diagram.
Quite special on the above relation is the fact that it's never necessary to name the role of the extends relation more specifically. Extends remains extends no matter what is extended.
The next example shows a meta-model for a component which has a collaboration relation to other components. The difference to the above design is that the collaboration relation has a role which has further information (i.e. at least a name.) For that reason the role has to be designed as an own class on the meta level called Collaborator in the subsequent example.
Let me give a résumé: First of all we distinguish structural and functional use-relation. As a rule of thumb only structural use-relations matters for the overall component structure.
Taking a closer look at structural use-relations one notice that there are relations with and without roles. If no role is needed the design is simple as seen above. If A extends B the extends relation between A and B needs no further information.
But if we do need to distinguish roles for a structural use-relation this role has to be modeled in a separate class providing at least a name. In the example below component A uses B1 as xAxis and B2 as yAxis. Note that xAxis and yAxis are instances of Collaborator.
It's quite interesting that the class Collaborator of the meta-model is visualized as a role in the instance-model. Since the decision if a structural use-relation needs a role or not is taken by the designer, we have to distinguish 3 different modes for use-relations:
- functional use-relation
- structural use-relation without a role
- structural use-relation with a role
To conclude this blog let's think if this concept might work for a generic diagram editor which can visualize meta-model and model at the same time. For this reason let's have a look at the following simplified UML meta-model (which can be seen as meta-meta-model for our example).
- The type-relation from Argument to Class is a functional use-relation
- The extends relation from class to class is a structural use-relation without a role
- The type-relation from Member to Class is a structural use-relation with a role (Member play the role)