Code Monkey home page Code Monkey logo

pluralsight-ddd-fundamentals's Introduction

Pluralsight DDD Fundamentals Sample

Sample code for the Pluralsight DDD Fundamentals course (2nd edition) by Julie Lerman and Steve "ardalis" Smith. If you are looking for the .NET Framework sample from the original 2014 DDD Fundamentals course, it's available as the ddd-vet-clinic sample.

Additional exercises from Steve's DDD workshops (separate from Pluralsight course)

Give a Star! ⭐

If you like or are using this project to learn, please give it a star. Thanks!!!

Table of Contents

1. Running the Sample

  1.1 Docker

  1.2 Visual Studio and VS Code

2. Student Recommendations

3. Architecture Notes

4. Developer Notes

5. Credits

1. Running the Sample

You can run this sample in Docker or in Visual Studio. Docker is recommended.

Watch how to set up and run the sample app using Docker, Visual Studio, or VS Code here:

image

Running the DDD Fundamentals Sample by Philippe Vaillancourt

1.1 Docker

The easiest way to run the sample is using docker. Download the source and run this command from the root folder:

docker-compose build --parallel
docker-compose up

The build step will take a while. It's way faster if you run it in parallel, assuming you have a fast machine and download speed. The up command is much faster but will also take a moment and you may see some errors as apps try to connect to docker or databases before they're responsive. Give it a minute or two and it should succeed. RabbitMQ errors should go away once that service starts up. If you get SQL Server login errors, I've found it's best to just restart everything (ctrl-c, then docker-compose up again).

This will start RabbitMQ (for messaging between apps) and build and run each of the applications involved in the sample:

  • FrontDesk.Api
  • FrontDesk.Blazor
  • ClinicManagement.Api
  • ClinicManagement.Blazor
  • VetClinicPublic

It also adds the following supporting containers:

  • RabbitMQ with Management
  • FrontDesk SQL Server
  • ClinicManagement SQL Server
  • Test Mailserver (Papercut)

Once running, you should be able to access the various apps using localhost (HTTP not HTTPS because of Kestrel configuration restrictions) and the following ports (you can also find these bindings in the docker-compose.yml file):

Service (in docker) Docker Port Visual Studio Port
FrontDesk (main app) 5100 5150
ClinicManagement 6100 6150
VetClinicPublic 7100 7150
FrontDesk API / Swagger 5200 5250
ClinicManagement API / Swagger 6200 6250
RabbitMQ Management 15673 15672
RabbitMQ Service (5672) 5672
Papercut Management 37409 37408
Papercut SMTP (25) 25

The ports in () are only open inside of docker, not exposed otherwise.

Here are the (localhost) links you should use once the apps are running in docker:

If you want to quickly clean up all of your docker containers (All of them not just the ones you created for this sample!) you can run this command:

docker kill $(docker ps -q)

Note that any data changes you make will not be persisted if you docker remove the SQL Server container. The Docker container for SQL Server will be recreated and seeded on the next docker run. In other scenarios, you might be using Docker volumes to persist or share the database across container instances but that's overkill for this demo.

1.2 Visual Studio and VS Code

You may need to configure a local NuGet server and put this package in it:

/FrontDesk/src/FrontDesk.Blazor/deps/Pluralsight.DDD.Deps/Pluralsight.DDD.Deps.1.0.0.nupkg

Running the sample from Visual Studio (or VS Code or Rider, etc) requires some additional setup. You will need to run multiple solutions side by side. You will also need to run RabbitMQ and PaperCut, ideally as a docker images. You can run RabbitMQ from Docker using this command:

docker run --rm -it --hostname ddd-sample-rabbit -p 15672:15672 -p 5672:5672 rabbitmq:3-management

You should be able to open localhost:15672 to view RabbitMQ management interface (login as guest/guest).

rabbitmq management app

When new appointments are created, confirmation emails are sent out to clients. Start a test mailserver using this command (learn more):

docker run --name=papercut -p 25:25 -p 37408:37408 jijiechen/papercut:latest

You should be able to open localhost:37408 to view Papercut test mailserver management interface, where sent emails will appear.

Papercut management app

You can run individual solutions independently from one another, but obviously you won't see live sync between them when entities are updated, new appointments created, appointment confirmation emails clicked, etc. To get that, you'll need to run all three of the web applications:

  • FrontDesk
  • ClinicManagement
  • VetClinicPublic

