Assuming that the philosophy of Non-Virtual Interface (NVI) idiom is strictly adhered I came up with a table that summarizes the design intent in terms of access modifiers and virtuality. Strict adherence of NVI allows separation of the interface of a class into two distinct interfaces: client interface (public non-virtual) and subclass interface (protected virtual/non-virtual). Such a structure helps mitigate the Fragile Base Class (FBC) Interface problem if discipline is followed. Its only downside is a little bit of code bloat. More about this approach of resolving FBC can be found here.
The structure of NVI is similar to the Thread-safe Interface pattern. The purpose of public methods in thread-safe interface is to acquire lock and let the helper functions do the real job without worrying about locking. In NVI, the public non-virtual methods do a simple job of dynamic dispatching of protected virtual helper functions.
non-virtual | virtual but not pure | pure virtual without body | pure virtual with body | |
Public | Clients expect substitutability. Extension points are encapsulated. Subclasses should stay away from this if an equivalent protected function using NVI is given. | Clients expect substitutability. Extension points are visible. Subclasses can optionally extend them but assuming NVI is place, subclasses should not reuse it. | Substitutability is mandatory as base class itself can't be instantiated. | Substitutability is mandatory as base class itself can't be instantiated. Subclasses should call the method in the base. e.g., destructor. |
Protected | For the purpose of reuse only by subclasses. An interface for subclasses. Beware of the Fragile Base Class (FBC) interface problem. | An optional extension point for subclasses. FBC applies here. | A mandatory extension point for subclasses | A mandatory extension point for subclasses and it should call the method in the base. e.g., destructor. |
Private | Clients as well as subclasses have to live with it. Like final keyword in Java. Not for reuse. Top secret of a class. | If you happen to know the secret, it is not for (re)use but you can risk extending it. Don't scream if the the treasure evaporates tomorrow. | If you happen to know the secret, it is not for (re)use but you must risk extending it! Surprises for tomorrow if base is updated. | Ditto as for pure virtual without body |
The structure of NVI is similar to the Thread-safe Interface pattern. The purpose of public methods in thread-safe interface is to acquire lock and let the helper functions do the real job without worrying about locking. In NVI, the public non-virtual methods do a simple job of dynamic dispatching of protected virtual helper functions.
Comments