Re: Text terminal rendering design



H. S. Lahman wrote:
The client should NEVER be knowingly invoking methods of your UI
objects.

I guess that you are speaking figuratively here. If the client cannot
invoke methods of any object in my subsystem, how can it send
messages to my subsystem? I infer that there is a facade object that
the client can invoke methods on and using poetic licence we are not
calling it an object.

The client sends a message to your UI interface. Your UI
interface then re-dispatches that message to some method in your
UI. But the client should have no idea what method, if any,
responds to the message.

This all sounds a lot like exactly what my current design already
does, so I would take it as confirmation of the quality of my design,
but for one detail. The issue that I think might be important is that
I do not quite fallow the GoF facade pattern in that my facade is
made of multiple objects.

Specifically, I have both a Terminal class and a SymbolFactory class
and all objects of both classes act as a combined facade for the
subsystem. I cannot see any harm in this design. Just because the
client invokes a method on a particular factory does not mean the
client knows even one detail about what happens in response to that
message. Correct me if I am wrong.

An alternative would be for the client to request a specific factory
by a factory ID that is passed in as data, but I can see only a
slight increase in complexity and no benefit at all from that.

It's all a matter of
bigFacade.createSymbol(factory,symbolData);
versus
factory.createSymbol(symbolData);
Why should I or the client or anyone care which is used? I'm exposing
the existence of a factory object with certain methods, but that is
no worse than exposing the existence of a facade object. I expect
that you see some sort of mess resulting from the second way, but I
need that mess to be illustrated clearly before I will be able to see
it.

In all this I have ignored the Symbol objects because they are mere
data objects and not worthy of all the discussion we have been having
over them. They only exist to be passed around in messages as part of
the data, even in my current design.

The interface provides two-way decoupling. The client can't know
about objects in your subsystem, so it can't talk to them
directly. Conversely, your UI service can't know about objects
like Icon in the client so it can't talk to them.

This is exactly the sort of thing that needs to be explained and
justified rather than simply stated. Even if the client knows about
objects in my subsystem, it does not mean that it knows the
implementations of those objects. There can still be limitless layers
of complexity that are hidden from the client beneath those exposed
objects. In fact, those exposed objects could be nothing more than
place-holders to satisfy what the client expects from the subsystem
interface while having no role at all in the implementation of the
subsystem.

The GoF Facade pattern is designed to reduce complexity for the
client. If the complexity is actually increased by trying to pack
everything into a unified facade object then doing so is not
appropriate.

Here is a quote from Design Patterns, Implementation of Facade
section:

"A subsystem is analogous to a class in that both have interfaces,
and both encapsulate something--a class encapsulates state and
operations, while a subsystem encapsulates classes. And just as it's
useful to think of the public and private interface of a class, we
can think of the public and private interface of a subsystem.

"The public interface to a subsystem consists of classes that all
clients can accesss; the private interface is just for subsystem
extenders. The Facade class is part of the public interface, of
course, but it's not the only part. Other subsystem classes are
usually public as well."

On the utility of handles:
[...]
To clarify, my problem is not with handles per se. As I mentioned,
one really can't implement decoupling interfaces in asynchronous
environments without them. My problem is with using them in this
context. I suspect the client already has a reasonable way to
identify Icons. Rather than having the client keep track of how
your Symbol addresses map to Icon identity, I think it would be
better for the client to just provide you with Icon identity and
let you map that to Symbol identity internally.

I think I can see why you would think that, but I have concerns. Your
suspicion that the client already has an identifier for symbols is
not always correct. In fact, in the practical implementation that I
am working on, often the client uses a factory to create a symbol
constructively out of several parts and then takes the resulting
Symbol as its only identifier for the new symbol. If the UI subsystem
did not provide the identifier the client would be forced to create a
new arbitrary identifier in that case.

Plus, the client is not actually forced to keep track of what each
Symbol object represents. It is not impossible for it to request that
the factory create a new copy of a Symbol that it has already
created. So the client does not need keep a table mapping 'A' to one
Symbol and 'B' to another and 'C' to another, it can just order the
creation of those Symbols each time it needs them.

Letting the client keep track of the Symbols that it needs also
allows the client to discard Symbols that it no longer needs, while
the subsystem would have to maintain a list of every symbol ever
created. (Or else it would need a dispose(symbolID) method, which
works but requires special garbage collection effort from the
client.)

The pipeline idea is fascinating. I will have to think further on it.
.


Quantcast