yary wrote: >>The current approach is violating the DRY principle. When you write a >>.new method that wants to initialize private attributes, you have to >>repeat all their names again in the signature of your BUILD submethod:
The other way of looking at this is that redefining the new() is about changing the constructor interface, whereas defining the BUILD() is about changing the initialization behaviour. So the current approach is violating DRY in order to preserve the more important principle of Separation of Concerns. After all, it doesn't seem unreasonable that, if you want to modify two behaviours, you have to rewrite two components to do it. On the other hand, rather than adding a blessall() alternative, perhaps we could say that, if the class explicitly redefines new(), then any call to bless() within that redefined new() will accept both public and private attributes for auto-initialization...under the theory that, by redefining new() the class implementor is taking direct responsibility for the construction...and is willing to live with the dire consequences if they mess it up. Incidentally, blessall() seems a dubious name to me, given that we already have BUILDALL() and CREATEALL(), where the '-ALL' suffix means something quite different from what the '-all' would mean at the end of blessall(). Better still, on the principle that abnormal behaviour should always be explicitly marked and lexically predeclared, perhaps a pragma would be appropriate: class A { has ($!x, $!y, $!z); method new($x, $y, $z) { no strict :autoinit; self.bless(*, :$x, :$y, :$z) } } >>The whole point of having BUILD() is to separate allocation >> concerns from initialization concerns. > > Here's where I am late to the conversation, I hadn't known that > distinction. S12 doesn't talk about the "why" of BUILD/BUILDALL, at > least not that detail. If "BUILD" is for allocation, and "new" is for > initialization, then hiding private attributes from "bless" is forcing > the programmer to use BUILD for initialization which wasn't the > intent. You have it the wrong way round: new() is for allocation; BUILD() is for initialization. From a design point-of-view, BUILD() probably should have been called INIT(), but that keyword was already taken. > "you must write your own BUILD (as above) in order to present private > attributes as part of your initialization API." > > And that's not so good, because it forces BUILD to be used for > initialization, ...which is precisely what it's supposed to be for. :-) Damian