A way to fire logic at the end of completion of the current class method (regardless of super call order).

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

A way to fire logic at the end of completion of the current class method (regardless of super call order).

#!/JoePea
I many times find myself in cases where a base class wants to ensure that logic is always fired after the current method's execution, so that for example no matter in which order sub classes call the `super` method, the `super` method can still guarantee that logic fires after the whole stack of the same method in the class hierarchy.

So what I can do now is use `Promise.resolve().then(() => { ... })` to schedule that logic for later, that way all the invocations of a `foo` method along the class hierarchy have all fired. But this means that other code can also fire before the next microtask.

Is there some way to do it? If not, I wonder if some language feature for doing it would be possible?

- Joe

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: A way to fire logic at the end of completion of the current class method (regardless of super call order).

Isiah Meadows-2
I've also had *several* scenarios where I could've used this
personally. I feel ES classes are overly restrictive in preventing
this, since it basically forces you to force subclasses to do
something like `this.init()` right after the class is allocated,
leaking implementation details left and right.

-----

Isiah Meadows
[hidden email]
www.isiahmeadows.com

On Fri, Feb 8, 2019 at 1:22 AM #!/JoePea <[hidden email]> wrote:

>
> I many times find myself in cases where a base class wants to ensure that logic is always fired after the current method's execution, so that for example no matter in which order sub classes call the `super` method, the `super` method can still guarantee that logic fires after the whole stack of the same method in the class hierarchy.
>
> So what I can do now is use `Promise.resolve().then(() => { ... })` to schedule that logic for later, that way all the invocations of a `foo` method along the class hierarchy have all fired. But this means that other code can also fire before the next microtask.
>
> Is there some way to do it? If not, I wonder if some language feature for doing it would be possible?
>
> - Joe
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: A way to fire logic at the end of completion of the current class method (regardless of super call order).

kai zhu
I feel ES classes are overly restrictive in preventing
this, since it basically forces you to force subclasses to do
something like `this.init()` right after the class is allocated,
leaking implementation details left and right.

its not a design-flaw.  the flaw is you trying to shoehorn “classical” inheritance-based design-patterns on a language better suited to use static-functions to baton-pass json-data (over class-instance).

here’s a real-world example of a ```dbTableCreateOne``` static-function to initialize a mongo-like collection/table, and then sync it with indexeddb persistence-store [1].  imagine how much more difficult these [common-case] async-initializations would be using inheritance-based constructors.

```javascript
local.dbTableCreateOne = function (options, onError) {
/*
 * this function will create a dbTable with the given options
 */
    var self;
    options = local.objectSetOverride(options);
    // register dbTable
    self = local.dbTableDict[options.name] =
        local.dbTableDict[options.name] || new local._DbTable(options);
    ...
    // restore dbTable from persistent-storage
    self.isLoaded = self.isLoaded || options.isLoaded;
    if (!self.isLoaded) {
        local.storageGetItem('dbTable.' + self.name + '.json', function (error, data) {
            // validate no error occurred
            local.assert(!error, error);
            if (!self.isLoaded) {
                local.dbImport(data);
            }
            self.isLoaded = true;
            local.setTimeoutOnError(onError, 0, null, self);
        });
        return self;
    }
    return local.setTimeoutOnError(onError, 0, null, self);
};
```

p.s. - going off-topic, but above-mentioned code/library (as well as proposals for standard tree/stl libraries) shouldn’t even exist if javascript had a builtin/standard sqlite3 library (like python).

[1] initialize a db-table and sync it with persistence-store

[2] discuss including tree and stl in proposed standard-library

On 9 Feb 2019, at 4:18 AM, Isiah Meadows <[hidden email]> wrote:

I've also had *several* scenarios where I could've used this
personally. I feel ES classes are overly restrictive in preventing
this, since it basically forces you to force subclasses to do
something like `this.init()` right after the class is allocated,
leaking implementation details left and right.

-----

Isiah Meadows
[hidden email]
www.isiahmeadows.com

On Fri, Feb 8, 2019 at 1:22 AM #!/JoePea <[hidden email]> wrote:

I many times find myself in cases where a base class wants to ensure that logic is always fired after the current method's execution, so that for example no matter in which order sub classes call the `super` method, the `super` method can still guarantee that logic fires after the whole stack of the same method in the class hierarchy.

So what I can do now is use `Promise.resolve().then(() => { ... })` to schedule that logic for later, that way all the invocations of a `foo` method along the class hierarchy have all fired. But this means that other code can also fire before the next microtask.

