Closed AthenaAzuraeaX closed 1 month ago
Hi, thanks for the feedback and suggestion, much appreciated!
First impressions look like it'd be quite a major change, but I can see how such a feature would be useful thanks to your example.
I don't know what's up with Github not formatting code correctly. Not sure how to do it, but great that you could still understand my example!
If you're up for maintaining this feature going forward, then I figure I might try to contribute a little. But Vogen is a big project. I don't know where I would start, honestly. But having this feature would be a boon for me, and really add a lot of flexibility to value objects, I think.
This would be quite a big feature to implement. I think maybe the first step would be to consider adding just the TryFrom
method.
Then, maybe in the future, a feature closer to what you describe could be implemented outside of Vogen by using static abstract interfaces.
A TryFrom method would absolutely be a boon. But I also think that a bigger boon would be the ability to remove static methods like From and TryFrom and either generate a factory type for constructing the type or use normal constructors. The problem with static methods is that they can't be mocked and are therefore difficult to test.
Hi @AthenaAzuraeaX - it is now possible to create factories. The documentation describes how to use it for sequential GUIDs, but the concept is the same for your case.
Was what was added only the interface so we could do a .From on a type parameter, as in the example in the documentation? My idea was more to eliminate the static From and TryFrom methods and instead use a (non-static) Factory to create instances of the value object. This allows for much more flexibility, such as passing down Factories using interfaces and injecting state into the factories. Not to mention, much more testable since static methods aren't mockable.
@AthenaAzuraeaX - From
is still present in the value objects. The factory, although static in the example, can be constructed any way you like and injected with interfaces of other types.
more testable since static methods aren't mockable.
For typical value objects, I've never needed to mock them. Could you describe a scenario where mocking would have been useful?
Well, one situation where one might want to mock value objects is when one specifically want to be able to create invalid units for something like testing how a system might recover from invalid inputs. But I don't think the question is about why - but rather about what advantages using non-static methods give.
Describe the feature
Hi,
Let me just first complement you on a nice library for value objects.
Now, I would like to suggest the possibility to support Factories to construct the value objects instead of the static From method.
Consider this code:
Here we can manually specify a narrower allowed Range for Port depending on our domain rules, by always ensuring the Port is within acceptable good practices. But the From method makes this custom range difficult to use. Due to its static nature, it would need the custom range to be static or somehow dependency injected via some framework.
That is why I would like to propose the Factory pattern, where we can instantiate a Factory, whose Create or Build method can create an instance of the Value object. Since the Factory is an instance, we can inject variables into it necessary for the constructing the value object. For example:
And now we can create it using:
var Port = new Port.Factory(new(2000, 2100)).TryFrom(1200);
Ensuring consistency between the TryFrom (would love to see a TryFrom method, btw) and From.
This could perhaps be optionally opted-into using an attribute. Ideally, I'd love to see similar approaches for serialization too, to keep things consistent.