Singular Focus and Coupling
This will be the first installment of a multiple part
posting on object design principles.
These are vital to keep in mind as we go through creation of large
product platforms with many interaction services and objects that must be
maintained and enhanced over time.
Object Responsibility
In my mind, the most vital question you can ask yourself at
the outset of an object design is, "What is this object's core
responsibility?" Your entire design
should flow from that very basic question. You should consistently look for the
most granular object definition possible and work back from that. It's really easy to get blinded by the
vastness of the entire project and the complete set of user stories and
completely misjudge where to segregate your logic. Once you have defined the core responsibility
and focus of an object, you can immediately start creating an inheritance path
as well as supplemental interfaces to bring your object into full
functionality. This is the most vital
step in ensuring a scalable and easily maintainable system long term. Consider the following basic user
requirement: "I need to be able to
view images and apply enhancements to them." The first thing that comes to my mind is that
although the user requirement is to always view images, every image view
session will not ultimately result in an image enhancement session. So, I immediately break into two objects, a
viewer and an editor : viewer. At its
core, the viewer object should do nothing more than accept image data and
render in a viewable state. The viewer should have no concept of any data or
state outside of the image itself. It
should interact via an interface with a standardized image format so that it
doesn't need to have any system context.
The system also should have no specific knowledge of the viewer (more on that when we talk about coupling). Then, the editor class should start by extending the known viewer class. It should not extend any operation that pertains to the loading and displaying of the base image. That aspect of responsibility should be a black box to the editor. The editor should contain an interface for advertising its list of manipulations as well as a standardized message based interface for executing them. This object is not responsible for a menu or toolbar system, it is simply an image manipulator requiring system input to launch an execution of its internally known action. It also would not have any context for displaying an image history listing. It would maintain a list of events, based on its internally known list of manipulations and allow an outside source to interact with that list via a standardized message or interface.
The system also should have no specific knowledge of the viewer (more on that when we talk about coupling). Then, the editor class should start by extending the known viewer class. It should not extend any operation that pertains to the loading and displaying of the base image. That aspect of responsibility should be a black box to the editor. The editor should contain an interface for advertising its list of manipulations as well as a standardized message based interface for executing them. This object is not responsible for a menu or toolbar system, it is simply an image manipulator requiring system input to launch an execution of its internally known action. It also would not have any context for displaying an image history listing. It would maintain a list of events, based on its internally known list of manipulations and allow an outside source to interact with that list via a standardized message or interface.
Loosely Coupled Objects
The main point of the granularity of the design listed above
is to ensure a loosely coupled framework.
These controls and objects should all be interacted with via their
interface over standardized messages. If
each object is singularly purposed and has a black box for its implementation,
the only exposure and ultimate point for breakdown is the interface itself. The loosely coupled system (or systems)
interacts with itself based on standard messages or interfaces. The
granularity, once released to production, allows for a dynamically upgradeable
system with hot swap components. In this
scenario, we could easily swap out our image viewer or image editor in any
given system with a very limited impact on the system as a whole. The change would be contained in a singularly
purposed object that is loosely coupled with its housing system. We would be able to quickly respond to a requirement for viewing a new image format without having to make changes to our image editor control. Additionally, this transforms every control,
service or object in every system into a plausible enterprise level base class by
never assuming product knowledge or any aspect of external state.
By thoroughly investigating singular focus and coupling as part of every design, we can work toward a much more stable and dynamic system in the future.