Is there some way to do it? If not, I wonder if some language feature for doing it would be possible?

- Joe
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: A way to fire logic at the end of completion of the current class method (regardless of super call order).

Jordan Harband
In reply to this post by Isiah Meadows-2
If the superclass constructor has a way to run any code after subclass constructors, then implementation details of the *subclasses* are then leaked.

On Sat, Feb 9, 2019 at 2:15 AM Isiah Meadows <[hidden email]> wrote:
I've also had *several* scenarios where I could've used this
personally. I feel ES classes are overly restrictive in preventing
this, since it basically forces you to force subclasses to do
something like `this.init()` right after the class is allocated,
leaking implementation details left and right.

-----

Isiah Meadows
[hidden email]
www.isiahmeadows.com

On Fri, Feb 8, 2019 at 1:22 AM #!/JoePea <[hidden email]> wrote:
>
> I many times find myself in cases where a base class wants to ensure that logic is always fired after the current method's execution, so that for example no matter in which order sub classes call the `super` method, the `super` method can still guarantee that logic fires after the whole stack of the same method in the class hierarchy.
>
> So what I can do now is use `Promise.resolve().then(() => { ... })` to schedule that logic for later, that way all the invocations of a `foo` method along the class hierarchy have all fired. But this means that other code can also fire before the next microtask.
>
> Is there some way to do it? If not, I wonder if some language feature for doing it would be possible?
>
> - Joe
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: A way to fire logic at the end of completion of the current class method (regardless of super call order).

Isiah Meadows-2
I get that, but it's usually part of the API subclassing contract that
the superclass *explicitly* depends on certain parts of the subclass.
Abstract classes immediately come to mind, and I'd say it's no more
leaking than any inherited method. It's not giving them any more
access to information than they would've gotten from an explicit `if
(new.target === Subclass) this.init()` call at the end (which is
basically what I want mod the exposed method).

-----

Isiah Meadows
[hidden email]
www.isiahmeadows.com

On Sat, Feb 9, 2019 at 4:53 PM Jordan Harband <[hidden email]> wrote:

>
> If the superclass constructor has a way to run any code after subclass constructors, then implementation details of the *subclasses* are then leaked.
>
> On Sat, Feb 9, 2019 at 2:15 AM Isiah Meadows <[hidden email]> wrote:
>>
>> I've also had *several* scenarios where I could've used this
>> personally. I feel ES classes are overly restrictive in preventing
>> this, since it basically forces you to force subclasses to do
>> something like `this.init()` right after the class is allocated,
>> leaking implementation details left and right.
>>
>> -----
>>
>> Isiah Meadows
>> [hidden email]
>> www.isiahmeadows.com
>>
>> On Fri, Feb 8, 2019 at 1:22 AM #!/JoePea <[hidden email]> wrote:
>> >
>> > I many times find myself in cases where a base class wants to ensure that logic is always fired after the current method's execution, so that for example no matter in which order sub classes call the `super` method, the `super` method can still guarantee that logic fires after the whole stack of the same method in the class hierarchy.
>> >
>> > So what I can do now is use `Promise.resolve().then(() => { ... })` to schedule that logic for later, that way all the invocations of a `foo` method along the class hierarchy have all fired. But this means that other code can also fire before the next microtask.
>> >
>> > Is there some way to do it? If not, I wonder if some language feature for doing it would be possible?
>> >
>> > - Joe
>> > _______________________________________________
>> > es-discuss mailing list
>> > [hidden email]
>> > https://mail.mozilla.org/listinfo/es-discuss
>> _______________________________________________
>> es-discuss mailing list
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: A way to fire logic at the end of completion of the current class method (regardless of super call order).

Isiah Meadows-2
In reply to this post by kai zhu
I presume you've *never* written non-trivial server-side logic in
Node. I find myself using classes *far* more often in Node than in the
browser simply because it's more than just passing strings and object
bags around. You've got caching, process management, and even
sometimes task queues. The traditional MVC architecture doesn't need
classes to implement in Node (and the corresponding idioms don't use
them, either), but it's all the machinery around it that result in all
the server-side classes.

Also, I'd like to note a few things:

- Some functional languages, notably OCaml, support classes with
classical inheritance. Inheritance *does* actually help from time to
time.
- JS is not opinionated on the matter - it supports both styles. In
fact, it lacks some of the utilities for pure POJO passing and
manipulation, while classes are mostly complete. In reality, it's
slightly biased *in favor* of classes, something several people have
been complaining about (me included).
- I'm *very* well used to passing POJOs around to static functions -
it's called functional programming.

> its not a design-flaw.  the flaw is you trying to shoehorn “classical” inheritance-based design-patterns on a language better suited to use static-functions to baton-pass json-data (over class-instance).
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

RE: A way to fire logic at the end of completion of the current class method (regardless of super call order).

Michael Haufe-2
In reply to this post by Isiah Meadows-2
You can use a Proxy in the base class:

<script>
let handlerExample = {
    get(target, prop) {
        let feature = target[prop]
        return feature instanceof Function ?
            function () {
                console.log('Before call');
                let result = feature.apply(this, arguments)
                console.log('After call');
                return result
            }
            : feature
    }
}

class Base {
    constructor() {
        return new Proxy(this, handlerExample)
     }
    m1() { return "m1" }
}

class Sub extends Base {
    m1() { return `override ${super.m1()}` }
    m2() { return `m2` }
}

let base = new Base()
console.log(base.m1())

let sub = new Sub()
console.log(sub.m1())
console.log(sub.m2())
</script>

/Michael


On Fri, Feb 8, 2019 at 1:22 AM #!/JoePea <[hidden email]> wrote:

 > I many times find myself in cases where a base class wants to ensure that logic is always fired after the current method's execution, so that for example no matter in which order sub classes call the `super` method, the `super` method can still guarantee that logic fires after the whole stack of the same method in the class hierarchy.

> So what I can do now is use `Promise.resolve().then(() => { ... })` to schedule that logic for later, that way all the invocations of a `foo` method along the class hierarchy have all fired. But this means that other code can also fire before the next microtask.

> Is there some way to do it? If not, I wonder if some language feature for doing it would be possible?
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

RE: A way to fire logic at the end of completion of the current class method (regardless of super call order).

Michael Haufe-2
Revisiting this topic: why is the Template Method pattern not acceptable to accomplish this?

<script>
class Base {
    constructor() {
        this._beforeAction()
        this._action()
        this._afterAction()
    }
    _beforeAction(){
        console.log(`Base._beforeAction()`)
    }
    _action(){
        console.log(`Base._action()`)
    }
    _afterAction(){
        console.log(`Base._afterAction()`)
    }
}

class A extends Base {
    _action(){
        console.log(`A._action()`)
    }
}

let a = new A()
// console reads:
// > Base._beforeAction()
// > A._action()
// > Base._afterAction()
</script>

/Michael
-----

Monday, February 11, 2019 10:34 PM Michael Haufe <[hidden email]> wrote:

> You can use a Proxy in the base class:
>
> <script>
> let handlerExample = {
>     get(target, prop) {
>         let feature = target[prop]
>         return feature instanceof Function ?
>             function () {
>                 console.log('Before call');
>                 let result = feature.apply(this, arguments)
>                 console.log('After call');
>                 return result
>             }
>             : feature
>     }
> }
>
> class Base {
>     constructor() {
>         return new Proxy(this, handlerExample)
>      }
>     m1() { return "m1" }
> }
>
> class Sub extends Base {
>     m1() { return `override ${super.m1()}` }
>     m2() { return `m2` }
> }
>
> let base = new Base()
> console.log(base.m1())
>
> let sub = new Sub()
> console.log(sub.m1())
> console.log(sub.m2())
> </script>
>
> /Michael


On Fri, Feb 8, 2019 at 1:22 AM #!/JoePea <[hidden email]> wrote:

 > I many times find myself in cases where a base class wants to ensure that logic is always fired after the current method's execution, so that for example no matter in which order sub classes call the `super` method, the `super` method can still guarantee that logic fires after the whole stack of the same method in the class hierarchy.

> So what I can do now is use `Promise.resolve().then(() => { ... })` to schedule that logic for later, that way all the invocations of a `foo` method along the class hierarchy have all fired. But this means that other code can also fire before the next microtask.

> Is there some way to do it? If not, I wonder if some language feature for doing it would be possible?
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: A way to fire logic at the end of completion of the current class method (regardless of super call order).

Naveen Chawla
Can anyone tell me what's wrong with a really simple approach? Wherever you are calling method(), just call methodWithAfter():

//in base class
methodWithAfter(){
    method();
    after()
}

What am I missing, guys?

On Fri, 19 Jul 2019 at 07:43, Michael Haufe <[hidden email]> wrote:
Revisiting this topic: why is the Template Method pattern not acceptable to accomplish this?

<script>
class Base {
    constructor() {
        this._beforeAction()
        this._action()
        this._afterAction()
    }
    _beforeAction(){
        console.log(`Base._beforeAction()`)
    }
    _action(){
        console.log(`Base._action()`)
    }
    _afterAction(){
        console.log(`Base._afterAction()`)
    }
}

class A extends Base {
    _action(){
        console.log(`A._action()`)
    }
}

let a = new A()
// console reads:
// > Base._beforeAction()
// > A._action()
// > Base._afterAction()
</script>

/Michael
-----

Monday, February 11, 2019 10:34 PM Michael Haufe <[hidden email]> wrote:

> You can use a Proxy in the base class:
>
> <script>
> let handlerExample = {
>     get(target, prop) {
>         let feature = target[prop]
>         return feature instanceof Function ?
>             function () {
>                 console.log('Before call');
>                 let result = feature.apply(this, arguments)
>                 console.log('After call');
>                 return result
>             }
>             : feature
>     }
> }
>
> class Base {
>     constructor() {
>         return new Proxy(this, handlerExample)
>      }
>     m1() { return "m1" }
> }
>
> class Sub extends Base {
>     m1() { return `override ${super.m1()}` }
>     m2() { return `m2` }
> }
>
> let base = new Base()
> console.log(base.m1())
>
> let sub = new Sub()
> console.log(sub.m1())
> console.log(sub.m2())
> </script>
>
> /Michael


On Fri, Feb 8, 2019 at 1:22 AM #!/JoePea <[hidden email]> wrote:

 > I many times find myself in cases where a base class wants to ensure that logic is always fired after the current method's execution, so that for example no matter in which order sub classes call the `super` method, the `super` method can still guarantee that logic fires after the whole stack of the same method in the class hierarchy.

> So what I can do now is use `Promise.resolve().then(() => { ... })` to schedule that logic for later, that way all the invocations of a `foo` method along the class hierarchy have all fired. But this means that other code can also fire before the next microtask.

> Is there some way to do it? If not, I wonder if some language feature for doing it would be possible?
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

RE: A way to fire logic at the end of completion of the current class method (regardless of super call order).

Michael Haufe-2

Assuming your base class:

 

<script>

class Base {

    methodWIthAfter(){

        method()

        after()

    }

}

</script>

 

If I override the method, there is no guarantee that I called `super.methodWithAfter()`, so `after()` is never executed.

 

<script>

class A extends Base {

    methodWithAfter() {

        method2()

    }

}

</script>

 

Additionally, requiring me to call ` super.methodWithAfter()` is an Anti-Pattern: https://en.wikipedia.org/wiki/Call_super

 

/Michael

 

From: Naveen Chawla <[hidden email]>
Sent: Friday, July 19, 2019 3:24 AM
To: Michael Haufe <[hidden email]>
Cc: [hidden email]; es-discuss <[hidden email]>
Subject: Re: A way to fire logic at the end of completion of the current class method (regardless of super call order).

 

Can anyone tell me what's wrong with a really simple approach? Wherever you are calling method(), just call methodWithAfter():

 

//in base class

methodWithAfter(){

    method();

    after()

}

 

What am I missing, guys?

 

On Fri, 19 Jul 2019 at 07:43, Michael Haufe <[hidden email]> wrote:

Revisiting this topic: why is the Template Method pattern not acceptable to accomplish this?

<script>
class Base {
    constructor() {
        this._beforeAction()
        this._action()
        this._afterAction()
    }
    _beforeAction(){
        console.log(`Base._beforeAction()`)
    }
    _action(){
        console.log(`Base._action()`)
    }
    _afterAction(){
        console.log(`Base._afterAction()`)
    }
}

class A extends Base {
    _action(){
        console.log(`A._action()`)
    }
}

let a = new A()
// console reads:
// > Base._beforeAction()
// > A._action()
// > Base._afterAction()
</script>

/Michael
-----

Monday, February 11, 2019 10:34 PM Michael Haufe <[hidden email]> wrote:

> You can use a Proxy in the base class:
>
> <script>
> let handlerExample = {
>     get(target, prop) {
>         let feature = target[prop]
>         return feature instanceof Function ?
>             function () {
>                 console.log('Before call');
>                 let result = feature.apply(this, arguments)
>                 console.log('After call');
>                 return result
>             }
>             : feature
>     }
> }
>
> class Base {
>     constructor() {
>         return new Proxy(this, handlerExample)
>      }
>     m1() { return "m1" }
> }
>
> class Sub extends Base {
>     m1() { return `override ${super.m1()}` }
>     m2() { return `m2` }
> }
>
> let base = new Base()
> console.log(base.m1())
>
> let sub = new Sub()
> console.log(sub.m1())
> console.log(sub.m2())
> </script>
>
> /Michael


On Fri, Feb 8, 2019 at 1:22 AM #!/JoePea <[hidden email]> wrote:

 > I many times find myself in cases where a base class wants to ensure that logic is always fired after the current method's execution, so that for example no matter in which order sub classes call the `super` method, the `super` method can still guarantee that logic fires after the whole stack of the same method in the class hierarchy.

> So what I can do now is use `Promise.resolve().then(() => { ... })` to schedule that logic for later, that way all the invocations of a `foo` method along the class hierarchy have all fired. But this means that other code can also fire before the next microtask.

> Is there some way to do it? If not, I wonder if some language feature for doing it would be possible?
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: A way to fire logic at the end of completion of the current class method (regardless of super call order).

Naveen Chawla
Is this a problem in the real world? Most people understand that simply overriding methods can break functionality. Therefore, doesn't the simple approach I gave suffice for the requirement in at least most cases? Are you able to describe a scenario in which we really need to protect people who are overriding a method from breaking functionality that they might not even expect to occur after they've overridden it?

On Fri, 19 Jul 2019 at 09:32, Michael Haufe <[hidden email]> wrote:

Assuming your base class:

 

<script>

class Base {

    methodWIthAfter(){

        method()

        after()

    }

}

</script>

 

If I override the method, there is no guarantee that I called `super.methodWithAfter()`, so `after()` is never executed.

 

<script>

class A extends Base {

    methodWithAfter() {

        method2()

    }

}

</script>

 

Additionally, requiring me to call ` super.methodWithAfter()` is an Anti-Pattern: https://en.wikipedia.org/wiki/Call_super

 

/Michael

 

From: Naveen Chawla <[hidden email]>
Sent: Friday, July 19, 2019 3:24 AM
To: Michael Haufe <[hidden email]>
Cc: [hidden email]; es-discuss <[hidden email]>
Subject: Re: A way to fire logic at the end of completion of the current class method (regardless of super call order).

 

Can anyone tell me what's wrong with a really simple approach? Wherever you are calling method(), just call methodWithAfter():

 

//in base class

methodWithAfter(){

    method();

    after()

}

 

What am I missing, guys?

 

On Fri, 19 Jul 2019 at 07:43, Michael Haufe <[hidden email]> wrote:

Revisiting this topic: why is the Template Method pattern not acceptable to accomplish this?

<script>
class Base {
    constructor() {
        this._beforeAction()
        this._action()
        this._afterAction()
    }
    _beforeAction(){
        console.log(`Base._beforeAction()`)
    }
    _action(){
        console.log(`Base._action()`)
    }
    _afterAction(){
        console.log(`Base._afterAction()`)
    }
}

class A extends Base {
    _action(){
        console.log(`A._action()`)
    }
}

let a = new A()
// console reads:
// > Base._beforeAction()
// > A._action()
// > Base._afterAction()
</script>

/Michael
-----

Monday, February 11, 2019 10:34 PM Michael Haufe <[hidden email]> wrote:

> You can use a Proxy in the base class:
>
> <script>
> let handlerExample = {
>     get(target, prop) {
>         let feature = target[prop]
>         return feature instanceof Function ?
>             function () {
>                 console.log('Before call');
>                 let result = feature.apply(this, arguments)
>                 console.log('After call');
>                 return result
>             }
>             : feature
>     }
> }
>
> class Base {
>     constructor() {
>         return new Proxy(this, handlerExample)
>      }
>     m1() { return "m1" }
> }
>
> class Sub extends Base {
>     m1() { return `override ${super.m1()}` }
>     m2() { return `m2` }
> }
>
> let base = new Base()
> console.log(base.m1())
>
> let sub = new Sub()
> console.log(sub.m1())
> console.log(sub.m2())
> </script>
>
> /Michael


On Fri, Feb 8, 2019 at 1:22 AM #!/JoePea <[hidden email]> wrote:

 > I many times find myself in cases where a base class wants to ensure that logic is always fired after the current method's execution, so that for example no matter in which order sub classes call the `super` method, the `super` method can still guarantee that logic fires after the whole stack of the same method in the class hierarchy.

> So what I can do now is use `Promise.resolve().then(() => { ... })` to schedule that logic for later, that way all the invocations of a `foo` method along the class hierarchy have all fired. But this means that other code can also fire before the next microtask.

> Is there some way to do it? If not, I wonder if some language feature for doing it would be possible?
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

RE: A way to fire logic at the end of completion of the current class method (regardless of super call order).

Michael Haufe-2

You should read the original message I quoted and the related thread:

 

https://mail.mozilla.org/pipermail/es-discuss/2019-February/thread.html#52279

 

Assuming what people understand is a recipe for disappointment in my experience. Also, we should differentiate between “simple” and “simplistic”.

 

/Michael

 

From: Naveen Chawla <[hidden email]>
Sent: Friday, July 19, 2019 3:51 AM
To: Michael Haufe <[hidden email]>
Cc: [hidden email]; es-discuss <[hidden email]>
Subject: Re: A way to fire logic at the end of completion of the current class method (regardless of super call order).

 

Is this a problem in the real world? Most people understand that simply overriding methods can break functionality. Therefore, doesn't the simple approach I gave suffice for the requirement in at least most cases? Are you able to describe a scenario in which we really need to protect people who are overriding a method from breaking functionality that they might not even expect to occur after they've overridden it?

 

On Fri, 19 Jul 2019 at 09:32, Michael Haufe <[hidden email]> wrote:

Assuming your base class:

 

<script>

class Base {

    methodWIthAfter(){

        method()

        after()

    }

}

</script>

 

If I override the method, there is no guarantee that I called `super.methodWithAfter()`, so `after()` is never executed.

 

<script>

class A extends Base {

    methodWithAfter() {

        method2()

    }

}

</script>

 

Additionally, requiring me to call ` super.methodWithAfter()` is an Anti-Pattern: https://en.wikipedia.org/wiki/Call_super

 

/Michael

 

From: Naveen Chawla <[hidden email]>
Sent: Friday, July 19, 2019 3:24 AM
To: Michael Haufe <[hidden email]>
Cc: [hidden email]; es-discuss <[hidden email]>
Subject: Re: A way to fire logic at the end of completion of the current class method (regardless of super call order).

 

Can anyone tell me what's wrong with a really simple approach? Wherever you are calling method(), just call methodWithAfter():

 

//in base class

methodWithAfter(){

    method();

    after()

}

 

What am I missing, guys?

 

On Fri, 19 Jul 2019 at 07:43, Michael Haufe <[hidden email]> wrote:

Revisiting this topic: why is the Template Method pattern not acceptable to accomplish this?

<script>
class Base {
    constructor() {
        this._beforeAction()
        this._action()
        this._afterAction()
    }
    _beforeAction(){
        console.log(`Base._beforeAction()`)
    }
    _action(){
        console.log(`Base._action()`)
    }
    _afterAction(){
        console.log(`Base._afterAction()`)
    }
}

class A extends Base {
    _action(){
        console.log(`A._action()`)
    }
}

let a = new A()
// console reads:
// > Base._beforeAction()
// > A._action()
// > Base._afterAction()
</script>

/Michael
-----

Monday, February 11, 2019 10:34 PM Michael Haufe <[hidden email]> wrote:

> You can use a Proxy in the base class:
>
> <script>
> let handlerExample = {
>     get(target, prop) {
>         let feature = target[prop]
>         return feature instanceof Function ?
>             function () {
>                 console.log('Before call');
>                 let result = feature.apply(this, arguments)
>                 console.log('After call');
>                 return result
>             }
>             : feature
>     }
> }
>
> class Base {
>     constructor() {
>         return new Proxy(this, handlerExample)
>      }
>     m1() { return "m1" }
> }
>
> class Sub extends Base {
>     m1() { return `override ${super.m1()}` }
>     m2() { return `m2` }
> }
>
> let base = new Base()
> console.log(base.m1())
>
> let sub = new Sub()
> console.log(sub.m1())
> console.log(sub.m2())
> </script>
>
> /Michael


On Fri, Feb 8, 2019 at 1:22 AM #!/JoePea <[hidden email]> wrote:

 > I many times find myself in cases where a base class wants to ensure that logic is always fired after the current method's execution, so that for example no matter in which order sub classes call the `super` method, the `super` method can still guarantee that logic fires after the whole stack of the same method in the class hierarchy.

> So what I can do now is use `Promise.resolve().then(() => { ... })` to schedule that logic for later, that way all the invocations of a `foo` method along the class hierarchy have all fired. But this means that other code can also fire before the next microtask.

> Is there some way to do it? If not, I wonder if some language feature for doing it would be possible?
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss