Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Model-View-Controller versus Document/View

3 views
Skip to first unread message

de...@stingray.com

unread,
May 7, 1998, 3:00:00 AM5/7/98
to

In my first post, people spoke more about gcc, emacs etc. than the topic of my
post: MVC. Apparently, people interpreted me to say emacs, Gnu and freeware
in general were a bad thing. Certainly not my intention, but if you felt it
was, my appologies. Hopefully, the discussion doesn't have to focus on this
any longer.

Still, several stated that they wanted a more detailed comparison of
Document/View versus MVC. So, here it is. If you are one of those people who
wanted this comparison, read on.

But first, I work at Stingray <g>, and I wrote this implemention of MVC. I
hope people find it useful and a better way to architect GUI applications.
Second, I think free software is a wonderful thing when you can find something
that solves your particular problem!

For more information on MVC go to http://www.stingray.com/otpmfc and download
the whitepaper.

---------

The Model-View-Controller (MVC) Framework

Some of the more complex challenges facing MFC developers are the shortcomings
of the MFC's document/view architecture. While the MFC document/view
architecture provides many benefits to developers of small- to medium-size
applications, its limitations become apparent when it is used in large,
complex applications. To help overcome these problems,Objective Toolkit PRO
provides support for an object-oriented framework called the
model-view-controller (MVC) architecture. The goal of MVC is to make it easy
to create highly reusable, easily extensible objects by dividing the
functionality of an application into three logical categories: document (or
model) classes, view classes, and command handling (or controller) classes.
While this architecture represents a paradigm shift from the two class
types—documents and views—used in traditional MFC applications, its
implementation is simple and elegant. We think you’ll find that the MVC
framework makes it much easier to create large-scale applications.
Furthermore, because our implementation of MVC coexists peacefully with MFC
and the document/view architecture, you’ll still be able to draw from the rich
user interface features provided by MFC and the
Objective Toolkit classes.

Introduction

MVC is an object-oriented framework that provides a clear and concise
definition for how to construct reusable and extensible graphical user
interface parts. Despite its lack of wide spread use, the
model-view-controller architecture is not a new concept. It was invented—
along with the graphical user interface and the concept of object oriented
programming—about twenty years ago by researchers at the Xerox Palo Alto
Research Center (PARC). The culmination of that research was the Smalltalk
language and its multi-windowed, highly interactive Smalltalk-80
interface. Amazingly, both of these inventions are revolutionary, even by
today’s standards.

To some degree, nearly ever user interface developed in the last two decades
has been an adaptation of the work done at Xerox PARC. Indeed, MVC has been
partially reproduced in many other development environments. In fact, the MFC
document/view architecture is an adaptation of the concepts introduced by the
MVC paradigm. However, it can be argued that the key purpose of MVC, reuse,
was lost in the adaptation. While Document/View is based on the very sound
design principle of separation of data from presentation, its implementation
of this ideal compromises reuse, modularity and scalability. This article
will illustrate that many of the drawbacks and limitations of the
Document/View architecture can be resolved by simply adapting some of the
forgotten concepts of MVC to MFC. This adaptation will require a
different usage of Document/View than Microsoft instructs, but one which is
better aligned with what those who pioneered the concepts intended.

Why a Document/View Alternative?

Over the last five years, MFC and the document/view architecture (DVA) have
been used in the development of thousands of Windows applications. The
advantage of DVA is that it can be adapted without much difficulty to solve
most of the problems that arise in medium-sized Windows applications. Its
relative simplicity and generality have made it a great foundation for many
Windows applications.

Still, you shouldn’t automatically assume that DVA is the right architecture
for your needs, especially if you are developing large, complex applications.
Despite a proven track record, DVA does fall short in some areas (as described
in the next section). The net effect is a reduced capacity for reuse and an
inherent lack of scalability. Specifically, while DVA works acceptably well
for applications containing two or three CDocument- or CView-derived classes
of small to medium complexity, you might find it somewhat less accommodating
for applications with larger, more complex or more numerous documents and
views. Of course, when DVA was first introduced, C was the programming
language of choice for Windows developers—many of us had never even used C++.
Therefore, one of the primary goals when developing the MFC implementation of
DVA was ease of comprehension, even at the expense of object-orientation and
scalability. At that time, introducing a more complex, albeit more
object-oriented and reuse-friendly, architecture might have made the paradigm
shift in Windows development from C to C++ a bit too harsh. Consequently, DVA
is a relatively thin layer of C++ code on top of the procedural-based Windows
event model.

While DVA works great for the applications like the Visual C++ Scribble
sample, it is somewhat under-powered for large, highly object-oriented
applications. As a result, advanced developers may find DVA to be
limited. Since the development framework you use affects the organization and
structure of your application, your framework has the potential to impact
years of application development and maintenance. No
segment of code should be trusted with such influence without careful
scrutiny. The larger and more complex your project, the more you owe it to
yourself to think twice about basing your application on DVA.
While the document/view architecture may be a well-worn path, if your
application doesn’t fit its profile, you may still find yourself headed in the
wrong direction.

What’s Wrong with Document/View?

If you’ve done any development with MFC, you already know that the Visual C++
Scribble tutorial is widely accepted as the canonical form of a Windows
graphical user interface application using MFC and the
document/view architecture. What you might not know, however, is that the
architecture of the Scribble tutorial is far from exemplary. In fact, at least
one Microsoft technical publication has described Scribble as
the perfect example of how not to structure your graphical user interface
code. The Document/View architecture may be suitable for the Scribble sample,
but consider what would happen in an application a
hundred times as large and functional. Unfortunately, because Scribble is
seen as the Microsoft-recommended model for correct MFC usage, this is exactly
what has happened to many Windows development
efforts. Developers have followed the path prescribed by Scribble, and
consequently their projects have reached a size not supported by the
architecture. So, what are these inherent shortcomings we speak of?
The following sections will attempt to pinpoint them.

The Document/View Architecture is Vague

You might argue that the document/view architecture is not itself responsible
for the problems in the Scribble sample—they might instead simply be due to a
violation of the principle of encapsulation. However,
there are the problems inherent in DVA that tend to encourage this violation.
Chief among them is the fact that it is difficult to separate data from its
visual representation because the concept of application data is
not clearly defined. Thus, it is unclear how DVA is supposed to map onto an
application’s problem domain. For some applications—such as a simple word
processor— the answer seems obvious: an MFC
document represents a user document. But what about applications like
interface builders or graphical tools? The data for such applications might
include colors, fonts, pens, and window bounds, all of which need
to be saved. However, it seems inappropriate to include this information in a
CDocument-derived class because it describes a visual representation of the
underlying data. It is unclear how you would separate the
document and view classes in that scenario. Because DVA is vague and contains
few usage restrictions, it’s easy to make a bad decision as was done in the
Scribble sample.

Document/View’s Monolithic Nature

The document/view architecture takes a monolithic approach to application
decomposition. Since documents and views cannot easily be nested, a DVA
application typically contains large, highly functional
document classes paired with equally large, highly functional view classes. Of
course, it is possible to place one CView-derived class inside another, but
that construct is not specifically supported by the
document/view architecture—you must perform all message forwarding yourself.
Moreover, while it’s certainly not a requirement that CDocument-derived
classes be large and bulky, they often end up that way
because developers add representation information to the document class so
that it can be serialized along with the data. Consequently, DVA is not well
suited to decomposing an application into small building
block classes that can be composed into larger ones. This results in large,
cumbersome classes that complicate the model and make it difficult to divide
an application along functional boundaries. Due to the lack of
modularity and numerous interdependencies inherent in DVA, development teams
usually find it difficult to subdivide a problem and work in parallel. In
fact, the lack of modularity usually requires every team
member to fully comprehend the entire application model. Dependencies like
that translate into reduced team productivity and reduced application
stability.

CViews Are Not Reusable

The CView class is one of the most significant and fundamental building blocks
of any MFC-based application. In fact, MFC programmers often place a majority
of their code in CView-derived classes,
particularly in graphics-intensive applications. The important role of the
CView class leads many MFC developers to assume that Microsoft has architected
this class with due diligence, taking care to ensure that
the class which houses 30-70% of your code is reusable. Such is not the case.
CViews are not reusable. Unfortunately, if you arriving at this realization
late in the development of a large DVA application, you will
pay dearly.

So, why isn’t a CView reusable? Put simply, CViews depend on an
application-specific document type. This dependency renders them unusable in
applications that have a different document type! To illustrate the
point, assume you are developing a set of CView-derived classes that are to be
reused throughout your company. Further, assume that you’ve made the design
decision that your reusable views will adhere to the
document/view architecture. This means that for each view you declare, you
must also create an associated document type that the view understands and
expects whenever and wherever it is used. The
implication is that wherever the reusable view goes, the document must follow.
This is often undesirable because you might want to use the view in an
existing application that has an incompatible document class.

There are a number of imperfect solutions available in this situation. First,
you can simply change the base class of the reusing application’s document
from CDocument to the document type expected by the
reusable view. Of course, this approach will eventually force you to multiply
inherit your document class. Not only is such code difficult to read and
maintain, but MFC discourages multiply inheriting from two
CCmdTarget-derived classes due to complications that can arise. Therefore,
this solution is fragile and ill advised.

Another possibility might be to reach an agreement among all MFC developers in
a company that a common document class will be used. Then all CViews could be
easily exchanged between projects.
Unfortunately, coming to such an agreement—and then maintaining it—would be
difficult or impossible for complex documents. Of course, even if you managed
to agree upon a shared document class, a
document with an interface wide enough to serve all possible view types is
usually an undesirable solution anyway.

Another frequently used solution is to make all data accesses go through
virtual functions rather than directly access the members of a document. By
doing this, you remove the reusable view’s dependency on any
document. However, you are no longer adhering to the document/view
architecture, so it’s not really a solution. In addition, accessing data
through virtual functions, rather than directly from the document, is
certainly not your first instinct based on the example set by Scribble.
Usually, the virtual data access methods are retrofitted after the realization
that CViews are not reusable.

The best solution short of creating an alternative to document/view is to have
the CView do as little as possible. Ideally, it should only contain an
OnUpdate() handler. All of the drawing logic should be contained
within a completely reusable CWnd. The purpose of the CView in this case is to
adapt the reusable CWnd for use within a particular application that defines a
document and updates hints. This solution admits that
CViews are not reusable so no potentially reusable code is placed here. In
this case, the CView acts as an adapter (or wrapper) translating the
weakly-typed messaging protocol defined by the document’s update
hint into calls to a strongly-typed C++ interface defined by the CWnd child of
the CView. One problem with this approach is that you miss some of the chief
CView features, such as the print and print preview
support.

CView/CDialog Incompatibilities

One of the unfortunate limitations of MFC is the incompatibility that exists
between CView and CDialog. Simply stated, MFC disallows the placement of a
CView-derived class inside a dialog. If you are trying to
create a reusable GUI component that can be used inside a frame window or a
dialog, you are forced to confine your design to CWnd-derivation and thus you
must avoid document/view altogether. However, you
can use templates as a work-around for this problem. See the
SECTreeCtrl/TreeView for an example.

OnUpdate Woes

Ironically, the popular UpdateAllViews and OnUpdate notification mechanism is
one of the most unsavory aspects of DVA. It is important to take extreme care
in designing your notification system. Otherwise,
your OnUpdate handlers can easily grow into pages of switch statements and
weakly typed hints that are difficult to read and maintain. In addition,
because this notification mechanism is a weakly typed interface,
coding errors are not caught at compile time. By following Scribble’s lead,
people tend to use notifications at too low a level. In other words, update
hints tend to be numerous and very detail-oriented, leading to
pages of weakly typed checks in the OnUpdate handler.

Moreover, DVA gives you little help in determining how best to use the
notification mechanism. You’re simply passed an opaque pointer to a hint. This
lack of specificity often leads people to embed the API to
their component inside the notification hints to the OnUpdate() handler. To
illustrate the point, consider the following example: suppose you are
developing a Windows Explorer-like application for the display of
hierarchy data. In such a tool, you’d have a splitter window containing a tree
view on the left and a list view on the right. The typical approach to this
type of user interface is to maintain the hierarchy data in a
document that is observed by both tree and list views. The synchronization of
the two panes is accomplished by passing update hints via CView::OnUpdate().
When the document/view architecture and its
OnUpdate mechanism is used with too fine a granularity, you end up with the
interface to a logical control (or widget) embedded in the hints. For example,
you want to avoid code that looks like this:

UpdateAllViews(this, HINT_NODE_EXPANDED, pNode);

A client wishing to cause an expansion of a node may then have to understand
this message passing protocol in order to effect a desired change.

No Separation of Presentation From Control

Roughly speaking, a CView has two responsibilities. First, it must present the
data contained in the document to the user. Second, it must interpret and
react to user input. There are several imposed limitations
here. Both presentation and control come packaged in one class. That means
that you cannot reuse a view’s presentation data without also reusing that
view’s reaction to user input.

Overview of the Model-View-Controller Architecture

The MVC paradigm is a way of breaking an application, or even just a piece of
an application’s interface, into three parts: the model, the view, and the
controller. MVC was originally developed to map the
traditional input, processing, output roles into the GUI realm:

Input --> Processing --> Output
Controller --> Model --> View

The user input, the modeling of the external world, and the visual feedback to
the user are separated and handled by model, viewport and controller objects.
The controller interprets mouse and keyboard inputs
from the user and maps these user actions into commands that are sent to the
model and/or viewport to effect the appropriate change. The model manages one
or more data elements, responds to queries about its
state, and responds to instructions to change state. The viewport manages a
rectangular area of the display and is responsible for presenting data to the
user through a combination of graphics and text.

As stated previously, DVA was derived from MVC. Consequently, many of the
concepts set forth in MVC will be familiar to you. MVC shares the same notion
of separation of data from presentation. However,
MVC gives a clearer, less ambiguous definition of how exactly to accomplish
this separation. Not only does MVC clarify the separation of data, it also
provides an more encompassing and full-featured
architecture. The added scope and specificity of MVC makes it clearer how to
add common pieces to the architecture, such as undo/redo support, scripting
mechanisms, record and playback, and more. So,
without further ado, let’s dive into the MVC concepts and classes!

The MvcModel Class

To a degree, the MvcModel class serves the same purpose as the CDocument
class—to manage information and notify observers when that information
changes. However, there is an important distinction. In
MFC, a CDocument is very prone to becoming a catch all for all sorts of
unrelated information. The justification goes, if it must be saved, it must
live inside a CDocument. So, the document’s design becomes a
function of what needs to be serialized rather than what needs to be
“modeled”. An MVC model is a cleaner abstraction that. It contains only data
and functionality that are related by a common purpose (other
than the need to be serialized). If you need to model two groups of unrelated
data and functionality, you create two separate models.

Another important difference between a model and a CDocument is that a model
encapsulates more than just data and functions that operate on it. A model is
meant to serve as a computational approximation or
abstraction of some real world process or system. It captures not only the
state of a process or system, but how the system works. This makes it very
easy to use real-world modeling techniques in defining your
models. For example, you could define a model that bridges your computational
back-end with your GUI front-end. In this scenario, the model wraps and
abstracts the functionality of a computation engine or
hardware system and acts as a liaison requesting the real services of the
system it models.

The MvcViewport Class

The MvcViewport class is very similar to the MFC CView class. We chose to
call the class a viewport instead of an MvcView to avoid overlapping
terminology and to make the distinctions between a view and a
viewport clearer. The MvcViewport class is responsible for mapping graphics
onto a device. A viewport typically has a one to one correspondence with a
display surface and knows how to render to it. A
viewport attaches to a model and renders its contents to the display surface.
In addition, when the model changes, the viewport automatically redraws the
affected part of the image to reflect those changes. As
with DVA, there can be multiple viewports onto the same model and each of
these viewports can render the contents of the model to a different display
surface.

The biggest difference between CView and MvcViewport is that a viewport is not
derived from CWnd. The designers of MFC chose to implement the notion of a
view through derivation. MVC does it through
aggregation. This is a common theme throughout MFC and a common distinction
relative to MVC. In many cases, where MFC and Document/View use derivation,
MVC uses aggregation. In this case, a
window aggregates one or more viewport objects and then delegates to them when
a paint event occurs. Think about that for a minute, as it is one of the key
differences between DVA and MVC. Because a
viewport avoids the CWnd derivation and no physical window is created, a
viewport is a significantly lighter-weight object than a CView. A viewport
simply takes a pointer to a device context and draws to
whatever device context it’s passed. In addition, because a viewport can be
aggregated into any window (CFrameWnd, CWnd, or CView), a viewport can be
displayed inside a CWnd, a CView or a dialog box
without modification. In addition, support for printing and print-preview
features is preserved.

Another difference between MvcViewport and CView is that MvcViewport should
not contain menu handlers or command handlers of any kind. This responsibility
will be delegated to the view’s controller object.
Additionally, a MvcViewport class can easily be nested but a CView cannot. For
example, a MvcViewport may be a composite viewport containing several
sub-views, which may themselves contain several
sub-views.

The MvcController Class

A controller is the means by which the user interacts with the application. A
controller accepts input from the user and instructs the model and viewport to
perform actions based on that input. In effect, the
controller is responsible for mapping end-user action to application response.
For example, if the user clicks the mouse button or chooses a menu item, the
controller is responsible for determining how the
application should respond. The MvcController class has no analogue in MFC.

In MFC, the CView is both the view and controller, taking on the
responsibilities of presentation and control. In small applications, it may
be simpler to handle user input in the view. Whereas in large applications,
the separation affords you greater modularity, reuse and control
exchangeability. At least, with MVC, you have a choice. You can preserve the
separation or collapse presentation and control into one class. If
you want a separate controller, derive your viewport from MvcViewport and your
controller from MvcController. If you want presentation and control in one
class, multiply derive your viewport from both
MvcViewport and MvcController.

Connecting the Model, Viewport and Controller

The model, viewport and controller are intimately related and in constant
contact. Therefore, they must reference each other. The picture below
illustrates the basic Model-View-Controller relationship:

<figure>


The figure above shows the basic lines of communication among the model,
viewport and controller. In this figure, the model points to the viewport,
which allows it to send the viewport weakly-typed notifications
of change. Of course, the model’s viewport pointer is only a base class
pointer; the model should know nothing about the kind of viewports which
observe it. By contrast, the viewport knows exactly what kind of
model it observes. The viewport also has a strongly-typed pointer to the
model, allowing it to call any of the model’s functions. In addition, the
viewport also has a pointer to the controller, but it should not call
functions in the controller aside from those defined in the base class. The
reason is you may want to swap out one controller for another, so you’ll need
to keep the dependencies minimal. The controller has
pointers to both the model and the viewport and knows the type of both. Since
the controller defines the behavior of the triad, it must know the type of
both the model and the viewport in order to translate user
input into application response.

Additional Reading on MVC

Before we dive into the MVC class hierarchy, I’d like to recommend some
additional references on the subject. MVC is regarded as a classic example of
a design pattern and has therefore experienced a
resurgence with the recent publications on the subject. The classic text
“Design Patterns: Elements of Reusable Object-Oriented Software” by Erich
Gamma et. al. ISBN 0-201-63361-2 discusses MVC and the
Command design pattern. However, its coverage of MVC is minimal. The more
recent text, “A System of Patterns: Pattern-Oriented Software Architecture”
by Frank Buschmann et. al. ISBN 0 471 95869 7
offers more complete coverage of MVC and the Command Processor design pattern
within the context of C++.

...continued in next message...

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/ Now offering spam-free web-based newsreading

de...@stingray.com

unread,
May 7, 1998, 3:00:00 AM5/7/98
to

The MVC Class Hierarchy

So far, we’ve given a brief overview of the MvcModel, MvcView and
MvcController objects. But there is much more to MVC than these three surface
classes. In fact, MVC embodies a rich framework of
base classes, the most derived of which are the model, viewport and controller
classes. It is important to gain a complete understanding of the entire MVC
class hierarchy if you expect to fully benefit from MVC.
The complete class hierarchy is shown below:

<figure>

The following sections will delve more deeply into the MVC framework and the
individual classes that comprise it.

MvcVisualComponent

A visual component is an object that can draw itself to any given device
context. Basically, a visual component is a rectangle with a draw function.
The MvcVisualComponent base class defines an interface that
all other displayable objects in MVC ultimately derive from, allowing you to
treat a collection of visual components consistently. The MvcVisualComponent
class was intentionally kept very light, because some
applications may need to instantiate many of them.

A visual component maintains its size and position relative to its container’s
origin. Because its origin is an offset from its container’s origin, if the
container moves, all subcomponents move with it. One important
question is what are the units of measure of the size and position values?
The answer is, a visual component doesn’t know and doesn’t care. That is the
business of its container. If the container measures its
client area in inches, the bounding rectangle of the visual component is in
inches.

So, who contains an MvcVisualComponent? Another MvcVisualComponent or derived
class. Any visual component derivative can be nested and this nesting can go
on to any depth. But, ultimately, there must
be a viewport type of container at the root of this hierarchy of visual
components in order to map the visual components onto a real device. In other
words, visual componens cannot render themselves by
themselves. They must be told which device context to render to and only a
viewport knows this.

MvcVisualPart

A visual part is a type of visual component that keeps a back pointer to its
container. That’s it. The only other thing it adds is a few member functions
to support invalidation. You may be wondering why we
didn’t just collapse this class into MvcVisualComponent since it is so small.
The answer is we wanted to keep MvcVisualComponent as small as possible
because you could conceivably instantiate thousands of
them in an application. It this case, it wouldn’t be necessary or desirable
for each visual component to know its container.

MvcLogicalPart

An MvcLogicalPart is a visual part that adds support for a logical coordinate
system. You may already be familar with a logical coordinate system from
MFC’s CScrollView and the
SetWindowExt/SetViewportExt members of the CDC. It is basically the same
idea. The logical part establishes a unit of measure which it uses to measure
and draw to its client area. That unit of measure may
be pixels, inches, millimeters or something application-specific. When the
logical part is instructed to draw itself, it first prepares the given DC so
that its units of measure are in effect for its subsequent drawing.

The MvcLogicalPart is the largest body of code in MVC and provides quite a bit
of functionality. The MvcLogicalPart adds zooming a panning support to the MVC
framework, support for mapping modes, a
virtual size and more.

There is another important characteristic of MvcLogicalPart: they can be
nested. Like any visual component, a logical part can be a child of another
logical part. This means a child can establish an entirely
different mapping mode than its parent. For example, the parent could measure
its client area in inches, while its child measures its own client area in
twips.

MvcViewport

An MvcViewport is a kind of logical part that observers a model and delegates
user input to an MvcController for handling. A viewport is responsible for
getting graphics to the screen and reflecting updates in
model state. To do these things, it will generally request information
required for rendering from the model and respond to notifications of change
from the model. A viewport is also responsible for routing
messages to a suitable handler. By default, it routes all messages to its
controller for handling, but this routing is overridable. When would a
message be routed elsewhere? Consider a viewport that contains
several child viewports. In this scenerio, the parent viewport might route
the messages to one or more children first. Only after giving its children a
crack at the message would the parent viewport route the
message to its own controller.

Another very important aspect of the viewport is that it retains a pointer to
the CWnd which contains it. Knowing the containing CWnd is critical, because
this gives the viewport a special significance. For
example, a viewport is the only visual component derivative than can actually
retrieve a real window pointer, instantiate a real CDC pointer for rendering,
map logical to device coordinates or perform a real
invalidation of a window’s client area. Why did we delay the introduction of
a real window binding to the viewport? Because you may want to put your
visual component hierarchy in a model and render it through
multiple viewports. This would mean a visual component, visual part or
logical part might appear in multiple windows and, therefore, cannot be bound
to any one window.

MvcWrapper_T

The MVCWrapper_T class implements the “Decorator” design pattern as described
in Design Patters book. A wrapper is a container with a single component. The
wrapper provides certain services to its
component such as decorating the component with a border or adding scroll bars
to the sides of the component. Wrappers are classes that can be plugged into
any window in place of the component it wraps and
the window remains unaffected by the swap. The ability to dynamically add on
wrappers without effecting client code is accomplished by endowing the wrapper
with the same interface as its component. That’s
why the MVCWrapper_T class is a template. Using a template, we can specify
which component to inherit and emulate.

