NetCrudExample
Minimal example of a simple Crud rest Api in C#
Considerations and shortcomings
-
Repository
- Consider a Maybe/Option type return from the Get operation instead of a nullable
- Consider using mutable Employee class and setting its Id on insert rather than just returning the Id
- Could use interface with more generic data-language (save/load instead of insert/update/get) to support different storage mechanisms behind repo interface - in practice sql is standard for such repos.
- Orm use would make repo code easier to read
- Soft deletes would probably make more sense
- In practice might not need to care about race conditions/concurrency in slow moving api, but they are definitely possible with the MaxOccupation condition
-
Api
- Should add documentation
- Should add better error messages
- Could consider only mapping set fields in PUT
-
Tests
- Integration vs. unit tests. I personally prefer integration/end-to-end/functional over unit tests, but understand others prefer differently
- Testing on a local database is faster (especially if no schema changes) but docker can be easier to integrate in pipelines
- Consider Autofixture or similar for testdata
-
System guarantees
- Guarantees can be made on the database but require triggers for the MaxOccupation one - or denying access on object and only having that on a stored proc. A more pragmatic approach is probably to loosen guarantees a bit and just have interactions through the Api with only very restricted access to direct table interactions
- When should birthday checks be made? On insert/update or scheduled in order to check "vampire" criteria - a pragmatic approach is imo better than guarantees again.
-
Performance
- Outside of using Async no big considerations for this simple api.
- On the database a nonclustered index on reg.Employee(OfficeId) makes sense for queries ala SELECT FirstName, LastName FROM reg.Employees e INNER JOIN reg.Offices o ON o.Id=e.OfficeId WHERE o.Location='Silkeborg'. But generally I'd much rather make that assessment when seeing real usage. Also given the size of these tables it's no issue imo.
-
Configs/Environments/Security
- Ideally sql connections are made with ad-users but other sensitive info should be stored in Azure Keyvault or similar. Otherwise at least make sure not to commit sensitive info to source control.
- Returning exceptions as api-error messages isn't great - but for an internal application it is fine for a demo imo. Custom tailored replies in the api would obviously be better.
-
Maintainability
- If multiple and more complex models exist for interacting with the API consider putting these in a nuget package to share these model classes. That makes implementation of consumers easier and also better communicates "breaking" changes with semantic versioning for new api-versions.
- Could consider using common libraries across projects to simplify e.g. validation.
-
Philosophical
- Primitive obsession - for a simple project like this it's probably fine, but the rules for birthdate, names etc. definitely calls for specific classes to guarantee validation need only be done once.