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.