I have recently looked at some Web APIs provided by well known companies' e.g. this one by HSBC: https://developer.hsbc.com/swagger-index.html#!/Products_Commercial_Credit_Cards/get_open_banking_v2_1_commercial_credit_cards/v2.1

I notice there is domain logic contained in the JSON returned by the web api. For example; maximum credit limit; minimum age etc. I work in a policing domain and the seriousness of a crime can change like this in an extract from the home office.

How do you deal like this? Do you put the domain logic in a class and then change the class when the business logic changes. For example, if the minimum age changed from 18 to 21 then change this:

if (age > 18)
  /do something

to this:

if (age > 21)
  /do something

or do you simply put the business rules in the database like this:

UPDATE HSBCLoan SET MinimumAge=21;

I believe the classes should change as domain logic should be contained in the domain layer, however this is more challenging because it is necessary to recompile and deploy. Therefore I am wandering if the business logic should be contained in the database or if there is a simpler approach or compromise that I have not considered. How would you deal with HSBC changing the age from 18 to 21?

  • The business rule is not "must be 18", rather "must be older than a certain age". This rule should be codified. What that min is, should go in the DB.
    – Brad Irby
    Dec 13, 2018 at 11:07

3 Answers 3


Fundamentally a policy like that is just data. The business logic of an application like HSBC's is more concerned with carrying out the rules encoded by the policy like validating constraints, carrying out scheduled tasks, etc. than it is with the details of any particular policy.

When the policy set changes very rarely, it makes sense to write them down in the code, which can be executed efficiently with regular tools. However, if policies need to be added or overridden, changed weekly, or are otherwise highly mutable, then encoding the policy in a non-code format adds the necessary flexibility by not triggering a rebuild on every policy change. It then becomes best practice to move the policy information into a single source wholesale. Even if a data field in a policy is unlikely to change, it would take a very compelling reason to separate it.

In addition, when a policy is represented as data, it can be shared with compatible systems as is the case here with HSBC's credit card API. The documentation you posted states (emphasis mine):

This API will return data about all commercial credit cards products and is prepared to the Open Banking standards as defined by the Open Banking Implementation Entity (OBIE) in data dictionary version 2.1. It is regulated by the UK Competition and Markets Authority (CMA). Data is only available for the United Kingdom.

So not only does it make sense to supply the "business logic" (ie. policy information) in the results of this API from a technical perspective, it might well be legally required as well.

Given this background, what it means for your application is that it needs to be robust to changes in the policies reported by HSBC. What this actually entails I suspect is encoded by the OBIE, as indicated in the documentation. But no matter what you actually do, the fact that HSBC has to encode their policies as data means you do too, since they could change at any time. It would be very brittle to personally update a class in response to external changes as you notice them.

  • What would you use as the "single source wbolesale"? Thanks.
    – w0051977
    Dec 10, 2018 at 22:32
  • Whatever bloats your application the least. Good options include RDBMS (like Postgres, MSSQL, etc.), JSON or XML configuration files, custom serialized formats if the data structures are exotic, etc. What matters is that the definition of a particular policy exists in one place and isn't chopped up and spread about the system. Dec 10, 2018 at 22:43
  • Thanks. I realise what the options are. I am trying to follow the principle of least astonishment.
    – w0051977
    Dec 10, 2018 at 22:45

Data is Code

So when HSBC distributes that product information via JSON, they are essentially passing you code. To use that in your application requires you to implement an engine that interprets that code, and applies the effects. This can be done in a number of ways.

You have already highlighted Compiling this code by writing it manually into your classes. In this sense you, the developer, are the interpreter. As a human is in the loop its naturally slower to update, and being pre-compiled it is faster to execute.

The other way to do this is to write an interpreter. In this case your application will interpret the received code directly. It will run a little slower as extra checks must be run first to ensure the received code is valid, but it is much more flexible allowing new versions of that code to be deployed to your platform without having to redeploy the platform itself.

There is a cost/benefit trade-off here and neither way is best. It does depend on the rate of change expected. I usually apply the principle of shear force to this sort of problem.

Shear Force

Code that changes often should be separated from code that changes infrequently.

The fact that the application will have an age check is not likely to change, what the minimum age to check for is likely to change simply by being in a different country.

Now factor your code to isolate the faster changing code, from the slower changing code. Push the faster changing code up into function arguments, or constructor arguments (for objects). Keep pushing until the faster changing code finds other code that changes at the same pace.

It is perfectly legitimate to push this code out into a configuration file, a database, or even a remote networked service. Just don't forget to implement good security. Allowing code to execute from an untrusted source is a recipe for disaster.


... however this is more challenging because it is necessary to recompile and deploy. Therefore I am wandering if the business logic should be contained in the database ...

You've got a point, but it only covers part of the logic.

Yes, age is just a number, and thus data. If the age changes from 18 to 21, that can be handled with a simple config change. But how sure are you that age is just a single number?
For example, if the minimum age changes for some of the users (e.g. based on their nationality or gender), that's not as easy anymore. You'd then need to have config settings for every combination of nationality/gender, which can lead to a whole lot of bloating in your config files. Whenever a nationality gets added (which would likely happen at runtime without needing a redeploy), you'd need to add the new nationality's config settings as well.

The thing is that changes to validation rules are not always as simple as changing a value. When some of the behavior changes, you're always going to be stuck having to redeploy your application. Even if you ensure all values are easily configurable, that only covers a subset of possible changes that can be made to the business logic.
The question then becomes whether the benefit of being able to swap the values (but not the logic) meaningfully contributes to the application. If any change to the validation rules should be treated as a change with major impact, there's little reason to ensure values changes are notably easier than logic changes.

Secondly, having the settings in the compilation means that you have some form of consistency guarantee. If you compile the minimum age into the DLL, then you know that the same version of the application will never alter its behavior. Especially for high importance systems like banking, that added layer of behavioral immutability can be desirable.

Regardless of business validations, you will always have a secure production environment because you want to prevent people from wantonly swapping the DLLs (whether it's malicious intent or reckless maintenance). If you have that security in place anyway, having the validation rules compiled into your DLL inherently means you have the same secure environment to guarantee that no one changes the validation rules (whether it's malicious intent or human error).

In the end, whether you put your validation rules in the database, config file, or assembly hinges on one question: Do you want to be able to change validation rules without redeploying the application?

There is no objectively superior answer to that question. Different companies have different priorities, and different types of validation can have different impacts on the business when something goes wrong.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.