Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Non-framework approach to JavaScript apps - hexagonal.js (andrzejonsoftware.blogspot.com)
30 points by andrzejkrzywda on Feb 22, 2013 | hide | past | favorite | 21 comments


When I went ahead and had a look at one of the examples of hexagonal.js, Misko Hevery's answer in quora http://www.quora.com/Ember-js/Which-one-of-angular-js-and-em... immediately came to my mind. He notes that there are 3 ways to bind data to view. 1 ) in the code - jquery way 2 ) In html bindings - angular way 3 ) in a metadata file.. which is the glue that is professed in this library.


Thanks for the link. I wasn't aware of this discussion.

Yes, it seems that hexagonal.js uses the third approach - a metadata file.


According to the page, it's neither a framework, nor a library - isn't that a bit counterintuitive? That makes it sounds as if it is beyond any of the existing styles of code reuse in software development, which is not the case.

I'm sure many would identify it as a library in the classical sense, since it is a bundle of code you include in your application and make calls to.


We were struggling with this problem for months.

What would you suggest to bundle into this library?


It's probably a design pattern, or a flavor of AOP (Aspect Oriented Programming).


Maybe I'm not "getting it", but what is the difference between:

    After(@useCase, "askForName", => @gui.showAskForName())
vs.

    @useCase.askForName()
    @gui.showAskForName()

?


In runtime, this is exactly the result.

As code modules, those two things are separated. The usecase doesn't need to know about the gui and vice versa.

In theory, they can even be reusable.

We combine those two things in the glue code. Thanks to the glue code, it's the usecase which drives the other things. The usecase makes sense even without thinking about a specific GUI solution.

I'm not sure where we could put the second piece of code you mention. Any suggestion?


I find it amusing that you are trying so hard to avoid naming this MVC. The "glue code" contains the code that would typically be a controller.

The difference is that you do it by modifying the model and view, and that is the problem to me: You are making non-local modifications to the code, which means that while you are separating it in source, you are not keeping a separation in the running code. You make it extremely hard to reason about the system.

This is already a problem in large event/notification driven systems, but this takes it to the extreme by removing the hint to look for non-local behaviour by having the equivalent to the notification imposed by an external actor.

If you want to improve on a notification driven system, in my opinion you don't do that by making the extension points less obvious.

And if you first are going to do that, at the very least do it in very obviously named functions, and don't modify passed in objects by make copies. But to me, those are workarounds to ameliorate a situation that's already undesirable. E.g. if you're making copies and modifying the copies and keeping those internal to the glue class you might as well go back to implementing an actual controller.


The difference is that After() modifies @useCase to that gui.showAskForName() always gets called after askForName on that object. Putting that kind of behaviour in a constructor in that way to me reads like a horrible anti-pattern.


Please explain the anti-pattern you see and the pattern your prefer.


A very non-obvious modification of objects that are passed in as arguments to the constructor.

Looking purely at the code calling the constructor, there is no good indication that the behaviour of the objects I pass in will fundamentally change.

If you are going to mutate arguments like that, I would at the very least expect naming that made it far more obvious, but much preferrable would be to not do it at all. They are implementing the observer pattern in a way that obscures the fact that notification happens in the implementation of an external class (the Glue) class, and so a consumer of the classes that are modified have no immediate reason to suspect that calling methods will trigger behaviour on other objects.

In a small system you can expect people to know the whole implementation, but in a larger project, this is a recipe for surprises where people have no idea which methods have side effects because they can't read the implementations of a class itself to find out if it does.

If I saw code like this in projects I manage, I'd have someone rewrite it.

The are good use cases for aspect oriented programming, but they tend to involve cases where the aspect that is extracted is orthogonal to the normal operation of the object. E.g. logging.


You are right that there is a danger in the fact that the object being passed into the AOP advices can be changed.

Usually, I'm avoiding this kind of situations. It can be terrible to debug.

In our teams, we have a rule that the calls to Before/After/Around can only happen in the Glue code.

Obviously, we also make sure that everyone involved is familiar with AOP and knows what is the architecture.

As for the use cases for AOP, I know it's not a common practice to use it. Orthogonal concerns are the best fits, but not the only ones.

There was an interesting research project at IBM, called Hyper/J. It was a little bit of inspiration for the AOP usage in the hexagonal.js architecture.

Here is a good paper on Hyper/J (and the idea of Multi-Dimensional Separation of Concerns)

http://helios.mm.di.uoa.gr/~anya/pms521_papers/p734-ossher.p...

Thanks for your comment, it was very valuable.


I'd love to check it out, but I had too much coffee. Pun intended.


Don't call something .js if it's all in .coffee.


We're going to include pure JavaScript examples. I understand the confusion that comes with the fact that most examples are CoffeeScript.

There's nothing that makes this approach impossible to use with JS. The code samples are Coffee, because that's what we write our production apps in.


It would be interesting to see at least a simple Hello World example in JavaScript, but I suspect the library is too dependent on CoffeeScript, and a compatible JS code would be too convoluted (I'd be glad to be proven wrong though).


So, name it "hexagonal.coffee" instead.


If a version of hexagonal targeted java then it would be "hexagonal.java". But .coffee and .js target the same "binary" so .js is the correct designation. It's about the runtime not the language.


Following this logic, they could have called it hexagonal.asm since it's eventually run as binary code.


Is hexagonal.js basically a very simple state machine framework? :) E.g., https://github.com/pluginaweek/state_machine





Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: