[stringtemplate-interest] getting rid of StringTemplateGroupLoader
Zenaan Harkness
zen at freedbms.net
Sun Nov 8 21:37:39 PST 2009
On Sun, Nov 08, 2009 at 05:20:38PM -0800, Terence Parr wrote:
> inheritance and polymorphism. To make inheritance work in the previous
> version we said something like:
>
> group AdminView : GeneralView;
Ahah! Time to strike :)
Multiple-inheritance/ MI - yay!
OK, now MI is considered possibly challenging to implement.
What is it I really want?
I want a complexity management tool.
Java provides my precedent. In Java we do:
import java.net.*;
import java.io.*;
import java.awt.Button;
import static my.static.Interface.*;
Re. inheritance, java has single inheritance, with multiple interfaces
(the safe design-by-composition vs unsafe design-by-inheritance).
BUT, we DO have mutliple-imports, which is a library style complexity
management mechanism.
So, the complexity management tools in our reference of Java are:
- Single inheritance clause.
- Multiple interface "implements" clauses.
- Multiple library "uses" or "imports" clauses.
Referencing our friendly Design Patterns, we have, respectively:
- design by inheritance (inheritance clause)
- design by composition (implements and import clauses)
Of course, the group "inherited from", in the Java way, would first
have to be explicitly 'imported' as well. so each mechanism
interrelates
Java is evidently a little strict in requiring such specification of
all imports, alternatively allowing the programmer to fully-qualify
the items not otherwise imported.
A classpath (templatepath) is provided as part of the java (st)
runtime conveniences/ necessities.
It appears to me that Java does some sort of scanning/ loading/
hashing thing on all classes (template groups) that it finds as it
scans the classpath when it first loads a particular item.
This speeds up subsequent lookups which are thence already hashed.
Then, as import(/uses), extends (inherits) and implements (implements
specified interfaces) clauses are encountered, either the runtime is
already aware of the named group, interface or template (class,
interface or method) or an error is thrown.
ST could borrow the concept of 'package' (hey, let's call it package)
and require groups and templates referenced from within a template/
group, to be explicitly imported, just like in Java, or otherwise
fully qualified when used.
Simplifies the loader.
Provides various complexity management tools, great for large systems.
Aligns closely with expectations and experiences with Java.
The design of Java, with it's plentiful complexity management tools -
packages, classes, interfaces, methods, classpath, imports etc, is
proven to work well for supporting both very large, as well as small,
systems.
Let's take advantage of these proven things, yes?
> That means that we are creating a new group derived from GeneralView.
> Any template that we don't find in AdminView, we will look up in
> GeneralView. This lets us inherit and refine templates from above. As
> the comment suggests, we need the group file loader so that ST knows
> how to locate GeneralView as it parses that file. I no longer have
> that header inside group files so I don't think we need the group
> loader anymore; we will construct the hierarchy manually:
Sounds ... manual.
> STGroup g = new STGroupDir("GeneralView"); // the default look of the
> website let's say
> STGroup a = new STGroupDir("AdminView"); // a specialization of the
> general view for a website
> // now make 'a' load files from 'g' that it can't find
> a.setSuperGroup(g);
How about something like this:
StringTemplateEngine e = STFactory.getPlatformInstance();
e.addTemplatePath("~/st/mylibs");
e.addTemplatePath("C:\st\mylibs"); // Windows version
ST t1 = e.getTemplate("mydb/AdminBean");
ST t2 = e.getTemplate("myviews/AdminView");
Map myAtts = ...
Map myOverrideAtts = ...
t1.setAttributes(myAtts);
t2.setAttributes(myAtts);
t2.addAttributes(myOverrideAtts);
t1.toString()...
t2.toString()...
And inheritance, interfaces and imports, are all included, Java-style,
within the template group files themselves.
This to me looks clean.
Of course, no reason to not have "programmatical assembly of templates
and groups" api, as we have now. But I imagine, for any system of
significant size, the process I suggest above will be a godsend.
I've been craving for such simplicity for a while, and was
contemplating for some time (for when I had time) to create a separate
module which would do a little custom parsing and assembling, to
effectively get this auto-import/multi-inheritance type thing off the
ground for my own system. But a generic solution is always preferable.
Q:
Does the above suggestion look clean, workable, and implementable?
...
> This will decrease complexity significantly (by removing the entire
> concept of group loader).
Nice. But we should not need to put complexity back onto the ST user.
Let's follow Java's lead, and make ST more structured - increase
performance of ST, and provide greater flexibility and complexity
management to the user, at a small cost of syntax overhead (to the
user - implementation aside).
It's really nice to be able to work within ST 'text' files,
without having to re-compile some host (java, c# etc) code
to get my latest changes.
When factoring ST templates and groups, being able to do it all
in the ST files without having to update host code, is a nice
trait of ST at the moment.
> My only concern is that now we have two trees:
>
> * trees of templates. For websites we often have many directories of
> templates grouped into subtrees on the disk
> * inheritance hierarchy (tree)
I think we should deprecate the old concept of templates in individual
files grouped into directories.
Allow the user to choose one or the other 'loader' :)
to provide a version or two worth of backward compatibility.
I know it's the way you used to do it, but for editing templates
without some custom ST-aware editor, group files grouped in directory
'packages' is definitely the preferred way to use directories as a
complexity management tool. Simply makes large systems development
sane, at least in my world.
Again think Java:
- Directories correspond to packages ('packages' in ST).
- Files correspond to classes (ST groups),
which contain methods (ST templates).
It's a 3-level hierarchy, and it works.
The only things missing in ST are multiple imports, and a ClassPath/
TemplatePath or TEMPLATE_PATH. So we can consider MI as multiple
"imports", which is really what I am after here: I want to be able
to do something very similar to Java's package "import" statements,
where I can 'import' needed ST functionality (groups, or even
individual templates).
> That could get really confusing. When I say supergroup, do I mean the
> group that lives above me in the directory structure or do I mean
> where I inherit templates? In the case above, there are two subtrees
> of templates rooted at directories GeneralView and AdminView, let's
> say. Underneath those root directories I might have lots and lots of
> subdirectories and/or group files. So, I can ask for:
>
> a.getInstanceOf("/AdminView/misc/leftgutter");
> a.getInstanceOf("/AdminView/search");
>
> It will look in subdir misc to find leftgutter.st. It will look for
> search.st in root dir AdminView. Notice that now we use '/' on the
> front to mean absolute start from the root. Without the / on the front
> it looks in the surrounding group's directory. If we template x says
> <foo()> ST would look in x's associated directory for foo.
I think leading / should mean "from root of my TEMPLATE_PATH/
classpath.
No leading / would mean relative to 'current' directory (package).
> Anyway, what if AdminView doesn't have misc/leftgutter.st? We need to
> look in the supergroup. It will attempt to load file /GeneralView/misc/
> leftgutter.st. That all make sense to me but I wondered about the
> users. Well, actually, I guess I hide the internal tree of groups from
> the user so maybe it's not a big deal. Perhaps I should throw any
> legal argument exception if someone tries to set the supergroup on a
> non-root group.
>
> does any of this make sense? any comments?
In hindsight to the above, and thinking of the Java analogy,
I have to add that providing ST group in-file inheritance, interface
and imports specifications is a nice, analogous-to-java way to go.
I like ST using /, the file path separator (stick to unix separator
and switch internally when on Windows), to specify template groups to
load.
But Java's period ('.') separator would be fine too I imagine.
either way.
best
zen
--
Free Australia: www.UPMART.org
Please respect the confidentiality of this email as sensibly warranted.
More information about the stringtemplate-interest
mailing list