A case study of creating configurable values

Glossary DAO - Data access object Case study Once upon a time, there was a process within a monolithic enterprise system. Its purpose was to receive product codes from external API, query the database, and send product data to another external API. PlantUML Text @startuml Example Process skinparam componentStyle rectangle database "Product Table" rectangle "Process" { [Admin UI] [Service] [DAO] } [Admin UI] --> Service: clicks to run [API 1] -> [Service] : product\ncodes [Service] -> [API 2] : products [Service] -> [DAO] : product\ncodes [Service] [Product Table] : database query @enduml The new requirement We want to divide the product codes into batches, so that the database query wouldn't be too big. The proposed solutions Obviously, there would be a value "number of products per batch". 1. The configurable solution There is a school of thought - "Data should be separated from logic". Following this thought, the value should be configurable from Admin UI, and subsequently passed down to DAO. PlantUML Text @startuml Example Process skinparam componentStyle rectangle skinparam defaultTextAlignment center [Admin UI] as "Admin UI\n(with **value**)" [Service] [DAO] [Admin UI] --> Service: value [Service] --> [DAO] : value @enduml In this scenario, a few things could happen: A system user accidentally updates the value to a non-sensible value, breaking the system. Another requirement comes in to ensure that only developers can configure the value from the UI. With hundreds of configurations, the system user would have a hard time finding the configuration that they can really update. On the flip side, this approach does have an advantage: We don't need to deploy code changes to adjust the value. This approach is suitable for an environment where deployment is infrequent. 2. The environment variable solution Given it's not an user-facing configuration, another approach would be to store the value in environment variable. The DAO will directly obtain the value from environment variable and use it. PlantUML Text @startuml Example Process skinparam componentStyle rectangle skinparam defaultTextAlignment center [Admin UI] [Service] [DAO] [Environment Variable] [Admin UI] -.> Service [Service] -.> [DAO] [Environment Variable] -> DAO : value @enduml It's a better approach because Service and Cron Job don't need to know anything about "Number of products per batch", which is purely a concept in application logic (as opposed to business logic). In this approach, a few things could happen: The code passes QA environment easily because the value is lower. The code fails in Prod environment because the value is higher. A lot of work is required to ensure environment consistency because some environment variables do vary between environments, such as API URLs. 3. The hard-coding solution The value is only used by DAO. The value should not change across environment. Therefore, the best place for it is within the DAO itself. It is version-controlled. If someone changes it and breaks the system, we will know. Conclusion Configurable values mean maintenance and potential inconsistency. Create configurable values only when there is a real need. Thank you for reading. Feel free to share your thoughts in the comments!

Jan 17, 2025 - 13:20
A case study of creating configurable values

Glossary

  • DAO - Data access object

Case study

Once upon a time, there was a process within a monolithic enterprise system.

Its purpose was to receive product codes from external API, query the database, and send product data to another external API.

System diagram

PlantUML Text

@startuml Example Process
skinparam componentStyle rectangle

database "Product Table"

rectangle "Process" {
  [Admin UI]
  [Service]
  [DAO]
}

[Admin UI] --> Service: clicks to run
[API 1] -> [Service] : product\ncodes
[Service] -> [API 2] : products
[Service] -> [DAO] : product\ncodes
[Service] <-- [DAO] : products

[DAO] --> [Product Table] : database query
@enduml

The new requirement

We want to divide the product codes into batches, so that the database query wouldn't be too big.

The proposed solutions

Obviously, there would be a value "number of products per batch".

1. The configurable solution

There is a school of thought - "Data should be separated from logic".

Following this thought, the value should be configurable from Admin UI, and subsequently passed down to DAO.

System diagram

PlantUML Text

@startuml Example Process
skinparam componentStyle rectangle
skinparam defaultTextAlignment center

[Admin UI] as "Admin UI\n(with **value**)"
[Service]
[DAO]

[Admin UI] --> Service: value
[Service] --> [DAO] : value

@enduml

In this scenario, a few things could happen:

  1. A system user accidentally updates the value to a non-sensible value, breaking the system.
  2. Another requirement comes in to ensure that only developers can configure the value from the UI.
  3. With hundreds of configurations, the system user would have a hard time finding the configuration that they can really update.

On the flip side, this approach does have an advantage:

  • We don't need to deploy code changes to adjust the value.

This approach is suitable for an environment where deployment is infrequent.

2. The environment variable solution

Given it's not an user-facing configuration, another approach would be to store the value in environment variable.

The DAO will directly obtain the value from environment variable and use it.

System diagram

PlantUML Text

@startuml Example Process
skinparam componentStyle rectangle
skinparam defaultTextAlignment center

[Admin UI]
[Service]
[DAO]
[Environment Variable]

[Admin UI] -.> Service
[Service] -.> [DAO]
[Environment Variable] -> DAO : value

@enduml

It's a better approach because Service and Cron Job don't need to know anything about "Number of products per batch", which is purely a concept in application logic (as opposed to business logic).

In this approach, a few things could happen:

  1. The code passes QA environment easily because the value is lower.
  2. The code fails in Prod environment because the value is higher.
  3. A lot of work is required to ensure environment consistency because some environment variables do vary between environments, such as API URLs.

3. The hard-coding solution

The value is only used by DAO.
The value should not change across environment.
Therefore, the best place for it is within the DAO itself.

It is version-controlled.
If someone changes it and breaks the system, we will know.

Conclusion

Configurable values mean maintenance and potential inconsistency.

Create configurable values only when there is a real need.

Thank you for reading.
Feel free to share your thoughts in the comments!