<snusnu>
dkubb: i have a question, since you mentioned on GH that you liked how i didn't return a mutable reference to internal state from a DSL class .. do you generally .dup.freeze internal DSL state when passing it to the object to be constructed by the DSL ?
<snusnu>
dkubb: and i'm about to introduce another simple DSL class, and i wonder if it's really "worth it"
snusnu has quit [Ping timeout: 245 seconds]
snusnu has joined #rom-rb
<snusnu>
dkubb: actually, thinking about it some more, i don't really like it, it's private api anyway, and public clients only ever stuff those mutable data structures into immutable objects
<snusnu>
dkubb: if you have time, i have a (possibly stupid) question regarding threads and how they relate to substation chain invocation
<snusnu>
dkubb: basically it boils down to this: in a multithreaded application, does it matter / is it better to have, say, 10 chain instances if my app exposes 10 endpoints, and those 10 chains get invoked over and over again, with different request data … or to have 10 "templates" or "definition objects" for the chains .. and every actual invocation, constructs a new chain instance and passes in request data
<snusnu>
dkubb: i tend to lean towards the latter, but i can't properly explain (to myself) why
<snusnu>
dkubb: the assumption is, the chain definition objects (basically the instance_eval'ed DSL instances) provide sort of what a class normally does, the "template" .. and every request then instantiates a concrete chain instance .. which is immutable, and pipes request data through
<snusnu>
dkubb: if i were to write something that just spawns a thread for every incoming request, instantiates a new chain in that thread, invokes it and joins .. i somehow think the one instance per chain approach fits better?
<snusnu>
dkubb: currently, substation uses the 10 chain instances for 10 endpoints approach, but i could *very* easily change it to instantiate a new chain instance for every invocation
zekefast has quit [Ping timeout: 240 seconds]
<dkubb>
snusnu: I wrote a chain of responsibility in axiom-optimizer
<dkubb>
snusnu: originally it was a chain of classes, and I would call class methods on each of them
<dkubb>
snusnu: I often needed to access the same kinds of values in each class method, so I started to write utility methods to extract those values when needed
<dkubb>
snusnu: when I realized I needed the same kinds of attributes I changed the system so it creates an instance for each object in the chain based on a chain of classes.. it's much simpler now, and cleaner that I have the state encapsulated
<dkubb>
snusnu: so I would tend to say I like your latter case more
<snusnu>
dkubb: yeah, so in my case, first i create a custom DSL subclass, which adds method based on the processors registered with an environment … i then use that custom "compiled" DSL class to let users construct an array of processor instances that essentially make up the chain (that's the #processors i changed to ordered_hash and back)
<snusnu>
dkubb: currently, if a user invokes that DSL, it returns a chain instance
<snusnu>
dkubb: and i currently store those chain instances in constants in my app
<snusnu>
dkubb: those chains are then mapped to a name in a Dispatcher instance
<snusnu>
dkubb: and i then do dispatcher.call(:create_person, some_input)
<dkubb>
btw, I generally design my private and public interfaces the same way, as least for publicly visible methods
<dkubb>
(that is in answer to your earlier statement about private apis)
<snusnu>
dkubb: heh ok, i was confused for a bit :)
<snusnu>
dkubb: so, apart from a "design pov" .. do you think this is a decision that has any effect on the multithreading fitness for an app?
<snusnu>
dkubb: i always find it so hard to wrap my head around threading
<dkubb>
snusnu: the main thing is sharing state between the threads
<dkubb>
snusnu: you can create two objects in different threads and it won't matter if there's no shared global state
<dkubb>
snusnu: you can create a mutable object and share it if you use locking or some other mechanism to make sure modifications are done properly
<dkubb>
snusnu: immutable objects should be sharable between threads with no issues
<snusnu>
dkubb: i guess it just clicked for me, essentially, all the objects substation provides (the chain and its processors basically, are immutable anyway .. i guess it just doesn't matter wether i have 10 or n chain instances
<dkubb>
snusnu: btw, if you're doing threading testing you probably want to use jruby or rbx. the lack of the GIL can expose certain bugs that MRI may hide
<snusnu>
dkubb: if i were to spawn a thread for every Dispatcher#call .. it would have no problems since none of the objects share state anyway
<dkubb>
anything that runs nicely in jruby will work well in mri, but not always the other way around
<dkubb>
yeah, shared *mutable* state is when you have issues
<snusnu>
dkubb: yeah, at this point i was mainly interested in general, but we're running on jruby soon, so i guess i'll find out
<dkubb>
that's why I wrote ice_nine. some people freeze just the "top level" of the object, but still have parts that are easily modifiable
<dkubb>
I am thinking about making something ice_nine like that does deep copying
<dkubb>
then you can deep copy, then deep freeze, and there'd be no worries
<dkubb>
when it makes sense of course
<dkubb>
for configuration type information I think it's really important.. especially for things that can be shared between threads
<snusnu>
yeah, something like that would surely be nice to have
<dkubb>
snusnu: you should have a look at celluloid too. some interesting ideas there
<snusnu>
dkubb: it's been on my backlog for a while but i never got around to it, i really should at some point i guess
<snusnu>
dkubb: btw, do you use hamster for something?
<dkubb>
snusnu: no, I just thought it was an interesting design. I totally swiped the idea for ice nine from hamster
<dkubb>
I used it first in veritas, then extracted it
<snusnu>
dkubb: ok, my impression is, that i just never needed the "primitive" data structures to be immutable, and i never had a need for more advanced data structures either
cored has joined #rom-rb
sgrif has quit [Quit: Page closed]
cored has quit [Ping timeout: 248 seconds]
kpwz_ has joined #rom-rb
kpwz has quit [*.net *.split]
snusnu has quit [Quit: Leaving.]
fphilipe has joined #rom-rb
philipe1 has joined #rom-rb
fphilipe has quit [Ping timeout: 240 seconds]
philipe1 has quit [Ping timeout: 248 seconds]
fphilipe has joined #rom-rb
philipe1 has joined #rom-rb
fphilipe has quit [Client Quit]
philipe1 has quit [Client Quit]
fphilipe has joined #rom-rb
fphilipe has quit [Remote host closed the connection]
<mbj>
snusnu: Yeah, I was about to nitpick about that duplication :D
<mbj>
snusnu: I'm busy with some database maintainance
cored has quit [Ping timeout: 245 seconds]
cored has joined #rom-rb
knowtheory has quit [Quit: Computer has gone to sleep]
snusnu has quit [Quit: Leaving.]
snusnu has joined #rom-rb
<snusnu>
mbj: interesting, just got this: abstract_type.rb:35:in `new': undefined local variable or method `superclass' for Substation::Processor::API::Responder:Module (NameError)
<snusnu>
mbj: when trying to include a Processor::API::Responder.new(Result)
<snusnu>
mbj: seems like abstract type's .new method doesn't like to be invoked on modules
knowtheory has joined #rom-rb
<snusnu>
mbj: forget everything i just said
<mbj>
heh
<mbj>
snusnu: skype?
dkubb has joined #rom-rb
<dkubb>
good morning
<mbj>
dkubb: morning!
<mbj>
snusnu: do you consider a substation release with the latest changes?
travis-ci has joined #rom-rb
<travis-ci>
[travis-ci] mbj/mutant#462 (master - 0acb604 : Markus Schirp): The build was broken.
<snusnu>
dkubb: thx, i responded already and worked in your suggestions
cored_ has joined #rom-rb
cored has quit [Ping timeout: 246 seconds]
xybre has quit [Ping timeout: 246 seconds]
xybre has joined #rom-rb
solnic has joined #rom-rb
<snusnu>
solnic: i tend to agree with you re that PR
<snusnu>
solnic: initially i thought that this module class will be useful in other cases too, that's why i implemented it in the first place
<snusnu>
solnic: now i found out that i actually can't use it (or rather, it makes no sense to use it) in that other place i was thinking about
<snusnu>
solnic: it was a nice exercise tho, i finally implemented and mutation covered a module class
<snusnu>
solnic: but yeah, i guess it's not worth it
<snusnu>
solnic: i'll wait what mbj has to say about it, but i'm leaning towards not merging it into master
<snusnu>
solnic: another drawback of this approach (and i consider that fairly severe) is that it prevents me from documenting public api
<snusnu>
solnic: altho i dunno, maybe there's some yard stuff that would still allow me to do so
<snusnu>
solnic: even if there is something in yard, that would actually only add to the complexity
<snusnu>
solnic: (i'm always having a hard time remembering "advanced" yard syntax, which makes me think it's complex)
<solnic>
snusnu: fwiw I think its test sucks too ;P
<solnic>
which makes me think it's not worth it even more :D
<snusnu>
solnic: you mean the fact that mutant requires it to be there, or did i do it wrong?
<snusnu>
solnic: anyway, i can also "force myself" to look at it from another pov .. essentially, all that this module is (still) doing, is define 2 methods, granted, by metaprogramming, but yeah
<snusnu>
solnic: (that doesn't mean i changed my mind btw)
<snusnu>
solnic: also, fwiw, if that module class wouldn't need to rely on the #respond_with helper method, i'd probably not consider the metaprogramming involved to be that dramatic
<solnic>
snusnu: yes this doesn't feel like part of your public API
<snusnu>
well not really, the dynamically defined methods are part of the public api .. which actually frightens me even more
<solnic>
snusnu: I dunno, it's a ton of complex code to remove something that I wouldn't even call duplication
<snusnu>
solnic: i hear you
<solnic>
when I'm DRYing things up I'm looking for duplicated *concepts* in my code
<solnic>
not similar lines of code :)
<snusnu>
well, in this case, the concept is duplicated
<solnic>
obviously similar concepts are usually expresses with similarly looking code :)
<snusnu>
;)
<solnic>
it's a tricky thing
<snusnu>
yeah, i'm glad i opened up a PR for this, i needed to get you guys' opinion on this ..
<snusnu>
fwiw, in case you haven't read the logs, dkubb seemed to like it
<solnic>
snusnu: why did you do it in the first place?
<snusnu>
solnic: initially, i thought that i can use it in the 2 places it's used already, PLUS include it in custom action base classes, defined by substation clients in their app
<snusnu>
solnic: turns out, clients don't need it
<snusnu>
solnic: i overlooked that in the beginning
<snusnu>
solnic: but yeah, initially i thought it would remove duplication inside substation proper, PLUS being valuable for substation clients
<snusnu>
solnic: i was wrong
<solnic>
rite
<solnic>
well yeah I agree that if it'd DRY up client code it'd be worth it
<snusnu>
solnic: it *could* be used there too .. but it wouldn't make much sense i guess
<snusnu>
solnic: that Action base class could include the module, and only provide #respond_with .. then again, all of that is already available in #request .. so yeah, it's just not worth it
<solnic>
snusnu: ok :)
<solnic>
snusnu: I'm gonna hit bed, I got back from Oslo and I'm SUPER tired
<snusnu>
solnic: ah ok, well then, have a good night's sleep :)