andrewlock / StronglyTypedId

A Rosyln-powered generator for strongly-typed IDs
MIT License
1.5k stars 78 forks source link

[Question] How to prevent domain layer from direct reference to the infrastructure? #61

Open devbased opened 2 years ago

devbased commented 2 years ago

By specifying converters in attribute we automatically tie domain layer with infrastructure.

SteveDunn commented 2 years ago

Is that necessarily a problem with generated code? Does it reference your Infrastructure layer or merely references dapper/ef assemblies? I can understand the problem if it was hand-crafted code, as it'd break the inward-dependency rule.

prlcutting commented 2 years ago

Hi @SteveDunn - I'm not sure I follow your rationale here. Isn't the fact that a domain object has a direct dependency on some "infrastructure", e.g. EF Core, the very essence of "breaking the inward-dependency rule"? I don't understand how it matters if it's mine or somebody else's code that I depend, or if it's auto-generated. Can you elaborate on your thinking please?

SteveDunn commented 2 years ago

Hi @prlcutting - the way I see it is, the attribute acts as an abstraction over infrastructure concerns. Your domain ideas (types) are still domain specific, and have no intimate knowledge of infrastructure, but rather, just general knowledge of various persistence mechanisms.

Personally though, I tend to only use primitives in the DTOS that are [de]serialized outside of my application boundary.

mikechristiansenvae commented 1 year ago

I see the logic in @devbased 's request.

Suppose I have the following project structure

And I have an ID, FooId in MyApp.Core. Each of the consuming apps (MyApp.Web and MyApp.Standalone both have their own way of doing things. The web app pulls its data from a database. The standalone app pulls its data from JSON files.

With the current design, I have two options:

  1. MyApp.Core has to reference both my database library (EF/Dapper/etc.) and System.Text.Json.
    • The binaries for both of those libraries will be included in both of the consuming apps.
    • Even though MyApp.Standalone is not using any database stuff, it has to include those binaries.
  2. Don't have the StronglyTypedId library generate the serialization converters.
    • Now I have to write this myself, which goes against the whole point of this library.

I think there would be value in a [StronglyTypedIdSerializer] attribute. When applied to a partial class, it looks at the base type of the converter, determines what kind of serializer to generate, and generates the appropriate one. This type need not be in the same assembly as the ID we're generating a type for (but obviously, that assembly must be referenced)

[StronglyTypedIdSerializer]
public partial class FooIdConverter : System.Text.Json.Serialization.JsonConverter<FooId>
{
}
alphaleonis commented 6 days ago

Considering we have the ability to completely customize templates, if I could only add [StronglyTypedId] to a class, I could create templates for my converters manually and this would work as is. Unfortunately it can only be placed on structs, which makes sense for what it was intended for.

SteveDunn commented 5 days ago

I'm not trying to poach users from this great tool, but Vogen now generates ERCore converters in a separate assembly. Vogen is aimed more at value objects than IDs, but it can represent IDs just fine.

https://github.com/SteveDunn/Vogen

SteveDunn commented 5 days ago

https://stevedunn.github.io/Vogen/efcoreintegrationhowto.html

alphaleonis commented 5 days ago

I'm not trying to poach users from this great tool, but Vogen now generates ERCore converters in a separate assembly. Vogen is aimed more at value objects than IDs, but it can represent IDs just fine.

Thanks for the tip @SteveDunn, I was not aware of this library. Unfortunately in my case I want my JsonConverters in a separate assembly, which I can't seem to find a way to to with Vogen currently. (The reason is I have a library that needs to support json converters for both Newtonsoft and STJ in separate assemblies).

SteveDunn commented 5 days ago

Ah, I see. Vogen can generate system.text.json converters and factories in a separate assembly, but it doesn't do newtonsoft.json