Some wrappers are visual, and others are not. For example, a wrapper can be
used solely to offset the origin of its component. One of the most interesting
properties of wrappers is that they can be nested to any
depth. For example, you can create a border wrapper that wraps a scroll bar
wrapper that wraps another border wrapper that finally wraps the actual
component.

The Stingray MVC implemention currently has three wrapper classes:
MvcBorderWrapper_T, MvcScrollWrapper_T, and MvcBufferedWrapper_T. The naming
should make it fairly obvious what the border
and scroll wrappers do, but the buffered wrapper requires some explanation.
The buffered wrapper provides off-screen rendering for the component it wraps.
For a small memory overhead, off-screen rendering
reduces or eliminates flicker during redraw. What’s convenient about the
buffered wrapper is it provides buffered rendering to a component without
requiring any change to the component whatsoever. So,
buffered rendering can become an afterthought. (Note: more optimizations on
the buffered wrapper class are possible and will appear in a future release.)
IComposite_T
The composite interface includes members for adding, deleting, retrieving and
locating children. Mix this interface into anything you need to make
composite. For example, if you need to create a composite visual
component, you can do so by mixing this interface into your
MvcVisualComponent-derived class.

IMvcMsgHandler

IMvcMsgHandler is a small interface that can be mixed into any class that
requires the capacity to route and handle messages. By default, it is
implement in MvcViewport and MvcController.

The IMvcSubject, IMvcObserver and IMvcMessage Interfaces

The most fundamental of all MVC concepts and classes are the subject and
observer interfaces. These two interfaces constitute the dependency mechanism
that is central to MVC. The recent book “Design
Patterns: Elements of Reusable Object-Oriented Software” discusses what it
terms the Subject/Observer design pattern. This idiom is very similar to the
roles of document and view in MFC, where the document
is a subject and the view is an observer. However, the subject/observer design
pattern is more generalized. In the subject/observer relationship, a subject
encapsulates related data and functionality which an
observer monitors. If the state of the subject changes, the observer must
know about it. To accomplish this, the subject defines a notification
dictionary which is the set of all notifications of change a subject may
broadcast. A notification is any class which mixes in and implements the
IMvcMessage interface. It is the responsibility of the subject to define and
export a notification dictionary as well as to broadcast
individual notifications of change to its list of observers. It is the
responsibility of the observer to attach itself to a subject and understand
and react to the notifications it receives.

Sounds familiar so far, right? However, several properties distinguish the
subject/observer relationship from document/view. First, the subject and
observer interfaces can be mixed into any class via multiple
inheritance. Conceptually, IMvcSubject and IMvcObserver are interfaces, not
objects and therefore any existing class—including CWnd-derivatives—can become
a subject or an observer or both by simply
supporting the appropriate interface(s).

To reiterate, an object can mix in both subject and observer interfaces,
yielding an object that observes one object and serves as subject to another.
This would be like having a CDocument that could be dependent
upon other, nested documents. This concept has important implications. It
means, for example, that you could have nested models or even a directed
acyclic graph of models that inter-depend on each other. This
yields the very important composition quality that document/view lacks. With
respect to subjects (or models), you can compose larger, more intelligent
models out of smaller, reusable ones. This yields a composite
model that can itself be composed into an even larger model in unforeseen
applications.

The MvcModel Class

Although rich in concept, the MvcModel class is sparse on code. The MvcModel
class just mixes in the IMvcSubject interface and implements it. MvcModel’s
main purpose is to serve as a base class for your
domain-specific models.

The MvcPresentationModel_T Class

Broadly speaking, there are two types of models:

? System Models
? Presentation Models

A system model is an MvcModel-derived class that models some non-graphical,
real-world system or process. A presentation model models a graphical
presentation. System and presentation models can be used
exclusively or in combination. Used in combination, a presentation model
provides the presentation for a system model, essentially mapping the system
into the graphical realm. This scenerio is illustrated below:

<figure>


The presentation model is a piece that has been missing from both
Document/View and MVC since their inception. Most of you have probably
encountered the age-old question, “is this GUI data appropriate to
store in the model?” The presentation model removes the ambiguity and answers
this question once and for all.

A presentation model is a templatized class, which multiply inherits from both
MvcModel and MvcVisualPart. The use of multiple inheritance here allows the
presentation model to function as both a model and a
visual – in effect, a visual model. A good example of where this idea is
useful is in the implementation of a diagramming application. It is very
natural to implement a diagram class as a presentation model. A
diagram would be a kind of presentation model, which manages the graphical
symbol data, font choices, pen widths etc. Like a model, it manages data,
albeit graphical data, and exports functionality. But, like a
visual part, a diagram can draw itself and even be nested as a symbol inside a
parent diagram. Therefore, a diagram is both a model and a visual part.

You may be thinking, “if a presentation model can draw itself, what is the
viewport left to do?” Actually, the viewport is offloaded to some degree, but
it still has a well-defined role. When using a presentation
model, a viewport becomes a gateway for a presentation model to render itself
through. In other words, the viewport becomes a perspective on the
presentation, defining what subregion of the overall presentation
(or diagram) to display. The presentation model is essentially a graphics
server, serving up whatever rectangular portion of the graphics the viewport
instructs it to paint. This rectangle is measured in logical units
and corresponds to the zoom factor and scroll positions of the viewport.

For a more complete discussion of the motivations for a separation of system
and presentation models, see the section titled Solving Real Problems with
MVC.

IMvcVirtualPart

Now this interface is a tough one to explain. But, it does something really
cool, so pay close attention. Earlier, in the OnUpdate Woes section, we
talked about how hard it is to read and maintain the large switch
statements that usually live in CView::OnUpdate. Well, IMvcVirtualPart is the
answer! This interface used in combination with the presentation model
discussed previous nearly eliminates the need for the switch
statement. Why? Because usually, OnUpdate is just trying to figure what
rectangle to invalidate. But, with IMvcVirtualPart, invalidation no longer
goes through the OnUpdate channel, thereby eliminating 90 to
100% of the cases in the OnUpdate switch statement.

How does it work? It’s really very simple. It is a twist on the
subject/observer design pattern – the virtual part/renderer pattern, if you
will. In this case, you have one virtual part, which is rendered by one or
more renderers. Just like subject/observer, if the virtual part changes, the
renderers need to know about it. But, instead of passing a message from
subject to observer, the virtual part passes an invalid rectangle to
all its renderers. The virtual part notifies each render of what rectangle in
logical coordinates has been invalidated. How does the virtual part send this
rectangle? By simply calling InvalidateRect(), which then
broadcasts the invalidate call to all renders as follows:


void MyVirtualPart::InvalidateRect(const CRect& rcLog,
BOOL bErase, BOOL bRepairNow)
{
Iterator_T<MvcVisualPart*> i(&m_setRenderers);
MvcVisualPart* pRenderer;

for (pRenderer = i.GetFirst();
pRenderer != NULL;
pRenderer = i.GetNext())
{
pRenderer->InvalidateRect(rcLog,
bErase, bRepairNow);
}
}

It is the responsibility of the renderer to figure out where that logical
rectangle is on its display surface and (if it is currently showing the
invalid region) to perform a true windows invalidation.

The presentation model implements the IMvcVirtualPart interface and the
viewports serve as renderers. So, if a presentation model creates a new
visual component and positions it within its virtual display
surface, it just invalidates the visual component’s bounds. All attached
viewports “hear” the invalidation and trigger a repaint.

This technique is very convenient. It allows the presentation model to draw
and erase within its own virtual space using its own logical units, blissfully
ignorant of how the graphics it produces get mapped onto a
device.

The MvcTransactionModel Class

A transaction model is a central component of the Undo/Redo architecture.
Basically, it maintains the undo and redo stack. Seethe Undo/Redo section for
more details.

MvcController

The controller is what makes a viewport seem to respond directly to mouse
movements and keyboard activity. A controller receives input from the user
and translates that into application response. The
application response comes in the form of function calls to the model and
viewport. The MvcController class is an MVC base class that defines the basic
structure and behavior of a controller. This includes the
ability to acquire, maintain, and relinquish control as well as a mechanism
for mapping messages to handlers. This raises the question, for the
controller’s message mapping mechanism, can’t we just reuse MFC’s
message map solution? Ideally, yes. But there is one big problem here….

A separate controller class for message handlers may sound like a good idea,
but MFC was designed in such a way that this was thought impossible. MFC
allows commands such as menu picks to be rerouted to
non-windows, but not windows messages such as mouse clicks. In MFC, only a
CWnd can receive windows messages and only one instance of a CWnd can receive
the messages for a real Windows window.
Since a controller is meant to be a non-window that can handle windows
messages and exist in multiple instances per window, we seem to be stuck! An
interesting aside, this problem was sited by an original
MFC team member as the main reason Microsoft emulated MVC for the CDocument
and CView, but stopped short of implementing a controller (MFC Professional
Developers Conference, 1995).

At first, this problem appeared to be unsolvable. We arrived at a number of
relatively undesirable workarounds but no solution. Eventually, we did find a
unique trick that has allowed us to do something MFC was
never meant to do: route windows messages such as mouse clicks to any number
of potential handler classes. The solution is what we call a windows plug-in
(SECWndPlugIn). A windows plug-in is a class that
you can plug into a window and it will listen to and potentially handle all
messages that window receives. In essence, it’s equivalent to a modular MFC
message map. Imagine being able to take a large message
map, break it up into blocks and put each block and its associated handlers in
their own classes. Then, you could dynamically and conditionally aggregate
only the message map blocks you need, and pay for only
the features you require. In addition, if you had two window types that
needed to handle the same messages in the same way (i.e. mouse wheel support),
then you could put that code in one place and aggregate
this block of handlers in all window types that require the feature. This is
exactly what window plugins give you.

The controller class (i.e. MvcController) overcomes the aforementioned
problems through its derivation from SECWndPlugIn. An MvcController serves as
a listener that allows all derivatives to plug into a
window and control it. A window can host any number of controllers and the
controllers can be delegated to in any order you see fit. Once again, where
MFC uses derivation, MVC uses aggregation and the
result is greater flexibility and reusability.

Another convenient characteristic of controllers is that they are seen by MFC
and Developer Studio as a CWnd even though they aren’t (they don’t incur the
overhead of a Windows window - window handle).
This allows you to create a standard MFC message map in your derived
controller classes and even edit them using Class Wizard! In addition,
controllers don’t disturb the normal MFC message and command
routing channels—they simply extend them. Furthermore, since controllers route
messages using MFC’s own highly-optimized message map mechanism, there is
virtually no performance degradation.
The Collection Classes
The collection classes ( CCArray_T, MvcSet_T, CCStack_T etc.) are just simple
wrappers around MFC’s collection classes. The only reason we’ve wrapped them
is to make it more convenient for someone to
use STL or their own internal collection classes without having to modify the
MVC framework. Our goal was to remain collection class independent without
inventing a new set of collection classes and without
becoming notationally inconvenient. We believe we accomplished this goal by
doing the following:

1. We’ve wrapped the MFC collection classes using inheritance. In other
words, CCArray_T derives from CArray, so you can still use the collection as
if it were a CArray if you like.

2. We’ve created a very convenient iterator class called Iterator_T. Using
this class, you can iterate over any collection that happens to implement the
ICollection_T interface, regardless of whether the actual
collection implementation is MFC, STL or otherwise. The following code shows
how Iterator_T is used:

Iterator_T<MvcVisualPart*> i(&m_setParts);
MvcVisualPart* pParts;

for (pPart = i.GetFirst();
pPart!= NULL;
pPart = i.GetNext())
{
// Do something
}

MVC’s Undo/Redo Architecture

While not part of the classical MVC architecture, we’ve added support for
Undo/Redo on top of the MVC framework. This Undo/Redo architecture is based on
well-known design patterns and, as it turns out, is a
very natural extension of the MVC concepts. At the core of the Undo/Redo
architecture are the MvcCommand and MvcTransactionModel classes. MvcCommand
is equivalent to the Command design pattern as
described in the classic text “Design Patterns: Elements of Reusable
Object-Oriented Software” by Erich Gamma et. al. In addition, the
MvcTransactionModel is based upon the Command Processor design
pattern as describe in “A System of Patterns: Pattern-Oriented Software
Architecture” by Frank Buschmann et. al. Please see these books for more
information.

The MvcCommand Class

The command class is really very simple. It has two primary virtual
functions: Execute and Unexecute. As you might expect, these members must be
overridden in concrete command classes that you define.
Effectively, this moves the implementation of undoable operations out of
member functions and into persistent records. Why is this necessary? Because
there’s no way to undo a function call since no record of
the parameter values or even the call itself is maintained. This is what
MvcCommand is - a persistent function call, which stores all parameter values
so that it may later be undone.

The Transaction Model

The transaction model is where the command records are stored upon their
execution. The transaction model is responsible for storing the commands and
undoing or redoing the most recent ones. In terms of
implementation, the transaction model maintains two separate stacks: an undo
stack and a redo stack. As commands are executed, they are automatically
pushed onto the undo stack. If the transaction model is
instructed to undo the most recent command, it pops the command off the top of
the undo stack and tells it to Unexecute itself. Then, it pushs the command
onto the redo stack. If a redo is requested, the exact
opposite occurs.

The IMvcUndoRedo Interface

The Undo/Redo interface can be mixed into any class that you want to provide
undo/redo support for. By default, it is already supported by the
MvcPresentationModel_T. The undo/redo interface is very
straightforward. It simply gives you Undo and Redo member functions, along
with a few other utility and query members.

Tying Undo/Redo into the MVC Framework

So far, nothing that has been discribed about the Undo/Redo architecture is
really MVC-specific. So, how does the Undo/Redo architecture tie into MVC?
The answer is an MvcCommand mixes in the
IMvcMessage interface. This means that a command can double as both a
persistent function call record and a notification of change. So, a model can
define a notification dictionary and a command dictionary
one and the same. After a model executes a command which it defines, it
forwards the command itself as the notification to its observers.

Patrick Logan

unread,
May 7, 1998, 3:00:00 AM5/7/98
to

In comp.object Patrick Wray <tw...@ozemail.com.au> wrote:

: Do you happen to know from experience or hearsay whether the JFC (Swing)
: library provides a good implementation of MVC? I haven't really looked into
: this yet, but now seems like a good time to start.

Yes. There are some good Swing tutorials on various web sites. Search
engines should easily find them.

--
Patrick Logan (H) mailto:plo...@teleport.com
(W) mailto:patr...@gemstone.com
http://www.gemstone.com

de...@stingray.com

unread,
May 7, 1998, 3:00:00 AM5/7/98
to

In article <6ispk8$6gp$1...@reader1.reader.news.ozemail.net>,
"Patrick Wray" <tw...@ozemail.com.au> wrote:
>
>
> de...@stingray.com wrote in message <6isk35$ttv$1...@nnrp1.dejanews.com>...

> >Still, several stated that they wanted a more detailed comparison of
> >Document/View versus MVC. So, here it is. If you are one of those people
> who
> >wanted this comparison, read on.
>
> [ treatise on MVC vs Document/View snipped ]
>
> Fascinating reading! These are brilliant ideas.

Thanks!

>
> Do you happen to know from experience or hearsay whether the JFC (Swing)
> library provides a good implementation of MVC? I haven't really looked into
> this yet, but now seems like a good time to start.

I've only looked very briefly at the JFC implementation of MVC. I got the
impression it was more like document/view, but I could be wrong.

>
> PS. I've had (mostly) very good experiences with ObjectiveGrid. Reading this
> makes me more inclined to have a closer look at ObjectiveToolkit.
>
>

Glad to hear it. Let me know if I can help in your evaluation.

Dean

Jerry Coffin

unread,
May 7, 1998, 3:00:00 AM5/7/98
to

In article <6isk35$ttv$1...@nnrp1.dejanews.com>, de...@stingray.com
says...

[ ... ]

> Some of the more complex challenges facing MFC developers are the shortcomings
> of the MFC's document/view architecture.

I think there are three issues here that are best separated:
1) shortcomings of the Doc/View architecture in general,
2) shortcomings in MS' implementation of Doc/View
3) tailoring of MFC toward particular types of applications at the
expense of others.

> Despite its lack of wide spread use, the model-view-controller
> architecture is not a new concept. It was invented— along with
> the graphical user interface and the concept of object oriented
> programming—about twenty years ago by researchers at the Xerox Palo Alto
> Research Center (PARC). The culmination of that research was the Smalltalk
> language and its multi-windowed, highly interactive Smalltalk-80
> interface. Amazingly, both of these inventions are revolutionary, even by
> today’s standards.

Not IMO, but perhaps my considering them less revolutionary stems from
having started to use Smalltalk in 1981. Having used it for close to
20 years tends to make almost any concept seem a bit less
revolutionary.

Alan Kay doesn't seem to consider them particularly revolutionary
either. In the paper he presented at HOPL-II, he said:

I have been asked by several reviewers to say more about the
development of the "Smalltalk-style" overlapping window user
interfaces in as much as there are now more than 20 million
computers in the world that use its descendents.
[ ... ]

All of the elements eventually used in the Smalltalk user
interface were already to be found in the sixties -- as
different ways to access and invoke the functionality provided
in an interactive system. The two major centers of ideas were
Lincoln Labs and RAND Corporation -- both ARPA funded.

He goes on at some length, but mostly points out that Smalltalk
consolidated quite a few ideas that had been around for quite a while.
The result has been used widely as examples for successful products,
but that doesn't really make it revolutionary.

> To some degree, nearly ever user interface developed in the last two decades
> has been an adaptation of the work done at Xerox PARC. Indeed, MVC has been
> partially reproduced in many other development environments. In fact, the MFC
> document/view architecture is an adaptation of the concepts introduced by the
> MVC paradigm. However, it can be argued that the key purpose of MVC, reuse,
> was lost in the adaptation.

The implementation of almost any theory is generally (at least
somewhat) more limited than the theory itself. Nonetheless, Doc/View
certainly _can_ provide a great deal of reuse. MFC's implementation
may not be the ultimate, but with proper use, provides a great deal of
reuse, at least for some types of projects. (I certainly wouldn't
claim it's all things to all people though.)

> for applications containing two or three CDocument- or CView-derived classes
> of small to medium complexity, you might find it somewhat less accommodating
> for applications with larger, more complex or more numerous documents and
> views.

Hmm...silly me; I thought my app that used roughly 15 different
documents and around 25 views was stilL "Pretty small and simple."
Maybe if I thought of it as "large" or "complex", DVA would start to
actually cause problems...

> If you’ve done any development with MFC, you already know that the Visual C++
> Scribble tutorial is widely accepted as the canonical form of a Windows
> graphical user interface application using MFC and the
> document/view architecture.

Here's the real crux of what I consider your problem: you're taking
one program that makes poor use of DVA, and using it as a prosecution
of DVA itself. This argument is fundamentally flawed. Quite a few
people have written programs that are excessively large and complex,
using almost any paradigm you'd care to name. The measure of MFC is
not how widely it's been abused, but how well it can work when used
properly.

> You might argue that the document/view architecture is not itself responsible
> for the problems in the Scribble sample—they might instead simply be due to a
> violation of the principle of encapsulation. However,
> there are the problems inherent in DVA that tend to encourage this violation.
> Chief among them is the fact that it is difficult to separate data from its
> visual representation because the concept of application data is
> not clearly defined.

I beg your pardon? This sounds like utter clap-trap to me. Worse
yet, since MVC uses _exactly_ the same separation of data from user-
interface, the problem is equally inherent in MVC as DV.

> Thus, it is unclear how DVA is supposed to map onto an application’s
> problem domain.

Most of programming undoubtedly isn't obvious to everybody. I could
equally easily (and correctly) state that "it is unclear how MVC is
supposed to map to an application's domain." The simple fact is, a
document and a model are _exactly_ the same thing -- somebody who
can't design a document properly is equally incapable of designing a
model properly.

> For some applications—such as a simple word
> processor— the answer seems obvious: an MFC
> document represents a user document. But what about applications like
> interface builders or graphical tools? The data for such applications might
> include colors, fonts, pens, and window bounds, all of which need
> to be saved. However, it seems inappropriate to include this information in a
> CDocument-derived class because it describes a visual representation of the
> underlying data.

According to whom?

> It is unclear how you would separate the document and view classes in that
> scenario.

The only part that's unclear is your description of the problem. With
a proper problem specification, figuring out what needs to go in the
view and what needs to go in the document is easy. Figuring out what
goes in the model requires _exactly_ the same information and
decisions, as a model and a document really just two names for the
same thing.

> The document/view architecture takes a monolithic approach to application
> decomposition.

Is this, in your opinion, a problem with the document view
architecture itself, or a problem with MS' implementation of it?

> Since documents and views cannot easily be nested, a DVA
> application typically contains large, highly functional
> document classes paired with equally large, highly functional view classes.

Does MFC truly prevent such nesting, or does it simply not do anything
in particular to support it?

> Of
> course, it is possible to place one CView-derived class inside another, but
> that construct is not specifically supported by the
> document/view architecture—you must perform all message forwarding yourself.

Ahh...now the truth comes out: MFC does NOT prevent it -- it just
doesn't do the work for you. I'm not making light of the latter,
merely pointing out that this isn't something MFC prevents.

[ ... ]

> Due to the lack of
> modularity and numerous interdependencies inherent in DVA, development teams
> usually find it difficult to subdivide a problem and work in parallel. In
> fact, the lack of modularity usually requires every team
> member to fully comprehend the entire application model. Dependencies like
> that translate into reduced team productivity and reduced application
> stability.

Hmmm...I haven't found this to be the case at all. Rather the
contrary: I've added a number of document and views to the application
mentioned above, paying absolutely NO attention to other parts at all.



> So, why isn’t a CView reusable? Put simply, CViews depend on an
> application-specific document type.

Hmm...a view displays data from a document. Do you propose something
that's supposed to display the data, without knowledge of the form or
function of that data?

> Another frequently used solution is to make all data accesses go through
> virtual functions rather than directly access the members of a document. By
> doing this, you remove the reusable view’s dependency on any
> document. However, you are no longer adhering to the document/view
> architecture, so it’s not really a solution.

How do you figure that this violates the document/view architecture?
If you want to virtualize something, the way you do that in C++ is via
virtual functions. Keep in mind that all of this case from Smalltalk,
where ALL data members are private (there's no way to make them
anything else) and the _only_ access you get to the model/document's
contents is via Smalltalk's equivalent to member functions, which are
_always_ equivalent to virtual. In short, if virtual functions didn't
follow the document/view architecture, then neither document/view nor
MVC could be implemented in Smalltalk AT ALL!

> In addition, accessing data through virtual functions, rather than
> directly from the document, is certainly not your first instinct based on
> the example set by Scribble.

<Linguitics mode>
The definition of an instinct is that it's something that is NOT
learned. If you base something on Scribble (or any other example)
it's clearly not an instinct.
</Linguistics mode>

> The best solution short of creating an alternative to document/view is to have
> the CView do as little as possible. Ideally, it should only contain an
> OnUpdate() handler. All of the drawing logic should be contained
> within a completely reusable CWnd.

I'm still a bit lost on this idea of a completely reusable view of
some sort. The idea of a view is to encapsulate the rendering of some
sort of data. Assume for the moment that you write a view intended to
render HTML. How, pray tell, will code that was written specifically
to render HTML make sense of something else, even if it's fairly
similar. E.g. if I have code that's intended to render HTML, I fail
to see how it would make sense of, say, RTF. How can such a thing be
made "completely reusable"?

> One of the unfortunate limitations of MFC is the incompatibility that exists
> between CView and CDialog.

IMO, this is a strength rather than a weakness -- one of the _truly_
significant accomplishments of Alan Kay and the Xerox PARC in general,
was the elimination of nearly all modality/modiness from the systems
in general. Things that discourage modiness are GOOD.

> No Separation of Presentation From Control

Here, finally, we get to a real difference between DV and MVC...



> Roughly speaking, a CView has two responsibilities. First, it must present the
> data contained in the document to the user. Second, it must interpret and
> react to user input.

With the proviso, that any particular view may have only one of these
responsibilities. Anybody who wants to can separate the two quite
easily. I've written a few views that responded to input (generally
not directly from the user) but didn't display anything, and _many_
that showed things without being able to update the data in response
to the user's input.

> There are several imposed limitations
> here. Both presentation and control come packaged in one class. That means
> that you cannot reuse a view’s presentation data without also reusing that
> view’s reaction to user input.

Unless, of course, you create separate views to do each part. The DV
mechanism leaves this mechanism up to you. Of course, in most cases,
the rendering of the data determines the method of input that makes
sense, and trying to separate the two does little or no real good for
anybody. (E.g. if you've displayed data in a graph, you may well
allow the user to drag things around on the graph to change the data.
OTOH, if the user tried to "drag" same data displayed in a chart, your
response would have to be completely different.)



> Another important difference between a model and a CDocument is that a model
> encapsulates more than just data and functions that operate on it. A model is
> meant to serve as a computational approximation or
> abstraction of some real world process or system. It captures not only the
> state of a process or system, but how the system works. This makes it very
> easy to use real-world modeling techniques in defining your
> models. For example, you could define a model that bridges your computational
> back-end with your GUI front-end. In this scenario, the model wraps and
> abstracts the functionality of a computation engine or
> hardware system and acts as a liaison requesting the real services of the
> system it models.

Maybe if you tried again, you could write something sensible here.
I've re-read this about a half-dozen times, and for all I got out of
it, I might as well have been trying to read Chinese.



> The biggest difference between CView and MvcViewport is that a viewport is not
> derived from CWnd. The designers of MFC chose to implement the notion of a
> view through derivation. MVC does it through
> aggregation. This is a common theme throughout MFC and a common distinction
> relative to MVC. In many cases, where MFC and Document/View use derivation,
> MVC uses aggregation.

Here, it should be pointed out, that you're talking _strictly_ about
YOUR implementation of MVC, rather than MVC in general.

> In this case, a window aggregates one or more viewport objects and then
> delegates to them when a paint event occurs.

[ ... ]

> In addition, because a viewport can be
> aggregated into any window (CFrameWnd, CWnd, or CView), a viewport can be
> displayed inside a CWnd, a CView or a dialog box
> without modification. In addition, support for printing and print-preview
> features is preserved.

Hmm...are you of the opinion that you can't have one window contain
another? How would the mere fact of derivation from CWnd prevent one
sort of Window from containing some other sort of CWnd-derived object?



> Another difference between MvcViewport and CView is that MvcViewport should
> not contain menu handlers or command handlers of any kind. This responsibility
> will be delegated to the view’s controller object.
> Additionally, a MvcViewport class can easily be nested but a CView cannot. For
> example, a MvcViewport may be a composite viewport containing several
> sub-views, which may themselves contain several
> sub-views.

Hmm...this starts to sound a great deal as if you've merely changed
responsibilities a bit: instead of CView's being contained in a
CFrameWnd (or derivation thereof) you have views that can contain
other views. I can see a theoretical advantage to that, but I can't
say that I've seen a situation yet in which it seems like it would
have been useful.

My feeling right off, is that this is likely to make poor designs
easier to implement, but have little or no real effect on better
designs. However, I'll openly state that I'm NOT at all certain of
this.



> In MFC, the CView is both the view and controller, taking on the
> responsibilities of presentation and control. In small applications, it may
> be simpler to handle user input in the view. Whereas in large applications,
> the separation affords you greater modularity, reuse and control
> exchangeability.

In my experience, this is _rarely_ the case. Having used MVC in
Smalltalk for quite a while, it's been my experience that in most
cases, you end up with a 1:1 correspondence between views and
controllers. You _can_ frequently use a common base class for all the
controllers for a particular model, but in most cases, the controllers
have to be specialized to the view: the example above of the user
dragging data in a view is typical. Things like menu entries often
make sense across all views/controllers on a given document/model, but
many require tailoring and/or make no sense at all for particular
views.

There are sometimes advantages to separating control from display, but
in my experience they're almost entirely in the realm of organization,
not reuse. (Not to make light of organization: IMO, reuse is
generally a pleasant by-product of OO programming that's easy to sell
to management, but NOT its main advantage.)

--
Later,
Jerry.

The Universe is a figment of its own imagination.

Patrick Wray

unread,
May 8, 1998, 3:00:00 AM5/8/98
to

de...@stingray.com wrote in message <6isk35$ttv$1...@nnrp1.dejanews.com>...

>Still, several stated that they wanted a more detailed comparison of
>Document/View versus MVC. So, here it is. If you are one of those people
who
>wanted this comparison, read on.

[ treatise on MVC vs Document/View snipped ]

Fascinating reading! These are brilliant ideas.

Do you happen to know from experience or hearsay whether the JFC (Swing)


library provides a good implementation of MVC? I haven't really looked into
this yet, but now seems like a good time to start.

PS. I've had (mostly) very good experiences with ObjectiveGrid. Reading this

Dean Hallman

unread,
May 8, 1998, 3:00:00 AM5/8/98
to


Jerry Coffin wrote:

> In article <6isk35$ttv$1...@nnrp1.dejanews.com>, de...@stingray.com
> says...
>
> [ ... ]
>
> > Some of the more complex challenges facing MFC developers are the shortcomings
> > of the MFC's document/view architecture.
>
> I think there are three issues here that are best separated:
> 1) shortcomings of the Doc/View architecture in general,
> 2) shortcomings in MS' implementation of Doc/View
> 3) tailoring of MFC toward particular types of applications at the
> expense of others.

Apparently, I didn't make one point crystal clear in this paper, mostly because it
was intended for an MFC audience. So let me be more precise: All matters discussed
in this paper relate to MFC's implementation of Doc/View directly and exclusively.
These problems aren't inherent in the Document/View theory, only in MS' realization
of it. In fact, that is the whole point.

The theory behind Doc/View is really no different than MVC. The MVC View and
Controller classes can be combined into one class through multiple inheritance,
yielding a Doc/View subset of MVC. If you define Doc/View this way, then these
problems don't apply. But the MFC definition of Doc/View is not the same thing.
Where does MS' implementation of Doc/View stray from the theory? They key
differences IMO are:

1) In theory, a view and a window are not the same thing. In MFC Doc/View, they
are.
In theory, the view should be a aggregated by a CWnd. In MFC, the CView is
derived
from CWnd and therefore statically bound to it.
2) In theory, documents can be nested. MFC CDocuments cannot.
3) In theory, views can be nested. In MFC Doc/View, they cannot.
(Of course, you can nest CWnds but CViews cannot be nested in
any meaningful way where the Doc/View architecture is concerned.)
4) In theory, entire triads or doc/view pairs can be nested. In MFC Doc/View, they
cannot.
5) In theory, documents can be small, granular pieces that can be
composed into larger, more application-specific ones. MFC's CDocument
cannot do this.
6) In theory, it should be possible to have one document observe another
almost as if it were a view. MFC's CDocument gets in the way of doing
this. The Subject/Observer design pattern is not followed in MFC's
implementation of Doc/View, but obviously, subject/observer is a very
useful design pattern and would have been a better implementation
choice.

Yeah.. I agree. I wouldn't really consider it revolutionary by today's standards,
but it was a very minor point relatively speaking.

Still, I consider it pretty amazing that Xerox Parc in the mid-70's had
a prototype computer that realized a GUI, a mouse-driven user interface,
a very advanced object-oriented programming language (Smalltalk), an
Integrated Development Environment, an Ethernet network, Email and
the concept of WYSIWYG, packaged into a $10k personal computer.
Meanwhile, the Altair PC had a few LEDs and switches to flip.

Oh god, I hope I'm not criticizing anyone's Altair :-)

