Taking the complex and making it simple:
what is DSL, and why you need a new programming language
To create something simple is sometimes harder
than to create something complex
© Michail Kalashnikov
Hello, everybody, my name is Vladimir Kozhayev, I am a freelance tools developer (may accidentally sound like Alcoholics Anonymous club introduction). This article launches a sequence of materials dedicated to the development of parsers, translators, compilers, and similar instruments designed to make our lives simpler.
Indeed, why would we need one more programming language? Sure, it may be appreciated in some university research institutes, but how can this crafty highbrow stuff be applied in and help businesses? At the end of the day, what for do we need such a mind-blowing variety of languages? Let’s sort it out.
Why not use one language?
Once upon a time, there was an English mathematician, computer scientist, logician, and cryptanalyst, named Alan Turing. Among many of his inventions, people would probably instantaneously recognize the machine that bears his name. Without going into detail, let’s say, his machine can implement the same tasks that are implemented using some more complex, higher level programming tools. This means any program in any language can be rewritten with the help of this relatively simple tool. This very machine can be implemented in any language of Java or PHP type.
So, why do we need all these languages, why can’t we use just one? It occurred to me that in his science fiction novel «Babel-17» Samuel Delany described a man with one part of the brain switched off. The man is taught an artificial language instead, that is similar to mathematical expressions in its syntax. It is perfectly tuned to solve logic problems quickly, its compact, it has a high usability but its limited. For instance, such words as “me” and “you” were out, which means some logical mysteries like «The Barber’s paradox» can’t be processed by the restricted mind. They get burnt or redirected to the brain part which is switched off. In other words, the language constructions can predetermine the thinking pattern.
Let’s dwell on the language of mathematics. For example, here is the theorem-proof description by math induction method:
Now, let’s decipher it. Supposing that:
It is found that P1is true. (this statement is called induction base)
It is proved for any n, if Pn is true, Pn+1 is also true. (this statement is called the induction step)
Then, all the statements of our sequence are correct. Please, pay attention: instead of a few strings of text, we have only one string with a rigorous definition, which is clear to any mathematician.
What is DSL
Domain Specific Language is a computer language specialized to a particular application domain. Its structure or data structure reflects the specifics of the problems it solves© Wikipedia.
In other words, if a specialist knows his specific domain, he doesn’t have to learn DSL — it is enough just to look at it (see the example with math). A quality DSL does not require extensive knowledge in programming theory and practice. Many DSLs do not have cycles. Some of them do not have «if» operator. A language can often prove to be Turing incomplete, which means you can’t use it to code any program. And again, let’s take a math language or language of quantifiers as an example. It is used only for theorem description or for their automatic proof. It would be really difficult to apply it for coding web-services.
DSL use cases
DSL application fields are quite varied. Let’s consider a few of them to understand when DSL should be used.
Supposing you are a marine engineer and you want to cut a huge part for the ship hull. In the past people did it the following way: they contoured details on a tough board or plywood, cut them out, and applied them to a steel sheet. Afterward, specially trained people called marking-off professionals were crawling on this steel sheet stamping in pits on the line of the cut. Then torch operator would go cutting down the contour line. Can you imagine if the torch operator has a horrible hangover in the morning?
A robot can do it automatically, instead. A robot has no issues with precision: it reads from the design and moves on the steel shit cutting out a required part. Yes, it is possible! But the thing is that the trajectory of the movement has to be assigned. It requires the following commands:
To move from point А to point B with the cutter off (bearing in mind that a straight line is the shortest distance between two points).
To move with the cutter on along the predetermined curve (straight line is a special case). To keep things simple, we speak here about a straight line piece and an arc of the circumference with radius and center defined. As the position of the cutter is predetermined by the previous movements we need to set only the point of a full stop. The full stop point for the straight line segment is the end of the segment. The full stop point for the circular arc is rotation angle and center of the circle.
Therefore, in the simple case we need only three commands:
As you can see, the language is simple but it can be applied to cut a part of any complexity. One only needs confident PC user skills in order to code with this language. By adding variables, conditional operators, cycles and procedures, we eventually come up with a powerful tool. As a bonus, we can have code research using white box technique. For example, we can check if the cutter trajectory happens to go beyond the metal sheet edges.
Trader seldom makes a mistake twice — usually three or more times
© Sad experience of a man who sold his apartment
Everyone wants to buy cheaper and sell more expensive, everything is clear here. But how do we define the right time to close the deal if any day the price may rise or fall? The decision is made through fundamental evidence (news, analysis of economic and political trends) and technical evidence (projection of resource costs based on previous data available). Indicators that are now used to predict the price behavior are not proved theoretically and they lack accuracy. There is a certain connection to reality; however, usually the decision to open or close a deal is made judging by a few indicators. So, when all of them give a signal about a sale or a purchase, the decision can be made.
A price curve changes rapidly. The data obtained 15 min ago can be relevant only to historians. The money people work with on the stock market is enormous so it is easy to lose a few hundred million dollars in a matter of minutes. Therefore, it makes sense to minimize the human factor. But how can we do it if there is no particular price behavior theory, and a trader uses his intuition to choose a trading strategy? One of the ways to avoid mistakes is to create a special language with as little «background noise» as possible while getting rid of all the impractical options and retaining only the necessary components in the language. What do we need for trading?
Well, it doesn’t take a genius to understand that the price of snow in the Antarctic and at the Equator would be really different. So, we need to specify the stock market where we analyze prices.
We define a strategy of trading (there is a variety of them).
We need to set the parameters specific to every stock market, as well as the time slot for the work.
Strategies are launched on servers, every one of them working with a specified stock exchange. We need to set the time frame within which they work, since the access to stock markets may not be free.
Let’s take a look at this strategy when performed in Java. Supposing we want to receive signals every time currencies are bought or sold on all three servers.
We use the strategy: «Fibonacci», «sliding average», «the Hilbert transform». To keep things simple, let’s assume the time is measured in ticks, the name field of the stock market where the server operates is set as a value of a string type; we trade in and exchange a few currencies such as dollars, euro and some else.
At a first glance the code looks okay, but if you just look closer you will notice a number of blunders.
Firstly, the operation time of strategies is shorter than the operation time of a server. Secondly, we start only one server, instead of three. So, using this code means the financial loss is inevitable.
On the other hand, trading is a nonstop stress and it’s a race. It requires speedy work which has to be error free. How to achieve this level?
Let’s see how the program text in the above format might look like if it was coded in a more practical and readable language.
The program start mark is at the top, the list of servers follows. The name of a stock market is set one time for every server. The time of work for the server is also set one time. Then a strategy list follows where each strategy has its specific parameters.
The advantages of the example provided are obvious. The text has been streamlined: servers are set only one time. Strategies are in close proximity to a server where they are run. Secondly, we dispose of extra details: trader doesn’t have to know what Thread is or that the final program will be coded in Java.
Game logic development
Error: robot dies when a grenade hits (exactly when it hits, not when the grenade detonates). D — designer, P — programmer.
D: programmers have spoilt the whole thing! why?!
P: the weight of the grenade is 100kl! Why did you do it?
D: really?! The grenade has to sink in water!
P: why doesn’t it sink with a proper weight?
D: water has a high density! (note: higher than mercury)
P: what do you mean higher than water?! It’s the impossibility!
D: wooden boxes have to float!
P: they can’t float any other way, can they?!
D: their weight is 50 kl!
P: why so big?!
D: other way they wouldn’t be falling apart so beautifully!
Supposing, you are a game designer and you need to create a behavior script for a robot. First, the robot shoots, and then when it is out of ammo, it runs. Programmers will implement it easily. But in a certain moment the behavior has to be changed, so that robot runs, and only starts shooting when he is nearly caught. Robot can also hide cozily behind the hill and move his ears in a sweetest manner. The programmer will do it as well, but it’s a loss of valuable time. There will be multiple fixings again and again and the programmer will have to be disturbed again and again.
Moreover, new games are released for numerous different platforms. One that is made for Windows can be in demand for Vii, tablets, smart TV and so on. Each release leads to rewriting the code, which has been tested and is already working, although the logic of actions of the characters does not change in general (when moving from device to device.). One may use cross-platform tools, such platforms as Unity or Haxe, but the problem stems from the fact that cross platform shows equally poor performance on all devices. What I’m trying to say is that it would be great if the logic could stay unaltered while we only change specific things for a specific platform.
We can also use script languages for logic, but they are also too complex to be used without properly learning them first. They have many details important for the work of a developer, but aren’t necessary for constructions like: «If this thing happened — do that thing».
You can’t make a designer learn programming, right? These fields are so distant from one another, and in many terms they are opposite. Sure, one would like to have a designer who can change behavior of game characters without having to disturb a developer.
Let’s consider the game logic through the character’s conditions and transitions between them. For instance, a robot can have three states: «run to a player», «shoot» and «look for the ammo», when it got short of supplies. Actions happen when a condition is entered, exited, during a transition between conditions and when the condition between actions hasn’t changed. Transitions and states can be described with the help of JSON or XML; then we can use the coding pattern «state machine», as described in “the gang of four”. XML for description is presented below:
<transition name=“shoot” methods=“run”>
<condition function=“near_the_enemy && have_bullets”/>
<transition name=“run_to_bullets” methods=“hi”>
<transition name=“run_to_enemy” methods=“eat_bullets”>
Yet, XML is so inconvenient for programming. Let’s take a look how to describe it with the help of DSL-language.
As you see, the description has got more streamlined and just more readable. We can see syntax highlighting now. By the way, it also features autocomplete and error highlighting.
This way, we can distinguish between the game logic and the things that are determined by and depend on the platform: visuals, IO, and controlling. We can even distinguish it from how methods of «shoot», «run» and «shout» are implemented in practice. The latter is a specific case of declarative programming: instead of implementing a detailed algorithm, we give the final result. Instead of telling a computer how to do something, we tell what to do.
All DSL analyzed here have the following features:
They are not big and do not require massive investments. It is right to say so on the whole: domain specific language with a high barrier to entry is not a good one.
They allow operation with the terms of the subject domain, without the specifics of software implementation. It’s like saying WHAT to do instead of HOW.
They make it unnecessary for a specialist to acquire a high qualification in programming.
DSL is applied in cases when rather complex logic is to be written. A specialist in a specific domain is liberated of the necessity to study programming while a programmer is liberated of the necessity to be well-versed in a subject. And again, if to implement a task one doesn’t need a qualification beyond programming, one doesn’t need DSL.
My second article will dwell on visual languages, while in the following ones we will consider the ways of DSL actualization and their application in various, sometimes unexpected, fields.