For the last couple of decades, major software gurus are predicting that the future of software development is component-based software, as an evolution of object-oriented software.
By “component-based”, I mean using third-party object-oriented libraries by instantiating objects whose classes are declared in those libraries, without necessarily inheriting from those classes. Inheritance is seen as an advanced option to extend the features of an already rather complete object.
This kind of component-based software has had a rather good success for some styles of software. For example software built using RAD tools (like Visual Basic or Delphi), and software using the Microsoft COM model.
Large software systems are often not based on components, because many component-based implementations have many liabilities. Let’s see them.
The most notorious one is the one nicknamed “DLL hell”. It is the dependency problem of having several executable modules, and not updating all of them at the same time.
Another problem is the “monster class problem”. If a single class must provide all the feature that a client may need, it must include a huge number of features. For example in the Microsoft .NET Framework, there is the Windows.Forms subsystem that is a (large) GUI library, and it contains the DataGridView class to implement a widget to display and edit a scrollable table of items, that may be bound to an external collection or to a database.
This class has 1 public constructor, 153 public properties, 20 protected properties, 87 public methods, 287 protected methods, 187 public events. In all, there are 428 public members and 307 protected members. The nice thing of object-oriented programming, is that client code programmers can ignore the implementation of members; they just need to know the interface of members. But learning an interface composed of 428 members is a huge job! And that is just for those who want to instantiate that class. For those who want to inherit from that class, the members to know become 735.
Actually most users of that class don’t know actually all the members, but stick to the members they really need. But that amounts to bad programming, as you lose time to find the member you need, and often choose the wrong member.
I think that to be really usable, a class should not have more than few dozens of members. And the Windows.Forms DataGridView class exceeds that limit by a factor of ten.
Anyway, everyone of those hundreds of members have been added for a purpose, and for every member some programmers may need just that member, so it is difficult to remove unneeded members.
A better solution is the following.
Most programming shops (software houses or software development departments) use several times a single library component. Maybe they build a large application with several instances of that component, or they build several similar small applications, each one of them using that component one or more times.
Typically all the instances of a single component as used by a single programming shop use or should use no more than a few dozen members of that component.
Even more typically, all the instances of a single component, as used by a single programming shop, set or should set many properties at the same value. For example, a user-interface component has a Font property, that has a default value; in that programming shop, that component is always used or should always used with another font.
Another common case is that a property of component, as used by a single programming shop, has for 90% of cases the same value, that is different from the default one, and in the other 5% of cases, it has other values. Simply using the component, programmers are forced to specify the value for every instance.
Here a solution for all these cases is presented.
A new custom component is built by the programming shop. That component is just a simplified and specialized version of the library component. It is simplified as it publishes only a small fraction of the members published by the original class. It is specialized as it has default values different from those of the original class.
Of course, to ease the implementation, this new class contains the old class, and therefore it is just a façade to it. It shouldn’t public inheritance, as its instances shouldn’t be seen by the clients as instances of the original class.
To specify proper default values has two advantages:
* It is easier to develop a consistent look-and-feel.
* Less application code (or manual property setting) is necessary.
To have fewer members has two advantages:
* For programmers, it is easier to learn how to use that class in their code and to understand the code of other programmers that use that class.
* For programmers, it is easier to write correct programs, as fewer properties may have wrong values.
The simplification may be a restructuring of the members, not just an elimination. For example, instead of simply removing the BackColor and ForeColor properties, an enumeration of color styles may be substituted to them.
The simplification may be also an agglomeration of widgets. For example, instead of using separately a Label and an EditBox, a single EditField may contain both features.
I think that many people would think: “But there are already zillions of beautiful custom components!”
What I really think, is that no given set of components may satisfy all needs, and therefore every programming shop should implement their own set of components.
How is designed a component?
First, a toy application (or set of applications) containing all uses cases for the needed component should be built. Then, a component having only the members needed by that toy application should be built and used by that application. Then, the component should be used in real projects.
When a shortcoming of the component is encountered, it should attentively determined which is the case among the following ones:
- The application is not really standard conforming, and therefore it should be changed, without changing the component.
- The component is not powerful enough to support the standard guidelines, and therefore it should be fixed or extended. If the a component feature already used by some installed applications is to be changed, it is possible that a new incompatible version of the component is generated, and therefore a migration guide or a migration tool is required.
- The standard guidelines are not flexible enough to support application requirements. A change in the guideline may result in a non-conformity of existing applications or components; in such cases, the previous two cases apply consequently.
Using this technique, the components begin as really minimal, and grow as applications require more features, but hopefully, remaining much simpler than the monstre components contained in libraries created by other organizations.