Imperative vs. Declarative Query Languages: What's the Difference?
The history of programming languages goes back to the beginning of computing, with new languages being created for each variation and paradigm. When it comes to databases, two well-known paradigms include imperative and declarative query languages.
All too often, the latter is often broadly defined as being any database query language that is not imperative. However, to define it in such a manner is too broad.
In this blog post, we will discuss the different features of the imperative and declarative database query languages, as each has its individual strengths and weaknesses. Selecting which language to use will depend specifically upon your individual situation.
Imperative Query Languages
If the query languages were human archetypes, imperative languages would be the micromanaging boss who gives instructions down to the final detail. In the most basic sense, imperative query languages are used to describe how you want something done specifically. This is accomplished with explicit control in a detailed, step-by-step manner; the sequence and wording of each line of code plays a critical role.
Some well-known general imperative programming languages include Python, C, and Java. In the world of graph databases, there aren’t any purely imperative query languages. However, both Gremlin and the Java API (for Neo4j) include imperative features. These two options provide you with more detailed power over the execution of their task. If written correctly, there are no surprises — you will get exactly what you want done.
However, imperative database query languages can also be limiting and not very user-friendly, requiring an extensive knowledge of the language and deep technical understanding of physical implementation details prior to usage. Writing one part incorrectly creates faulty outcomes.
As a result, imperative languages are more prone to human error. Additionally, users must double-check the environment before and after the query and be prepared to deal with any potential erroneous scenarios.
To better illustrate the differences, imagine you have two children: Izzy and Duncan. Izzy represents an imperative query language and Duncan the declarative query language.
To get the two children to make their beds, you take differing approaches. For Duncan, it is easy. Simply instruct Duncan to make his bed and he will do it however he sees fit. Yet, he might make it slightly differently than you had in mind, especially if you’re a picky parent.
Izzy requires an entirely different process. You must first inform her that she needs both sheets and blankets to make her bed, and that those materials can be found on top of her bed. Then she requires step-by-step instructions, such as “spread the sheet over the mattress” and “tuck in the edges.”
The final result will be closely similar to Duncan’s (or perhaps, exactly the same). At the end of the process, both children have their beds made.
Declarative Query Languages
On the other end of the spectrum, declarative database query languages let users express what data to retrieve, letting the engine underneath take care of seamlessly retrieving it. They function in a more general manner and involve giving broad instructions about what task is to be completed, rather than the specifics on how to complete it. It deals with the results rather than the process, thus focusing less on the finer details of each task.
Some well-known general declarative programming languages include Ruby, R and Haskell. SQL (Structured Query Language) is a declarative query language and is the industry standard for relational databases. In the graph database ecosystem, several query languages are considered declarative: Cypher, SPARQL, and Gremlin (which also includes some imperative features).
Using a declarative database query language may also result in better code than what can be created manually, and it is usually easier to understand the purpose of the code written in a declarative language. Declarative query languages are also easier to use as they simply focus on what must be retrieved and do so quickly.
However, declarative languages have their own tradeoffs. Users have little to no control over how inputs are dealt with; if there is a bug in the language, the user will have to rely on the providers of the language to fix the problem. Likewise, if the user wants to use a function that the query language doesn’t support, they are often at a loss.
In the previous example of the children, Duncan was able to complete his task in a method faster and easier for his parent than Izzy. However, imagine now that you want to them to wash the dishes.
It is the same process for Izzy: You’d need to walk through each step with her so she can learn how the process works. For Duncan, however, we have hit a snag. Duncan has never learned how to wash the dishes. You will stay in that impasse with Duncan unless his programming engineers decide to teach him how to wash the dishes. (Duncan isn’t like most children.)
Conclusion
This post is not meant to pit the two types of database query languages against each other; it is meant to highlight the basic pros and cons to consider before deciding which language to use for your project.
You should select the best query language paradigm for your specific use case. Neither paradigm is better than the other; they each have different strengths for software development.
If your project requires finer accuracy and control, imperative query languages do the job well. If the speed and productivity of the process matter more, declarative languages offer the flexibility of getting results without as much effort. Ultimately, the choice depends upon your individual use case.