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
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@alice.wu.ac.at http://alice.wu.ac.at/mailman/listinfo/xotcl
Hi, it's not what I really want. I have a session class, in the init method depending on property I create a storageObj like this: namespace eval oodz { nx::Class create Session { :property {persist_type "file"}
# Constructor :method init {} { set :dom_sess [ns_info server]_sessions_cl ns_cache_create -timeout ${:timeout} -expires ${:session_expire} ${:dom_sess} 10MB switch ${:persist_type} { "file" { set :storageObj [::oodz::SessionFile new] } "db" { set :storageObj [::oodz::SessionDB new] } default { error "Unsupported storage type: ${:persist_type}" } } } After that i can access it like: ${:storageObj} save $sessionId $data
Basically I want something like *Factory Method* pattern. What is 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@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@alice.wu.ac.at http://alice.wu.ac.at/mailman/listinfo/xotcl
Xotcl mailing list Xotcl@alice.wu.ac.at http://alice.wu.ac.at/mailman/listinfo/xotcl
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@wu.ac.at mailto:stefan.sobernig@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@alice.wu.ac.at <mailto:Xotcl@alice.wu.ac.at> > http://alice.wu.ac.at/mailman/listinfo/xotcl <http://alice.wu.ac.at/mailman/listinfo/xotcl> _______________________________________________ Xotcl mailing list Xotcl@alice.wu.ac.at <mailto:Xotcl@alice.wu.ac.at> http://alice.wu.ac.at/mailman/listinfo/xotcl <http://alice.wu.ac.at/mailman/listinfo/xotcl>
Thank you for your explanation and examples.
On Fri, Sep 15, 2023 at 9:08 AM Stefan Sobernig stefan.sobernig@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@wu.ac.at mailto:stefan.sobernig@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@alice.wu.ac.at <mailto:Xotcl@alice.wu.ac.at> > http://alice.wu.ac.at/mailman/listinfo/xotcl <http://alice.wu.ac.at/mailman/listinfo/xotcl> _______________________________________________ Xotcl mailing list Xotcl@alice.wu.ac.at <mailto:Xotcl@alice.wu.ac.at> http://alice.wu.ac.at/mailman/listinfo/xotcl <http://alice.wu.ac.at/mailman/listinfo/xotcl>