I have C# code that makes some calculations for physical models. I have this project class:
public class Project
{
public IEnumerable<GenericComponent> components;
private ValueService valueService = new ValueService(Guid.NewGuid().ToString());
public Project(string norm)
{
components = FactoryGenerator.GetFactory(norm).GetComponents();
}
public void SetValues(IEnumerable<ValueViewModel> values)
{
values.ToList().ForEach(t => valueService.SetValue(t.Key, t.Value));
}
public bool Valid(string componentName)
{
return components.Where(s => s.Title == componentName).Single().Valid();
}
}
That creates smaller components that do some calculations. E.g.
public class CrossSectionComponent: GenericComponent
{
public CrossSectionComponent(ValueService valueService): base(valueService)
{
}
ICrossSectionViewModel crossSection;
double valuex;
override
public bool Valid()
{
return valuex > valueService.GetValue<double>("valuey") ? true : false;
}
}
Each component has a list of values with keys that are unique over the entire model. At the moment I use a ValueService
, where each component registers its values with the respective keys. The ValueService
can be used to get values from other components in order to do validation calculations.
private string projectUUID;
private List<ValueViewModel> values = new List<ValueViewModel>();
public ValueService(string projectUUID)
{
this.projectUUID = projectUUID;
}
public void RegisterValue(string key)
{
if (!this.hasKey(key))
{
values.Add(new ValueViewModel()
{
Key = key,
});
}
}
public void SetValue(string key, object value)
{
if (this.hasKey(key))
this.values.Find(t => t.Key == key).Value = value;
}
public T GetValue<T>(string key)
{
return (T)values.Find(t => t.Key == key)?.Value;
}
private bool hasKey(string key)
{
return values.Any(t => t.Key == key);
}
}
This is part of a stateless API, i.e. for each HTTP request (at the moment) a new Project
object is generated and used to make validations.
My API controller looks like this:
public IActionResult postData([FromRoute] string norm, [FromRoute] string component, [FromBody] ValueViewModel[] data)
{
Project project = new Project(norm);
project.SetValues(data);
return Ok(project.Valid(component));
}
The validity of one component does depend in most cases on values of other components. If one wants to check the validity of a components, the use sends a list of values (ValueViewModel[] data
), the server creates the project where all available values are stored. Then IF AND ONLY IF all required values are set, the validity can actually be calculated. If not all values are provided inside the "data list", then the validity of said component is false. So there are two cases where component.Valid() => false
- The calculations yield false
- Not all values have been submitted
My concerns are
- When the project continues, the number of components will get quite large, I fear there will be a performance issue if for each request the whole set of components needs to be generated --> should I use LazyLoading?
- Is the
ValueService
approach good to share data between the components? Is there a better solution?
1 Answer 1
You have built a system of components and shared objects, but don't use its potential. In fact, for your use case the complete setup is an overkill.
- There is no component hierarchy
- There are no component-sensitive or -specific values
- You only need a single component to verify any incoming request
public IActionResult postData( [FromRoute] string norm, [FromRoute] string component, [FromBody] ValueViewModel[] data) { Project project = new Project(norm); project.SetValues(data); return Ok(project.Valid(component)); }
For the aforementioned reasons, I don't see a need for having a list of components and values. I would rewrite the API to be as simple as possible:
- Let the factory retrieved by
FactoryGenerator
get the requested component - Let that component validate the input values
code:
public IActionResult postData(
[FromRoute] string norm,
[FromRoute] string component,
[FromBody] ValueViewModel[] data)
{
var component = FactoryGenerator.GetFactory(norm).GetComponent(component);
return Ok(component.Valid(data));
}
-
1\$\begingroup\$ I have omitted a part of the code which I thought is not essential for the "problem" I wanted to address. However, I believe now it indeed is essential. I would like to rethink on how to properly ask the question and would simply accept your answer for the sake of reputation. \$\endgroup\$rst– rst2019年06月07日 11:41:46 +00:00Commented Jun 7, 2019 at 11:41
-
\$\begingroup\$ @rst Good call. I am happy to review an updated question that shows the potential of your API. \$\endgroup\$dfhwze– dfhwze2019年06月07日 11:42:54 +00:00Commented Jun 7, 2019 at 11:42
IDictionary<string, ValueViewModel>
for instance. \$\endgroup\$