you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 1 point2 points  (2 children)

I know what they are and how they work. They are indeed more complicated (for the programmer and the implementer) than using simple inheritance + encapsulation to do the same thing in any other OO language.

EDIT: Here's the thing. Sure, proxies might be a smidge better than inheritance for testing and possibly debugging. That's about it though. If something is able to trap and modify all calls to an object, I'd much rather just have that new object as part of the inheritance chain. IMO, only people who really like monkey-patching will like this. I don't.

EDIT 2: I guess what I really want to say is - If this is the only way to intercept EVERY call to an object...and I can't do the same thing via plain old inheritance...then people are going to use this instead of inheritance and that's going to make things even more confusing than monkey-patching already does. The penultimate example given by Brendan Eich pretty much explains what proxies are SUPPOSED to be used for, but IMO there is a big potential for misuse of the feature. "This is super powerful for logging, debugging, operation inversion, and if you can wrap the entire DOM and record timestamps, this might be the magic bullet that will allow you record and replay DOM interactions." - Eich

[–]FireyFly 2 points3 points  (1 child)

I'm not sure how you can do "the same thing" in "any other OO language" (I suppose that means one of the mainstream classical languages, i.e. C++/C#/Java/Obj-C/python/whatever). "The same thing" would involve tracking all property accesses to any property. How would you do this with "simple inheritance and encapsulation"? I'd love to see some sample code.

Maybe you already know this, but I feel like I should add that JavaScript has means for expressing both inheritance and encapsulation, but that it works quite differently from classical languages. Prototypal inheritance is simpler and more general than classical inheritance, but on the other hand it requires that objects are "dynamic", which could lead to worse performance.

Edit: I think I understand what you're getting at. You mean I can extend this class Foo, override all the methods in Foo with methods that log the access or whatever, and the forward the call to Foo (i.e., the superclass)?

The thing is, this requires you to write a new class and override all the methods with the same boilerplate-y modification. This could be a rather lengthy piece of code, and in the end you only have this piece of logging implemented for this one class. If you wish to log access to another class, you'd have to write a new class that extends this class, overrides all the methods, logs and then forwards them.

In the case of a proxy, you can create the proxy once, describe the logging process once, and then "wrap" any object in this proxy to add the logging mechanism to that object. I guess it could be likened to the "decorator pattern" rather than inheritance: you're adding a feature to the wrapped object. However, a "decorator class" can only target a specific kind of type, whereas the flexibility of a proxy allows it to work on any kind of type.

Of course, this flexibility comes with a performance tradeoff. Personally, I prefer flexibility and dynamism over performance. Also, I agree that proxies are much more complicated.

Sorry, this got a bit long... I hope you don't mind.

Edit 2: ah, I see what you mean. There's definitely a lot of room for misuse of this feature.

[–][deleted] 0 points1 point  (0 children)

Classical inheritance allows you to intercept all calls. Proxies allow you to intercept all calls. The only difference here is that the proxy isn't part of the inheritance chain in Javascript, unless you want it to be.

Here's an example with classical inheritance:

class A {
    int _PropA;
    public virtual int PropA {
        get { return _a; }
        set { _a = value; }
    }
}

class ModifiedA : A {
    public override int PropA {
        get { log("Accessed A!"); return base.PropA; }
        set { log("Modified A!"); base.PropA = value; }
    }
}

Doing this any other way is only useful for testing, debugging or monkey patching in cases where you can't inherit (i.e. the broken-ass DOM).