|more useful options|
OO design: returning string and/or special valueby wanna_code_perl (Friar)
|on Oct 07, 2019 at 20:04 UTC||Need Help??|
wanna_code_perl has asked for the wisdom of the Perl Monks concerning the following question:
I have a class with a $obj->method call that returns a value. (Earth shattering, no?) The vast majority of the time, the caller is going to want that value in plain old string format. A small (5%) percentage of calls, they want another, let's say special scalar format. Crucially, sometimes they want both string and special formats from the same call, and calls take around a second, and are non-idempotent. It is possible to convert from special to string after the fact, but not the other way around.
So for my first cut, I had a return object that is initialized with the special representation of a return value, with two methods: $ret->string and $ret->special. Simple enough. But it felt wrong to force the caller to remember to append ->string almost everywhere, so I decided to play around with overload, and was quickly reminded of the pain and potential pitfalls associated with overrides to "just" stringify an object. To wit, one has to overload the following "minimal" set, according to overload:
I doubt users are going to need trig functions in my case, but everything else is possible, and for the most part, likely.
As an aside, I've always been curious as to why so many overloads are necessary for basic stringification. Could q("") or perhaps even a q(scalar) not have been enough in many cases? Let all of the others automatically derive from that? For example, if my object already stringifies to "apple", why do I also need to define "cmp" to know if $obj lt 'banana' is true? But that's probably a separate question.
So I'd like some other opinions on this design. Having users do $ret->string in 95% of cases is undesirable, but isn't the end of the world.
I'm currently leaning toward returning both, i.e.: my ($string, $special) = $obj->method, (with my $string = $obj->method working in scalar context), but am very much open to other options.
The reason I'm here, though, is to ask: how would you design something like this (i.e., the first paragraph), and why?
As respects performance, an extra subroutine call or two isn't going to matter, as $obj->method is not CPU bound and takes around a second to return.