Lets do a quick recap. We looked at CBSE, explored the benefits of CBSE, defined components, physical component and logical component. With this, I believe we are ready to go for the kill - How to identify components ?
We have classified components as 'logical' and 'physical'. Therefore we need to identify both in software architecture. Lets start with 'logical' components as they are the 'first-cut' components.
Although it sounds simple, it is not. Software Architecture happens during the initial stages of the project, when, seldom complete requirements are available. In fact all you have is a list of high level features/functionality and not to forget another list of desirable non functional requirements such as performance, usability, extensibility, portability etc. Lastly lets not ignore the constraints imposed by external factors such as technology, management etc. An architect needs to take all of these into consideration while arriving at solution.
Expanding upon the above statement, to identify the logical components of the system, I would recommend the following process -- Divide the entire system as a set of functions ( not algorithms). Each and every function should provide a well defined & unique user functionality that is not provided by any other.
- Ensure that function should have a well defined boundary.
- Decompose further considering other non functional aspects such as performance, usability, technology, standards etc. to refine the function(s) into component(s). Yeah! this is lot of work and tricky as well.
- For each component so identified, define an interface.
- Finally, validate that it fits well with the other components.
Perhaps an Example would help. Consider a Real time Data Acquisition and Control system for a device connected to the serial port. Lets further assume that the data needs to be displayed on screen as well as recorded to a file. I can see 4 basic functions(and a good starting point) -
- Data Acquisition
- Control
- Display
- Record
Now lets look at Control - A close look reveals that 'Control' involves writing Data to the serial interface. So we need a Data Writer as well. The following figure depicts what we have compiled so far without interfaces.
Continuing with the refinement process..
Since Read & Write services complement each other, I think it makes sense to make it a single component and of course give a suitable name. This is what it all looks like along with the interfaces. Note that there is scope of further refinement, depending upon the requirements as well as application of other architectural styles.
Now having explored an example, let me clarify what did I mean by transformation of logical components. Taking the example above, Data acquisition got transformed (rather morphed) into 2 components - "Device Read/Write services" and "Data Publisher". In other words, a logical component at a higher level of abstraction gets transformed into one or more logical components ( that is closer to implementation) at a lower level of abstraction.
As mentioned before, it does not stop here. For e.g. If the development is done using .NET, then DataSet and DataGrid(for ScreenView) could be chosen for data representation and display. This will lead to further decomposition (perhaps the publisher is no longer required in the ScreenView as DataSet and DataGrid bind well).
Component Identification CheckList - Here is a list of guidelines that can be used to validate the credibility of the logical component. If all of these are positive for a component, then its a good abstraction of a component.
- Functional Cohesion - The component must fulfill a single goal completely.
- Well defined Boundary - Simple and well defined interface.
- Replaceable - Consider change scenarios that could occur in future and ensure that changes are isolated as components.
- Re-usability - Can it be reused as is? Are there portions that hinder reuse? If so, then there is a need for further decomposition.
That brings us to the end of Logical Component Identification.
I m not going to stress much on physical component identification as it is basically how you package the functionality.Taking the example above, all of the logical component may be packaged into a single executable ( if the deployment dictates that there be no files other than a single executable! ). Alternatively, it makes sense to package the UI components into one package and retain the non UI components (such as DataLogger) as separate DLL(s). Another option is to package the Publisher along with the Device Read/Write services. I leave it open. Although, the best option (unless otherwise constrained by something else) is to leave each of the component as a separate physical component.
This brings to the conclusion of my first technical topic and I would be glad to know what you think of it. I personally feel that i ran through some of the stages. If you want to know in detail or have trouble understanding some of the portions above, i would be more than glad to help.
I m not going to stress much on physical component identification as it is basically how you package the functionality.Taking the example above, all of the logical component may be packaged into a single executable ( if the deployment dictates that there be no files other than a single executable! ). Alternatively, it makes sense to package the UI components into one package and retain the non UI components (such as DataLogger) as separate DLL(s). Another option is to package the Publisher along with the Device Read/Write services. I leave it open. Although, the best option (unless otherwise constrained by something else) is to leave each of the component as a separate physical component.
This brings to the conclusion of my first technical topic and I would be glad to know what you think of it. I personally feel that i ran through some of the stages. If you want to know in detail or have trouble understanding some of the portions above, i would be more than glad to help.