DotNet Application vs Standard Library
Back to basics here. When you have a .NET application and want to add class library to the solution, it will be added as a standard class library. What it means is the project file will have this markup right on top.
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<RazorLangVersion>3.0</RazorLangVersion>
</PropertyGroup>
This is for a good reason, this project will only have access to basic class library classes (BCL), nothing related to web or GUI which makes it minimalistic and portable across different types of applications. The architecture guidelines for a long time favors layered approach that looks somewhat like this
It does not have to be this straightforward, for example standard Blazor Webassembly template has these project dependencies.
Here server-side MVC application
references both Client
and Shared
library projects. But basic principles stay intact - shared library has no clue what is happening upstairs and client has no knowledge of server existence. Well, almost - it still needs to know base API
address to be able to communicate with back-end, but this is loose coupling that does not require hard project reference.
Now if you look at Blogifier
projects, this looks like this.
Nice and simple, but... what? Why all three projects are applications? Well, fist of all, Blogifier
supports two different UIs, which is a problem in its own rights but I won't go there just yet. To support multiple UIs you would either have application logic implemented in both, or have a shared application logic that does not fit into standard library. So here we have Blogifier.Core
. At least for now, I'm ok with that. The Blogifier.Widgets
, though, should be a standard library. Why it is not? Because components in the library have CRUD logic and need reference to the Core library, and you can't reference application from standard library project. Bomber..
So how to get out of the corner I painted myself into? For starters, I'll need to rethink strategy I get used to - that shared code is where all the heavy lifting and all the smarts should go, so that client can stay light-weight and simple. That makes sense, it promotes building client code by making it easy. But it breaks fundamental principals where application layers have different responsibilities and should not have multiple dependencies.
I think for the next iteration Blogifier should look similar to the picture below - the Core, at least for some time, will remain an application status, but I want to move models out of the data/domain into its own shared library and, very likely, convert admin panel to web assembly at some point in the near future. Long term, Core should also free itself of any high-level functionality and become standard library, but that can wait. Very basic stuff indeed, but so easy to overlook.