Experiences when porting the OpenDolphin client to the web
We did a few demos with that prototype and found it to be valuable and promising such that we decided to bring it to production quality.
This blog post describes the experiences that we made along the way.
Non-functional requirements and technology choices
For the sake of getting to speed quickly, the prototype had used a zoo of technologies:
grunt, bower, require, jquery, angular, node, and a few more. For a production version, though, we
wanted to have the fewest amount of dependencies such that a user of OpenDolphin.js
would not run into compatibility issues with his own choice of libraries and their
We found namespacing and module management to be critical and decided to stay with
require.js (with the option to drop that later) but drop all other runtime dependencies.
Since OpenDolphin.js is a library (as opposed to an application) we expect that we
have to maintain it over quite some time – a longer period of time than most
current development tools will be available.
That is: we can only use tools that produce tool-independent artifacts.
This consideration ruled out tools like Dart and GWT for development since their
We tried TypeScript for a week before we decided that it looked pretty much like what we
needed (our state of information at the time of decision):
- abstraction over types (classes and interfaces)
- type safety
- code navigation (“where used”)
- simple test facility
- source-code debugging
than what I had written manually – mainly because it wouldn’t have any of the
Experiences with TypeScript
In hindsight, we should have experimented more before starting the real
development and should have tested the distribution story. As it turned out
I misunderstood TypeScript modules as being mainly a tool to provide
namespaces – like packages in Java – but it is just as well a distribution
mechanism. You see that when you try to “package” a module that spans
over multiple files, which is not supported.
A helpful voice pointed that out to me on stackoverflow and correctly
mentioned that the documentation also says so (even though not very
with some Gradle/Groovy trickery but overall it costed me a day of
investigation, trial, error, and fixing.
We wasted two more days with hunting down two TypeScript errors that we
simply didn’t expect to be possible: we ran into a situation where
TypeScript inheritance silently didn’t work and on a second occasion
we got two different instances of the same static reference.
Lesson learned: avoid inheritance and statics even more than usual.
This lesson actually turned out to be benefitial because it led to a simpler
design, e.g. around the HttpClientConnector that we refactored from a
subclass into a Transmitter interface that the ClientConnector points to
with NoTransmitter and HttpTransmitter as implementations.
We plan to refactor the Java version accordingly.
While it first felt a bit weird that TypeScript cannot compile all
our *.ts files at once, we learned to value the fast incremental compile
especially when combined with the Intellij IDEA file watcher setup.
or better say type-oriented. But the real benefit is that it
very much improves the “functional programming” story, which is already
when declaring, implementing, or calling functions.
This is kind of an under-marketed feature of TypeScript.
We struggled a bit with how to organize *.ts files and references
between them in a way that works consistently in all scenarios
- when delivered from a web server or node.js
- when loaded from a static html file
- when testing
- when debugging
and I’m afraid our solution is not optimal since it led to
quite a lot of duplication in the references (relative file paths).
It would be helpful if the TypeScript documentation gave better
advice on the topic or propose best practices.
The TypeScript documentation was generally a doubly-edged experience.
While the language part is well documented, the API is not.
When searching for a feature I often landed at places where the
shape of that feature was discussed between the developers
but could not find any kind of “user guide”.
But, well, it is version 0.9 and it is free, so we should not complain
especially since the response time for questions on stackoverflow
IDE support inside Intellij IDEA is pretty strong and has helped us a lot.
Basic things like highlighting, navigation, code completion, and so on
One should not expect the same sophistication like for Java or Groovy,
though, when it comes to refactoring across multiple files.
Would I decide for TypeScript again? Definitely yes!
But I would allow more time for finding the best setup.
OpenDolphin for the web
OpenDolphin is use-case driven. We only include a feature, if we have
a use-case for it and with any use case comes a demo. This nicely
leads to the comfortable situation that every feature is used
in at least one demo.
The additional feature of OpenDolphin.js over the Java version is:
“it also works in the browser” be it desktop or mobile.
Consequently, we created some demos.
Creating the demos immediately revealed how well the OpenDolphin architecture
(structure, concepts, abstractions) fits for web development. Having
- views in HTML5 that are totally separate,
- a binding technology of your choice
- server-side control over the presentation models with Java
leads to a new level of enterprise applications.
These new enterprise applications are automatically consistent,
they update their content immediately, they share information with other
users, and facilitate user collaboration at a totally new level.
One can see these features boiled down to the bare minimum in the chat demo.
Best of all: desktop, web, mobile, and even embedded applications all share
the same information at runtime and the same programming model!
They all connect to the exact same server-side application logic.
The web for application development
For anyone with experience in desktop UI toolkits like JavaFX, Swing, or
equivalents web development feels casual and coincidental.
Obviously, one can “get things done” but it is hard to say whether they
only work by chance, what the actual constraints are, and on which
guarantees one can build (pun intended).
Take a slider as in the master-detail demo.
There is no such control in HTML5 – as there are no
real “controls” in the browser anyway. Ok, you can use the “input” element
with type “range” in some browsers. But which events are fired when
you drag the thumb? And are they fired while you drag or only after
stop? Happy testing in all your supported browsers!
Now try to enlarge the thumb for touch support with CSS – and
consider that some browsers use circles and others use squares…
I wouldn’t even go into more advanced controls like tables. HTML5 has no control
that even remotely compares to what you have in the most basic JavaFX table view.
But sliders and tables are only the tip of the iceberg. There are no controls.
There are no layout managers. There is no usable logging. Basic datatypes are missing.
Performance characteristics of existing datatypes are unclear. Object lifecycle
is unclear. Scoping is counter-intuitive.
To make matters worse, you can add ever-changing libraries that try to fill these gaps.
Welcome to dependency hell!
In short: the browser is a problematic execution environment.
Now, if developing applications for the web is so immature, why do we even
bother creating OpenDolphin.js? Because the web is everywhere and easy to access
and there is an undeniable request for enterprise applications to have selected parts
of their functionality visible and accessible on the web.
The web makes an extremely good distribution channel for information.
While creating the OpenDolphin web demos, I started to make extensive use of
the browser features for developers (I know, I’m late to the party).
These are extremely helpful while developing and occasionally scary when they
reveal what many of the websites I visit are doing on my machine.
One should always keep in mind that there is no privacy in the browser.
As it stands today, we can recommend this mix for enterprise applications:
- desktop (preferrably in JavaFX) for the office worker to safely edit the core of the system
- web and mobile “extensions” for special purposes
(dashboard, directions, check lists, mobile data capture, location, local sensors, field work)
all conveniently integrated in the OpenDolphin architecture.
course profited much from having the Java implementation as a blueprint.
But it actually turned out to be benefitial both ways: the Java version also
profited since it was implicitly reviewed along the way and we could improve it in two places
where even our 100% test coverage was not good enough to uncover a bug.
Furthermore, the architecture was scrutinized a second time and I feel
“implement a second time in a different technology” is a great validation
technique for any architecture. This also led to a better distinction between
rules and concepts of the architecture versus special design decisions for
concurrency and inheritance -, which forced us into simpler albeit less powerful designs
that we may partially bring back to the Java (“compact-0 profile”) implementation in the future.
It was a pleasure to see that with OpenDolphin.js we can reap the same
architectural benefits for web applications that we experienced for desktop apps
while adding the web as a new option for exchangeable visualization technologies.
That was what we were hoping for but then to see it working out so well
has been a huge reward for the effort.
P.S. OpenDolphin.js will be part of the imminent 0.9 release of OpenDolphin.