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.