dao icon indicating copy to clipboard operation
dao copied to clipboard

Re-thinking the aspect class syntax

Open Night-walker opened this issue 10 years ago • 19 comments

A minor issue with aspect classes lies in the fact that they represent a separate kind of entity in the language. That is, we have classes, abstract interfaces, concrete interfaces and aspect classes. At the same time, aspect classes are nothing more than ordinary classes mixed-in automatically to all compatible targets.

Thus aspect classes are essentially a macro-feature used to make class compositions. So why not decouple it from class declarations? It could look like this:

class Mixin {
    ...
}

import Mixin for Target # following the present pattern semantics

class Target {
    ...
}

Here import-for (or import-in) is just a directive to glue ordinary classes together without introducing any extra layer of complexity.

Obvious advantages:

  1. Elision of needless language entity. No more magic @-prefixed classes which one should distinguish from ordinary classes.
  2. Ability to automatically mix-in any fitting class. Instead of declaring ad-hoc aspect classes for certain scenario, one might adopt existing classes for this role without changing the related source.

Also, I like to see import keyword here, as it does conceptually the same thing as with namespace importing :)

As for disadvantages, as of now I see none. I believe that in this case a fine-grained design, one with smaller 'bricks' easily combinable with each other, is apparently superior to a coarse-grained design with larger and more complex 'bricks'.

Night-walker avatar Jun 30 '15 15:06 Night-walker

I am afraid that import Mixin for Target does not reflect the fact that the decorator methods of Mixin should be automatically applied to the methods of Target, and its resemblance to namespace importing could be particularly misleading.

daokoder avatar Jun 30 '15 15:06 daokoder

class @Mixin reflects that even less, given that @ is perceived as an abstract sigil here. At least it does bear particular resemblance to routine decorators for me, given that Dao also uses '@' for type holders and verbatim strings.

Speaking about clarity, if one hasn't ever encountered such feature, neither of the syntax variant will explain its meaning just by themselves. But getting rid of aspect classes would make the language simpler -- that is the key motivation behind the idea.

Night-walker avatar Jun 30 '15 17:06 Night-walker

And as far as I can see, auto-application of decorators works with usual classes just as with aspect classes, so there doesn't seem to be a real necessity to distinguish the latter as a separate language entity.

Night-walker avatar Jun 30 '15 18:06 Night-walker

A more elaborated explanation of the logic behind the proposal.

This code

class A {
    routine @d(fun(args): routine) for ~ {
        io.writeln('@d')
        return fun(args, ...)
    }
}

class B(A) {}
B()

behaves identically to this one

class @A {
    routine @d(fun(args): routine) for ~ {
        io.writeln('@d')
        return fun(args, ...)
    }
}

class B(@A) {}
B()

And in the first example class A shows no special mark that would reflect that it contains auto-applied decorators. Seems like the only difference between A and @A is the ability to use for <pattern> with @A, which is what I propose to decouple in the form of import.

If, however, class @X syntax is to stay, it should represent something more then it is now. Something really diverging from the ordinary class semantics to deserve special place in the language. But I think that the less number of entities we have to keep in mind, the easier it is to reason about code structure.

Night-walker avatar Jun 30 '15 19:06 Night-walker

Speaking about clarity, if one hasn't ever encountered such feature, neither of the syntax variant will explain its meaning just by themselves. But getting rid of aspect classes would make the language simpler -- that is the key motivation behind the idea.

Actually I meant the clarity even after knowing other features. The syntax with @ is still a bit clearer or more logical than the import (mixin class --> decorator class --> aspect class), if we try to explain it with concept such decorator and aspect. import, though, has clear connection to mixin, its connection to decorator and aspect is much weaker. If we use import, we may have to stop using branding buzz word such as decorator and aspect for this feature. Not a big deal for the language per se, but might be something for marketing this language.

For clarity, something like aspect Mixin for Target would be ideal. But a new keyword just for this seems too much. Maybe we can keep the current syntax, and switch to import later at appropriate time.

daokoder avatar Jul 02 '15 14:07 daokoder

If we use import, we may have to stop using branding buzz word such as decorator and aspect for this feature. Not a big deal for the language per se, but might be something for marketing this language.

Language design is what makes a language attractive first and foremost. Buzzwords are often just empty words anyway. Languages which succeed achieve this not by having unique killer-features, vast out-of-the-box capabilities or so -- they conquer their users essentially by their look&feel qualities, which take roots directly in the design principles the language is built around.

For clarity, something like aspect Mixin for Target would be ideal. But a new keyword just for this seems too much. Maybe we can keep the current syntax, and switch to import later at appropriate time.

Well, I think default keyword for switch just to make it look like C/C++/Java/etc. is too much. For instance, Rust and Ceylon omit this keyword, relying on _ => ... and else: accordingly.

The problem, however, is not with the syntax. It's with the language entities. Aspect classes as separate addressable elements of code are arguably redundant. It seems appropriate to introduce a more light-weight and non-invasive way to provide the functionality provided by aspect classes.

Night-walker avatar Jul 02 '15 15:07 Night-walker

Not that I'm trying to push in my own a priori best way of auto-mixing. import may indeed be sub-optimal here. There might be other options. I'm just looking for a way to make the language simpler and easier to reason about, particularly by erasing various magic entities whose scope seems too narrow to keep them in the language core.

Night-walker avatar Jul 02 '15 17:07 Night-walker

I'm just looking for a way to make the language simpler and easier to reason about, particularly by erasing various magic entities whose scope seems too narrow to keep them in the language core.

I understand your motivation. You are probably as much a language idealist as me:-).

Now I think I has come to a conclusion that we should use import-in syntax for auto-mixing with decorator application. It seems clearer than import-for.

I also think that keyword such as aspect should be a voided. Because we should avoid giving people the impression that we are just trying to jam multiple paradigms into a single language. Instead we should try to make Dao (somehow) above paradigms with a very consistent and logical design. The features could have originated from different paradigms, but they are not necessarily incompatible, we can try to discover the logical connections between them, and use such connections to fit them well in Dao.

daokoder avatar Jul 03 '15 15:07 daokoder

Also aspect could imply more things, there is really no way we will support them all. On the other hand, import-in, once made clear, won't drag in any extra things.

daokoder avatar Jul 03 '15 15:07 daokoder

I even think that the word 'aspect' understates the related feature in Dao. 'Traditional' AOP, the one with aspects, is a rather marginal programming paradigm built around ad-hoc function hooks. It hasn't been broadly accepted exactly because it doesn't look like a bright idea when you look on a typical implementation. There it's essentially a hack.

We (I like to say 'we' even if my role was minimal) approached this concept from a different angle in Dao, and I think the results are much more convincing then with aspects. That is largely due to the fact that instead of spawning new entities we simply adopted routine decorators to this role, which fits them perfectly. To certain extent, this applies to import-in vs aspect classes as well.

Night-walker avatar Jul 03 '15 16:07 Night-walker

'Traditional' AOP, the one with aspects, is a rather marginal programming paradigm built around ad-hoc function hooks.

I also felt that AOP in some languages is quite ad-hoc. Not sure about other languages, but to fit strictly into the AOP definition, it might become inevitably ad-hoc.

We (I like to say 'we' even if my role was minimal) approached this concept from a different angle in Dao, and I think the results are much more convincing then with aspects.

I also felt our approach is better, but do not fit quite well with aspect.

To certain extent, this applies to import-in vs aspect classes as well.

Regarding keywords, I am not sure, but I take this as your preference for import-in over aspect, right?

BTW, using separate statements such as import-in is also a lot more flexible than aspect classes.

daokoder avatar Jul 03 '15 16:07 daokoder

To certain extent, this applies to import-in vs aspect classes as well. Regarding keywords, I am not sure, but I take this as your preference for import-in over aspect, right?

I wasn't clear enough. I actually meant ordinary classes (plus little extra import-in) vs aspect classes.

BTW, using separate statements such as import-in is also a lot more flexible than aspect classes.

Yes. Smaller, simpler things are usually more flexible as well.

Night-walker avatar Jul 03 '15 17:07 Night-walker

What an inspirating discussion and I couldn't participate due to my time constraints.

I've never used AOP directly in production code (only indirectly by using e.g. Enterprise Java Beans) - but the main reason was that there was usually no need for it (e.g. AOP in Java tries to solve the verbosity of Java and it's lack of high-level expressibility - in other words it made the ice-cream partially self-licking).

In Dao, I believe, the import-in will shift the archaic thinking about AOP a little bit higher.

dumblob avatar Jul 03 '15 22:07 dumblob

In Dao, I believe, the import-in will shift the archaic thinking about AOP a little bit higher.

Let's hope so.

daokoder avatar Jul 04 '15 00:07 daokoder

I am starting wonder if we really need support for patterns for classes and methods. I don't find it particularly useful. Automatic application of decorator methods to methods with the same name is probably enough, if not, explicit application of decorator can be used. Without for patterns, we won't need import-in or import-for anymore, normal mixin would be enough.

daokoder avatar Oct 04 '15 12:10 daokoder

I also think that metaprogramming and patterns don't quite fit each other. But I'm not sure I properly understand the phrase application of decorator methods to methods with the same name.

Night-walker avatar Oct 05 '15 07:10 Night-walker

I also think that metaprogramming and patterns don't quite fit each other. But I'm not sure I properly understand the phrase application of decorator methods to methods with the same name.

It's just a simple way to keep the previous for some_name decorator pattern for exact matching. This way, the functionality of the current aspect class can be kept to some degree.

daokoder avatar Oct 05 '15 08:10 daokoder

There may be use for decorators applied to multiple or all methods of a class, like logging or constraint checking. If this functionality is removed, I see no use in auto-applying anything -- manual decoration will do the same without extra indirectness.

Night-walker avatar Oct 05 '15 11:10 Night-walker

There may be use for decorators applied to multiple or all methods of a class, like logging or constraint checking.

I think only a few things such as logging need decorator application for multiple methods, other scenarios requires more specific targeting. Supporting name (and method signature) matched auto-application of decorators will make mixin more useful, in a similar way virtual method makes inheritance more useful.

daokoder avatar Oct 05 '15 11:10 daokoder