> > To some degree, nearly ever user interface developed in the last two decades
> > has been an adaptation of the work done at Xerox PARC. Indeed, MVC has been
> > partially reproduced in many other development environments. In fact, the MFC
> > document/view architecture is an adaptation of the concepts introduced by the
> > MVC paradigm. However, it can be argued that the key purpose of MVC, reuse,
> > was lost in the adaptation.
>
> The implementation of almost any theory is generally (at least
> somewhat) more limited than the theory itself. Nonetheless, Doc/View
> certainly _can_ provide a great deal of reuse. MFC's implementation
> may not be the ultimate, but with proper use, provides a great deal of
> reuse, at least for some types of projects. (I certainly wouldn't
> claim it's all things to all people though.)

Given that I'm talking about MS' implementation of Doc/View, and much
of your discussion assumes Doc/View theory, I think we agree. In theory,
Doc/View provides a great deal of reuse potential. MFC's implementation
often doesn't.

>
>
> > for applications containing two or three CDocument- or CView-derived classes
> > of small to medium complexity, you might find it somewhat less accommodating
> > for applications with larger, more complex or more numerous documents and
> > views.
>
> Hmm...silly me; I thought my app that used roughly 15 different
> documents and around 25 views was stilL "Pretty small and simple."
> Maybe if I thought of it as "large" or "complex", DVA would start to
> actually cause problems...

I did say you "might" find it less accommodating and pointed out specific reasons
and pitfalls to consider. If after reading this you still feel MS' implementation of
Doc/View is a perfect fit for your needs, then hopefully this paper will still
provide some value in terms of the pitfalls it forewarns.


>
>
> > If you’ve done any development with MFC, you already know that the Visual C++
> > Scribble tutorial is widely accepted as the canonical form of a Windows
> > graphical user interface application using MFC and the
> > document/view architecture.
>
> Here's the real crux of what I consider your problem: you're taking
> one program that makes poor use of DVA, and using it as a prosecution
> of DVA itself.

First:
If you can't count on MS' tutorial which they purport as the starting point for
every MFC beginner as a reference for how to use MFC properly, then
where would you suggest one look?

Second:
I'm not basing my arguments on one sample alone. I've pointed out many
reasons why MS' implementation of Doc/View has shortcomings. The
issue of a flawed tutorial is one of many reasons. Revisit the 6 key
differences between the theory and MS' implementation for a concise
description of the other reasons.

> This argument is fundamentally flawed. Quite a few
> people have written programs that are excessively large and complex,
> using almost any paradigm you'd care to name. The measure of MFC is
> not how widely it's been abused, but how well it can work when used
> properly.

I think you've got it backwards. Quality isn't defined by how well something works
when it works. Quality is defined by how infrequently something fails. So,
I'd put it another way. The measure of Doc/View is by how many people have
used Doc/View properly and still ended up with unsatisfactory results. And
I would take exception to the assertion that unsatisfactory results implies
that one did not apply Doc/View properly.

>
>
> > You might argue that the document/view architecture is not itself responsible
> > for the problems in the Scribble sample—they might instead simply be due to a
> > violation of the principle of encapsulation. However,
> > there are the problems inherent in DVA that tend to encourage this violation.
> > Chief among them is the fact that it is difficult to separate data from its
> > visual representation because the concept of application data is
> > not clearly defined.
>
> I beg your pardon? This sounds like utter clap-trap to me. Worse
> yet, since MVC uses _exactly_ the same separation of data from user-
> interface, the problem is equally inherent in MVC as DV.

Once again, our difference of theory versus implementation is getting in
the way. The theory of Doc/View affords more flexibility in defining
how this separation is achieved than the MFC implementation allows.
A very specific instance of this is the subject/observer design pattern.
If you could have one model that could observe another model, you could
logically divide the content of each into system data versus presentation
data. CDocument wasn't designed to do this because it isn't based on
the subject/observer design pattern.

>
>
> > Thus, it is unclear how DVA is supposed to map onto an application’s
> > problem domain.
>
> Most of programming undoubtedly isn't obvious to everybody. I could
> equally easily (and correctly) state that "it is unclear how MVC is
> supposed to map to an application's domain." The simple fact is, a
> document and a model are _exactly_ the same thing -- somebody who
> can't design a document properly is equally incapable of designing a
> model properly.

Not true. MVC does map onto an application domain in a much more
straight forward way than MS' implementation of Doc/View for the 6 key
reasons previously site. It boils down to one essence: flexibility.
MVC affords many more options in how your classes are architected,
your data is partitioned etc. because we are in closer agreement
with the theory.

> > For some applications—such as a simple word
> > processor— the answer seems obvious: an MFC
> > document represents a user document. But what about applications like
> > interface builders or graphical tools? The data for such applications might
> > include colors, fonts, pens, and window bounds, all of which need
> > to be saved. However, it seems inappropriate to include this information in a
> > CDocument-derived class because it describes a visual representation of the
> > underlying data.
>
> According to whom?

I've spoken to many MFC developer's that have expressed this same point. So,
I guess it would be according to colleagues, customers, and acquaintances.

>
>
> > It is unclear how you would separate the document and view classes in that
> > scenario.
>
> The only part that's unclear is your description of the problem. With
> a proper problem specification, figuring out what needs to go in the
> view and what needs to go in the document is easy. Figuring out what
> goes in the model requires _exactly_ the same information and
> decisions, as a model and a document really just two names for the
> same thing.

Doesn't apply. I've already explained why a model and MS' definition of
a document aren't the same thing several times so I'll not repeat myself
again.

>
>
> > The document/view architecture takes a monolithic approach to application
> > decomposition.
>
> Is this, in your opinion, a problem with the document view
> architecture itself, or a problem with MS' implementation of it?
>

Ahha! It is a problem with MS' implementation of a document. The theory doesn't
prescribe this limitation.

> > Since documents and views cannot easily be nested, a DVA
> > application typically contains large, highly functional
> > document classes paired with equally large, highly functional view classes.
>
> Does MFC truly prevent such nesting, or does it simply not do anything
> in particular to support it?
>

MFC actually gets in your way. You cannot put a document or a document/view pair
inside a document and I've never known anyone who tried.

> > Of
> > course, it is possible to place one CView-derived class inside another, but
> > that construct is not specifically supported by the
> > document/view architecture—you must perform all message forwarding yourself.
>
> Ahh...now the truth comes out: MFC does NOT prevent it -- it just
> doesn't do the work for you. I'm not making light of the latter,
> merely pointing out that this isn't something MFC prevents.
>
> [ ... ]
>

No. MFC gets in your way. You can nest CWnds. But you can't nest documents. You
can nest views, but to have two nested views attached to two separate documents
would require that you override a lot of default functionality and do all the
overhead of creation and initialization manually. So, part of it is possible but
only with a lot of extra effort and only if you are pretty familiar with how this
all works. Not suprisingly, I've never encountered an MFC programmer whose even
thought of attempting this, much less actually accomplished it.

> > Due to the lack of
> > modularity and numerous interdependencies inherent in DVA, development teams
> > usually find it difficult to subdivide a problem and work in parallel. In
> > fact, the lack of modularity usually requires every team
> > member to fully comprehend the entire application model. Dependencies like
> > that translate into reduced team productivity and reduced application
> > stability.
>
> Hmmm...I haven't found this to be the case at all. Rather the
> contrary: I've added a number of document and views to the application
> mentioned above, paying absolutely NO attention to other parts at all.

This problem isn't going to always occur. It is most likely to occur in a tool that
has one primary document type and is very complex. Take a UML modeling tool as an
example. Primarily one document that would probably be quite large and touched by
most or all team members.


>
>
> > So, why isn’t a CView reusable? Put simply, CViews depend on an
> > application-specific document type.
>
> Hmm...a view displays data from a document. Do you propose something
> that's supposed to display the data, without knowledge of the form or
> function of that data?

No. I'm proposing smaller, more granular model/view pairs that can becomposed or
reused in larger ones.

>
>
> > Another frequently used solution is to make all data accesses go through
> > virtual functions rather than directly access the members of a document. By
> > doing this, you remove the reusable view’s dependency on any
> > document. However, you are no longer adhering to the document/view
> > architecture, so it’s not really a solution.
>
> How do you figure that this violates the document/view architecture?
> If you want to virtualize something, the way you do that in C++ is via
> virtual functions. Keep in mind that all of this case from Smalltalk,
> where ALL data members are private (there's no way to make them
> anything else) and the _only_ access you get to the model/document's
> contents is via Smalltalk's equivalent to member functions, which are
> _always_ equivalent to virtual. In short, if virtual functions didn't
> follow the document/view architecture, then neither document/view nor
> MVC could be implemented in Smalltalk AT ALL!

That's not my point. I'm not saying virtual functions violate
DVA. I'm saying to use virtual functions to get data _instead_
of a document is not DVA. In other words, if you eliminate
the document by putting data in a derived class an accessing
it through virtuals, you're not using DVA, your avoiding it.

>
>
> > In addition, accessing data through virtual functions, rather than
> > directly from the document, is certainly not your first instinct based on
> > the example set by Scribble.
>
> <Linguitics mode>
> The definition of an instinct is that it's something that is NOT
> learned. If you base something on Scribble (or any other example)
> it's clearly not an instinct.

> </Linguistics mode>

>
>
> > The best solution short of creating an alternative to document/view is to have
> > the CView do as little as possible. Ideally, it should only contain an
> > OnUpdate() handler. All of the drawing logic should be contained
> > within a completely reusable CWnd.
>
> I'm still a bit lost on this idea of a completely reusable view of
> some sort. The idea of a view is to encapsulate the rendering of some
> sort of data. Assume for the moment that you write a view intended to
> render HTML. How, pray tell, will code that was written specifically
> to render HTML make sense of something else, even if it's fairly
> similar. E.g. if I have code that's intended to render HTML, I fail
> to see how it would make sense of, say, RTF. How can such a thing be
> made "completely reusable"?
>

Well.. for example, you might want to take your HTML view anduse it to display HTML
in another application. Assume your
HTML view has a particular CHTMLDocument that it attaches to
and expects. But to move it to the other application will require
that you move the CHTMLDocument to the other application.
Problem is, that application already has a document. You'd
like to just make your CHTMLDocument a nested document
inside the other application's document, but MFC doesn't
support nesting of documents.

Of course, you could create a separate document and a separate
MDI child to contain your HTMLDocument and View pair. But,
you want everything to be saved into one file, and creating
two distinct documents is going to make that very cumbersome.
Also, it doesn't allow you to show your HTMLView in a subregion
of a view that displays the other document.


> > One of the unfortunate limitations of MFC is the incompatibility that exists
> > between CView and CDialog.
>
> IMO, this is a strength rather than a weakness -- one of the _truly_
> significant accomplishments of Alan Kay and the Xerox PARC in general,
> was the elimination of nearly all modality/modiness from the systems
> in general. Things that discourage modiness are GOOD.

I think that is a separate issue. If I want to implement a pie chart view,I don't
want to have to copy and paste it into a pie chart window class
just so I can show pie charts in a dialog. Modality has nothing
to do with drawing something in the client area of the dialog. And it is
the drawing logic that you'll want to reuse.


>
>
> > No Separation of Presentation From Control
>
> Here, finally, we get to a real difference between DV and MVC...

This is the first difference in theory. Implementation differences abound.

>
>
> > Roughly speaking, a CView has two responsibilities. First, it must present the
> > data contained in the document to the user. Second, it must interpret and
> > react to user input.
>
> With the proviso, that any particular view may have only one of these
> responsibilities. Anybody who wants to can separate the two quite
> easily. I've written a few views that responded to input (generally
> not directly from the user) but didn't display anything, and _many_
> that showed things without being able to update the data in response
> to the user's input.
>
> > There are several imposed limitations
> > here. Both presentation and control come packaged in one class. That means
> > that you cannot reuse a view’s presentation data without also reusing that
> > view’s reaction to user input.
>
> Unless, of course, you create separate views to do each part. The DV
> mechanism leaves this mechanism up to you. Of course, in most cases,
> the rendering of the data determines the method of input that makes
> sense, and trying to separate the two does little or no real good for
> anybody. (E.g. if you've displayed data in a graph, you may well
> allow the user to drag things around on the graph to change the data.
> OTOH, if the user tried to "drag" same data displayed in a chart, your
> response would have to be completely different.)

I basically agree with you here. If you don't want to separate view from
controller, the your view derived class can multiply inherit from both. If you you
do want the separation, it's easy and often useful to leave them separate. In
addition, you might want to have multiple controllers for the same view: a
mouse/keyboard controller and a script controller for example.

>
>
> > Another important difference between a model and a CDocument is that a model
> > encapsulates more than just data and functions that operate on it. A model is
> > meant to serve as a computational approximation or
> > abstraction of some real world process or system. It captures not only the
> > state of a process or system, but how the system works. This makes it very
> > easy to use real-world modeling techniques in defining your
> > models. For example, you could define a model that bridges your computational
> > back-end with your GUI front-end. In this scenario, the model wraps and
> > abstracts the functionality of a computation engine or
> > hardware system and acts as a liaison requesting the real services of the
> > system it models.
>
> Maybe if you tried again, you could write something sensible here.
> I've re-read this about a half-dozen times, and for all I got out of
> it, I might as well have been trying to read Chinese.

How's this: a document is often a big melting pot for all the stuff you
wantserialized into one file. A model is defined by something more important:
object-orientation. A model models something in the real world.


>
>
> > The biggest difference between CView and MvcViewport is that a viewport is not
> > derived from CWnd. The designers of MFC chose to implement the notion of a
> > view through derivation. MVC does it through
> > aggregation. This is a common theme throughout MFC and a common distinction
> > relative to MVC. In many cases, where MFC and Document/View use derivation,
> > MVC uses aggregation.
>
> Here, it should be pointed out, that you're talking _strictly_ about
> YOUR implementation of MVC, rather than MVC in general.

This is also true of the VisualWorks MVC implementation which I regard as themost
standard and theoritically faithful implementation. Besides, I certainly
makes more sense to aggregate the view into a window than to inherit for
all the obvious reasons.


>
>
> > In this case, a window aggregates one or more viewport objects and then
> > delegates to them when a paint event occurs.
>
> [ ... ]
>
> > In addition, because a viewport can be
> > aggregated into any window (CFrameWnd, CWnd, or CView), a viewport can be
> > displayed inside a CWnd, a CView or a dialog box
> > without modification. In addition, support for printing and print-preview
> > features is preserved.
>
> Hmm...are you of the opinion that you can't have one window contain
> another? How would the mere fact of derivation from CWnd prevent one
> sort of Window from containing some other sort of CWnd-derived object?

No. Windows can contain other windows. My point is that since a viewportis
aggregated into a window, it can go inside any window type. If it were
derived from a window, it would be statically bound to that window type only.

>
>
> > Another difference between MvcViewport and CView is that MvcViewport should
> > not contain menu handlers or command handlers of any kind. This responsibility
> > will be delegated to the view’s controller object.
> > Additionally, a MvcViewport class can easily be nested but a CView cannot. For
> > example, a MvcViewport may be a composite viewport containing several
> > sub-views, which may themselves contain several
> > sub-views.
>
> Hmm...this starts to sound a great deal as if you've merely changed
> responsibilities a bit: instead of CView's being contained in a
> CFrameWnd (or derivation thereof) you have views that can contain
> other views. I can see a theoretical advantage to that, but I can't
> say that I've seen a situation yet in which it seems like it would
> have been useful.

Not exactly. Remember that a CView and an MvcViewport are nothing
alike. A CView is merely a window that can contain a viewport which
is attached to a model. Similarly, a CWnd, a CFrameWnd, a CDialog
etc. can contain a MvcViewport without the viewport caring what
"decorates" it.

>
>
> My feeling right off, is that this is likely to make poor designs
> easier to implement, but have little or no real effect on better
> designs. However, I'll openly state that I'm NOT at all certain of
> this.

Hopefully, after you read my response, you feel differently.

