Re: Text terminal rendering design
- From: Brendan Guild <dont@xxxxxxx>
- Date: Mon, 21 May 2007 21:16:11 GMT
H. S. Lahman wrote in
Ssj4i.10197$kf1.3056@trnddc01:">news:Ssj4i.10197$kf1.3056@trnddc01:
Responding to Guild...
On the need for identity: are handles the way to go?
The problem I am concerned about is giving the client one Symbol's
address in a handle (when a conversion is involved) and the client
has a subsequent request that applies to the other Symbol. For
example suppose the handle you always give back is for the
"natural" Symbol that is initially created, which might not be
augmented for background color needed for a graphic terminal
rendering. The client wants to later change the color and provides
that handle in a message requesting the color change.
It would be broken to give the natural Symbol, when what we need is
the Symbol that is native to the Terminal. The Terminal has an
associated factory and the client knows that the Symbols it needs to
use are the ones produced by that factory. Since that factory always
produces symbols of that sort, there is no choice of which Symbol is
the correct one to give to the client.
If the client is doing a multiple part conversion then the client
will also handle Symbols that are at an intermediate stage, but that
is its responsibility if it choose to do that.
On separating concerns of instantiation and data acquisition:
I mean that SymbolFactory has methods for accessing a certain set
of standard sources, and to access other sources you need a
method somewhere else to produce your Symbol and then use a
SymbolFactory to get it into the desired encoding.
I am concerned that there may be misunderstanding because your
question offers a false dichotomy. To the question "Do you have
multiple methods for different sources in the same
[SymbolFactory] subclass?" the answer is certainly yes, but I
also have classes for accessing individual sources that are not
handled by any of the methods of SymbolFactory.
These other classes also produce Symbol objects to hold the data
that they access, but they are not subclasses of SymbolFactory
because SymbolFactory only has methods for dealing with the few
standard sources. In fact, I see no reason why the client could
not instantiate the Symbol objects itself if the client has
symbol data, since Symbol object are merely data objects.
Wow. I afraid don't like the sound of that at all; it seems really
messy.
I must admit that it did sound bad to me when I wrote it. The idea is
as simple as the fact that the entire Symbol class is nothing but a
data holder, meaning its instantiation is always trivial once we have
the required data.
I think a trivial instantiation can be handled by the client as part
of forming the message to be sent to the subsystem.
Since I don't want the client to know the actual encoding of the
Symbol that is needed for the terminal, I give it a SymbolFactory
that will convert the data that the client has to offer into a Symbol
object that has the correct encoding and then I give that Symbol
object to the client so it can display it as necessary.
For an instantiation problem this complex I think it would
be highly desirable to use subclasses of [SymbolFactory] for all
instantiation so that there is a standardized way of handling
instantiation (i.e., polymorphic access to a single
generalization) and one can define context in the same way for all
instantiations (i.e., one always instantiates the same
relationship).
Presumably the [SymbolFactory] subclasses are mapped 1:1 to
different symbol subclasses.
A SymbolFactory always produces a Symbol of the same subclass.
However, it could accept Symbols of many subclasses as input.
Then the source of the initialization data is orthogonal and one
has a choice between providing that substitution as separate
methods or as combinatorial subclasses of [SymbolFactory].
The source of the initialization data is the client, so it is
certainly orthogonal.
It is unlikely that I understand what you are suggesting, because it
would be impractical to do what it seems you are suggesting.
Obviously I cannot have a different subclass of SymbolFactory for
each different conversion procedure, since each procedure by
definition works with data in a different form. The client cannot
supply that data polymorphically if it has to be in a different form
for each subclass.
That is why the nature of the problem strongly suggests to me that I
should make the procedures into different methods.
SymbolFactory {
Symbol fromSymbol(Symbol)
Symbol fromASCII(char,Color,Color)
Symbol fromUnicode(int,Color,Color)
}
The definition of SymbolFactory locks in the sort of input data it
can receive, except that it can receive a Symbol object which has the
possibility to hold many sorts of data in some intermediate form.
So if only subclasses of SymbolFactory were allowed to make symbols,
then the only symbols we could ever display would be those ultimately
derived from (ascii,color,color) or (unicode,color,color). Despite
the variety of unicode symbols, that is unacceptable. It is also
completely unnecessary, since I am fully capable of offering other
mechanisms for creating symbols.
All that the UI subsystem asks is that the Symbols be passed through
a certain given SymbolFactory to ensure they are in the correct
encoding before being displayed.
SymbolFactory could just have only one method, the 'fromSymbol'
method. The other methods are just there for the convenience of the
client, since those are very common froms of data.
What you seem to be suggesting is either that SymbolFactory should
have dozens of methods, one for each possible input data format, or
else that the SymbolFactory factory should correspond to exactly one
input data format and have a subclass for each output encoding. In
the second case, it would look like this:
ASCIISymbolFactory {
Symbol fromASCII(char,Color,Color)
}
UnicodeSymbolFactory {
Symbol fromUnicode(int,Color,Color)
}
There of course are not subclasses of any SymbolFactory class, since
they have different methods. The large number of classes is not the
impractical part: that comes once again in the form of a method for
every possible input data format because in order for the client to
get a hold of one of these factory objects it needs to call a method
of Terminal to access it. Like this:
Terminal {
....other stuff...
ASCIISymbolFactory ASCIIFactory()
UnicodeSymbolFactory UnicodeFactory()
...etc for all input data formats...
}
Is the above really the separation of concerns that you are
suggesting? It certainly seems more horrible than my current design.
Even in my current design the SymbolFactory is not responsible
for actual data acquisition; it is only responsible for taking
already acquired data and converting it into the proper encoding.
The actual acquiring of data is a responsibility for the client.
That's fine if it is a simple computational conversion on an
attribute-by-attribute basis. It would normally be the factory's
job to do that sort of conversion. But some of your conversions
seem more complicated than and I would push for delegation of the
responsibility.
But cannot you explain to me why I should have a SymbolFactory at all
if I delegate out its only responsibility? Symbol objects are data
object; all they have is data. Once the data is in the correct form,
there is nothing left to do. The SymbolFactory is a converter of data
and nothing else; if I delegate that job then SymbolFactory has
nothing.
All I'd be doing is changing the name of SymbolFactory, which I
probably should do since it might be causing this confusion.
On why symbols symbols are created without displaying them:
There is something missing here because I can't follow this
argument. What you have described is a performance requirement for
your UI software. That's fine and resolving it may require
anticipatory Symbol creation.
What I don't follow is why the client cares anything about how you
resolve that requirement. The client just wants a symbol displayed
and tells you when to do that. It is up to your software to do
whatever is necessary to do that efficiently.
It is true that you can push that responsibility upon the subsystem.
I certainly have nothing to suggest that you cannot. That is a real
hole in my argument.
So then what sort of design would you suggest? Remember that if you
want to let the subsystem decide when to create a symbol, you cannot
have the client spring its representation of a never-before-seen
symbol upon the subsystem the very moment that symbol is to be
displayed, because that would give the subsystem no choice at all of
when to create that symbol.
Oddly, I thought the design you were suggesting would have always
had symbols popping up by 'surprise' in that manner.
IOW, resolving the performance requirement determines when Symbols
need to be created in memory. There are any number of techniques
for doing that ranging from instantiating them all at startup to
some sort of fancy LRU scheme.
I think those techniques need a little more detail or at least
references. Can I instantiate them all at startup if there is no
finite set of all symbols that might be used? Does that particular
technique become impossible in that case? Even if it were possible I
am not eager to keep track of a permanent list of all possible
symbols, especially if that list includes millions of symbols.
Does LRU stand for Least Recently Used? Are we talking about the
least recently used symbol? Symbol creation has to happen before a
symbol is used even once, so what relevance could the least recently
used symbol have?
I cannot see what those requirements could be. I have already
talked about how the client requires control over the moment at
which symbol conversion happens. Other than that there is just
converting and displaying symbols.
Actually, I don't think you have. All you have said is that in
your design the client has control over when the conversion
happens.
Yes, looking back upon previous posts I see that you are right. I
never actually said that it is a requirement that the client control
when the symbol is created. I thought I had, but the fact that I
hadn't likely reflects the fact that it is not truly a requirement.
The only real requirements is just what I have said in previous
posts: Symbol creation cannot happen at the time that the symbol is
displayed. (Nor can it happen afterwards, of course).
Another requirement is that the subsystem cannot know all the symbols
that will be used in advance for creating all the symbols at startup.
I had inferred from those things that the subsystem was in no
position to decide when a Symbol should be created. Perhaps that
inference is incorrect.
What I am pushing back on is why that should be the case because at
least superficially it seems to trash subject matter cohesion.
Then feel free to suggest a way to let the UI subsystem decide the
Symbol creation time.
[...]I am getting the impression that there is some suite of "generic"
Symbols that are always around from which the client selects
particular ones for display.
I was thinking in terms of something like base Symbols for the
ASCII character set that the client might select from.
In an abstract sense I suppose that ASCII characters always exist
even before the application starts and after it finishes. Those
symbols are just represented by integers. I don't consider myself
responsible for creating those symbols because no conversion is
required.
However, if a certain Terminal subclass represented its symbols as
pure ASCII with no color or font or anything else, then the
SymbolFactory for that Terminal would produce a subclass of Symbol
that was just a wrapper around that integer value.
BTW, what is a 'terminal' in your world? In particular, does you
application ever need to instantiate more than one terminal at a
time or more than one terminal in a session?
From a UI perspective a terminal is an array of symbols and blankspaces that is used to display whatever the application needs to
show. I have never seen an application use more than one of those,
but it would not be inconceivable.
However, I have been designing the subsystem with the assumption that
only one Terminal object will be instantiated at a time and most
likely for the entire duration of the application.
There is the possibility that one platform might be such that more
than one subclass of Terminal could be used. In that case an
application could theoretically allow the user to change the terminal
to an alternate display mechanism. Upon some command from the user,
the application would close the current terminal and open a different
one. The might be done on a platform that supports both PDCurses and
graphics, for example.
.
- Follow-Ups:
- Re: Text terminal rendering design
- From: H. S. Lahman
- Re: Text terminal rendering design
- References:
- Text terminal rendering design
- From: Brendan Guild
- Re: Text terminal rendering design
- From: H. S. Lahman
- Re: Text terminal rendering design
- From: Brendan Guild
- Re: Text terminal rendering design
- From: H. S. Lahman
- Re: Text terminal rendering design
- From: Brendan Guild
- Re: Text terminal rendering design
- From: H. S. Lahman
- Re: Text terminal rendering design
- From: Brendan Guild
- Re: Text terminal rendering design
- From: H. S. Lahman
- Re: Text terminal rendering design
- From: Brendan Guild
- Re: Text terminal rendering design
- From: H. S. Lahman
- Re: Text terminal rendering design
- From: Brendan Guild
- Re: Text terminal rendering design
- From: H. S. Lahman
- Text terminal rendering design
- Prev by Date: Re: Turned based games and model-view-controller
- Next by Date: Re: non mutually exclusive subtypes.
- Previous by thread: Re: Text terminal rendering design
- Next by thread: Re: Text terminal rendering design
- Index(es):
Relevant Pages
|
|