On the surface, Dana looks like a typical object-oriented programming language. This is something we've worked very hard to achieve so that, as a programmer, all of your existing skills from languages like Java and C# are easily transferrable to Dana programming. This allows you to quickly get started building your first projects.
Below this surface level, however, Dana is structured very differently to object-oriented languages. It is these specially-designed features of Dana that give us powerful, generalised runtime adaptation capabilities in which we can hot-swap behavior extremely quickly in a running program, without losing any state or in-progress computation when we do so.
The unique language design of Dana also strongly resonates with modern guidelines for robust software engineering. The key features of the Dana programming language are:
In Dana, components (analogous to classes in Java or C#) are the fundamental unit of encapsulation and composition for writing software. A component is different to a class because its functionality is declared in an interface which is separate from the implementation in the component. By universally making this separation throughout a software system, we maximise the re-usability of code. A Dana interface is a list of functions, constants and transferrable state variables for runtime adaptation.
Every component can provide one or more such interfaces, specifying that it will implement every function in each provided interface, and can require zero or more interfaces, specifying which external functionality it depends upon from other components -- where any and all external functionality used by a component must be accessed via a required interface.
All of this means that the concept of dependency injection, sometimes called inversion of control, is ubiquitous in all Dana programs because it's part of the fundamental programming language: every dependency of every component is externally injected before a system runs and can be seamlessly reconfigured while it runs. To avoid this becoming a chore, however, Dana also automatically resolves all dependencies to default implementations. For every program written in Dana, this allows you to take control of dependency resolution when and where you want to and leave it to the system to handle automatically when you don't.
To enable runtime adaptation we need very strict encapsulation of component behaviour and state. This imposes a few extra constraints at a language level, but again are constraints that are strongly supported by good software engineering practice in general.
Firstly, interfaces cannot contain variable declarations, which means that components cannot have any publicly accessible state: all state access must occur via accessor or mutator functions defined in the interface. From a re-usability perspective we gain much more independence for each component implementation, because different implementations of an interface can have completely different internal state representations.
This, in turn, motivates another language design choice: we separate data from behavior by introducing a special data type. Dana programs therefore have both interface and data types, so that pure information is represented by data types while behavior is represented by interface types -- which often operate over data types that they take as input.
Finally, instances of data types that are passed between components are read-only in any component other than the one in which they were created. This upholds the strict encapsulation requirement of highly adaptable code, where a component could otherwise expose its internal state via a function call for direct manipulation.
Besides being a general-purpose programming language which upholds strong software engineering principles, Dana is also powering cutting-edge research in self-aware and self-designing software. This research is uniquely supported by Dana because it allows externalised, automated reasoning about how a software system is composed from building blocks of components.
Advanced machine learning algorithms can therefore automatically compose a software system from a palette of small building blocks and can continually observe how that system is behaving in the operating environment to which it is deployed; thanks to Dana's hot-swapping support the system can then be continually and very cheaply re-assembled while it is still running to better shape the system to the characteristics or requirements of its environment.
You can read more about this ongoing work in several peer-reviewed publications at some of the top computer science conferences, including USENIX OSDI 2016
and IEEE SASO 2016
We'd love to know about any research you're doing with Dana so do get in touch!
We support the free hosting of all research source code and experimental setup so that the community can reproduce results via research.projectdana.com
Yes! Dana's entire standard library is open-source, with all source code included in its standard download package. This means you can see how everything works and you can also submit your own new components for inclusion in the standard library.
Some components use native libraries to perform platform-specific functionality; note that we don't include the source code for these libraries in our release package but we do maintain this as open-source code on Github, so you can write your own native code too.