Framework Best Practices

9/29/99 - Jack Harich - In progress, incomplete


These are not required, but tend to appear in the better frameworks. They have overlap.

Avoid Inheritance - Many early framework approaches emphasized inheritance, especially as OO rose to prominance. For example the "Design Patterns" book, 1995, on page 360 uses this definition of a framework:

"A framework is a set of cooperating classes that make up a reusable design for a specific class of software. A framework provides architectural guidance by partitioning the design into abstract classes and defining their responsibilities and collaborations. A developer customizes a framework to a particular application by subclassing and composing instances of framework classes."

Recall that inheritance is very tight coupling. The main problem with inheritance as a chief reuse mechanism is the Fragile Base Class Problem. A change in a base class (aka superclass) can unintentionally wreck havoc in subclasses, because those making the change may not be aware of assumptions made by subclasses. This is a gigantic problem in large inheritance trees and systems build from them. As a system using an inheritance based framework grows larger and older, the Fragile Base Class Problem can drive a developer up the wall and right to a sanitorium, unless they can figure out a better way.

There is a better way. In the early days of OO, the alternatives to inheritance for reuse were not as well refined as they are today. Top alternatives are delegation and designing less responsiblities per class. We also have interfaces as a good reuse coupling mechanism. Interfaces are not nearly as fragile as superclasses because they have no functionality, only a contract specification. Also, interface architectures tend not to have deep, large trees like inheritance architectures. We also have Declarative Knowledge as a powerful form of reuse.

There is a time and a place for inheritance. Just don't over use it.

Domain Breadth - A framework should either handle a specific domain well, or a variety of domains. There's a tradeoff between greater reuse and better behavior for a particular system. This gives rise to a continuum of frameworks running from domain neutral to domain specific. Generally the greater a framework's Domain Breadth (more domain neutral), the more effective it is. However, due to the continuum it is very appropriate for some frameworks to be focused on a single domain.

Ease of Use - The main problem encountered by framework users is the framework is hard to learn, use, modify, etc. They may spend more time scratching their heads, modifying the framework to get it to do something simple, or engaging in workarounds than normal development.

Framework designers must remember that most framework users will NOT be the ones who designed the framework. The users will have an entirely different perspective and expertise level. Thus a framework must be designed from the start for ease of use, such as with good visual tools, simple easily understood architecture, great documentationa and ample examples.

Events - This is a loose coupling pattern (Observer) that allows an anonymous callback. Instead of an object having to take specific action when things occur, it merely notifies its event listeners and then take the action they prefer. A bonus is that events can be multicast and filtered.

Flexibility - This measures how applyable a framwork is to the problem at hand. Can it solve just a few problems, such as those in its first use, or can it solve many, including the unexpected? Flexibility is hard to design in. A few things that help greatly are Simplicity, Interface Based, Parameter Driven, Loose Coupling, Events and most of all, "good design".

Independent Extensibility - xxx??? <-----<<<

Interface Based - An interfaced based framework has everything it exposes defined with interfaces, including objects passed though those interfaces. This allows:

  1. Varying the framework to fit the application.
  2. Different parties to offer different implementations.
  3. Designing to interfaces instead of implementations.
  4. A framework to age more gracefully.

Hide Framework Internals - Some frameworks suffer from exposing their internals, when they should only reveal an impenetratable external interface. For example a part may use a framework service (external use), fit in a plugpoint (external use), call a framework library that is also used by the framework itself (external and internal) or cleverly navigate deep within the framework to use something that shouldn't have been exposed (internal use). This is a mess. Frameworks should not expose their internals, because unwanted dependencies will develop, breaking systems when the framework tries to evolve.

As you can see, this is a gray area - What about that shared library? One solution is the framework has its own library. Another is the library is interface based.

What about parts that need to fiddle with the framework itself? This should be done with additional interfaces that are not used by most parts. Examples are Visual Tools and dynamic framework behavior.

Interface Based - This occurs when all exposed objects in a framework are interfaces, including objects passed through those interfaces. The advantage is an Interface Based framework is very customiziable, because an interface is a simple type of plugpoint.

Layered Architecture - This is explained in an earlier writeup.

Management of Complexity - Such as tree so a container behaves as a leaf as far as the rest of the system is concerned.

Minimal Core -

Modifyability -

Pattern Use -

Scalability -

Self Referential - Such as DK can use itself, like DTDs, or systems can build themselves from primordial matter.

Simplicity -

Solid Architecture -

Standards Use -