biojs / biojs

🔬A library of JavaScript components to represent biological data
http://biojs.net/
Apache License 2.0
491 stars 120 forks source link

Models instead of events #95

Open wilzbach opened 10 years ago

wilzbach commented 10 years ago

This is an open discussion issue. Feel free to share your opinion with us.

Problem

If one wants to combine two BioJS components that is moderately easy with events. However this glue layer doesn't scale (in my eyes).

-> imho there should be only one model for the same data so that it is very easy to combine those components and the views only update itself on changes of the model.

Technical aspects

In the examples below you can see that whether the on method is provided by an model framework (e.g. Backbone) or one uses Object.observe(selection) isn't so important as long as there is a common model.

A list of more approaches to data binding can be found on Wikipedia.

Tricky (open): finding/agreeing on a common model

-> share you opinion/experience with us.

Example depicting the different approaches

1. using events

(for simplicity we assume the existence of setSelection method).

msa.on("change:selection", function(seqs){
  tree.setSelection(seqs); 
  seqLogo.setSelection(seqs);
});
seqLogo.on("change:selection", function(seqs){
  msa.setSelection(seqs); 
  tree.setSelection(seqs); 
});
tree.on("change:selection", function(seqs){
  msa.setSelection(seqs); 
  seqLogo.setSelection(seqs); 
});

2. Using a common model

a) with a JS model framework (e.g. backbone)

selection.on("change", function(seqs){
  // one might translate the event here for different components
  msa.setSelection(selection.seqs); 
  tree.setSelection(selection.seqs); 
  seqLogo.setSelection(seqs);
});

b) with Object.observe

Object.observe(selection, function(changes){
  // one might translate the event here for different components
  msa.setSelection(selection.seqs); 
  tree.setSelection(selection.seqs); 
  seqLogo.setSelection(seqs);
});
mhelvens commented 10 years ago

The advantage of Object.observe is that it does not require the library to be set up in any particular way. It is (will be) just a part of Javascript.

That being said: I don't believe people will ever agree on a common model. This problem has plagued developers for decades.

gyachdav commented 10 years ago

Unfortunately while the motivation and problem statement are correct the solution is not so easy. Trying to set up a data exchange model in biology is a monumental challenge that many have been and are working on. It is best if we (BioJS) stay away from it.

On Sep 24, 2014, at 11:44 AM, Michiel Helvensteijn notifications@github.com wrote:

The advantage of Object.observe is that it does not require the library to be set up in any particular way. It is (will be) just a part of Javascript.

That being said: I don't believe people will ever agree on a common model. This problem has plagued developers for decades.

— Reply to this email directly or view it on GitHub.

mhelvens commented 10 years ago

I think the described problem is a bit lower level than setting up a data exchange model for biology. This is about the basic mechanism for subscribing to any data from one module by another. If we agree on a common mechanism (and it's a big if), which format that data should have is yet another problem, likely even harder to solve.

homonecloco commented 10 years ago

As each component is displaying a different type of data, which different properties , I don't think an enforced object type will work. However, I would suggest to use duck typing. I would have the event receiving a single object and the receiver should validate that it contains the attributes to do the action. In that way, related components should be able to provide a minimum common set of properties to communicate. Between my components , I use a seqregion object, that has the entry , start and end encapsulated (https://github.com/homonecloco/biojs-alg-seqregion/blob/master/lib/biojsalgseqregion.js). What we could give is a guidance on standard names to be expected for common names that developers should follow if they want better compatibility. A solution for file formats that have different standard names would be to make aliases to the natural name in the file, to a standard.

Ricardo H. Ramirez G.

On 24 Sep 2014, at 10:14, Michiel Helvensteijn notifications@github.com<mailto:notifications@github.com> wrote:

I think the described problem is a bit lower level than setting up a data exchange model for biology. This is about the basic mechanism for subscribing to any data from one module by another. If we agree on a common mechanism (and it's a big if), which format that data should have is yet another problem, likely even harder to solve.

— Reply to this email directly or view it on GitHubhttps://github.com/biojs/biojs/issues/95#issuecomment-56644321.

jmvillaveces commented 10 years ago

As stated before, this is a lower level (or technical) problem. During the Munich hackathon, we agreed to use a common event structure among biojs 2.0 components and there are two main advantages from doing so :

  1. It is a shared concept with biojs 1.0.
  2. A common model allows developers to connect components easily almost without duct tape code.

With that said, it is also very difficult to enforce (or suggest) a developer which tools to use or how to use them so I really doubt the current approach will be adopted by the community. Perhaps Object.observe is the way to go but it is not part of JavaScript yet and I probably won't be supported by legacy browsers.

wilzbach commented 10 years ago

Wow thank you all for this active discussion :)

I don't believe people will ever agree on a common model. This is about the basic mechanism for subscribing to any data from one module by another (@mhelvens) It is best if we (BioJS) stay away from it. (@gyachdav)

I know this is a very difficult topic, but in my opinion one of the key ideas behind of BioJS is that a user can combine different visualization components easily. Otherwise BioJS would be only a awesome registry with a great community and "getting started with JS + NPM" docs.

If we really don't manage to agree on a common model, we could provide a small lib that does something like my suggestion for artificial models (more sophisticated, of course).

Currently the only (well hidden) guide (see Step 4) we have have is sending one event (one-way) to another component. So whatever the outcome of this discussion will be, we would should provide better documentation (and make it easier to find).

A common model allows developers to connect components easily almost without duct tape code (@jmVillaveces)

Yep exactly that is what I try to suggest here, because only with an event system you will have this annoying glue code.

However, I would suggest to use duck typing (@homonecloco)

I created a common place (biojs-model) for those definitions. We could collect minimal schemes we agreed on there?

Artificially enforced model

The main problem here would be to prevent ping-pong loops. This approach here depends on the component to send the origin encapsulated with the event.

// for simplicity every components has the same event name (without any translation)
msa.on("selection", function(data){
  if(data.origin !== "commonModel"){
    commonModel.set("selection", data.seqs);
  }
}
tree.on("selection", function(data){
 if(data.origin !== "commonModel"){
    commonModel.set("selection", data.seqs);
  }
}
seqLogo.on("selection", function(data){
 if(data.origin !== "commonModel"){
    commonModel.set("selection", data.seqs);
  }
}
commonModel.on("change", function(data){
  // one might translate the event here for different components
  msa.setSelection({data: selection.seqs, origin: "commonModel"});
  tree.setSelection({data: selection.seqs, origin: "commonModel"});
  seqLogo.setSelection({data: selection.seqs, origin: "commonModel"});
});
emepyc commented 10 years ago

On 24/09/14 12:10, José Villaveces wrote:

Perhaps |Object.observe| is the way to go but it is not part of JavaScript yet

For me, this only is enough to leave this option out. M;

mhelvens commented 10 years ago

For me, this only is enough to leave this option out.

No event system is part of Javascript right now, i.e., they all require a library of some sort.

In the case of Object.observe, the functionality can be imported with a polyfill library. The difference is that Object.observe will be a part of JavaScript. And as browsers start to support it natively, the application will automatically become faster (and the polyfill will become redundant).

The main question is which model we want to use. Subscribing to events or observing values.

maxkfranz commented 10 years ago

I think Object.observe() may not be viable in general for the reason that you're not always going to have access to model objects from other libraries. If you don't have a stable (i.e. documented) object definition, you've got nothing to reliably observe. Object.observe() also has the limitation that you can't listen to events that don't change an observed object.

You could work around these limitations by separating the model from the third-party libraries --- in other words, creating a BioJS-centric model. Depending on what type of biological information you want to model, you may be able to reuse languages like BioPAX so that Object.observe() makes sense to use.

A common event system is useful, but it requires the developer to define intercomponent relationships. For rich applications, this is almost always required anyway.

If you want flexibility, you'll almost certainly need to use an event system instead of Object.observe().

If you want to make it easier (but possibly less flexible) for developers, you need a full BioJS model that manages everything -- and this could potentially use Object.observe() or an event system. In this case, it may make sense to reuse an existing MVC framework/lib rather than reinventing the wheel. Since it looks like you're targeting beginners, I don't think they'll care too much about your choice of framework as long as things work.

You should also consider using tools like Yeoman. That way, a dev can just specify the components he wants to use in his app and the initial app is built for him (sans business logic etc).

mhelvens commented 10 years ago

I've been exploring the concept of Functional Reactive Programming (FRP). It's a paradigm where 'observable events or values' become first-class citizens. This includes ways to pass, return, merge, zip, combine, fold, etc. event-streams. It's quite elegant.

Possibly the best known JavaScript FRP library is Bacon.js. We're now using it for ApiNATOMY, and it's cut down code-size, solved a few bugs and improved readability.

One way we could communicate between components is to put Bacon.js based EventStreams and Buss in our public APIs. Then it's a simple matter to plug them together the way you want. There is also Propertys, which have the concept of a 'current value'. This is kind of like Object.observe, except the interface publishing the property needs to use Bacon.js to do it.

It's quite trivial to maintain support the traditional on, trigger, off, etc. with Bacon.js as the backend.

daviddao commented 10 years ago

I think this is an interesting idea. However, I am worried about the learning curve in using FRP (I think it is quite an uncommon concept - especially when you are not used to FP). Furthermore, we still need people to document and list all of their EventStreams. Any than that, I am happy to discuss the Event System in the next BioJS Call.

maxkfranz commented 10 years ago

+1 for FRP

Though there is a learning curve, I think it is relatively small compared to other concepts in compsci -- and the benefits can be substantial. Perhaps a system of rules for translating library events into Bacon.js events (or similar) could be used such that you could defer to each individual library's documentation for details. Just a thought.

manuelcorpas commented 10 years ago

Definitively interoperability between components was an aim that BioJS 2.0 should aspire to even if it is at a low level.

@Michiel @Max it would be great to see FRP in action with some BioJS 2.0 components as a proof of concept to see its feasibility.

Cheers Manny

Dr Manuel Corpas Project Leader The Genome Analysis Centre Norwich Research Park Norwich, UK

Tel: +44 1603 450 095 Fax: +44 1603 450 021 Web: http://goo.gl/ELtV4 Blog: http://manuelcorpas.com/

http://www.facebook.com/corpasgenome https://twitter.com/#!/manuelcorpas http://www.linkedin.com/profile/view?id=5414661 https://plus.google.com/u/0/101146878928866340609/

On 29 November 2014 at 17:40, Max Franz notifications@github.com wrote:

+1 for FRP

Though there is a learning curve, I think it is relatively small compared to other concepts in compsci -- and the benefits can be substantial. Perhaps a system of rules for translating library events into Bacon.js events (or similar) could be used such that you could defer to each individual library's documentation for details. Just a thought.

Reply to this email directly or view it on GitHub https://github.com/biojs/biojs/issues/95#issuecomment-64959221.

mhelvens commented 10 years ago

@Michiel @Max it would be great to see FRP in action with some BioJS 2.0 components as a proof of concept to see its feasibility.

You got it! ApiNATOMY is now all about the Bacon. :-)

manuelcorpas commented 10 years ago

would you like to tell us about it and perhaps show us a short demo on Thursday? Manny

Dr Manuel Corpas Project Leader The Genome Analysis Centre Norwich Research Park Norwich, UK

Tel: +44 1603 450 095 Fax: +44 1603 450 021 Web: http://goo.gl/ELtV4 Blog: http://manuelcorpas.com/

http://www.facebook.com/corpasgenome https://twitter.com/#!/manuelcorpas http://www.linkedin.com/profile/view?id=5414661 https://plus.google.com/u/0/101146878928866340609/

On 29 November 2014 at 18:35, Michiel Helvensteijn <notifications@github.com

wrote:

On Sat, Nov 29, 2014 at 7:34 PM, manuelcorpas notifications@github.com wrote:

Definitively interoperability between components was an aim that BioJS 2.0 should aspire to even if it is at a low level.

@Michiel @Max it would be great to see FRP in action with some BioJS 2.0 components as a proof of concept to see its feasibility.

You got it! ApiNATOMY is now all about the Bacon.

www.mhelvens.net

Reply to this email directly or view it on GitHub https://github.com/biojs/biojs/issues/95#issuecomment-64960958.

mhelvens commented 10 years ago

would you like to tell us about it and perhaps show us a short demo on Thursday?

Sure. I have to point out though, that I am by no means an expert at FRP.

daviddao commented 10 years ago

Probably you also put some thoughts into using bacon.js instead of other FRP JS libraries like Kefir.js or [RX.js](http://reactive-extensions.github.io/RxJS/#Getting Started). It would be nice if you also point out why you choose bacon.js :)

mhelvens commented 10 years ago

@daviddao: I did put some thought into that. And here it is:

RX.js comes from Microsoft, ported from .net. I admit this already leaves a bad taste in my mouth, but that's subjective. Bacon.js was written from the ground up with JavaScript in mind, and makes up for a number of deficiencies in RX.js. Additionally, it is already a more starred library on GitHub.

Kefir.js was a serious contender. It's apparently more performant, and we might switch to it someday. However, for now it feels too new to me, and doesn't support error propagation.

There are also a number of promising extensions to Bacon.js, in the form of bacon.model, bacon.jquery and bacon.matchers.

Still, I haven't looked at the alternatives as closely as I might have. But at some point you have to make a choice and go with it. I'd certainly be happy to be convinced to switch for good reasons.

mhelvens commented 10 years ago

would you like to tell us about it and perhaps show us a short demo on Thursday?

It occurs to me that the way these calls take place, I can't really show anything?

wilzbach commented 10 years ago

Do you have a link? Otherwise you could copy screenshots into the Google Doc..

mhelvens commented 10 years ago

Neh. I was just going to show some code examples. I now just explained FRP and Bacon with... words. :-)

daviddao commented 10 years ago

Was really nice though! :)