The MVCObject code ended up in OpenLayers 3 as the ol.Object class. In
OpenLayers 3 we only use it for high level objects (maps, layers,
collections of layers, markers) and not for low level objects like
colors and coordinates. It's very much there because I found MVCObject
in the Google Maps API to be very powerful, particularly when it came
to binding object properties together (e.g. ensuring that a HTML popup
follows a marker as it is dragged around).
We wrestled with a number of design constraints related to this. Some
observations/constraints that we had:
- OpenLayers 3 has to run on a variety of older browsers, so we
- We wanted the ability to be able to fire events at the instant a
property is changed, rather than detecting changes at a later time.
- We wanted to use the Closure Compiler in advanced mode with full
type checking, which adds further constraints.
libraries, but they have many disadvantages for large projects.
As a particularly problematic example, consider the use of combined
getters and setters in a fluent interface (I know Victor wasn't
suggesting this, but this is what Leaflet looks like):
camera.position([5, 45, 1000]).lookAt([5.5, 45.5, 0]); // set
camera's position and lookAt
var p = camera.position(); // returns the camera position
This causes several problems:
1. The position() function must check its arguments every time to work
out whether it is being called as a setter or a getter; this is a
performance price that is paid every function call.
2. Arguments must be converted into their implicit types, e.g. the
array [5, 45, 1000] must be converted into a Cartesian3 (or similar);
once again this performance price must be paid every time.
3. In fluent interfaces, there is often a lot of flexibility in the
types accepted by functions. This tends to prevent the virtual machine
from optimizing the code.
4. The return type of position() varies: in setter mode it returns a
camera ("this"), in getter mode it returns a Cartesian3. This makes
type checking hard.
For information, in OpenLayers 3, we use separate getters and setters
for all public properties. This provides a consistent API with the
ability to hook in extra functionality if needed. We rely on the
Closure Compiler to inline these getters and setters as direct
property accessors when there is no extra functionality to avoid the
performance penalty of the extra function call.
So, overall, I think fluent interfaces are perfectly fine in small
projects without performance concerns. However, they do cause problems
for larger projects or when performance matters.
If you haven't already seen it, this talk explains clearly how to
write code that V8 will optimize well: