The initial idea was to release our visual layer as an open source addon to our client library. It was 2011 and at that time the latest release of our client library was still version 5. Unfortunately, the visual layer of that lib was quite entangled with the subscription layer, so that such separation was unlikely. We also had in mind to completely revise our client APIs and planned to full embrace the AMD philosophy. So, we decided to wait. Fast-forward to 2012, with client version 6 we finally had a modular library and an independent visual layer, and the separation was finally possible. Other priorities took our time though, so the release had to wait until last summer.
Before we could release the visual layer, we had to release a common layer of utilities we shared across our whole library. The idea of a second project, to host the various utilities, was born... Following closer, came the idea to isolate the logging infrastructure in its own project and to also publish our testing framework. In the end, we had 4 projects to publish.
Let me introduce the various libraries to you.
This is the core of all the other projects. It contains different kinds of classes that are exploited by the other libraries:
- The collections (List, Matrix, DoubleKeyMap)
These classes do not need any kind of introduction; they are just collections.
- The exceptions (IllegalArgumentException, IllegalStateException)
- The simple helpers (BrowserDetection, CookieManager, Environment, EnvironmentStatus, Helpers, IFrameHandler)
These classes basically wrap informations and functionalities of the browser in an easy to use format. You may argue that we should not have a BrowserDetection module but rather have a FeatureDetection module (you know, something like Modernizr). I would agree, but unfortunately, there are certain things you can't detect unless you use UA sniffing. It is mostly stuff from the past but since we (proudly?) still support down to IE6 we need to keep this module. I'll make just an example to give you an idea: most browsers never show a hourglass when the browser is downloading something through XHR, while some Safari versions in some situations did: we found a way to block such hourglass but no way to detect the issue avoiding the use of UA sniffing. The workaround also comes at a cost, so we are not willing to apply it everywhere.
- The inheritance module (Inheritance)
- The mixin classes (Dismissable EventDispatcher Setter)
These are abstract classes that can be extended to import their functionalities in your own modules. Dismissable enables you to share a single object across different parts of your code not knowing of each other and giving you the possibility to release resources when no one is using the object anymore. Useful to create and then release resource-hungry multitons.
EventDispatcher can be used to handle a list of listeners. Each instance of classes extending the EventDispatcher can be configured to fire events in both synchronous and asynchronous mode.
Setter just offers validation of numeric and boolean parameters throwing exceptions when needed.
- The executor classes (ExecutorInterface Executor ExecutorSimple)
The ExecutorInterface (and thus its implementations Executor and ExecutorSimple) aims to offer a centralized handling of tasks to be executed. It is similar to a Java Timer.
This library exposes a set of logger facilities that can be used to write a logging-library-agnostic code: using the LoggerManager class, the code will be able to flush its log even if no logging library is available. Then, implementing the Logger and LoggerProvider interfaces, it is potentially possible to wrap any 3rd-party logging library, making it easy to switch from one library to another. The LoggerProvider can also be specified at runtime. A ready-made simple implementation SimpleLoggerProvider is already provided with this library.
This approach to logging actually originated from our .NET client library: at some point we wanted to ditch the log4net dependency but also wanted an easy way to attach it back to consume our library logging. See http://www.lightstreamer.com/docs/client_dotnet_api/Lightstreamer_DotNet_Client_Log_ILoggerProvider.html
There are several Unit Test frameworks around but I never found something I was willing to integrate in our environment. This test framework is very simple but has some advantages: it can run on both browsers and Node.js and can run both Unit Tests and Integration Tests, as a test can also be completed asynchronously. This is perfect for a framework like Lightstreamer, where you have to run many integration tests along with unit tests to verify that everything is working as expected. Each test is also isolated in its own module making it easy to mantain a full set of tests.
Finally, this is the visual layer we wanted to separate from the beginning. It mostly consist of two kinds of classes: classes implementing the SubscriptionListener interface and classes implementing the ClientListener interface.
- The SubscriptionListeners (Chart StaticGrid DynaGrid)
These classes implement the SubscriptionListener interface but can also be used without bounding them to a Subscription, because their internal model can be modified via direct API calls. The three classes are made to represent tabular data showing it in the form of a grid (StaticGrid - DynaGrid) or chart (well, Chart).
All the features offered when these classes are listening to a Subscription (like, as an example, real-time sorting) are also available if the model is manually populated.
- The ClientListeners (StatusWidget StatusImageWidget StatusBarProgressIndicator)
On the other hand, these classes are kind of specific to the Lightstreamer client library, since they are made to show the user the status of the Lightstreamer connection. Note that only the StatusWidget is actually included in the library we distribute. The other two classes are implementations of the behavior of previous versions of our library.