Some of the ports may not be set up in config; you may need to adjust them by hand. They assume you'll run primarily in docker to see everything running. If you're trying to get things working outside of docker, you should try with the ports shown in the table above.

2. Student Recommendations

If you're coming here from the Pluralsight Domain-Driven Design Fundamentals course, great! Download this sample and look around. See if you can run it on your machine (docker recommended). Your next assignment is to look at the TODO comments in the code, and see if you can implement any of them. You can view todo comments as tasks in Visual Studio, or there are plugins for VS Code.

Don't worry about submitting a pull request for any TODO comments you fix. They're left there intentionally to help students learn by providing some ways to extend the solution from the course.

3. Architecture Notes

The reference application is built as a small set of related monolithic ASP.NET Core applications. The two Blazor applications are built using a modified version of the CleanArchitecture solution template and also bears a great deal of similiarity to the eShopOnWeb application (also maintained by @ardalis). To learn more about migrating toward a domain-centric architecture from a data-centric one, check out Steve's two courses on N-Tier architecture on Pluralsight. You'll also find videos covering Clean Architecture on Steve's YouTube channel as well as on the eShopOnWeb home page.

If you or your team need help with architecting your .NET application following principles of clean architecture, with or without microservices, Steve and his team and NimblePros have a great deal of experience helping clients do just that. Get in touch.

4. Developer Notes

If you're new to this kind of application development, and you have a Pluralsight subscription, I strongly advise you to learn about SOLID principles and various code smells and refactoring techniques. You'll find the background in these principles informs most of the design decisions used in the individual classes and projects used in the sample code provided here. If you're really serious about learning these topics, watch the original versions of these courses, which were able to go into more depth (more recent courses need to be shorter since Pluralsight found too many students didn't complete longer courses. But not you - you have what it takes to finish the whole thing. Right?). They're available from Steve's author page on Pluralsight.

The sample doesn't include exhaustive test coverage, but does demonstrate some automated tests. If testing is new to you, Julie has a great course on automated testing that you should check out.

4.1 Referenced NuGet Packages

This course uses several NuGet packages that you may find useful.

Ardalis.ApiEndpoints A simple base class that lets you keep your API endpoints small and focused on one endpoint at a time. MVC is replaced with Request-EndPoint-Response (REPR).

Ardalis.GuardClauses Contains common guard clauses so you can use them consistently. Also can be easily extended to apply your own guards for custom/domain exception cases.

Ardalis.Specification An implementation of the Specification design pattern that is well-suited to work with ORMs like Entity Framework (Core).

Ardalis.Specification.EntityFrameworkCore Adds EF Core-specific functionality, including a default implementation of a generic EF repository that supports Specifications.

Ardalis.Result Provides a generic result type that can be returned from application services. Can easily be translated into HTTP status codes or ActionResult types.

Ardalis.HttpClientTestExtensions Removes boilerplate code from ASP.NET Core API integration/functional tests.

Autofac Powerful open source DI/IOC container for .NET that supports more features than built-in ServiceCollection.

Blazored.LocalStorage Blazor utility for accessing browser local storage in Blazor WebAssembly apps.

MediatR Used to implement mediator pattern for commands and events.

Pluralsight.DDD.Deps Includes required trial binaries from Telerik. Currently this includes both Kendo UI and Blazor controls; Kendo should be replaced with just Blazor later in 2021. To build locally you may need to place this package in a local nuget repository. This package and its contents are subject to Telerik's EULA located in the same folder.

PluralsightDdd.SharedKernel An example SharedKernel package used by this sample built just for this course.

RabbitMQ.Client Client for communicating with RabbitMQ.

5. Credits

This sample is from Julie Lerman and Steve Smith's Pluralsight course. The original sample was written for .NET Framework by Steve. The current .NET 5 version was initially ported with the help of Shady Nagy. Progress Software provided the Blazor Scheduler control used to display the clinic's schedule*.

* Initial version is using a Kendo schedule since certain features weren't available at recording time

Additional credits include:

Matheus Penido: Fixing a bug (#36) https://github.com/matheuspenido https://www.linkedin.com/in/matheus-penido-8419a890/

  • Your name could be here...

pluralsight-ddd-fundamentals's People

Contributors

aleks-ivanov avatar ardalis avatar dependabot[bot] avatar imgbotapp avatar julielerman avatar matheuspenido avatar maxgonzaga avatar mikecasas avatar rahtgaz avatar shadynagy avatar snowfrogdev avatar szlatkow avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pluralsight-ddd-fundamentals's Issues

Add Social Card Image

After course is published, add a social card image with:

  • Name of course
  • URL of course
  • Julie and Steve names/contact
  • Julie and Steve photos (from course)

May be able to just use the course's intro image and add the link to the course to it.

Diagram: Mind Map with Specification

WebGraphViz.com definition:

digraph G {
  "Model-Driven Design" -> "Services" [ label=" express model with"]
  "Model-Driven Design" -> "Domain Events" [ label=" express change with"]
  "Model-Driven Design" -> "Entities" [ label=" express identity with"]
  "Model-Driven Design" -> "Value Objects" [ label=" express state & computation with"]
  "Model-Driven Design" -> "Layered (Dependency Inverted) Architecture" [ label=" isolate domain with"]

  "Entities" -> "Domain Events" [ label=" push state change with"]
  "Entities" -> "Repositories" [ label=" persist with"]
  "Entities" -> "Aggregates" [ label=" encapsulate with"]
  "Entities" -> "Aggregates" [ label=" act as root of"]
  "Entities" -> "Specifications" [ label=" query with"]

  "Value Objects" -> "Aggregates" [ label=" encapsulate with"]

  "Aggregates" -> "Repositories" [ label=" persist with"]
  "Aggregates" -> "Specifications" [ label=" query with"]

  "Repositories" -> "Specifications" [ label=" encapsulate queries with"]
}

Improve encapsulation of the entities.

I took a brief look at the project.
I'd suggest refactoring some of the entities with purely immutable properties (wherever is required). Now that EF can utilize constructors, we can better model our entities.

Also, I noticed almost all entities contain a constructor that accepts only id parameter. This allows the users to create instances in an incorrect states.

public Patient(int id)
{
      Id = id;
}

If you do agree with these sentiments, I may look into this someday soon. A related blog post here, and a sample application here

Version with the todos completed

I'm having an issue not quite understanding some of the todos and wondering if you would provide a branch with the completed todos so we can compare with our solutions

FYI, Love the course, I've watched it twice

Unable to use Schedule app.

After initial docker setup, with all containers running, when firing up the http://localhost:5100/
I'm welcomed with following exception in browser's console:

crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: String '09/23/2030 00:00:00 -04:00' was not recognized as a valid DateTime.
System.FormatException: String '09/23/2030 00:00:00 -04:00' was not recognized as a valid DateTime.
   at System.DateTimeParse.Parse(ReadOnlySpan`1 s, DateTimeFormatInfo dtfi, DateTimeStyles styles)
   at System.DateTime.Parse(String s)
   at System.Convert.ToDateTime(String value)
   at FrontDesk.Blazor.Services.ConfigurationService.ReadAsync()
   at FrontDesk.Blazor.Pages.Index.OnInitializedAsync()
   at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)

In addition:
obraz

ValueObject to Implement IEquatable<ValueObject>

In an old implementation of ValueObject used in the clean architecture solution, it was using reflection but also implementing IEquatable<ValueObject>

This new, improved version has since been updated using IComparable, IComparable<ValueObject>

Is there a reason why IEquatable was removed from ValueObject? It doesn't seem necessary as the base object Equals method suffices, but I was wondering if I adding it in my project would yield any sort of "PROs" if you will.

Ardalis Endpoints problem in Read.cs of DDD Fundamentals Course

I've been going through the FrontDesk project updating it to the latest Nuget packages.

Some changes are required in Read.cs to make the project Frontdesk.Api build, one of these is in Read.cs

I'm able to follow some of the 4.x upgrade steps to fix the problems, these are listed as the two main changes.

The final problem is confusing as the HandleAsync method in Read.cs looks like the example. I have changed WithResponse to WithResult

However I am getting a compiler error on the following code:

public override async Task<ActionResult<string>> HandleAsync(CancellationToken cancellationToken)
{
  return Ok(new OfficeSettings().TestDate.ToString(CultureInfo.InvariantCulture));
}

I had assumed that the WithResult<string> would have been the line that made the above code valid!

What is the correct fix here?

Appointments not showing in calendar

I tried to set it up in docker and in visual studio. The app is running but the appointments are not showing in the calendar even though I created a new one.,

Delete Appointment endpoint is not deleting appointments

I'm creating my own project based in this solution and I reached a situation that is not handled in this repo either.

Looking at the code in Endpoint/Appointment/Delete. The appointment it's just being removed from Schedule's list, but in the db this means removing the reference to the schedule in the appointment table for that particular record, not removing the record itself.

What would be the best practice approach to achieve that? I cannot create a repository of this entity as it's not Aggregate root (required by the RepositoryBase interface)

Thanks

The docker-compose file is incorrect because no version tag.

When I run this project as is on windows 11 with WSL in ubuntu, I get error on the docker-compose file

ERROR: The Compose file './docker-compose.yml' is invalid because:
Unsupported config option for services: 'clinicmanagement-api'

When I add a version tag at the top of the file

Version: "2"
The error is fixed.

api/clients is blocked by CORS policy

Hi,

I have been watching your Pluralsight Course and thought I would run the code locally in docker. The docker build seemed to work OK, as did the compose up.

However, when I launch the front end, I get the following error:
image

Maybe I am missing something, but as far as I can see, i have followed the instructions.

Thanks.

Appointments not showing in Schedule [June 2023]

I have downloaded latest pluralsight-ddd-fundamentals-main.zip and started the apps with docker. However when I start ddd.frontdesk.blazor in browser the Schedule is displayed for 30-09-2030 but no appointments. There are multiple rows of data in dbo.Appointments for this date. If I select a Client and Patient and double click in a blank space the Appointment Data appears in a modal but when Save clicked a notification appears but nothing still displays in the Schedule.

This might not be related but in the browser DevTools there are 2 messages under console:

 DevTools failed to load source map: Could not load content for http://localhost:5100/css/kendo/kendo.common.min.css.map: HTTP error: status code 404, net::ERR_HTTP_RESPONSE_CODE_FAILURE
DevTools failed to load source map: Could not load content for http://localhost:5100/css/kendo/kendo.default.min.css.map: HTTP error: status code 404, net::ERR_HTTP_RESPONSE_CODE_FAILURE

dbo.Appointments.txt

Error NU1101 Unable to find package Pluralsight.DDD.Deps. No packages exist with this id in source(s)

During the build one of the custom public Nuget package restore fails:

Severity	Code	Description	Project	File	Line	Suppression State
Error	NU1101	Unable to find package Pluralsight.DDD.Deps. No packages exist with this id in source(s): Microsoft Visual Studio Offline Packages, nuget.org	FrontDesk.Blazor.Host	C:\Users\ArunPaul\source\repos\DDD\pluralsight-ddd-fundamentals\FrontDesk\src\FrontDesk.Blazor.Host\FrontDesk.Blazor.Host.csproj	1	

When I checked the Nuget repository, it doesn't exist, but the closest package available is
PluralsightDdd.SharedKernel.
I tried for building the application with the PluralsightDdd.SharedKernel package but it never builds.

Can someone suggest a solution?

Telerik credentials are in source control

I was just following the readme file and noticed that there are credentials hard-coded into FrontDesk/src/FrontDesk.Blazor/nuget.config

I'm guessing this was not intentional - these should probably be deleted.

SharedKernel project is not a SharedKernel

From the original documentation:

Designate with an explicit boundary some subset	of the domain	model that the teams	
agree to share. Keep this kernel small.

SharedKernel is about sharing a domain models across bounded context. Not about sharing infrastructure code. The shared kernel in this project is rather a Common/Core and has nothing to do with Domain Driven Design. DDD does not care about infrastructure.

I know people have many different opinions on this topic, thanks to the vagueness of the original source. Still, a dependency to MediatR and other infrastructure libraries in the SharedKernel project seems wrong.

Makes sense to get rid of Action scheduleHandler?

It's unclear to me why the Schedule and Appointment entities rely on the consumer (i.e. the Create and Update endpoints) to maintain their invariants, namely appointments that overlap and share a patient/room/doctor have IsPotentiallyConflicting set to true, all others have it set to false (and `

Of course, in the example with only one schedule it's rather esoteric to expect the consumer to pass the wrong handler to UpdateStartTime or UpdateAppointmentType or to forget calling AddNewAppointment, but it would be easy to eliminate the risk once and for all by giving Appointment a property that holds its Schedule and is set from the constructor (by exchanging Guid scheduleId for Schedule schedule). If that property is kept private, the consumer cannot abuse it to do schedule-things through the appointment, while entity framework will still populate it when querying for the appointment.

Wild guess at the rationale: older versions of entity framework couldn't deal with private properties, and you didn't want to burden the repository with manually assigning the Schedule to the Appointment.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.