User Tools

Site Tools


about:navigating_principle_languages

This is an old revision of the document!


Navigating Principle Languages

Introduction

When making a design decision based on principles, it is necessary to find those principles which fit to the given design problem. This means the designer has to figure out which aspects need consideration. Seasoned designers will already know that by experience but there is also some guidance for that task. Principle languages interconnect principles in a way that the consideration of one principle automatically leads to other principles which are likely to be relevant in the same design situations. They point to other aspects to consider (complementary principles), to possibly downsides (contrary principles), and to principles of different granularity which might fit better to the given problem (generalizations and specializations).

Characterizing Sets

A principle language cannot free the designer from actually taking a decision. There is no algorithm which replaces a sound judgment. Rather principle languages point to the relevant aspects to consider. For a given design problem, the result is a characterizing set of principles which describes the dimensions of the design space, i.e. the advantages and disadvantages of possible solutions. A typical characterizing set has around five principles.

There are two typical questions which can be answered using a characterizing set:

  1. Given a design problem and a solution, is the solution good?
  2. Given a design problem and several solutions which one is the best, i.e. the appropriate one?

In the first case the solution can be rated according to the principles in the characterizing set. If the benefits justify the liabilities, the solution is appropriate. Otherwise it is worthwhile to think about alternatives.

For the second question all the solutions are rated. The solutions which are not pareto-optimal (see conflicting principles) are clearly bad solutions. The others are all “good” but have different downsides and benefits. The characterizing set of principles shows which they are and helps reasoning about which solution to take.

Weighting Principles

Note that it's not the number of principles which is essential. Weighting the principles and taking the decision is still the task of the designer. Sometimes the weights may be derived from the requirements. Where this is not possible the weighting is an expression of the personal style of the designer, the team or the project.

The DRY principle is a typical example of a principle which might be weighted differently. Virtually everyone will agree that DRY is valid. But there are also downsides of DRY code. The wiki page lists KISS as a contrary principle. Removing duplication typically has the downside of increased complexity. But how much complexity is justified for making code less redundant? Moving duplicate code to an extracted method creates a further level of indirection but is typically still quite light-weight. But refactoring code according to DRY sometimes also means to extract a new base class. And for some forms of duplication, even code generators are necessary adding further complexity to the build process.

Certainly some people will rather favor KISS and others will prefer DRY. Some will say one duplication is tolerable and you should only refactor when there are three similar pieces of code (see Rule Of Three). But others will say that every tiny bit of duplication demands refactoring and even complex code generators are justified if they ensure that there is a single, unambiguous, authoritative representation for each piece of information (see Rule Of Generation). Neither position is wrong and to some extent this kind of weighting is just personal style. Nevertheless according to UP it is a good idea to roughly agree on some weighting in a team or for a specific project.

How to Navigate