>
>
> > In MFC, the CView is both the view and controller, taking on the
> > responsibilities of presentation and control. In small applications, it may
> > be simpler to handle user input in the view. Whereas in large applications,
> > the separation affords you greater modularity, reuse and control
> > exchangeability.
>
> In my experience, this is _rarely_ the case. Having used MVC in
> Smalltalk for quite a while, it's been my experience that in most
> cases, you end up with a 1:1 correspondence between views and
> controllers. You _can_ frequently use a common base class for all the
> controllers for a particular model, but in most cases, the controllers
> have to be specialized to the view: the example above of the user
> dragging data in a view is typical. Things like menu entries often
> make sense across all views/controllers on a given document/model, but
> many require tailoring and/or make no sense at all for particular
> views.
>
> There are sometimes advantages to separating control from display, but
> in my experience they're almost entirely in the realm of organization,
> not reuse. (Not to make light of organization: IMO, reuse is
> generally a pleasant by-product of OO programming that's easy to sell
> to management, but NOT its main advantage.)

I agree you to an extent. But, I've found many cases where it is useful to
separate out the controller. It can be very helpful
in some circumstances where the feature is distinct from the view.
For example, a controller to support the MS mouse wheel, or scroll bar
movement etc. Also, it can be useful to divide up all possible control
into logical blocks. For example, a drag and drop controller, an editing
controller etc. This allows you to pick the major blocks of control you
want or to pick an implementation of the control. For example, you
might have a clip board, OLE, and in-process implementation of your
drag and drop controller and you can pick the one you need.

> --
> Later,
> Jerry.

Thanks for your reply. The Smalltalk perspective on MVC was very interesting.

Dean

Anders N Weinstein

unread,
May 8, 1998, 3:00:00 AM5/8/98
to

In article <MPG.fbc01958...@news.rmi.net>,

Jerry Coffin <jco...@taeus.com> wrote:
>> So, why isn’t a CView reusable? Put simply, CViews depend on an
>> application-specific document type.
>
>Hmm...a view displays data from a document. Do you propose something
>that's supposed to display the data, without knowledge of the form or
>function of that data?

Of the criticisms in the Stingray paper, this one strikes me as the
most accurate. How does the MFC DocView design enable you write a
reusable data presenter as a view? Say you want a a pie chart
view or an object graphics functionality in a view that is going to be
re-used in many different applications. How do you do it, if a view
needs reference to a specific document type?

Of course you are right that a re-usable view has to know the *data
structure* it is presenting. Suppose we say that this view knows how to
present a CChartInfo data object. But our view certainly need not know
the type of the *whole application document*. The chart info object
might only be one sub-part of a complex document (shades of OLE). The
only thing a modular view should care about is that it is bound to some
CChartInfo object. Then you could embed these in many different
application documents or write an adapter for some existing data
representation to make its data accessible to the re-usable chart data
presenter.

It is quite remarkable to me that the most common and well-understood
sort or structuring technique, recursive or hierarchical decomposition,
is not built in to MFC documents or views.

Jerry Coffin

unread,
May 8, 1998, 3:00:00 AM5/8/98
to

In article <3552BE0B...@mindspring.com>, rd...@mindspring.com
says...

[ ... ]

> Still, I consider it pretty amazing that Xerox Parc in the mid-70's had
> a prototype computer that realized a GUI, a mouse-driven user interface,
> a very advanced object-oriented programming language (Smalltalk), an
> Integrated Development Environment, an Ethernet network, Email and
> the concept of WYSIWYG, packaged into a $10k personal computer.

Not really - the Xerox Star eventually made it onto the market for
around $10K, but that was quite a bit later. They certainly had Altos
doing roughly the same thing in the mid-70's, but I _really_ doubt
they could have been sold for much less than $50K apiece or so -- they
were built out of almost entirely custom hardware. Worse yet, they
used almost entirely bipolar logic, so they needed a fair amount of
cooling to keep from burning up too. It wasn't until 10 years later
(or so) that off-the-shelf microprocessors were powerful enough to run
Smalltalk reasonably well.

> Meanwhile, the Altair PC had a few LEDs and switches to flip.

...and was real, and could be bought for less than $1K.

> Oh god, I hope I'm not criticizing anyone's Altair :-)

I doubt it -- it's a pretty accurate description.



> If you can't count on MS' tutorial which they purport as the starting point for
> every MFC beginner as a reference for how to use MFC properly, then
> where would you suggest one look?

This isn't really particularly related to doc/view -- it's a specific
application of the general question "How should I map this problem
into classes that will solve the problem well." Since that's really
THE central question in most object oriented programming, answering it
is best done by reading good books on OO programming. The most
obvious would be Booch's, but there are certainly others.

> I think you've got it backwards. Quality isn't defined by how well something works
> when it works. Quality is defined by how infrequently something fails. So,
> I'd put it another way. The measure of Doc/View is by how many people have
> used Doc/View properly and still ended up with unsatisfactory results.

How many of those are _using_ Dov/View, and how many are really
_ab_using it? I don't expect a solid answer to this, as I'm not sure
one is available. My point is that every programming paradigm,
language, framework, etc., I've seen yet has been open to abuse.

> And I would take exception to the assertion that unsatisfactory results
> implies that one did not apply Doc/View properly.

I wouldn't say it's a given. However, it'd be interesting to know how
many of those failures are really due to problems inherent in
Doc/View, how may to MS' implementation of it, and how many simply due
to misuse of what MS has provided.

> Not true. MVC does map onto an application domain in a much more
> straight forward way than MS' implementation of Doc/View for the 6 key
> reasons previously site. It boils down to one essence: flexibility.
> MVC affords many more options in how your classes are architected,
> your data is partitioned etc. because we are in closer agreement
> with the theory.

I'm not entirely certain I agree -- I haven't used your particular
implementation, but I think the majority of the problem you're dealing
with stems primarily for misuse (or outright abuse) of Doc/View. In
particular, it seems (at least to me) that a lot of people more or
less forget what they know of good programming the minute they write
MFC code -- they tend to throw _everything_ into what the ClassWizard
generates. Rather than writing sensible functions to carry out parts
of what needs to be done, partitioning their data in sensible ways
based on its own structure, etc., all the code ends up on functions
generated by the Class Wizard, and all the data ends up directly in
the document. While I certainly wish MS did more to stress _using_
design skills people have learned when they're writing real programs,
I can't say it's really their fault when people do stupid things
either.

I'm trying to be careful NOT to imply that it's ONLY when people do
stupid things that failure results -- there may be more to the
situation than that. However, there's NO question that a LOT of MFC
code I've seen has been truly execrable, even quite a bit that was
written by people who clearly knew better.

[ interdependencies when adding new views and/or documents ]

> This problem isn't going to always occur. It is most likely to occur in a tool that
> has one primary document type and is very complex. Take a UML modeling tool as an
> example. Primarily one document that would probably be quite large and touched by
> most or all team members.

Hmm...I haven't worked on such a thing, so I guess I'd have a hard
time commenting on it. OTOH, back when Rational Rose was quite new, I
played with it a bit, and a friend and I contemplated what it would
take to write something better. We never wrote any code, but I didn't
see much that looked problematic to me. One thing I should add is
that if the document was complex, I'd probably decompose things by
having a couple of layers to things, with the document probably
primarily containing a collection of other items, each of which
derived from a common base so I could manipulate them easily.

I.e. where it sounds like you'd build the document from a number of
other documents, I'd probably just have the document contain a number
of more or less independent objects. OTOH, either is an improvement
over the typical situation of simply putting everything directly in
the document.

> How's this: a document is often a big melting pot for all the stuff you
> wantserialized into one file. A model is defined by something more important:
> object-orientation. A model models something in the real world.

Okay -- I'll buy the possibility that many people write CDocument
classes with lots thrown in for little real reason. However, I think
this is more a lack of education (or application of it) on many
people's part than a characteristic of MFC itself.

> Thanks for your reply. The Smalltalk perspective on MVC was very interesting.

Oddly enough, a similar dichotomy existed for years in the Smalltalk
universe as well: PARCPlace ST-80 used MVC, while Smalltalk/V used
something thing Doc/View, with only two classes. At least for the
size of projects I worked on, I generally preferred the latter, though
if I'd spent more time on really big projects, that might have been
different. In all honesty, I've used Smalltalk more for prototyping,
with the projects being moved to other languages by final production,
so even when the project was going to be quite large, the prototype
typically wasn't.

Robert C. Martin

unread,
May 8, 1998, 3:00:00 AM5/8/98
to

de...@stingray.com wrote:
>
> For more information on MVC go to http://www.stingray.com/otpmfc and download
> the whitepaper.
>
> ---------
>
> The Model-View-Controller (MVC) Framework
>

I found this paper to be quite good. The points it makes are salient,
and appropriate. This is an excellent treatise on the inadequacy of
MFC, and gives some important clues as to how to structure a superior
MVC architecture.

However, I was concerned that MVC was not explained adequately.
Morevoer, it seems that the second half of the paper is more a
"hook" for a stingray product than a reasoned exposition of MVC.

The implication is that the best way to use MVC is to buy the
stingray framework. I have my doubts about whether this is true,
since MVC is not a very difficult framework to build from scratch.

So my question is this: What value does the stingray framework add
to traditional MVC architecture? How much functionality does the
framework supply? What aids and helps does the framework give to
the engineer?

An example would be useful.

--
**We are looking for good engineers, See our website
**for more information.

Robert C. Martin | Design Consulting | Training courses offered:
Object Mentor | rma...@oma.com | Object Oriented Design
14619 N Somerset Cr | Tel: (800) 338-6716 | C++
Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com

"One of the great commandments of science is:
'Mistrust arguments from authority.'" -- Carl Sagan


Tony Gee

unread,
May 9, 1998, 3:00:00 AM5/9/98
to

In comp.object de...@stingray.com wrote:
: In article <6ispk8$6gp$1...@reader1.reader.news.ozemail.net>,
: "Patrick Wray" <tw...@ozemail.com.au> wrote:
: >
: > Do you happen to know from experience or hearsay whether the JFC (Swing)

: > library provides a good implementation of MVC? I haven't really looked into
: > this yet, but now seems like a good time to start.

: I've only looked very briefly at the JFC implementation of MVC. I got the


: impression it was more like document/view, but I could be wrong.

JFC uses a modified MVC which they call Model/Delegate where the VC part
is merged together (a common modification of the MVC architecture). For
a really good overview of JFC's architecture take a look a Javasoft's
whitepaper on the topic:

http://www.javasoft.com/products/jfc/swingdoc-static/swing_arch.html

A snippet of their discussion of the delegate:

"We quickly discovered that this split didn't work well in practical
terms because the view and controller parts of a component required
a tight coupling (for example, it was very difficult to write a
generic controller that didn't know specifics about the view). So
we collapsed these two entities into a single "UI delegate" object."

Tony

Patrick Logan

unread,
May 9, 1998, 3:00:00 AM5/9/98
to

In comp.object Tony Gee <tgee-...@gpu.srv.ualberta.ca> wrote:

: JFC uses a modified MVC which they call Model/Delegate where the VC part


: is merged together (a common modification of the MVC architecture).

Merged together, except the delegates are "pluggable" where you can have
arbitrary listeners plugged into respond to specific events without having
to create subclasses. So maybe this is a "hybrid" rather than either MVC
or M(V+C).

Dean Hallman

unread,
May 9, 1998, 3:00:00 AM5/9/98
to


Anders N Weinstein wrote:

> In article <MPG.fbc01958...@news.rmi.net>,
> Jerry Coffin <jco...@taeus.com> wrote:

> >> So, why isn’t a CView reusable? Put simply, CViews depend on an
> >> application-specific document type.
> >
> >Hmm...a view displays data from a document. Do you propose something
> >that's supposed to display the data, without knowledge of the form or
> >function of that data?
>

> Of the criticisms in the Stingray paper, this one strikes me as the
> most accurate. How does the MFC DocView design enable you write a
> reusable data presenter as a view? Say you want a a pie chart
> view or an object graphics functionality in a view that is going to be
> re-used in many different applications. How do you do it, if a view
> needs reference to a specific document type?
>
> Of course you are right that a re-usable view has to know the *data
> structure* it is presenting. Suppose we say that this view knows how to
> present a CChartInfo data object. But our view certainly need not know
> the type of the *whole application document*.

Exactly.

> The chart info object
> might only be one sub-part of a complex document (shades of OLE). The
> only thing a modular view should care about is that it is bound to some
> CChartInfo object. Then you could embed these in many different
> application documents or write an adapter for some existing data
> representation to make its data accessible to the re-usable chart data
> presenter.
>
> It is quite remarkable to me that the most common and well-understood
> sort or structuring technique, recursive or hierarchical decomposition,
> is not built in to MFC documents or views.

I couldn't have said it better myself. <g>

Dean


Dean Hallman

unread,
May 10, 1998, 3:00:00 AM5/10/98
to


Robert C. Martin wrote:

> de...@stingray.com wrote:
> >
> > For more information on MVC go to http://www.stingray.com/otpmfc and download
> > the whitepaper.
> >
> > ---------
> >
> > The Model-View-Controller (MVC) Framework
> >
>

> I found this paper to be quite good. The points it makes are salient,
> and appropriate. This is an excellent treatise on the inadequacy of
> MFC, and gives some important clues as to how to structure a superior
> MVC architecture.

Thanks for the summation.

>
>
> However, I was concerned that MVC was not explained adequately.
> Morevoer, it seems that the second half of the paper is more a
> "hook" for a stingray product than a reasoned exposition of MVC.

This paper is an excerpt and represents maybe a third of the total documentation.
There is quite a bit more describing MVC in detail with case studies, tutorials
etc. Still, I agree that the MVC introduction could be improved upon.

>
>
> The implication is that the best way to use MVC is to buy the
> stingray framework. I have my doubts about whether this is true,
> since MVC is not a very difficult framework to build from scratch.

I would agree that some of the fundamental concepts are not very difficult to
implement - the subject/observer design pattern for example. But, other parts of
the framework are more difficult because of limitations inherent in MFC. For
example, MFC gives you no way to route windows message to a non-CWnd-derived
class. This makes implementing the controller piece very problematic.

> So my question is this: What value does the stingray framework add
> to traditional MVC architecture? How much functionality does the
> framework supply?

At this point, the framework provides the fundamental MVC architecture with an
undo/redo architecture built on top. The framework supports macro record and
playback, zooming and panning, off-screen buffered rendering, layout management,
persistence, scripting, some facilities for regression testing, just to name a
few. We also have an _extensive_ structured graphics framework built on top of MVC
that handles symbols, composites, links, a sophisticated style architecture etc.
etc. And, we've just gotten started.

> What aids and helps does the framework give to
> the engineer?

Aside from a better conceptual model for designing GUI applications in MFC, it
gives you a good deal of prepackaged functionality.

>
>
> An example would be useful.

We do have several examples in the documentation but they are too time-consuming
and involved to place here. Our web site has some examples that were built using
our MVC implementation under the OT PRO and OD sections.

Robert C. Martin

unread,
May 10, 1998, 3:00:00 AM5/10/98
to

Dean Hallman wrote:

>
> Robert C. Martin wrote:
> >
> > The implication is that the best way to use MVC is to buy the
> > stingray framework. I have my doubts about whether this is true,
> > since MVC is not a very difficult framework to build from scratch.

Having read your other article that described the stringray framework
in more detail, I have to withdraw this complaint. It looks to me
like you have a rather well thought out design. This is not
an endorsement, since I haven't actually used the framework. But
the issues covered by the article indicate to me that the designers
were *thinking* while they did the design. Something that I have
found to be rather rare in GUI frameworks.

It appears that the framework is actually quite elaborate, and simply
uses MVC as an underlying theory, while adding lots of value for
dealing with lots of the problems faced in GUI design.

Chris Hill

unread,
May 12, 1998, 3:00:00 AM5/12/98
to

In article <6ispk8$6gp$1...@reader1.reader.news.ozemail.net>, tw...@ozemail.com.au
says...

>
>
>de...@stingray.com wrote in message <6isk35$ttv$1...@nnrp1.dejanews.com>...
>>Still, several stated that they wanted a more detailed comparison of
>>Document/View versus MVC. So, here it is. If you are one of those people
>who
>>wanted this comparison, read on.
>
>
>[ treatise on MVC vs Document/View snipped ]
>
>Fascinating reading! These are brilliant ideas.
>
>Do you happen to know from experience or hearsay whether the JFC (Swing)
>library provides a good implementation of MVC? I haven't really looked into
>this yet, but now seems like a good time to start.
>

You might also look at Borland's JBCL which comes with JBuilder. Is is an all
Java solution that is much more MVC than Swing is. The version in JBuilder
uses the Swing components as a base, but maintains the superior MVC model from
JBCL (the previous version of JBCL was based on AWT).

Just to give you an idea about the system works, there are serveral basic model
interfaces: Singleton, Vector, Matrix, Graph (ACyclic). You would implement
one of these interfaces in your _existing_ data storage class and then your
data will flow into a control based on the view classes.

So a vector might displayed in a Listbox or a Tab Control, while a matrix would
be displayed in a grid, and a graph in a tree control.

JBCL further makes a distinction between the Painter and the Editor. The
Painter displays the data to the user by drawing it on a Canvas while an editor
provides an interface to change the value. You can have multiple painters and
editors and plug them in to each control as required.

JBCL allows you to nest painters so that you could have a composite painter
that paints both a picture and text that represent your object.

I must agree that the original post raised many issues that I have noticed
about MFC's Doc/View architecture. It is hard to produce a component view that
can be reused. When you write to this model, it seems that everything becomes
a tangled mess. You end up with one big application that is hard to break up.
Perhaps it is because I lack the skill to use the model correctly as some have
suggested, but I believe that it is a property of MFC.

I really like the Model View Controller idea that a general data structure like
a vector, matrix or graph can hold my objects (without knowing anything about
my objects). I can specify several ways to draw (Painters) or edit my data,
and plug these into standard controls. Each part of the system can be replaced
and nested to form composite documents.

--
Chris Hill
hil...@cs.purdue.edu


Ashley Frieze

unread,
May 19, 1998, 3:00:00 AM5/19/98
to

>I must agree that the original post raised many issues that I have noticed
>about MFC's Doc/View architecture. It is hard to produce a component view
that
>can be reused. When you write to this model, it seems that everything
becomes
>a tangled mess. You end up with one big application that is hard to break
up.
>Perhaps it is because I lack the skill to use the model correctly as some
have
>suggested, but I believe that it is a property of MFC.


The thing which Doc View has, is an inherent simplicity. This stands strong
over the rather wide-range of classes that an MVC app might need to get
going.

However, the fact that a View must know the type of its document is a
problem for reusable code. The solution, however, is simple.

You write a view in two classes, a base class, which does drawing and
handles mouse interaction and which has a series of pure virtual functions
for accessing the data which is to be rendered. You then have a
light-weight, app-specific sub-class which links the data-getting-functions
to the outside world.

Alternatively, you can go a step further and write UI objects. These objects
have drawing and mouse handling methods and data-getting methods (pure
virtual again). To use these UI objects in a particular view, you sub-class
them to attach the data getting functions to the outside world (these
functions could, just-as-easily be routed through command handlers to allow
them to be attached to any window without the need for app-specific
subclass) and then you provide the logic inside the view to determine
whether to ask the UI object to draw onto the view's dc at any stage and
whether to pass the mouse-handler opportunities to the UI object. In my UI
classes, I have my mouse-handlers return a status code to indicate whether
the view needs to redraw or something.

The point I'm making is that DocView can be used without much extra work in
a more reusable manner.

Just my litle thoughts.

Dean Hallman

unread,
May 20, 1998, 3:00:00 AM5/20/98
to


> The thing which Doc View has, is an inherent simplicity. This stands strong
> over the rather wide-range of classes that an MVC app might need to get
> going.

I don't see it this way. MVC may have more classes, but that's because it
answers questions Doc/View leaves completely unaddressed. To say that Doc/View
is simpler because it has fewer classes is like saying that an article that
omits paragraphs is a simpler thing to read. You're left to infer what's
unsaid, and everyone infers differently (which inhibits reuse). In fact, a
major motivation for MVC is to provide thorough and common answers to many
questions Doc/View forgot.

Another point, MVC has better support for composition. MVC could have few
classes too if we threw everything into one class, but that reduces the
potential to employee hierarchical composition techniques.

Besides, how many more classes does MVC really have? I believe you're counting
all the MVC base classes, but not Doc/View's base classes. If you count all of
CDocument and CViews base classes (i.e. CObject, CCmdTarget, CWnd etc.) than the
comparison is fair and the class count is comparable.

> However, the fact that a View must know the type of its document is a
> problem for reusable code. The solution, however, is simple.
>
> You write a view in two classes, a base class, which does drawing and
> handles mouse interaction and which has a series of pure virtual functions
> for accessing the data which is to be rendered. You then have a
> light-weight, app-specific sub-class which links the data-getting-functions
> to the outside world.
>

This was one of the potential solutions that I outlined in the original post.
But I also pointed out that this solution is not really using Doc/View, it's
avoiding it. To reuse a Doc/View pair, you eliminate the Document? And, if
you do that, your CView-derived class may as well have been CWnd-derived. Once
again, by definition this is not Doc/View. (Just because a class derives from
CView doesn't mean its Doc/View adherent).

Also, this approach comes after the realization that Doc/View doesn't yield
reusable code, which is sometimes too late.

Lastly, it's just not convenient. Why can't we just use a doc/view pair as
intended without compromising reuse? The answer is, you can, but not with MFC's
interpretation of the paradigm.

> Alternatively, you can go a step further and write UI objects. These objects
> have drawing and mouse handling methods and data-getting methods (pure
> virtual again). To use these UI objects in a particular view, you sub-class
> them to attach the data getting functions to the outside world (these
> functions could, just-as-easily be routed through command handlers to allow
> them to be attached to any window without the need for app-specific
> subclass) and then you provide the logic inside the view to determine
> whether to ask the UI object to draw onto the view's dc at any stage and
> whether to pass the mouse-handler opportunities to the UI object. In my UI
> classes, I have my mouse-handlers return a status code to indicate whether
> the view needs to redraw or something.

Now your starting to describe some of the other classes in MVC that you
initially site as introducing complexity compared to Doc/View. Interesting that
you needed them anyway. Your UI Objects are very similar to generalized classes
MVC already has built in. But, you had to come up with these classes yourself
because Doc/View omits them.

One interesting Difference between your UI Object and MVC's:
In MVC, the UI Object equivalents can plug-into the CWnd they're inside of and
listen to the messages it receives. This means your view doesn't have to do
anything to pass mouse-messages onto the UI objects. They'll hear them by
themselves. This is nice because the view need not know anything about UI
objects, which reduces coupling and simplifies things.

> The point I'm making is that DocView can be used without much extra work in
> a more reusable manner.
>

Well, I've not found this to be the case. Also, there are much better
architectural guidelines than those Doc/View purports. Sometime, it seems the
AppWizard, ClassWizard, Doc/View defaults are too easily accepted and too
sparingly examined. In other words, I believe many people were designing
better architectures before they started letting the Wizards and Doc/View do
their thinking for them.

> Just my litle thoughts.

Thanks,
Dean Halman
Stingray Software


Andy Yee

unread,
May 20, 1998, 3:00:00 AM5/20/98
to

In article <35627674...@mindspring.com>, Dean Hallman <rd...@mindspring.com> wrote:
>
>
>Well, I've not found this to be the case. Also, there are much better
>architectural guidelines than those Doc/View purports. Sometime, it seems the
>AppWizard, ClassWizard, Doc/View defaults are too easily accepted and too
>sparingly examined. In other words, I believe many people were designing
>better architectures before they started letting the Wizards and Doc/View do
>their thinking for them.
>

So does Stingray have an AppWizard to construct the most basic MVC classes?

--------------------------------------------------------------------------------
Andy Yee Corporate E-mail: an...@xiotech.com
Principal Software Engineer Corporate Web Page: http://www.xiotech.com
XIOtech Corporation Personal E-mail: n...@yuck.net
Eden Prairie, MN Personal Home Page: http://www.visi.com/~nde

"Question authority...and the authorities will end up questioning YOU!"
--------------------------------------------------------------------------------

0 new messages