Fork me on GitHub

Graphical Configuration

OfficeFloor uses Graphical Configuration to ease the complexities of software development and allow developers to focus on writing code rather than configuration.

Background

The following discuss various aspects of configuration that are not always considered by many frameworks.

Differing configuration between components

Good code is organised into flexible components that enable its re-use in a variety of different applications. These components could range from being small libraries providing utility functions to large frameworks that govern how the application works. What is common between these components is that they expose interfaces (whether specific java types or implied signatures via reflection) that provide the ability to interact with the component.

To enable ease of re-use these components typically provide simple interfaces with specific details of how the component operates contained in some form of configuration. An example of this would be a logging component that only exposes methods on its interface to capture information to log and has its configuration specify where the information is to be logged (stored).

The configuration of a component can become a language of its own. To illustrate this point take for example XML configuration. The XML configuration will have a structure (possibly specified by an XML schema) that indicates how the elements are to be nested within each other along with the attributes for each element. To configure the component an understanding of what each element and attribute represents is required. This attached meaning to each XML element and attribute becomes a language by which to configure the component.

The configuration language is additional knowledge that the developer must learn. Should the developer not be familiar with the configuration they will be required to take the time to learn its specifics. This can be a costly effort in terms of time as the configuration may:

  • not be completely documented requiring browsing of the component's code to gain this understanding
  • have the component fail silently or with uninformative errors that leaves the developer unsure of what is wrong
  • not be intuitive as the component focuses on functionality and flexibility rather than focusing on ease of configuring

Managing configuration

After the developer has understood the configuration the next issue that typically arises is managing the configuration. As the application grows in functionality, the configuration of many components also grows to aid in supporting this functionality.

In many cases configuration for a component is kept in a single file that ends up becoming an 'uber' file of information. The file contains all the details to configure the component and can grow to thousands of lines long. This then creates problems such as:

  • too much detail that forces the developer to invest a significant amount of time in trying to understand the configuration
  • merge conflicts as the configuration file becomes a central point that all developers require changing
  • fragile applications as small configuration changes can cause unexpected behaviour (typically because of lack of encapsulation in these large configuration files)

Importance of configuration

Configuration is as important as the code. While many developers may like to focus on writing code, the components they are using to build applications typically do not operate unless configured. To build and run an application the developer's code, components and component configuration are required. It is also not uncommon to have the configuration kept under the same source code repositories as the developer's code.

As the configuration is as important as the code, it should follow similar principles as code in being managed. Some of these might include providing:

  • Encapsulation of configuration. In other words, exposing only certain information for an aspect of configuration to allow easier internal changes to that aspect
  • Modularising configuration so that each module is responsible for a certain aspect of configuration. This should allow developers some level of isolation in creating the configuration and also enable easier code/configuration reviews by their peers.
  • Abstraction of configuration. This is not so much in the form of inheritance but more in the form of simplifying the configuration
  • 'Strong' validation that validates the configuration and the connections between the individual items in the configuration. This for example includes XML schema validation to ensure the XML structure is valid. However more importantly validation that the XML element content and relationships between that content are valid. This is much like a java compiler validating the arguments to a method are of the correct number and type.

Configuration describes the application

Frameworks are pushing more and more detail into configuration with developers only providing snippets of code where necessary. The code developed is typically becoming small encapsulated functions/components that are plugged together by frameworks. The result is that these snippets of code become too fragmented to provide an overview of the application. The overview of how the application operates is now contained in the configuration that joins these code snippets together.

The configuration becomes the information that must be understood to obtain an overview of how the application works. In using frameworks developers will typically look for specific configuration files or sections of configuration files that contain core information on how the application is structured.

There is always going to be the necessity for code to define the finer points of how an application functions. However, should configuration be represented in a similar fashion to code? In other words, why does configuration require special syntax needing technical skills to understand it?

Having the configuration readable by non-technical individuals means that additional effort by developers to explain the application is minimised. The non-technical individuals would be able to review the configuration and provide feedback as to whether it is meeting their requirements. If the configuration could also be edited in this fashion the developer and non-technical individual (likely from the business providing the requirements) could work together. They would use the configuration as a visual aid to enable clearer communication to build the application.

Graphical Configuration

The issues highlighted in the background indicate that configuration should be:

  • intuitive
  • compiled to ensure its validity
  • managed similar to code (especially in encapsulation and modularising)
  • understood by non-technical individuals

Of these issues the one most emphasising the need for graphical configuration is the ability for non-technical individuals to understand the configuration. Having the configuration graphical means that it will be much easier to understand than pages of text. Development teams even use graphical representations (eg design/architecture diagrams) that illustrate the functionality of an application and enable clear discussion. Furthermore, spotting errors in digrams is much easier than trying to spot errors in, for example, XML files.

Graphical configuration also addresses the other issues above. Developers intuitively get further with graphical editors than they would with text editors. Graphical configuration would also require modularising and encapsulating the configuration so that these modules can be graphically connected together.

Graphical configuration would be required to represent the underlying model in the configuration and make this available in the graphical editors to manipulate. In other words, the configuration can no longer be free text and must subsequently become an object model that graphical tools can edit (the M of MVC).

As the configuration becomes a model, this model can be used as input to a compiler. The model and the connections between the objects in the model can be validated by rules. The model can also be transformed into other represenations. This ability to validate and transform the model is similar to compilers validating source code and translating it into machine/byte code.

In compiling the model it enables the model to be modularised and encapsulated which results in types. As the model is now being compiled it is possible to use this compilation to validate the connection between separate pieces of configuration. To enable this validation each piece of configuration is compiled into a type that can then be validated against the other connected configuration types. As the types need only specify certain information about the configuration, this enables encapsulation of the configuration.

Having graphical editors that configure models that can be compiled into types leaves two questions open:

  • What is the model?
  • What are these types?

OfficeFloor answers these questions by using a Job Based Architecture. The Job Based Architecture defines an application as a listing of Jobs that are executed by Teams with each of these Jobs requiring object dependencies. From this architecture, the model can be extracted and subsequently the types can be derived:

  • Jobs which have inputs, outputs and object depenendencies (the information about the inputs, outputs and type of object dependencies required constitute the Job's type)
  • Teams that execute the Jobs (Teams can be implemented many ways but have a similar type - they are assigned Jobs to complete)
  • Object dependencies (the type of object defines its type)

This underlying model in the Job Based Architecture provides the information for typing and subsequently compiling. As the parts of the model can be compiled into types, graphical editors can then represent each part based on their types. These parts can then be connected together by the graphical editor.

OfficeCompiler introduces additional types (SectionSource, OfficeSource, OfficeFloorSource) that focus on organise configuration into managable fragments. As these only expose the fragment's public information, this provides the modularising and encapsulation of configuration. The actual content of the model compiled into the type is not required by the graphical editor as the graphical editor only requires the public interface of the type to connect it to other types. Using only types in the graphical editors achieves the following:

  • The underlying models for these types are free to be implemented as required (as long as they contain the necessary information to be compiled into a type).
  • The details of these models do not clutter the graphical editor making it easier for the developer to obtain an overview of the information.
  • With an explanation of each type that may be used, a non-technical individual should be able to follow the meaning of the graphical configuration and provide feedback on its correctness in terms of application requirements.

The flexibility of the graphical editor only using types means that these graphical editors can even import non-graphical configuration (with the caveate that a Source is written to compile the configuration into a type).

OfficeFloor provides the Graphical Configuration of its Job Based Architecture to enable developers to be more productive.