Previous posts in the Factory 201 series:
We have seen what a factory is in concrete terms, we have seen what conditions warrant the pursuit of building a software factory for a specific domain, and some of the value proposition, considerations and costs associated with that decision. So far we have painted a pretty good picture of the context within which factory development should get started.
This is the first of several posts discussing the actual implementation of a factory. Now, "What would you build?”
We want to have a look conceptually at the types of things that you want to do to automate the assembly of our product, and how those things map to types of automation assets you can use to make your factory.
Building a factory is a progressive and iterative process. We can have a look at the steps in that process in more detail in a future post called "How would you build it?" but for the time being, it should be emphasised that building a factory is not an 'all or nothing effort' and certainly not an 'all upfront effort' where you meticulously plan the entire factory before getting started on building it. Although a popular myth, the 'big-bang' expectations of analysing and engineering a fully-blown factory in the first development iteration is simply not realistic - and not highly recommended as a successful approach.
What is called for is a more progressive, iterative development approach from initial product-based assets (ideally a reference implementation) and then gradual analysis, refactoring and application of automation to these initial assets. Each development iteration commits the factory builder to increasing levels of automation and automation asset creation, but also in each iteration, yielding a completed product from the factory.
[I wanted to use the word ‘agile’ in the previous paragraph to describe the iterative, progressive approach to building a factory. But in my experience, when people say the word agile, it tends to get misinterpreted to meaning agile development practices such as extreme programming and test driven development etc. That is not the intended meaning here at all. The intended meaning is agile development; i.e. developing software in iterations of short periods of time, releasing increments of new functionality. The development practices used to achieve that are not relevant for the purposes of this argument]
You have to keep in mind that a factory is a tool, and because it is a tool, it is in fact a development project in itself. You can expect many versions of your factory, and each release to have ever increasing functionality, and more reusable automation assets. Conversely perhaps, you can imagine that the product the factory creates will remain relatively the same (with respect to scope). All that will really change is the variation in the products the factory creates and the form of the product assets. That is, your product line grows to suit the scenarios you want to address.
At some point you'll have to determine how far to go in moving from building a specific solution (reference implementation) to a fully automated tool (software factory) for building general solutions to your particular domain – a product. How far you go will be determined largely by the scenarios you'll want to address for the products you are creating; i.e. how much variability you want to automate, the level of usability you want to offer, the productivity you want to gain, and of course, realistically, how much resource you can commit in the construction of the factory.
So let’s have a look at some examples of the sorts of things you would want to do to automate the assembly of your products.
Generalise the Solution - in the simplest case you may just decide to generalise and refactor an existing solution (a reference implementation), identifying the variable parts and refactoring the invariable parts in preparation for automation. The common parts of this commonality/variability analysis might simply be a set of class libraries or ideally a framework tailored specifically to this domain, which will be delivered as part of the product from the factory. The variable parts will be configured by the factory user whilst using the factory and the patterns for those parts may also be harvested for automation at this stage, resulting in patterns, code templates or perhaps a description or meta-model of those variable parts. Your framework won't be highly generalised just yet because you might not know of many concrete scenarios to accommodate yet, but this is typically the first step. One could argue that this is indeed the minimal pre-requisite step before the application of automation. Many mature frameworks have already performed this generalisation and refactoring many times over and so those are most ideal to start with.
Define a Solution Structure – more than likely you will want to offer the user of your factory some guidance about what artefacts make up the product and how those artefacts are physically related for deployment purposes. Not only might you want to structure the physical product in the artefacts that represent it (i.e. projects, files, solution folders etc.), you will probably also want to make suggestions about the naming of those artefacts and possibly how they are namespaced by default. Your factory will be adding a specific set of artefacts and structure to represent each component of the product. Handling structure, name and namespace changes to artefacts could also be handled automatically by the factory.
Automate a Development/Design Task - you may want to automate a development or design task. These would typically be mundane tasks that need to be performed throughout the life cycle of the product you are building. The objective being either to remove mundane and manual processes, and/or increase the chance that the task is executed predictably, accurately and completely. Examples may include, changing the name of an artefact or class, namespace, running build commands, automating configuration tools, completing development processes etc.
Generate Artefacts or Configure a System - at some point in some factories you'll want to generate some artefacts or configure some other system. Generation of artefacts is not restricted to source code generation; it could just as well be generating configuration files, XML files, database records, intermediary data, documents etc. You may also want to configure another system (i.e. web server, or collaboration platform) as part of the product. Typically, what is generated or configured will be determined and controlled by the factory user's configuration by some means of interacting with the factory. Sometimes, this configuration is persisted by the factory (domain models), other times it is requested at generation time from the user or environment.
Model a Pattern, Process or Architecture - you may decide to model an architecture, process or pattern to simplify the problem domain and focus only upon the variable parts of it. You may also want to be explicit about a process or pattern to aid the user in designing the solution. For this you would typically create a domain model for either the whole or part of the solution. Typically, these models require associated editors or views (windows) with which the factory user can interact with them.
Now that we know the sorts of things we want to do, let’s have a look at the types of automation assets we need to create our factory.
[Incidentally, each one of these assets requires an increasingly higher cost and larger commitment to automation level provided by the factory]
Solution or Project Templates – probably the first step to automating the construction of the product is to place the reference implementation or its non-variable parts in solution or project templates for easy installation to the developer’s environment. The templates provide the physical structure and naming for the artefacts of the product. Templates can also be easily used to add parts of the product as they are required by the factory user. Supplementing this mechanism with a means to define the specific naming of the artefacts (and various parts of their content) would very quickly gain productivity in the assembly of the physical product.
Artefact Templates – (code templates) these are often the result of refactoring and generalising an actual reference implementation, where it is pretty easy to see what parts of solution artefacts (i.e. source code) of the reference implementations vary and therefore needs to be provided by the factory user. Artefact templates are easily built and customized to suit specific naming and formatting practices. Furthermore, they are easily deployable in the solution or project templates and their content could be initialised by the mechanism that drives that.
Automated Action - there are many actions required to be performed in the assembly of any given product, and many of these can be automated to some degree. Some of these actions will require specific context and configuration, and this can either be gathered from the environment, the factory runtime, the state of the current product, or the user can be prompted to provide that context and state, using abstractions like wizards and models etc. Automated actions can be combined with templates to supplement the initialisation of the artefacts created.
Domain Specific Language – in some cases it’s beneficial to provide useful abstraction using a tailored, specific language to describe a part of the product you are automating – a specific domain. A custom language will define a logical domain model of that part and expose a meta-model which describes the configuration of the variability of those parts. Typically, there would be at least one view (representation) of that domain model with which the user manipulates the underlying domain model. In some cases there may be multiple views each manipulating a different aspect of the same model, or multiple models concerned with different aspects. These views maybe visual (diagram) or textual like a programming language, and typically the artefacts of the product parts are generated using automated actions, and artefact templates. Domain models are ideal for maintaining the state of a product and the basis of mapping from one abstraction to another, be that source artefacts or other domain models.
Integrated Logical Design Experience - if desirable, further automation and contextual guidance can achieved by defining an entire integrated logical design experience that the factory can use to control the entire state and automation of a whole product. Creating domain specific languages and automated actions are typically applicable to only parts of a product, and the factory user is relied upon to compose the final product according to some understanding of its overall architecture. By creating a domain model of the entire logical architecture of the product and providing views of that tailored to various aspects of its assembly, an enormous amount of productivity and quality can be achieved with this high level of automation. In such cases, the factory requires a much larger degree of integration and control of the product, and the abstractions it defines and generation of its physical parts. In most cases this requires a runtime to manage the processes of assembly, and invoke automated actions at appropriate times to orchestrate the construction of the product. In some cases, providing such a comprehensive, integrated design experience may require additional extensibility to allow other factories to provide the necessary parts, so the factory does not become too inflexible to variation, and over complicated.
In this post we have had a look at the conceptual types of things that we want to do to automate the assembly of our product for our factory. We have then had a look at what kinds of automation assets we would require to do that and how they are expected to work logically.
In the next post (“With what would you build it?”), we can see how the automation assets are provided by current tools and technologies, understand the terminology they use, and how to use them to create our automation assets.