Introduction to Data Driven Programming

A lot of code is still written as a sequence of if-then-else statements, which is perfectly fine, however in some cases a data driven programming approach can prove to be more flexible and reduce the amount of code that needs to be written and maintained.

It is important to note I am not arguing the merits of one method over the others, instead I would like to introduce you to the concept and show you how it can be helpful. We will discuss some pros and cons towards the end of this post.

Traditional (non-data driven) Solution

The following code snippet shows a typical coding solution of sending a set of emails to a user who just happen to sign up on our website.

from User import User
from EmailService import EmailService
#
# main function
#
def main():
#
# Fetch the current user
#
new_user = User()
new_user.load_from_session()
#
# Welcome email
#
if new_user.country == "fr":
subject = "Bonjour et bienvenue sur notre site"
content = "Bonjour et Bienvenue sur notre tout nouveau site. Contactez l'équipe de support si vous avez des..."
EmailService.send(new_user.email, subject, content)
elif new_user.country == "us" or new_user.country == "ca":
subject = "Welcome to our site"
content = "Hello and Welcome to our brand new site. Contact support team if you have any questions."
EmailService.send(new_user.email, subject, content)
#
# Age check reminder
#
if new_user.age < 18:
subject = "Important reminder"
content = "Important: Please note that user under the age of 18 must provide a signed waiver from a parent ..."
EmailService.send(new_user.email, subject, content)
#
# Payment verification reminder
#
if new_user.payment_status == "Unverified":
subject = "Reminder about your payment status"
content = "Please don't forget to update your payment information on our site"
EmailService.send(new_user.email, subject, content)
#
# run main
#
if __name__ == "__main__":
main()
view raw Sequential.py hosted with ❤ by GitHub

In this implementation, as new rules and scenarios need to be added, we will continue to make code changes to meet the requirements. Overtime this will become more and more complicated to read and maintain, specially when there is a large number of scenarios to cover.

Data Driven Solution

A data driven programming approach simplifies this solution by separating the logic and data as you can see in the following code.

from User import User
from EmailService import EmailService
#
# rules data
#
rule_set = [
{
"country": ["fr"],
"subject": "Bonjour et bienvenue sur notre site",
"content": "Bonjour et Bienvenue sur notre tout nouveau site. Contactez l'équipe de support si vous avez des..."
},
{
"country": ["us", "ca"],
"subject": "Welcome to our site",
"content": "Hello and Welcome to our brand new site. Contact support team if you have any questions."
},
{
"min_age": 18,
"subject": "Important reminder",
"content": "Important: Please note that user under the age of 18 must provide a signed waiver from a parent ..."
},
{
"payment_status": "Unverified",
"subject": "Reminder about your payment status",
"content": "Please don't forget to update your payment information on our site"
}
]
#
# main function
#
def main():
#
# Fetch the current user
#
user = User()
user.load_from_session()
#
# Process the config data and fire actions
#
for rule in rule_set:
# Process country rule
if "country" in rule and user.country in rule["country"]:
EmailService.send(user.email, rule["subject"], rule["content"])
# Process minimum age rule
if "min_age" in rule and user.age < rule["min_age"]:
EmailService.send(user.email, rule["subject"], rule["content"])
# Process payment status rule
if "payment_status" in rule and user.payment_status == rule["payment_status"]:
EmailService.send(user.email, rule["subject"], rule["content"])
#
# run main
#
if __name__ == "__main__":
main()
view raw DataDriven.py hosted with ❤ by GitHub

Pros and Cons

The biggest benefit of separating the data and the code is that the data can now be moved completely out of code. In the example above I used a local rule_set structure, but I might very well read it through a file or database or download it over the network. Even non-programmers can maintain and control the rule set without writing any code.

For example adding a different welcome message for a new supported country, for example Mexico in Spanish, would require minimum code changes. However if a new type of rule needs to be added then yes we will need to write code to support that.

On the down side, for some of the complex data driven applications you will find that debugging may not be straight forward because a bug may just depend on the data and state of the program, this is specially true when we have a large set of rules to process. I recommend spend extra time in designing data driven applications, read Coding By Thinking post for some advice on how to do that.

In addition the implementation could get tricky when rules have inter-dependencies or when the order of processing matters.

Cover Photo by Lorenzo from Pexels

%d bloggers like this: