[Xotcl] parameters to keep Class objects
Maksym Zinchenko
siqsuruq at gmail.com
Sun Sep 17 20:34:21 CEST 2023
Thank you for your explanation and examples.
On Fri, Sep 15, 2023 at 9:08 AM Stefan Sobernig <stefan.sobernig at wu.ac.at>
wrote:
> Hi Maksym!
>
> > Basically I want something like *Factory Method* pattern.
>
> This clarifies your request! Thanks!
>
> Looking at your design snippet, I would have some suggestions for
> improvement.
>
> From what I see, your design is not really realising the advantages of
> the FACTORY METHOD (e.g., adding new types of sessions *without* having
> to touch the factory method and the switch in there), nor is it very
> robust because of re-using the NX constructor "init" as the factory method.
>
> o Robustness: Re-using "init" that way is not a good choice in the
> context of NaviServer, because unless you are careful, NaviServer will
> run "init" just once (when building the blueprint script). When shipping
> the script to the interpreters of connection threads, init will not be
> run again (-noinit is added). In addition, autonamed NX objects (those
> created via calling "new") are also not exported into the blueprint
> script. Hence, you experience the "${:storageObj} doesn't exist" issue
> in the connection threads.
>
> o FACTORY METHOD: The by-the-book design of a FM implementation creates
> two lines of concepts: session factories and sessions. For both lines,
> two class hierarchies are typically created, like:
>
> namespace eval ::oodz {
>
> nx::Class create Session {
> :public method save {args} {;}
> }
> nx::Class create FileSession -superclasses Session
> nx::Class create DBSession -superclasses Session
>
>
> nx::Class create SessionFactory {
>
> :public method createSession {} {
> error "[:info class]: abstract method, use subclass!"
> }
>
> :create ::sessionFactory
> }
>
> nx::Class create FileSessionFactory -superclasses SessionFactory {
> :public method createSession {} {
> return [FileSession new]
> }
> }
>
> nx::Class create DBSessionFactory -superclasses SessionFactory {
> :public method createSession {} {
> return [DBSession new]
> }
> }
>
> namespace export Session DBSessionFactory DBSession
> FileSessionFactory FileSession
> }
>
> This way, you could call:
>
> namespace import ::oodz::*
> set s [[DBSessionFactory new] createSession]
> $s save
>
> This is a lot of design boilerplate, I prefer the following (using NX/
> XOTcl idioms incl. a metaclass):
>
> namespace eval ::oodz {
>
> nx::Class create SessionClass -superclasses ::nx::Class
>
> SessionClass create Session {
> :public method save {args} {;}
> }
> SessionClass create file -superclasses Session
> SessionClass create db -superclasses Session
>
>
> nx::Class create SessionFactory {
>
> :public method createSession {-persist_type:class,type=SessionClass} {
> return [$persist_type new]
> }
>
> :create sessionFactory
> }
>
> namespace export sessionFactory file db
> }
>
> Then:
>
> namespace import -force ::oodz::*
> set s [sessionFactory createSession -persist_type db]
> $s save
>
> Some remarks:
>
> - "init" is not used!
>
> - session-class names are used as first-class symbols of your factory
> method (no need to maintain yet another mapping: "file" <->
> "FileSession" or similar)
>
> - You can easily add new session types, by creating new SessionClass
> instances;
>
> - Clearly, as always, there are alternatives (e.g., maintain a
> dictionary of persist_types symbols and session classes).
>
> HTH, Stefan
>
> > happening right now is that I am initializing my Session class. It works
> > fine but after some time I'm getting an error that ${:storageObj} doesnt
> > exist.
> > In your example I need to know my type of the class before. Sorry, maybe
> > I understood wrong. If you have a simple example of illustrating factory
> > method I would be grateful.
> > Thank you
> >
> > On Tue, Sep 12, 2023 at 7:02 AM Stefan Sobernig
> > <stefan.sobernig at wu.ac.at <mailto:stefan.sobernig at wu.ac.at>> wrote:
> >
> > Hi Maksym!
> >
> > I would recommend using a "property", watch:
> >
> > package req nx
> >
> > nx::Class create a {
> > :public method hmmm {} {
> > return "Hmmmm!!!"
> > }
> > }
> > nx::Class create b {
> > :property -accessor public aObj:object,type=::a
> >
> > :public method saysmth {} {
> > puts "Hello!? [${:aObj} hmmm]"
> > }
> > }
> >
> >
> > # in init.tcl / created once
> > ::b create bobj
> >
> > # somewhere else (later):
> >
> > ::bobj aObj set [::a new]
> > ::bobj saysmth
> >
> > What do you think?
> >
> > HTH, Stefan
> >
> >
> > > Hello, can I use parameters to keep Class objects? Like this:
> > >
> > > package require nx
> > >>
> > >> nx::Class create a {
> > >> :public method hmmm {} {
> > >> return "Hmmmm!!!"
> > >> }
> > >> }
> > >>
> > >> nx::Class create b {
> > >> :method init {} {
> > >> set :aObj [a new]
> > >> }
> > >>
> > >> :public method saysmth {} {
> > >> puts "Hello!? [${:aObj} hmmm]"
> > >> }
> > >> }
> > >>
> > >> ::b create bobj
> > >> ::bobj saysmth
> > >>
> > > Is it possible that it will not be set if I create my "bobj" from
> > init.tcl
> > > in Naviserver at startup?
> > >
> > > Thank you in advance
> > > _______________________________________________
> > > Xotcl mailing list
> > > Xotcl at alice.wu.ac.at <mailto:Xotcl at alice.wu.ac.at>
> > > http://alice.wu.ac.at/mailman/listinfo/xotcl
> > <http://alice.wu.ac.at/mailman/listinfo/xotcl>
> >
> > _______________________________________________
> > Xotcl mailing list
> > Xotcl at alice.wu.ac.at <mailto:Xotcl at alice.wu.ac.at>
> > http://alice.wu.ac.at/mailman/listinfo/xotcl
> > <http://alice.wu.ac.at/mailman/listinfo/xotcl>
> >
>
>
More information about the Xotcl
mailing list