Re: Role::Tiny: When to use apply_roles_to_object?
by LanX (Saint) on May 02, 2019 at 16:52 UTC
|
From Object-oriented_programming#Criticism
> The problem with object-oriented languages is they've got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle
or
> Furthermore, he cites an instance of a Java professor whose "idiomatic" solution to a problem was to create six new classes, rather than to simply use a lookup table.
Classes are templates defining behavior (methods) for object instances belonging to that "type". The "constructed" objects are usually restricted to hold data (attributes).
Sometimes you just need flexible objects having a variety of behaviors which can't be easily typed.
For instance (let's objectify a $woman ;-) ...
metaphor
I always say: My father is German and my mother is complicated.
The truth is she has three passports, a college degree from a 4th country and speaks 3+ languages.
I.e. I can't "type" her anymore.
So I'd rather avoid this discussion, before my food gets cold. And it's annoying to finally point out that people don't have the necessary background to understand. (that is their (stereo)type system sucks)
So creating a singleton "class" for every combination of attributes and functions an object could have is expensive, especially in Perl where you have to represent classes in a global hierarchy::of::packages .°
It's easier to add methods to an object without the need of typing.
Self or JS are classless, a JS object inherits from another JS object.
But that's also bit one dimensional. *
There are good reasons for OOP like encapsulation or polymorphism, but you could easily be trapped in design hell if you have to maintain an overly complicated class hierarchy, especially because
people often can't even agree on the terminology.
another quote:
> Paul Graham has suggested that OOP's popularity within large companies is due to "large (and frequently changing) groups of mediocre programmers". According to Graham, the discipline imposed by OOP prevents any one programmer from "doing too much damage"
update
*) you can also add methods on the fly to an object in JS.
object.my_sub = function (...) { ... this.bla ...};
°) Well, she may be a class of her own but she's not my type. | [reply] [d/l] [select] |
|
|
| [reply] [d/l] |
Re: Role::Tiny: When to use apply_roles_to_object?
by 1nickt (Canon) on May 02, 2019 at 16:39 UTC
|
use Test::Most 'die';
use Role::Tiny;
package MyClass {
# standing in for the real consumer of the role,
# which is expensive to instantiate in some way ...
use Moo;
};
package MyRole {
use Moo::Role;
sub foo { 42 }
};
subtest 'Applying' => sub {
my $o = MyClass->new;
is( ref $o, 'MyClass', 'object instantiated' );
ok( Role::Tiny->apply_roles_to_object($o, 'MyRole'), 'role applied
+' );
is( $o->foo, 42, 'method in Role works!' );
};
done_testing;
Hope this helps!
The way forward always starts with a minimal test.
| [reply] [d/l] [select] |
|
|
| [reply] [d/l] |
Re: Role::Tiny: When to use apply_roles_to_object?
by Fletch (Bishop) on May 02, 2019 at 16:26 UTC
|
Not an outright answer but the example that comes to mind (vaguely from when I actually skimmed about it aeons ago when dinosaurs still roamed the earth) was the Self language (see Self_(programming_language); also this SO thread looks to have some good pointers (and discussion WRT to JavaScript which has similar prototype inheritance features)).
The cake is a lie.
The cake is a lie.
The cake is a lie.
| [reply] |
|
|
"...aeons ago...JavaScript which has similar prototype inheritance features"
Do'h!. It's a matter of taste after all. I repressed my JavaScript experience. Or may be i never got a proper understanding of the language.
Thanks and best regards, Karl
«The Crux of the Biscuit is the Apostrophe»
perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help
| [reply] [d/l] |
Re: Role::Tiny: When to use apply_roles_to_object?
by tobyink (Canon) on May 03, 2019 at 16:22 UTC
|
One example might be you have a Backend class where your app sends all its data. You might instantiate the backend object like this:
my $backend = Backend->new();
Role::Tiny->apply_roles_to_object(
$backend,
qw( Backend::Storage::PostgreSQL Backend::Log::Debug Backend::Interf
+ace::TCP ),
);
And now your backend object will store its data in PostgreSQL, and spit out debugging information to its log file, and listen on a TCP port for instructions.
If you have eight different possibilities for storage (different types of database, XML files, JSON files, etc), 4 different options for logging, and 4 different interfaces (TCP, Unix Sockets, Command Line, and HTTP), that gives 128 possible combinations. You don't really want to have to create classes for Backend::PostgreSQL_Debugging_TCP, Backend::MySQL_Debugging_TCP, Backend::PostgreSQL_Debugging_HTTP, etc. Instead you just compose the combination of roles you want.
(In this particular example, there's an argument for making more use of delegation instead of composition, but I digress.)
| [reply] [d/l] |
|
|
> In this particular example, there's an argument for making more use of delegation instead of composition
actually I also had rather delegation in mind when answering this question.
As far as I understood does Role::Tiny -> apply_roles_to_object() actually create a new anonymous package and is reblessing the object. °
IMHO delegation sounds like a better approach, unless the performance penalty of the extra forwarding sub matters.
°) quote "Object is reblessed into the resulting class."
| [reply] |
|
|
That's how it works, but should be considered an internal implementation detail.
Delegation is probably a better approach for the example I used earlier, but it requires the base class to have prior knowledge of the kinds of "plugin functionality" that will be added to it, so that it knows when to delegate to them. In many cases, the base class won't have prior knowledge.
| [reply] |
|
|
|
|
use strict; use warnings; use feature 'say';
use Role::Tiny;
package MyClass { use Moo };
package MyRole { use Moo::Role };
my $o = MyClass->new;
Role::Tiny->apply_roles_to_object($o, 'MyRole');
say ref($o);
Output:
MyClass__WITH__MyRole
The way forward always starts with a minimal test.
| [reply] [d/l] [select] |
|
|
| [reply] [d/l] |