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!
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] <-- [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.
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!