On 14 Mar 2012, at 17:21, Caleb Cushing wrote:

> On Wed, Mar 14, 2012 at 4:57 AM, Tomas Doran <bobtf...@bobtfish.net> wrote:
>> 
>> On 14 Mar 2012, at 02:14, Caleb Cushing wrote:
>> 
>>> Why are the options for using MX::Traits either
>>> 
>>> Class->with_traits(...) or Class->new_with_traits({ traits => ... });
>>> 
>>> why can't we have just a Class->new({ _traits => ... })?
>> 
>> Because then ->new returns an entirely different class to the one you asked 
>> for.
>> 
>> Which breaks people's expectations of what ->new does.
> 
> one could argue that if you're programming to a concrete class vs an
> interface ... you're doing it wrong (I'm sure that's an opinion). The
> problem I'm having is having to program for 2 interfaces.
> 

No, you're not - or you shouldn't be.

You provide a $myfactory->construct_class() wrapper (about 6 lines of code for 
the entire factory class), and this moves the construction logic to a common / 
shared place.

You've suddenly gained the ability to have conditional logic based on the type 
of class that you're constructing, without said logic having to reside within 
the class you are constructing. This means that to use an entirely new type of 
class (e.g. non-moose classes that are constructed using a hypothetical 
->make_me method), then you can just add a couple of lines of code in your 
factory (without needing to touch the new classes that you're using).

> 
>> Also - this is hard to make work 'right', as what happens with classes which 
>> implement their own BUILDARGS / BUILD to do custom argument processing? How 
>> would we hook into that to get { _traits } out before construction, etc..
> 
> You don't? if someone adds { _traits } then in BUILDARGS you compose
> it like you would if they did it in new_with_traits,

Right, but you don't get the option to stamp on the class name during 
BUILDARGS, which is what you need to do :)

> and IIRC the
> class is composed by the time you get to BUILD, and so if the class is
> immutable you can't add them at that point. BUILDARGS needs to return
> a hashref, if you need a custom argument processing, and _traits, then
> you need to deal with that in your BUILDARGS somehow.

Sure, but by the time you're in BUILD, you have an instance already, and you 
can apply the roles at this point, but it's less elegant :)

> The problem I'm having is that I've been wanting to add traits at
> ->new, including in things like MX::AbstractFactory (and I think maybe
> this is why Bread::Board doesn't support Interface Injection? though
> maybe idk what that actually means, ignore if I'm completely off base
> ). The problem is that because MX::Traits doesn't allow me (even
> optionally) to use plain old new to do this, then I have to add all
> kinds of code to handle the different interface, and explain to people
> "Don't use new, it won't do what you need".

Erm, isn't the point of the abstract factory to be the implementation of this 
(i.e. the thing I suggested above)?

You don't need to tell anyone "Don't use new, it won't do what you need", 
because you're already explicitly documenting that you should call a ->create 
method!

Why don't you just us MooseX::Traits::Util::new_class_with_traits at the 
appropriate place in that ->create method, and your problem is entirely solved?

You don't need to in any way touch any of the implementation classes :)

Cheers
t0m

Reply via email to