• Ei tuloksia

Example solutions

7. Experiments

7.2. Example solutions

Raw numerical fitness data does not reveal much of a produced solution: the fitness values merely benefit the analysis of how the values evolve, and ensuring that there is variance within the population. Statistics of the amount of classes or interfaces used does not reveal much of the structure either, apart from special cases when the number of classes is very small or very big, and likewise with the use of interfaces. In order to somehow evaluate the “goodness” of the produced solution, one needs a visualization to see how the responsibilities are distributed, how the patterns and dispatcher are used, and how clear the presented solution is overall. Thus, when evaluating the goodness of a solution from a class diagram, the evaluation is bound to be subjective, and people from different backgrounds may appreciate different things. I have evaluated the goodness of the solution based on three things: the structure, the use of patterns, and the use of dispatcher. The structure should be clear: there should not be a complex web of dependencies. Patterns should be used so that they clearly benefit the architecture and the structure should not suffer extensively. The dispatcher should also be used “with a thought”; the amount of connections to a dispatcher should remain reasonable and the connections should add a minimal amount of complexity to the system.

I will now present some example solutions achieved with the presented implementation. As these solutions demonstrate, it is difficult to achieve a solution, which could be appreciated from all viewpoints – normally a maximum of two of the three evaluation criteria (structure, patterns, dispatcher) have been satisfied. Thus, I have chosen examples which depict a good architecture from some viewpoint. Naturally, the goal is to achieve a combination of these solutions, so that the architecture would have a high overall quality that can be seen instantly with expert eyes.

In Figure 15, an example with quite a clear structure is shown. Here the different subsystems have been separated from each other, with the exception of the drape regulation system, and the responsibilities of individual subsystems have been well grouped. For instance, the coffee machine system has one big class with many responsibilities, from which several responsibilities have been extracted and put behind strategy-interfaces to support variability. The same design decisions have been made with the user registry subsystem – although in this case, some responsibilities belonging to the drape regulation system have been “falsely” combined in the same class with the user registry responsibilities. Also, the music system has been effectively combined with the speaker driver responsibilities. The user interface and main controller have been situated in their own classes, which call the other responsibilities. This is a very clear and

good design decision, as there is no need to combine these special responsibilities with anything else. This solution is fairly simplistic, as the only design pattern used is Strategy.

A similar solution is presented in Figure 16, which also has some big classes, quite a clear structure, and efficiently uses the Strategy pattern. Especially notable is the use of Strategy in the cases of measuring temperature and drape positions (Strategy1 at the very left side, and Strategy4 at the bottom right): these are operations that can quite naturally be varied depending on the circumstances and data at hand, and separating such operations behind an interface through Strategy, greatly increases the modifiability of the system.

Figure 15. Example solution 1.

Figure 16. Example solution 2.

A solution that takes good advantage of the message dispatcher is depicted in Figure 17. Here the structure is not as clear as in Figures 15 and 16, and there are more dependencies between classes as in the solution in Figure 15. However, the solution is more modifiable, as many calls happen through the dispatcher, and thus the classes are not directly dependent on each other. For example, a good design decision in this case has been to put the water control subsystem behind the dispatcher, thus alleviating the dependency between the coffee machine and the water control. The benefits and shortcomings of using a message dispatcher architecture style are not straightforward.

The positive effect in modifiability and the negative effect in efficiency are easy to see, but how the dispatcher affects the structure, the “beauty”, of the solution, is more complicated. A well-placed message dispatcher may actually simplify the structure, and different components can easily be separated from the class diagram. A badly-placed dispatcher, on the other hand, can make the solution extremely messy, if there are many connections to and from the dispatcher and the class division of the responsibilities is not extremely successful. The solution shown in Figure 17 is somewhere between these extremes: the basic structure is successful enough so the use of message dispatcher does not make the solution completely incomprehensible, while some connections to the dispatcher clearly do more harm than good. In this case, the solution could benefit from either removing some connections to the dispatcher, or actually adding more connections, as the connections between classes would become more unified, and the dispatcher more central in the solution.

The Façade design pattern is not very often seen in the proposed solutions, as there are few places where it can be implemented in the example system. Also, as it adds complexity by bringing technical classes to the design, one might question the use of both a façade and a dispatcher in the same system. Figure 18 shows a solution where the Façade pattern has been used efficiently. Here, the user interface and the main controller call the façade interface instead of calling several responsibilities belonging to the many subsystems that these special responsibilities control. However, in this case the structure is not very good – there are many small classes and responsibilities from non-related subsystems have been grouped in the same class, e.g., class 24 contains responsibilities from the water control subsystem and the music system. The message dispatcher has also been brought to the system and used very inefficiently: only one responsibility uses the dispatcher to call two responsibilities through one interface.

Figure 17. Example solution 3.

Figure 18. Example solution 4.