Preface
The
What is better? Smarter programmers or safer programming environments?
is the impetus for this article. After I stuck my foot in it
(again), saying that .NET and MFC are not frameworks, Paul Watson asked
one of the two obvious questions--"what is a framework?" (the other
obvious question being, "If .NET and MFC are not frameworks, then what
are they?") Well, Paul's question is an excellent one (and the better
of the two, I think), and it led me down this road in an attempt to put
my money where my mouth is, as it were. So, here goes. I'd like to
hear your opinions as to whether you agree or disagree with my analysis,
what areas you'd like to have explored in further detail, and whether
you think this fits in your own experiences. I've tried to keep this
article brief (isn't that a welcome change?), and I'll leave it to the
reader responses to determine if there's anything that needs
elaboration.
Introduction
From my perspective, a framework does several things:
- it makes it easier to work with complex technologies
- it ties together a bunch of discrete objects/components into something more useful
- it forces the team (or just me) to implement code in a way that
promotes consistent coding, fewer bugs, and more flexible applications
- everyone can easily test and debug the code, even code that they didn't write
If I look at this list of vague framework requirements, I come up
with a set of specific classifications that define a framework:
- wrappers. A wrapper:
- simplifies an interface to a technology
- reduces/eliminates repetitive tasks
- increases application flexibility through abstraction
- are often re-usable regardless of high level design considerations
- architectures. An architecture:
- manages a collection of discrete objects
- implements a set of specific design elements
- methodologies: A methodology:
- enforces the adherence to a consistent design approach
- decouples object dependencies
- are often re-usable regardless application requirements
So, before talking about frameworks, we need to talk about wrappers,
architectures, and methodologies. After that, I'm not sure what will be
left to say about frameworks!
A Framework Is...
A Wrapper
A wrapper is way of repackaging a function or set of functions
(related or not) to achieve one or more of the following goals (probably
incomplete):
- Simplification of use
- Consistency in interface
- Enhancement of core functionality
- Collecting discrete processes into a logical association (an object)
It's easy to fall into the idea that everything is a wrapper, just
like saying "everything is relative" (which is untrue, because that
statement itself is an absolute), but if you think about it, not
everything is a wrapper. Most of MFC and .NET are wrappers are the core
API's. Some are laughably so, providing classes that merely wrap
messages into inline methods. Other wrappers are more complex. For
example, I've written a wrapper for the Visio COM object that takes all
the grunt work out of using Visio's primitive functions (primitive in
the sense of "fundamental", as opposed to "poorly implemented") to do
basic things like drop shapes, connect shapes, and read a shape
collection.
But then, you get into implementation that truly provides new
functionality. Yes, it utilizes other objects, other API's, even other
wrappers, but it isn't a wrapper in itself because it does something
totally new, rather than just adding to, subtracting from, or managing a
collection of existing work. A wrapper modifies existing behavior.
There's a lot of code out there that creates new behavior (thus becoming
subject to
An Architecture
An architecture is a style that incorporates specific design
elements. Obviously, a framework needs to have a design. Its
architecture is separate from the collection of wrappers that it
implements and from the enforcement of a specific implementation
methodology. MFC's document-view classes are an architecture.
Essentially, an architecture implements associations between
objects--inheritance, container, proxy, collection, etc. Architectures
have the interesting attribute that, if you don't like them, you can
usually ignore them or replace them (at least at the beginning of a
project). Architectures can and are useful because they create a
re-usable structure (a collection of objects) that provide some enhanced
functionality, but once you start using them, you're pretty much stuck
with them unless you do some major refactoring.
A Methodology
Let's look at this word:
- Method - a way of doing something
- -ology - in a "scientific" manner--designed, consistent, repeatable, testable, proven
or, if you want to look it up in the dictionary:
A body of practices, procedures, and rules used by those who work in a discipline.
OK, we've all worked with design methodologies, but not too many
people have worked with a framework that implements a particular
methodology. I don't think arguing that MFC is a methodology (with
exceptions) is the right way to think about classes. While a class
specifies visibility, interface, and inheritance usage, and these, along
with language syntax, can certainly be classified as "a body of
practices, procedures, and rules", saying that a class or a collection
of classes is a methodology is like saying that a bunch of leaves make a
tree. A methodology fills in the supporting structure. Is MFC's
message mapping implementation a methodology? Mostly, yes. While I
view it primarily as an architecture that wraps the underlying API, and
you don't have to use it if you don't want to, in some cases you pretty
much can't avoid using it, especially when you want to define
specialized message handlers. You have to use the method that MFC
implements in order to specify and override the base class
implementation. And since this is an application wide issue, it fits
better into the definition of a methodology than a wrapper (which it is)
or an architecture (which it is). So, things can be fuzzy, and
sometimes they can feel like splitting hairs, but it doesn't detract
from the value of looking at methodology as a classification.
While architectures deal with the associations between things, a
methodology deals with the interaction between things. The first is a
passive relationship and the second is an activity. Most of the
methodology that I implement is in the activity of communicating between
objects, managing data persistence, responding to user events, etc.
Within those activities are architectures that associate interrelated
objects.
Design Patterns
Design patterns are both architectures and methodologies. The
structural patterns are more architecture, when the creational and
behavioral patterns are more methodologies because their usage enforces a
particular method of interaction. However you implement, say,
behavioral patterns, you're entire application has to adhere to that
implementation. However, I will say this one thing--design patterns are
in a category that I would call "lightweight methodologies". They are
not necessarily heavy handed about how components and objects interact
with each other.
Heavyweight Frameworks
The
Application Automation Layer
that I've written about (you really didn't think I'd write about
frameworks without mentioning the AAL, did you?) is what I'd call a
heavyweight framework. It strictly enforces (to within the reasonable
realm of the possible) component management, data interaction, the usage
of external XML files for GUI definitions, scripting driven functional
programming, etc. Now, you may all say that this is excessive, but I
must disagree. We need frameworks like this to improve quality,
consistency, and usability. Furthermore, a heavyweight framework can
(and has been proven to) allow even junior programmers to be productive
in a large scale development effort with minimal guidance. Why?
Because the framework doesn't provide a lot of room for, well, screwing
up. Even as an experienced programmer, it helps me from screwing up
(for example, taking shortcuts) as well!
Thoughts About Frameworks
Rather Black & White, Isn't It?
At some point, a framework becomes all three simply out of
necessity. You can't implement a methodology without implementing
wrappers and an architecture. Like any other kind of programming,
abstract concepts don't necessarily translate directly into concrete
implementation, and the same is true for the
wrapper-architecture-methodology view. But it's still useful to look at
these two topics separately so that, come implementation time, we can
make better decisions regarding the goals of the framework we are
implementing. For example, the issue of re-use regarding wrapper vs.
architecture vs. methodology is different because the focus of the
re-use is different. For wrappers, the focus of the re-use is the
process, whereas for an architecture, it is the associations between
objects, whereas for a methodology, the focus of the re-use is in the
interactions between objects.
Why Should A Framework Enforce A Methodology?
Well, I wanted to avoid analogies to architecture and buildings, but
this seems like such a good place for one, but, I'm sure you can figure
out the rest of what I can say! So why say it? Well, sometimes it's
important to pour a thought down on paper so it becomes a bit more
concrete (no pun intended). If you only have wrappers, your team (or
just you) is left to build the application in whatever way their
experiences (or lack thereof) have taught them. In the end (if you even
get to the end), you've got a collection of different styles,
approaches, and solutions that have no consistency. This is hard to
debug, hard to maintain, and hard to extend. And you when you're done,
you almost certainly don't want to repeat the experience. A framework
that enforces a methodology, on the other hand, tells each programmer
how to do important things like interface with other
objects/components/technologies, how to manage and persist data, and how
to avoid crossing application layers (as examples). The resulting
application is easy to debug, easy to maintain, and very flexible.
Code Reviews
Code reviews are fine, but they're misapplied if you use them to fix
coding consistency issues. It's like health--you want to be proactive
in preventing disease (dis-ease, ha ha ha), rather than taking a handful
of pills after you get sick. So, code reviews should be used to
prevent sickness rather than to cure a sick implementation. This means,
a code review should always look at whether the framework methodology
is being applied properly, is itself appropriate, and that the code is,
in other ways, handling its requirements correctly.
Unit Testing
If your methodology includes unit testing (and thus a framework to
support this methodology), the issue of meeting requirements becomes
preventative--the unit tests prevent the code from becoming sick in the
first place. However, unit tests can be a lot like the new age idea of
using magnets to cure arthritis--they can be quite useless. And I'm not
going to write about good unit tests here--you can read my articles on
unit testing if you're interested.
Agile Methods
OK, touchy subject with very opinionated people in all camps. So,
I'm going to skirt around the issue and say only that agile methods talk
about how to manage a project more than they talk about how to design
the objects or implement the actual code. This is why they're not much
help, in my opinion. What I've found is that just about every job,
customer, or article requires a unique approach. There is no
cookie-cutter method for working with a customer, figuring out what the
application needs to do, and managing the process of implementation.
There is, however, considerable re-use achievable in how each
application is designed, and the framework and wrappers that are used to
reduce implementation time. Agile methods on the other hand are really
good as ideas you can use to work with the customer or other people in
the company.
What About Creativity?
This argument (which, believe it or not, I've heard many times) holds
no water for me. A two year old can be creative with paint and a
canvas, but you won't get the Mona Lisa. An trained artist uses a
method which allows him to channel his creative forces into creating his
work within the confines of the chosen method. Even Jackson Pollock
had a method to his paintings, although they do look a bit like what a
two year old would do. The point is, a good methodology actually frees
you from the mundane task of figuring out basic things, so you can apply
your creativity in better user interface design, better performing
functions, smoother user experience by using threads, etc. The result
is something aesthetically pleasing to the user. As a programmer, I can
immediately tell you when a product did not have a good framework
methodology because it is clunky, clumsy, rough in performance, and most
likely, buggy (and the biggest indicator of all--it got delivered a
year later than promised). Are you listening, Microsoft?
An Example: The Document-View Architecture
What would it take for the document-view architecture to be a true
framework? In my opinion, this would require an automatic coupling
between GUI controls and the document. The programmer need only specify
issues such as data lifetime, the control representing the data, and
the document (or documents!) containing the data. The framework would
then handle all persistence issues, data translation between the
representation of data in the document and the representation of the
data in the view, and would do so without requiring any coding. A
document-view implementation at this level wraps data translation,
provides an architecture for coupling data with documents, and enforces a
methodology by implementing and hiding the coupling between the GUI
control and the document.
What Does The Rest Of The World Say?
A framework is a set of common and prefabricated software building
blocks that programmers can use, extend or customize for specific
computing solutions. With frameworks developers do not have to start
from scratch each time they write an application. Frameworks are built
from collection of objects so both the design and code of the framework
may be reused. - JavaFramework.
That sounds like an architecture and a collection of wrappers. OK, 2 out of 3.
A skeleton of an application into which developers plug in their code and provides most of the common functionality. -- E. Gamma, et al., "Design Patterns", Addison-Wesley, 1995
Well, now that's a radically different definition, and in my thinking
certainly incorporates the idea of a methodology, if for no other
reason than because the "skeleton" has to define how developers plug in
their code and how they interface with the common functionality provided
by the "skeleton". Implied here (but not necessarily) may also be how
the code intercommunicates.
A set of classes which defines a model of interaction among objects… -- Moduleco (of course, they totally blow it in the additional definitions)
OK, this falls into the category of a methodology because it clearly
enforces the interaction style between objects, but it leaves out the
wrapper and architectural aspects.
- A comprehensive, integrated class library
- An entire architecture is the unit of reuse
- Defines the control logic and class interactions of the application's architecture
- Reduces "dog work" at the cost of some flexibility
--
Software Engineering Associates, Inc
Hmm. OK, that encompasses the three things I'm talking
about--wrappers (integrated class library), architecture (an entire
architecture), and methodology (defines the control logic and class
interactions). Although, this may not exactly be what the authors had
in mind, especially when reading what they think a
design pattern is, but you never know.
So far, we've seen:
- building blocks
- skeleton
- interaction model
- all of the above (sort of).
Frankly, I'm not sure that there really is a good definition out there. But really, the one I like best is from the authors of
Design Patterns:
"When you use a toolkit, you write the main body of the
application and call the code you want to reuse. When you use a
framework, you reuse the main body and write the code it calls."
"Not only can you build applications faster as a result, but the
applications have similar structures. They are easier to maintain, and
they seem more consistent o their users. On the other hand, you lose
some creative freedom, since many design decisions have been made for
you."
"If applications are hard to design, and toolkits are harder, then
frameworks are hardest of all. ...Any substantive change to the
framework's design would reduce its benefits considerably, since the
framework's main contribution to an application is the architecture it
defines. Therefore it's imperative to design the framework to be as
flexible and extensible as possible."
This doesn't formally spell out the idea of a framework consisting of
wrappers, architecture, and methodology, but it's certainly all there,
between the lines. And it provides a different definition for what most
of MFC and .NET really are--toolkits, not frameworks. Which is the
answer to the other question--what are MFC and .NET if not frameworks?
Conclusion
By thinking about what a framework is, I think I've come up with a
fairly good analysis of the subject as an introductory topic. Maybe
what I'm talking about is something different from a framework, but in
my mind, this is what a framework should be and do. There are a lot of
different ideas out there as to what a framework is, so now you have
mine as well.