The following approach is how you find a characterizing set for a given design problem.

  1. Starting Principles: Typically for each design decision there are one or two principles which obviously fit to the problem. When reasoning about duplicated code, DRY is an obvious start. When reasoning about interfaces, EUHM is the right starting point, etc. The OOD Principle Language gives further guidance by grouping the principles in different categories where each category roughly corresponds to typical kinds of design decisions. So when facing a design problem about how to divide a system into modules, how these modules shall communicate, how module interfaces shell be crafted or how the internal structure of a module shall look like, there is a small group of principles being candidates for a starting principle. Moreover the very first of the principles in these groups (ML, MP, TdA/IE, EUHM, IH/E) are slightly more general than the others making them a predominant candidates for a starting principles. Of course for choosing the right starting principles, one has to roughly know all the principles in the principle language.
  2. Traversing the Principle Language:
    1. First the characterizing set just consists of the starting principle(s).
    2. Then the following is repeated for each principle in the characterizing set
      1. Have a look at the related principles. They may or may not qualify for the characterizing set.
        • Contrary principles are likely to point to possible downsides, so they are the most important ones. If you find that a contrary principle is relevant for the given design problem (independent of whether it's a disadvanatge), add it to the characterizing set.
        • Complementary principles may point to further aspects which are relevant in the same context. These further aspects are less likely to be disadvantages (compared to the currently considered principle) but they can be nevertheless. If the principle is relevant, add it to the characterizing set.
        • Specializations may fit better to the given problem. They are typically more helpful but applicable to a smaller set of problems. If you find a specialization to be suited better than the currently considered principle, replace the current one with the specialization. You may also encounter situations where a specialized principle cannot replace the current one but adds a further aspect. In such a case, add it to the characterizing set.
        • Generalizations are handled similar to specializations. If a principle seems to describe a similar aspect but does not quite fit itself, a generalization may replace the current one. But there are also cases where one might want to keep both in the characterizing set.
      2. Repeat the procedure with the (now altered) characterizing set.
      3. The procedure stops when there are no further principles which qualify for the given design problem. Alternatively the procedure may be aborted if the designer already feels comfortable with making a decision.
  3. Result: The result is a characterizing set for the given design problem. Sets with around four or five principle are common. Characterizing sets with only one principle are rare. There may also be cases with seven or eight principles but that's also rare.

Remarks:

  • The procedure is not deterministic. The order in which the principles are considered, may vary.
  • Characterizing sets are not unique for several reasons:
    • Different starting principles may have been taken.
    • For some principles it may be a matter of opinion whether they qualify or not.
    • The procedure may be aborted at any time.
  • The whole procedure is meant to be light-weight. It's not meant to be documented or otherwise to be followed pedantically. The idea is to have a lightweight approach which is not much more than a way of thinking. While inexperienced designers might want to look every principle up, more advanced ones will only need a short glance at the principle language graph. Experienced designers who do not need this kind of guidance at all can skip all that and just use the principle language as a set of vocabulary for talking about their design. So the principle language helps designers with very different levels of experience.
  • The rationale section in the wiki may be used to justify whether a principle qualifies or not.

Example

The following example shows the usage of the OOD Principle Language. It details the assessment of a solution found in the CoCoME system1). The details of the system are irrelevant here but it resembles an information system which can be found in supermarkets or other stores. There are several components which are grouped into the typical layers of an information system: The presentation layer (GUI), the application or business logic layer and the data layer.

In CoCoME there is a mechanism for getting access to other components. In a nutshell it works like this:

  • For the data layer there is a data component, a class DataImpl which aggregates three subcomponents Enterprise, Persistence, and Store and gives access to them.

FIXME code for Data class

  • There are “factory” classes which lazily create and provide access to single instances of a component.
  • The “factory” itself is static and thus globally accessible.
public class DataIfFactory 
{
    private static DataIf dataaccess = null;
 
    private DataIfFactory () {}
 
    public static DataIf getInstance () 
    {
        if (dataaccess == null) 
        {
            dataaccess = new DataImpl ();
        }
        return dataaccess;
    }        
}

Essentially DataIfFactory resembles a mixture between the design patterns factory and singleton. The latter one is important here. The purpose of a singleton is to make a single instance of a class globally accessible. Here DataImpl is not ensured to be only instantiated once as it still has a public constructor. Nevertheless the “factory” class makes it globally accessible. In every part of the software DataIfFactory.getInstance() can be used to get hold of the data component. And since DataIf makes the three subcomponents accessible, also these are accessible from everywhere. There is no need to pass a reference around.

Is this a good solution?

We will examine this question using the OOD principle language. First we have to find suitable starting principles. This is one of the rather sophisticated cases where finding a starting principle is at least not completely obvious. If we don't have a clue where to start, we'll have a look at the different categories of principles in the language. Essentially the “factory” enables modules to access and communicate with each other. So we are looking for principles about module communication. There are three of them in the principle language: TdA/IE, LC, and DIP. TdA/IE does not seem to fit, but LC seems to help. So our characterizing set first looks like this: {LC}.

Now we'll have a look at the relationships. LC lists KISS, HC, and RoE as contrary, TdA/IE, MP, and IH/E as complementary, and DIP as a specialization.

about/navigating_principle_languages.1378758522.txt.gz · Last modified: 2013-09-09 22:28 by christian