What is Declarative Programming??

Declarative Programming encompasses a wide range of essential programming paradigms including Functional Programming, Logic Programming, and Data-Flow Programming. It reduces side affects, and allows you to write code without needing to specify how it’s done. This way, the computer can optimize how to fetch it based on your criteria. This also reduces the chances of bugs because you do not have to write the imperative instructions to execute the operation.

Here are some declarative programming languages:

  • Haskel, Lisp, Lambda, F#, Scala (Functional)
  • SQL, LINQ, jQuery (Declarative)
  • QML, XAML, HTML
  • Reactive Programming (style)

It differs from more popular Imperative Programming paradigms that encompasses Procedural Programming and Object-Oriented Programming. Imperative languages include JavaScript, Perl, C, C#, Java, Python, and the like. If this is the only paradigm you are familiar with, tune in because this article is meant for you!

So why is Declarative Programming important? Declarative Programming paradigms have solved a lot of the problems we take for granted today. It is a different way of identifying and solving your problems, and when used correctly, it will lead to cleaner, more organized, more reusable, more testable, and less error-prone code.

I know what you may be thinking. What about Object-Oriented Programming? Doesn’t it do all this stuff?? Actually, OOP is very good at abstraction (and analogies), and organizing code at the larger scale, but for specific problems, it actually has no specific guidelines to help you! As a matter of fact, you may end up misusing OOP if it is the only paradigm you know. The endless trails of abstraction can be a nightmare to comprehend.

Not to worry. This article is meant to introduce you to some of the common problems and how declarative programming can help you tackle them.

Take for instance bank transactions that need to be done in a specific order and need to be reversible. You would not want your money to be miscalculated, and if it was, you would like to be able see why and to reverse it. This might seem like a simple task, but when scaled to high volumes and handling requests in parallel, it is much more difficult than it appears. SQL databases that are ACID compliant guarantee this.

The application of this concept is utilized in memory transactions and seen in RxJS, Reactive Programming, Redux, Reflux, Games, and much more. You will also see this manifest in Java (streams), C# (LINQ), ReactJS, Angular, and more. There is much more to be said about this topic, so if you’re interested read up on Functional Programming and atomic transactions.

This sort of problem may appear in your application. It is very natural to use Functional Programming to solve this sorts of problems.

This is probably the most adopted feature to modern Imperative Programming languages. Function pointers, delegates, lambda expressions, event handlers, do these terms ring a bell? They should. Higher Order Functions is the ability to pass functions as a parameter inside another function. This ability allows the invoker to define a function that can be called at a later time. This terms out to be useful for multiple applications.

  • It allows your function to be customized by the people using your function.
  • It allows people who use your function to create as many procedures as they want and allows you to invoke them at a later time!
  • It allows for asynchronous/concurrent requests to be handled.

This prominent feature was introduced into languages like Java, C#, JavaScript, and C++.

As we mentioned earlier, the declarative style of programming allows us to simply specify a criteria and get a list back based on the criteria. Let’s dig deeper into why this is important.

  • It reduces bugs and saves time. Because there is already a language (SQL) or an API (LINQ, Streams, jQuery) dedicated to guaranteeing that your list will be returned based on your criteria, you wont have to write additional code. Needless to say, because you don’t have to write additional code, you wont need to worry about the additional bugs in your implementation and you will save precious time.
  • It optimizes execution. One of the advantages of abstracting away the implementation is that the owner of the language or API can tailor the execution for your computer to utilize all your processors. There may be multiple implementations of how to execute a query and it will pick the one to get the most of your machine.
  • It’s an actual language, a different way of thinking so you can actually get really good at solving this types of problems. As you detect more of these patterns, you will even be able to reuse the patterns.
  • Declarative programming is also a style. You can use the features of Object-Oriented Programming or the programming language to write your libraries and produce this declarative style. You see this in many modern JavaScript libraries like jQuery and method chaining.
  • Since we are not forced to write the details of the algorithm, it frees us to be more creative when writing this type of code. Yet, it also allows us to be very deliberate and concrete with our intention. This allows our code to be easy to design, easy to read for others, and clean.
  • Re-usability. This was taunted as being the whole point of Object-Oriented Programming, but in reality, you run into into issues relating to objects that depend on each other. Side affect is a huge problem in imperative programming. With Functional Programming, you are identifying the problem, breaking it down into it’s parts and solving them. In this way we are truly tackling the problem at it’s core (without abstracting it) and this form of re-usability is a lot more effective because functional-based and doesn’t mess object relationships. So how exactly is it re-useable? Just like it’s name suggests, functionally, the same way mathematical functions and formulas are! You find patterns and you find solutions to these patterns. For instance, your solution may be composed of a series of functional operations that are strung together to solve your problem.