Question Details

No question body available.

Tags

data-structures architectural-patterns separation-of-concerns

Answers (1)

February 4, 2026 Score: 0 Rep: 139,922 Quality: Medium Completeness: 30%

Dependencies

[...] to ensure that there are no circular dependencies [...]

When it comes to handling dependencies, don't reinvent the wheel (unless you actually enjoy doing it or see it as an opportunity to learn). Most popular programming languages should already have third-party libraries to handle a dependency graph. You feed it with elements and the dependency relations between them, and it handles all the difficult stuff for you. Including the circular dependencies or the actual storage of the directed acyclic graph in memory.

Caching

It is expected that SolveMethod will set the Value, which is then cached, and subsequent Value requests will use cached value [...]

Here too, leverage what you already have. As you're talking about an API, I suppose there is some standard that is being used, such as HTTP. You can therefore rely on HTTP caching to do the complex stuff for you, leaving you the task of setting properly the cache HTTP headers. Either the next call to a given API endpoint has different arguments, in which case a new response will be generated. Or the arguments are exactly the same, and then you'll get the cached response immediately.

Immutability

[...] makes the evaluation data mutable and difficult to protect [...]

Once you get the response from an API, it's up to you to freeze it if you want to. At what level would you freeze it is up to you. As you explained, one API call may be mapped to multiple properties:

For example, the API of the CAD application returns length and width of the waterline in a single API call, so they can and should be stored in respective properties.

With HTTP caching I mentioned above, this becomes less of a problem. If your dependency graph shows that you need to get the length of the waterline, and at some later point, you also need to get the width of the waterline, that's fine. You keep your two properties separate, given that each of those two properties will perform an HTTP GET your-api/waterline-metrics. The first call will be cached; the second one won't cost you time or bandwidth. The only issue is that you'll get a large JSON containing more than each property needs. But wait until it starts to be an actual problem (such as the actual cache starting to be too big) before thinking about the ways to solve it.

Layers

I think this is a terrible implementation [...] It smells of bad code [...]

In my opinion, your approach is pretty good and well thought. Great work! The only thing that's missing is a clear separation between what you need—that is, a given property, and how you get it.

Take the length of the waterline as a property. You may need to do an HTTP call. Or multiple calls to different APIs. Or maybe you need to send a message to a message bus and wait for a result to be generated. Or use map-reduce. or spin up a few GPUs to do heavy computations for you. Or read a local file from disk. The implementation of the retrieval of the information should be a distinct topic from how you handle/organize the properties, how you define the relations between them.

If you consider them as distinct layers, you can easily see that caching, for instance, belongs to the layer that deals with the actual retrieval of the information (the way you do HTTP caching is quite different from the way you'll cache responses from a message bus, and maybe you don't even need caching if the data comes from a local file). On the other hand, the dependency graph belongs to the layer that deals with the actual properties.