Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code Rules. Guidance and enforcement #10

Closed
jezzsantos opened this issue Oct 2, 2023 · 5 comments
Closed

Code Rules. Guidance and enforcement #10

jezzsantos opened this issue Oct 2, 2023 · 5 comments
Labels
enhancement New feature or request

Comments

@jezzsantos
Copy link
Owner

jezzsantos commented Oct 2, 2023

These coding rules should be backed by Rosyln Analyzers and Code Fixes.

API Class

Location: any project with variable: <HasApi>true</HasApi>
Definition: Any instance method of an API class (instance class derived from IWebApiService)

Rules:

  1. Warning: Should return a Task<T> or T, where T is either ApiEmptyResult or ApiResult<TResource, TResponse> or ApiPostResult<TResource, TResponse>.
  2. Warning: must have at least one parameter, and first parameter must be IWebRequest<TResponse>, where TResponse is same type as in the return value. Second parameter can only be a CancellationToken
  3. Warning: method must be decorated with a WebApiRouteAttribute
  4. Warning: the route of all methods in this class should start with the same path
  5. Warning: should not have more than one method (in the same class) with the same TRequest

API project file (csproj)

Location: any project with variable: <HasApi>true</HasApi>
Definition: N/A

Rules:

  1. Error: Should either have a package reference to SaaStack.Tools.Generators.WebApi or a project reference to Tools.Generators.WebApi.csproj
@jezzsantos jezzsantos added the enhancement New feature or request label Oct 2, 2023
@jezzsantos jezzsantos changed the title Code Rules Code Rules. Guidance and enforcement Oct 2, 2023
@jezzsantos
Copy link
Owner Author

jezzsantos commented Oct 6, 2023

commit 6c6fcd4 implemented the first few diagnostics

commit 04eb2d5 added project templates, which enforce the project references for the second part.

Not sure its worth implementing a Roslyn analyzer for a *.csproj file, since most developers don't spend much time inside them and may never see the diagnostics. However, the build warnings may direct them there. Can investigate

@jezzsantos
Copy link
Owner Author

jezzsantos commented Nov 1, 2023

Roslyn rules for Aggregates and value objects:

Root Aggregates

  1. classes that are derived from AggregateRootBase
  2. Must have at least one Create() factory method
  3. Must raise a create event in the Create method
  4. ctors must all be private
  5. Must have a public static AggregateRootFactory<TAggregateRoot> Rehydrate() method
  6. Is dehydratable if has a public Dehydrate() method
  7. If dehydratable, then must have a public override Dictionary<string, object?> Dehydrate method
  8. If dehydratable, then must have a [EntityName("AName")] attribute on the class

Entities

  1. classes that are derived from EntityBase
  2. Must have at least one Create() factory method
  3. ctors must all be private
  4. Is dehydratable if has a public Dehydrate() method
  5. If dehydratable, then must have a public override Dictionary<string, object?> Dehydrate method
  6. If dehydratable, then must have a public static EntityFactory<TEntity> Rehydrate() method
  7. If dehydratable, then must have a [EntityName("AName")] attribute on the class

Value Objects

  1. classes that derive from ValueObjectBase
  2. Must have at least one Create() factory method
  3. ctors must all be private
  4. must have public static ValueObjectFactory<TValueObject> Rehydrate() method
  5. Immutable methods only, or overriden

@jezzsantos jezzsantos reopened this Nov 1, 2023
@jezzsantos jezzsantos mentioned this issue Dec 9, 2023
66 tasks
@jezzsantos
Copy link
Owner Author

jezzsantos commented Dec 9, 2023

Architecture Tests library NetArchTest, or ArchUnit
NetArchUnit: https://www.youtube.com/watch?v=eWjNLYNS-og

Layers

API

  • Roslyn: All properties of IWebResponse derivative types must have primitives or Resources (Nullables, no Optionals) and must have public getters and setters?
  • Roslyn: All properties of all IWebRequest derivative types must have primitives or Resources (Nullables, no Optionals) and must have public getters and setters?

Applicaton

  • ArchUnit: No Application type depends on any infrastructure type
  • Roslyn: All resources can only have getter/setter properties and datatypes: primitives, and themselves (typeof(string), typeof(int), typeof(long), typeof(double), typeof(DateOnly), typeof(DateTime), typeof(decimal), typeof(bool), typeof(Stream), typeof(byte)) (nullable, not Optional)
  • Roslyn: All resources must be serilaizable. Must have parameterless ctors
  • Roslyn: All ReadModelEntities can only have getter/setters properties and data types: ValueObjects and primitives (typeof(string), typeof(int), typeof(long), typeof(double), typeof(DateTime), typeof(decimal), typeof(bool), typeof(byte)) (Optional not nullable)

Domain

  • Roslyn: all Valueobjects, Entities and Aggregate Roots are sealed
  • ArchUnit: No Domain type depends on any Application type
  • ArchUnit: No Domain type depends on any Infrastructure type
  • Roslyn: All events can only have getter/setter properties and datatypes: primitives: (typeof(string), typeof(int), typeof(long), typeof(double), typeof(DateTime), typeof(decimal), typeof(bool), typeof(byte)) or enums (Optional not nullable)
  • UnknownTechnique: All assemblies containing any aggregates, Entities, and ValueObject are registered for DomainFactory in code at startup
  • UnknownTechnique: All aggregates are registered in IdentityFactory at startup
  • UnknownTechnique: All aggregates and entities are mentioned in the Module with prefixes

Vertical Slices

  • ArchUnit: No type in any domain assembly (of a subdomain) can depend on types in any other subdomain domain assembly
  • ArchUnit: No type in any application assembly (of a subdomain) can depend on types in any other subdomain domain assembly
  • ArchUnit: No type in any API assembly (of a subdomain) can depend on types in any other subdomain domain assembly
  • ArchUnit: No type in any Infrastructure assembly (of a subdomain) can depend on types in any other subdomain domain assembly

@jezzsantos
Copy link
Owner Author

Last rule: (probably Roslyn)

Foreach ISubDomainModule, if the DomainAssembly property has a type (as opposed to null),

then load that type, and scan all entities and aggregates, and make sure they have entries in the AggregatePrefixes property

@jezzsantos
Copy link
Owner Author

CodeFixes:

  • change class to public
  • add a parameterless ctor
  • add RouteAttribute (and guess the ServiceOperation from the name)
  • make property serializable (getter and setter)
  • change to Optional (from nullable notation)
  • change to nullable notation from Optional
  • others?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant