Presentatie Tjeerd Seinen tijdens Tools4ever klantendag 2010:
Op het gebied van het beheer van User Accounts en Wachtwoorden heeft Tools4ever inmiddels een suite van producten ontwikkeld. Tijdens deze sessie worden alle producten kort toegelicht en gedemonstreerd. Tevens zal aandacht besteedt worden aan de roadmap voor de komende periode met betrekking tot de release van uitbreidingen aan de bestaande producten en de release totaal nieuwe producten.
This document provides instructions for using the hashtag #jomout to share plans and find friends for activities on JomOut, a directory for Twitter users' activities. It explains that tweets with #jomout that include the date, time, location, and activity will be captured by JomOut to display users' plans. Examples are provided of tweets sharing attendance at a tweetup in Kuala Lumpur and a party in Singapore.
The document discusses the benefits of exercise for mental health. Regular physical activity can help reduce anxiety and depression and improve mood and cognitive functioning. Exercise causes chemical changes in the brain that may help boost feelings of calmness, happiness and focus.
The document discusses passages from the Bible about the body of Christ and being baptized into one body. It references 1 Corinthians 12:13, Ephesians 4:4, and 1 Corinthians 12:27 which all discuss there being one body, one Spirit, one faith, and believers comprising the body of Christ.
The Walk Through Time exhibit at the Smithsonian National Museum of Natural History takes visitors on a journey through the past 3.5 billion years of life on Earth. Visitors can see full-scale models and replicas of dinosaurs, mammals, plants and more from different eras. The exhibit aims to educate the public about evolution and the incredible diversity of life that has inhabited our planet.
Presentatie Tjeerd Seinen tijdens Tools4ever klantendag 2010:
Op het gebied van het beheer van User Accounts en Wachtwoorden heeft Tools4ever inmiddels een suite van producten ontwikkeld. Tijdens deze sessie worden alle producten kort toegelicht en gedemonstreerd. Tevens zal aandacht besteedt worden aan de roadmap voor de komende periode met betrekking tot de release van uitbreidingen aan de bestaande producten en de release totaal nieuwe producten.
This document provides instructions for using the hashtag #jomout to share plans and find friends for activities on JomOut, a directory for Twitter users' activities. It explains that tweets with #jomout that include the date, time, location, and activity will be captured by JomOut to display users' plans. Examples are provided of tweets sharing attendance at a tweetup in Kuala Lumpur and a party in Singapore.
The document discusses the benefits of exercise for mental health. Regular physical activity can help reduce anxiety and depression and improve mood and cognitive functioning. Exercise causes chemical changes in the brain that may help boost feelings of calmness, happiness and focus.
The document discusses passages from the Bible about the body of Christ and being baptized into one body. It references 1 Corinthians 12:13, Ephesians 4:4, and 1 Corinthians 12:27 which all discuss there being one body, one Spirit, one faith, and believers comprising the body of Christ.
The Walk Through Time exhibit at the Smithsonian National Museum of Natural History takes visitors on a journey through the past 3.5 billion years of life on Earth. Visitors can see full-scale models and replicas of dinosaurs, mammals, plants and more from different eras. The exhibit aims to educate the public about evolution and the incredible diversity of life that has inhabited our planet.
Presentation on creating a bridge between formal and informal ECM processes in an organisation by using Lotus Quickr ECM. With a focus on desktop connectors to enhance the user with Basic Content Services within daily used content tools.
Veel organisaties die gebruik maken van TOPdesk, zetten de meldingen waarbij een aanpassing in de software noodzakelijk is door naar de ontwikkelafdeling. Vaak worden deze meldingen handmatig ingevoerd in Azure DevOps, wat dubbel werk oplevert, de kans op fouten vergroot en terugkoppeling aan de gebruiker lastig maakt. Een koppeling tussen TOPdesk en Azure DevOps kan daardoor een aanzienlijke efficiencywinst opleveren.
De TOPdesk – Azure DevOps koppeling
Wij hebben een TOPdesk – Azure DevOps koppeling ontwikkeld waarmee meldingen in TOPdesk eenvoudig kunnen worden doorgezet naar Azure DevOps. Er wordt automatisch een work-item gecreëerd in Azure DevOps dat door het ontwikkelteam kan worden opgepakt. Andersom worden statuswijzigingen van workitems in Azure DevOps teruggestuurd naar TOPdesk. Deze SaaS-koppeling werkt op basis van de online versies van beide software producten.
Inhoud webinar
Tijdens dit webinar zijn we ingegaan op de TOPdesk – Azure DevOps koppeling. Hoe werkt de koppeling, wat zijn de mogelijkheden, voordelen en randvoorwaarden. We hebben ook een demonstratie van de koppeling en de bijbehorende customer portal gegeven.
Ga voor de opname van het webinar naar: https://www.delta-n.nl/nieuws/efficiencywinst-met-de-topdesk-azure-devops-koppeling
Visual Studio Team Services (VSTS) is de Cloudoplossing voor ALM/DevOps tooling van Microsoft. Het is de tegenhanger van de on-premise variant, Team Foundation Server (TFS). Veel bedrijven gebruiken nu TFS en willen graag overstappen naar VSTS. Dat is logisch, want het neemt de zorg voor onderhoud van de omgeving voor een groot deel weg en maakt het eenvoudig om steeds de meest recente functionaliteiten te gebruiken. Microsoft heeft een oplossing gemaakt om de migratie van TFS naar VSTS mogelijk te maken. Deze oplossing is echter geen "next-next-finish" actie, maar een klus die je goed moet plannen. In deze online sessie vertellen we eerst wat de oplossing inhoudt, om daarna vragen te beantwoorden. Een interactieve sessie dus!
Getting a grip on your code dependencies (2023-10)Dennis Doomen
I'm sure every developer wants to be able to change code with confidence and without fear. Readable and self-explanatory code is one aspect of that. Too much coupling is another major source of problems that prevent you from changing one part of the system without causing side-effects. In this talk, I'd like you to show you common sources of unnecessary coupling and offer you options to help prevent and/or break those. I'll talk about how principles like Don't Repeat Yourself and Dependency Injection can be a double-edge sword, how to detect too unnecessary dependencies and how to use the Dependency Inversion Principle to unravel some of those. And yes, I will also talk about controlling dependencies on the package level.
Challenge
1. How to prevent too much coupling?
2. We are tought to decrease coupling and increase cohesion
3. How do you increase cohesion? By applying DRY!
4. But DRY creates more coupling
5. And too much decoupling results in a forest of abstractions
6. The solution is… find a balance (or "it depends")
On the architecture level
1. Use architecture style that embraces DIP (e.g. Onion, Hexagon, Clean Architecture)
2. Organize your code along functional boundaries -> this will make it easier to break off that boundary for rebuilding/strangler/microservices.
3. Apply DRY within those boundaries only, but allow shared services for complicated capabilities
4. Align your test scope with those internal boundaries…
On the package level
• Classes and interfaces that are almost always used together should be packaged together. Those that don’t meet that criteria don’t have a place in that package
• Packages should not require changes (and thus a new release) for unrelated changes.
• There must be no cycles in the dependency structure
• A package should only depend upon packages that are more stable than it is or abstract packages
On the code level
• Avoid technical folders and organize them by functionalities or capabilities
• Things in adjacent folders usually mean they are separate boundaries
• Use the Tell, Don't Ask principle
• Use the Law of Demeter to detect unnecessary coupling
• Encapsulate primitive types and collections in specific types
• Dependency injection is great, but try to avoid a global container
• It's fine to inject concrete classes inside boundaries
Strategy for legacy code
1. Ensure you have a safety net using characterisation tests
2. Find existing seams and decouple them better
a. Identify modules or functional slices
b. Identify groups of classes that are supposed to be used together and are designed to be reusable
c. Identify interfaces or abstractions in DI registration code and see if they are truly designed for reusability
d. Assume that code in adjacent folders is supposed to be independent
e. Move code from different technical folders that belong together in their own (functionally named) folderPublic
3. Use that to define (and visualize) the target architecture
Tools and practices to help you deal with legacy codeDennis Doomen
We all love to build greenfield projects, but the reality is that in most jobs you have to deal with a lot of legacy code. This doesn't mean the code is bad. It just means that choices were made that were the right ones at that time, or that the developers were not entire up-to-date with modern development practices. And that's exactly what this talk is about. I enjoy taking such a codebase and gradually introduce architectural seems, add a proper build pipeline, introduce temporary tests and then gradually refactor the codebase to combine more maintainable, testable and reliable. So in this talk, I'd like to unfold my extensive toolbox of practices, principles, tools and mindset to help you improve your legacy code without jeopardizing your business.
Understand production environment
See which vinaries are running in production and what config files are used
Verify the code and the production release are in sync, e.g. DotPeek
Analyze logs to understand what features are used
Try to get it to run on a local environment
Understand code
Generate project diagrams and class hierarchies
Find origin calls and destination of a parameter using Rider
Use navigation options to find inheritors, usages, etc.
Use the namespaces and project names to understand the relation
Have Rider's AI Assistant or ChatGPT explain the code
Track all documentation in a single place
Build C4 diagrams
Find dead code
Reduce the scope of types and members to internal to find more dead code
Detect code inefficiencies and dead code using Rider
Remove commented out code
Build a safety net
If therea are tests, add code coverage reporting using Coverlet and use that to find dark spots
(HTTP API) Characteristics tests using FluentAssertions, Bogus, xUnit. Use AI to generate them. It's fine, you'll delete them later on
Use test containers for .net t lo include the databse
Build a couple of end to end UI tests e.g. using Cypress, Playwright, efc
Improve deployability
Add scripts or builds steps to run the code locally, Nuke build pipeline to get consistency
Adopt a version strategy and name branches accordingly
Adopt automatic versioning using GitVersion
Adopt logging and exception strategy, e.g. Serilog
Pulumi to automate PR deployments
Improve code
Treat all warnings as errors and fix thhem
Editorconfig / eslint so auto-format works
Configure a personal Rider/R# clean-up profile to auto-format file, project and solution
Roslyn analyzers
Microsoft.CodeAnalysis.BannedApiAnalyzers
StyleCop.Analyzers
CSharpGuidelinesAnalyzer
Roslynator.Analyzers
Meziantou.Analyzer
Enable nullable types per file
Move new code to .NET 6+ or cross-compile
Switch to newer C# versions, possibly using Polysharp
File-scope namespaces
Target-typed news
switch expression
String interpolation instead of string.format
Use Directory.Build.Props to reduce duplication
Improve naming whenever you can
Encapsulate prim itive types and collections in d
More Related Content
Similar to Building a Service Oriented System: An Introduction
Presentation on creating a bridge between formal and informal ECM processes in an organisation by using Lotus Quickr ECM. With a focus on desktop connectors to enhance the user with Basic Content Services within daily used content tools.
Veel organisaties die gebruik maken van TOPdesk, zetten de meldingen waarbij een aanpassing in de software noodzakelijk is door naar de ontwikkelafdeling. Vaak worden deze meldingen handmatig ingevoerd in Azure DevOps, wat dubbel werk oplevert, de kans op fouten vergroot en terugkoppeling aan de gebruiker lastig maakt. Een koppeling tussen TOPdesk en Azure DevOps kan daardoor een aanzienlijke efficiencywinst opleveren.
De TOPdesk – Azure DevOps koppeling
Wij hebben een TOPdesk – Azure DevOps koppeling ontwikkeld waarmee meldingen in TOPdesk eenvoudig kunnen worden doorgezet naar Azure DevOps. Er wordt automatisch een work-item gecreëerd in Azure DevOps dat door het ontwikkelteam kan worden opgepakt. Andersom worden statuswijzigingen van workitems in Azure DevOps teruggestuurd naar TOPdesk. Deze SaaS-koppeling werkt op basis van de online versies van beide software producten.
Inhoud webinar
Tijdens dit webinar zijn we ingegaan op de TOPdesk – Azure DevOps koppeling. Hoe werkt de koppeling, wat zijn de mogelijkheden, voordelen en randvoorwaarden. We hebben ook een demonstratie van de koppeling en de bijbehorende customer portal gegeven.
Ga voor de opname van het webinar naar: https://www.delta-n.nl/nieuws/efficiencywinst-met-de-topdesk-azure-devops-koppeling
Visual Studio Team Services (VSTS) is de Cloudoplossing voor ALM/DevOps tooling van Microsoft. Het is de tegenhanger van de on-premise variant, Team Foundation Server (TFS). Veel bedrijven gebruiken nu TFS en willen graag overstappen naar VSTS. Dat is logisch, want het neemt de zorg voor onderhoud van de omgeving voor een groot deel weg en maakt het eenvoudig om steeds de meest recente functionaliteiten te gebruiken. Microsoft heeft een oplossing gemaakt om de migratie van TFS naar VSTS mogelijk te maken. Deze oplossing is echter geen "next-next-finish" actie, maar een klus die je goed moet plannen. In deze online sessie vertellen we eerst wat de oplossing inhoudt, om daarna vragen te beantwoorden. Een interactieve sessie dus!
Getting a grip on your code dependencies (2023-10)Dennis Doomen
I'm sure every developer wants to be able to change code with confidence and without fear. Readable and self-explanatory code is one aspect of that. Too much coupling is another major source of problems that prevent you from changing one part of the system without causing side-effects. In this talk, I'd like you to show you common sources of unnecessary coupling and offer you options to help prevent and/or break those. I'll talk about how principles like Don't Repeat Yourself and Dependency Injection can be a double-edge sword, how to detect too unnecessary dependencies and how to use the Dependency Inversion Principle to unravel some of those. And yes, I will also talk about controlling dependencies on the package level.
Challenge
1. How to prevent too much coupling?
2. We are tought to decrease coupling and increase cohesion
3. How do you increase cohesion? By applying DRY!
4. But DRY creates more coupling
5. And too much decoupling results in a forest of abstractions
6. The solution is… find a balance (or "it depends")
On the architecture level
1. Use architecture style that embraces DIP (e.g. Onion, Hexagon, Clean Architecture)
2. Organize your code along functional boundaries -> this will make it easier to break off that boundary for rebuilding/strangler/microservices.
3. Apply DRY within those boundaries only, but allow shared services for complicated capabilities
4. Align your test scope with those internal boundaries…
On the package level
• Classes and interfaces that are almost always used together should be packaged together. Those that don’t meet that criteria don’t have a place in that package
• Packages should not require changes (and thus a new release) for unrelated changes.
• There must be no cycles in the dependency structure
• A package should only depend upon packages that are more stable than it is or abstract packages
On the code level
• Avoid technical folders and organize them by functionalities or capabilities
• Things in adjacent folders usually mean they are separate boundaries
• Use the Tell, Don't Ask principle
• Use the Law of Demeter to detect unnecessary coupling
• Encapsulate primitive types and collections in specific types
• Dependency injection is great, but try to avoid a global container
• It's fine to inject concrete classes inside boundaries
Strategy for legacy code
1. Ensure you have a safety net using characterisation tests
2. Find existing seams and decouple them better
a. Identify modules or functional slices
b. Identify groups of classes that are supposed to be used together and are designed to be reusable
c. Identify interfaces or abstractions in DI registration code and see if they are truly designed for reusability
d. Assume that code in adjacent folders is supposed to be independent
e. Move code from different technical folders that belong together in their own (functionally named) folderPublic
3. Use that to define (and visualize) the target architecture
Tools and practices to help you deal with legacy codeDennis Doomen
We all love to build greenfield projects, but the reality is that in most jobs you have to deal with a lot of legacy code. This doesn't mean the code is bad. It just means that choices were made that were the right ones at that time, or that the developers were not entire up-to-date with modern development practices. And that's exactly what this talk is about. I enjoy taking such a codebase and gradually introduce architectural seems, add a proper build pipeline, introduce temporary tests and then gradually refactor the codebase to combine more maintainable, testable and reliable. So in this talk, I'd like to unfold my extensive toolbox of practices, principles, tools and mindset to help you improve your legacy code without jeopardizing your business.
Understand production environment
See which vinaries are running in production and what config files are used
Verify the code and the production release are in sync, e.g. DotPeek
Analyze logs to understand what features are used
Try to get it to run on a local environment
Understand code
Generate project diagrams and class hierarchies
Find origin calls and destination of a parameter using Rider
Use navigation options to find inheritors, usages, etc.
Use the namespaces and project names to understand the relation
Have Rider's AI Assistant or ChatGPT explain the code
Track all documentation in a single place
Build C4 diagrams
Find dead code
Reduce the scope of types and members to internal to find more dead code
Detect code inefficiencies and dead code using Rider
Remove commented out code
Build a safety net
If therea are tests, add code coverage reporting using Coverlet and use that to find dark spots
(HTTP API) Characteristics tests using FluentAssertions, Bogus, xUnit. Use AI to generate them. It's fine, you'll delete them later on
Use test containers for .net t lo include the databse
Build a couple of end to end UI tests e.g. using Cypress, Playwright, efc
Improve deployability
Add scripts or builds steps to run the code locally, Nuke build pipeline to get consistency
Adopt a version strategy and name branches accordingly
Adopt automatic versioning using GitVersion
Adopt logging and exception strategy, e.g. Serilog
Pulumi to automate PR deployments
Improve code
Treat all warnings as errors and fix thhem
Editorconfig / eslint so auto-format works
Configure a personal Rider/R# clean-up profile to auto-format file, project and solution
Roslyn analyzers
Microsoft.CodeAnalysis.BannedApiAnalyzers
StyleCop.Analyzers
CSharpGuidelinesAnalyzer
Roslynator.Analyzers
Meziantou.Analyzer
Enable nullable types per file
Move new code to .NET 6+ or cross-compile
Switch to newer C# versions, possibly using Polysharp
File-scope namespaces
Target-typed news
switch expression
String interpolation instead of string.format
Use Directory.Build.Props to reduce duplication
Improve naming whenever you can
Encapsulate prim itive types and collections in d
What you can learn from an open-source project with 250 million downloadsDennis Doomen
Dennis Doomen presented on FluentAssertions, an open source .NET library for validation of results and state. With over 244 million downloads, it is successful due to its clean code design using test-driven development, extensibility, clear documentation, and support. Doomen discussed tools, practices, and principles from the project, including editorconfig, Roslyn analyzers, approval tests, GitHub Actions, and semantic versioning that can be applied to other projects.
Getting a grip on your code dependenciesDennis Doomen
I'm sure every developer wants to be able to change code with confidence and without fear. Readable and self-explanatory code is one aspect of that. Too much coupling is another major source of problems that prevent you from changing one part of the system without causing side-effects. In this talk, I'd like you to show you common sources of unnecessary coupling and offer you options to help prevent and/or break those. I'll talk about how principles like Don't Repeat Yourself and Dependency Injection can be a double-edge sword, how to detect too unnecessary dependencies and how to use the Dependency Inversion Principle to unravel some of those. And yes, I will also talk about controlling dependencies on the package level.
My Laws of Test Driven Development (2023)Dennis Doomen
About 15 years ago, I got inspired by a series of posts on Test Driven Development written by the Jeremy D. Miller. Now, with many years of great and not-so-great experiences practicing Test Driven Development, I thought it is the time to capture my own “laws”. The term "law" is obviously an exaggeration and "principles or heuristics" cover my intend much better. Either way, I want to talk about the scope of testing, using the observable behavior, naming conventions, state-based vs interaction-based testing, the impact of DRY, patterns to build useful test objects and some of the libraries and tools I use. In short, everything I try to follow every day I write, review or maintain code.
Design patterns for Event Sourcing in .NETDennis Doomen
Event Sourcing is becoming more mainstream these days, and a lot of conferences have demonstrated the pros and cons of this architecture style from multiple angles. I've done a few of these and publishes a lot of articles on best practices and solutions to common problems. But what nobody did was to show you how to build an event sourced systems in the .NET ecosystem. There are a lot of open-source projects that you can use, so you'll need to find a right mix and your own code to that. So let me show you how I would implement this in .NET with almost 10 years of Event Sourcing experience behind my belt.
Automate Infrastructure with Pulumi and C#Dennis Doomen
Who remembers the days were you had to manually setup a physical server somewhere in a 19 inch rack? Nowadays those physical racks have been replaced by virtual machines provided by Google, Microsoft and Amazon. But some people are still provisioning them manually. The more mature organizations will script most of the provisioning using the native CLI or HTTP API provided by the specific cloud platform, but quite often those are maintained separately from the code of the system that is being deployed. Terraform by Hashicorp is another attempt to support infrastructure-as-code by using a declarative syntex to define the desired infrastructure. But then again, Yaml isn't really suited for anything but simple single-file configuration settings. Yaml isn't code and doesn't provide real Intellisense, line-by-line debugging and most importantly, refactoring.
But what if you could use C# and .NET to provision your infrastructure and treat that code as first-class citizens of your codebase, including all the capabilities that you would expect? Well, let me show you how Pulumi for .NET will allow you to evolve your infrastructure code with the rest of the code base without turning it in a big spaghetti of Yaml files.
What is the right unit in unit testing (UpdateConf 2022)Dennis Doomen
Whether you're just writing your first unit test or have been practicing Test Driven Development for many years, I'm sure your biggest challenge is to find the right scope for testing. Unfortunately a lot of books and guidance seem to imply that every class or type should be tested separately. Well, I can tell you from 15 years of unit testing experience that that's the best way to shoot yourself in the foot.
In this session, I'm going to show you some concrete examples and why I chose a certain boundary for the "unit" in unit testing. I will also share design heuristics I use myself to find those boundaries and why those are not guidelines. I'll also illustrate how principals like DRY and SOLID can be both a blessing and a curse that may lead to the wrong design choices
Slow Event Sourcing (re)projections - Just make them faster!Dennis Doomen
I don't have to tell anybody how awesome Event Sourcing is as an architecture style. But those that have been using it in production must have experienced the pains of keeping the upgrades fast enough, especially if you use a more traditional relational database like SQL Server. I've once heard somebody say: "If it's slow, make it faster", but rebuilding a big projection is simply a very expensive operations and involves a lot of network traffic between the application and the database servers.
Over the years since we adopted Event Sourcing, we've been experimenting a lot and have implemented various improvements to make those reprojections faster. And we haven't stopped. We're already working on some new ideas lately. So in this session, I'd like to share those techiques, their pros and cons and how we implemented them on a more detailed level.
50 things software teams should not do.pptxDennis Doomen
The document discusses 50 things that software teams should avoid doing related to architecture, code design, testability, documentation, team maturity and process. Some examples include treating a monolith as inherently bad, using microservices as an escape plan from technical debt, dogmatically using design patterns, insufficient test coverage, messy source control history, developers working in isolation, artificial sprint goals, and long-running stand-ups. The document is written by Dennis Doomen, an architect with 25 years of experience in the .NET space.
What is the right "unit" in unit testing and why it is not a class?Dennis Doomen
Whether you're just writing your first unit test or have been practicing Test Driven Development for many years, I'm sure your biggest challenge is to find the right scope for testing. Unfortunately a lot of books and guidance seem to imply that every class or type should be tested separately. Well, I can tell you from 15 years of unit testing experience that that's the best way to shoot yourself in the foot.
In this session, I'm going to show you some concrete examples and why I chose a certain boundary for the "unit" in unit testing. I will also share design heuristics I use myself to find those boundaries and why those are not guidelines. I'll also illustrate how principals like DRY and SOLID can be both a blessing and a curse that may lead to the wrong design choices.
A lab around the principles and practices for writing maintainable codeDennis Doomen
Writing maintainable code is not something that is easy to do. Not only is a pretty subjective, a lot of the techniques like Clean Code, SOLID and such can be misinterpreted resulting in unconstructive dogma. I've made it my career's goal to find a good balance between all those different patterns, principles, practices and guidelines.
In this talk, I'd like to share my own ideas on what it takes to write maintainable code. I'll talk about architecture, class design, automated testing and any consequences on your development process. If you care about your code, be there with me.
How to Practice TDD Without Shooting Yourself in the FootDennis Doomen
It’s 2021, so practices like Test Driven Development (TDD) have long found their way into organizations. However, the practices and principles to keep those unit tests maintainable haven’t really changed. Still, Dennis regularly talks to developers that somehow ended up with an incomprehensible unmaintainable set of unit tests that they once believed in, but are now holding them back. So in this session Dennis likes to provide a refresh of those fundamental ideas and talk about why you should practice TDD, revealing intentions, naming conventions, state versus interaction based testing, and how to stay out of the debugger hell with proper mocking and assertion frameworks.
Decomposing the Monolith using modern-day .NET and a touch of microservicesDennis Doomen
If I have to name a single biggest hype in software architecture land then it would be "microservice". They are supposed to be small and focused, can be deployed independently, can work with any technology and will solve all your monolithical problems. But we all know that silver bullets don't exist, plus technology should never be a goal, but merely a means to an end. Nonetheless, following the path towards real microservices is a great strategy for decomposing a monolith without the deployment complexity of the first. So how do you do that? What technologies does the .NET realm offer for us? In this talk, I'll show you some of the pros and cons of micro-services and its ingredients to leverage modern-day .NET and Event Sourcing to move your monolith into a bright new future.
Event Sourcing from the Trenches (DDD Europe 2020)Dennis Doomen
Over the years I've spoken many times about what Event Sourcing is and shared many of the good, the bad and the ugly parts of it in blog posts and various talks. However, I've never talked about how to actually build a system based on this architecture style. I keep getting the same questions over and over again. Like when to apply Event Sourcing and at what architectural level. How to deal with transactional boundaries within and outside the domain. How to build projections that are autonomous, reliable and self-supporting. How to deal with upgrades and blue-green deployments. But also on how to handle bugs, design mistakes and crashing projections. Having made a lot of these mistakes myself over these years, it's time to share my current thoughts and opinions about this. Since the .NET space has a pretty rich set of open-source projections to support this, the examples and code will be .NET. But the concepts are universal, so don't let that scare you off.
Practical introduction to DDD, CQRS and Event SourcingDennis Doomen
The document discusses various challenges and solutions related to building applications using an event-driven architecture and event sourcing approach. It addresses issues like handling schema changes, dealing with bugs in projections, improving performance of rebuilding projections, handling archiving of large amounts of historical data, and enhancing events with additional context like original names. Various database technologies and patterns are discussed as solutions, such as using different storage for projections, stream tombstoning, and event modifiers.
How to practice TDD without shooting yourself in the footDennis Doomen
The document discusses test-driven development (TDD) and provides an opinionated definition and guidelines for TDD. It defines TDD as designing class responsibilities, writing an initial unit test, generating code stubs, ensuring the test fails, implementing the code, ensuring the test succeeds, identifying alternative scenarios, and repeating the process twice before refactoring. It also provides examples of code organization for TDD and recommends keeping tests focused on relevant parts of the code and avoiding debugger use. External resources on effective TDD practices are referenced.
Decomposing the Monolith (Riga Dev Days 2019)Dennis Doomen
A micro-service architecture is a great strategy for decomposing a monolith. In this talk, I’ll show you some of the pros and cons of micro-services and how you can leverage OWIN, .NET, Event Sourcing and the Onion Architecture to gradually move your monolith into a bright new future.
If I have to name a single hype in software architecture land then I would have to mention the micro-service architecture. Micro-services are supposed to be small, have a very focused purpose, can be deployed independently, are completely self-supporting and loosely coupled. Ideally, micro-services are technology agnostic, but hey, we’re in the .NET space, aren’t we? And they are not a goal, but a means to an end. In fact, a micro-service architecture has many benefits and are a great strategy for decomposing a monolith. So how do you build a micro-service? What technologies does the .NET realm offer for us? And what if you don’t want to deploy them independently? In this talk, I’ll show you some of the pros and cons of micro-services and how you can leverage OWIN, .NET, Event Sourcing and the Onion Architecture to gradually move your monolith into a bright new future.
A lab around the principles and practices for writing maintainable code (2019)Dennis Doomen
Writing maintainable code is not something that is easy to do. Not only is a pretty subjective, a lot of the techniques like Clean Code, SOLID and such can be misinterpreted resulting in unconstructive dogma. I've made it my career's goal to find a good balance between all those different patterns, principles, practices and guidelines. In this talk, I like to share you my own ideas on what it takes to write maintainable code. I'll talk about architecture, class design, automated testing and any consequences on your development process. If you care about your code, be there with me.
Lessons learned from two decades of professional software developmentDennis Doomen
Dennis Doomen discusses key principles for maintainable code, including isolation, testability, being diagnosable, traceability, readability, and discoverability. The goal is code that can be changed confidently by any developer on a team without fear and has a low cognitive load for readers to understand. Dennis Doomen is focused on continuously improving code through these principles.
4. Visie External System Internet Extranet / DMZ Website Silverlight Client Intranet Sharepoint Portals Office Business Apps Smart Client Enterprise Service Bus Application Server Internal System
6. Overzicht Service Interfaces Service Contracts Data Contracts Host Service Implementation Message Contracts Business Logic Business Actions Business Workflows Business Entities Resource Access Repositories Service Agents Database
7. Services Verantwoordelijkheden Doorgeefluik naar Business Actions Business georiënteerd, niet technisch/applicatie (!) Identificatie o.b.v. functionele sleutels Verzorgt (protocol-afhankelijke) authenticatie Schermt technische fouten af
8. Services Aandachtspunten Chunky messages (i.p.v. chatty) Naamgeving moet consistent en intuïtief zijn Documenteer services centraal Altijd expliciete request en response berichten Gebruik altijd een WCF wrapper namespace Retourneer functionele unieke codes voor business rule violations
9. Business Entities Verantwoordelijkheden Vangengedrag en conceptenuit het domein Bevattenallebedrijfsregels en constraints Hebben (in principe) altijdeenfunctionelesleutel Zijn Persistency Ignorant Ontworpen conform de OO-regels en design patterns zodatbedrijfsregels/logicamakkelijkaanpasbaar is
10. Business Entities Aandachtspunten Ontwerpvolgens de DDD gedachte Gebruik UML class diagrammen Identificeeraggregratierelaties Bepaal cascading gedraga.d.h. aggregratie Implementeervolgens Active Record of Domain Model design pattern Gebruik VAB of Data Annotations voorvalidatie Mogelijk de scope van unittests
12. Business (Process) Actions Verantwoordelijkheden Kortdurende Units-of-Work Bepalen levensduur van ACID transacties Kan de scope zijn voor unittests Controleren autorisatie Verwerken request en response berichtenuit service interfaces Vertalingtussen data contracten (DTOs) en entiteiten
13. Business (Process) Actions Aandachtspunten Nooitgedistribueerdetransactiesgebruiken Minimalevalidatie van berichten Besteedt DTO validatieuitaanentiteiten Log op eenslimmemanierzodat auditing mogelijk is Controleeralleen inter-entity rules
14. Repositories Verantwoordelijkheden Regelentoegang tot de database Gedraagtzichalseencollectie van entiteiten (interface lijkt op die van ICollection) Zouvolgens Transparent Persistency pattern moetenwerken, dus Lazy loading en Automatic flushing Verzorgtoptimalisatieszoals caching Vervangt database excepties door functioneleexcepties
15. Repositories Aandachtspunten Gebruikeen ORM zoalsb.v. NHibernate / EF4 Eén repository per aggregratie root uit het domein model Gebruik interfaces om de database tekunnenfaken ImplementeerIQueryable (LINQ) Gebruik Query Object of Specification patterns
16. Service Agents Verantwoordelijkheden Technische details van de externesystemenafschermen Beperkt impact van wijzigingen Vertalingtussen interne en externe accounts (single single-on) Biedtadditioneledienstenzoals caching Resistenttegen (tijdelijke) afwezigheid of netwerkproblemen Verzorgt monitoring en tracing van externesystemen
17. Service Agents Aandachtspunten Gebruik interfaces omexterneafhankelijkhedentekunnenmocken Ook reporting servers en/of file I/O moeten via een service agent verlopen Moeten in principe via een workflow wordengebruikt
18. Business Workflows Verantwoordelijkheden Langdurende (asynchrone) units-of-work Units-of-work waarbijexternesystemenbetrokkenzijn Gebruikt compensating transactions tijdenseen rollback Aandachtspunten Windows Workflow Foundation is lastigteintegreren met WCF Makkelijkergeworden met .NET 3.5 (WorkflowServiceHost) WF is (nog) afhankelijk van SQL Server (Tip: WFTools project op CodePlex) Koppelingtussen WF en Domain Model o.b.v. functionelesleutels
19. Schaalbaar met eenhogedoorvoersnelheid Geen state (behalve de database) Caching (evt. gedistribueerd) Services zijnautonoom Geengedistribueerdetransactie’s Logica in .NET, tenzijereen bottleneck is Loadtestsvoorperformancemetingenom die bottlenecks tevinden Evaluatiet.o.v. ideaal
20. Ontkoppeld Service agents Platformonafhankelijke Web service technologie Interfaces en dependency injection tussenlagen en componenten Testbaar Test Driven Development alsuitgangspunt Mocken van repository/service agents interfaces Unittesten op business procesniveau en business entity niveau, eventueelzonder live database Evaluatie t.o.v. ideaal
21. Veilig en betrouwbaar Authenticatie op service niveau Autorisatie op business process niveau Exception shielding Logging/tracing, timeout controles FxCop, StyleCopvoor code kwaliteit, uniformemanier van werken Services validerenberichtentegen interne fouten Evaluatie t.o.v. ideaal
22. Agile Design Patterns om de ilities te garanderen Bedrijfslogica gecentraliseerd in domain model Unittests om kwaliteit te waarborgen Geen technische afhankelijkheid van database Evaluatie t.o.v. ideaal
23. Web Service Software Factory Service Interfaces Service Contracts Data Contracts Host Code wordt gegenereerd vanuit data contract, service contract en host modellen Service Implementation Message Contracts Business Logic Business Actions Business Workflows Projectenstructuur wordt door Guidance Automation Recipe aangemaakt Business Entities Resource Access Repositories Service Agents Database
27. Resources Aviva Solutions blog (nieuwste versie van sheets & demoproject)http://blog.avivasolutions.nl Web Service Software Factory: Modeling Editionhttp://msdn.microsoft.com/en-us/library/cc487895.aspx P&P Application Architecture Guide 2.0http://www.codeplex.com/AppArch Applying Domain Driven Design & Patterns, Jimmy Nilssonhttp://domaindrivendesign.org/books/index.html#DDD_apply Workflow Foundation Toolshttp://www.codeplex.com/WFTools
Editor's Notes
De referentiearchitectuur is bedoeldvoorgroteresystemenwaarbijverwachtwordtdatermeerdere frontends gebouwdzullenworden (o.a. Web, Windows, WPF, Silverlgiht, Mobile) of daterkoppelingen met anderesystemennodigzijn. De technischeoplossingsrichtingprobeertzichteconformerenaanbekende design patterns, maar waarnodigwordteenmeerpragmatischeinsteekgekozen, ook al gaatdat ten koste van eenpuurontwerp. En in principegaikuit van Microsoft componenten, maar waar Microsoft nogeen gat heeft, kiesikvoor open-source.
Vaak begint een opdracht als een simpele website die vanwege beveiliging opgesplitst moet worden in een webserver en een applicatieserver. Maar vaak zie dat een klant een aantal systemen kent die op termijn jusit goed te koppelen zijn. Bovendien introduceer je hiermee de potentie voor nieuwe ontwikkelen zoals integratie met Sharepoint of Office Business Applications.
De ideale architectuur is volgens mijSchaalbaarAls de belasting toeneemt, dan bepaalt de schaalbaarheid in hoeverre het systeem daar op kan worden aangepast zonder code te wijzigen. Een applicatieserver is daarbij in principe ook schaalbaarder dan een database. Uiteraard moet het systeem ook een hoge doorvoersnelheid hebben. Het uitroepteken staat er bij omdat ik vind dat performance niet te zwaar moet worden ingezet. Het is veel efficiënter om later de bottlenecks boven water te krijgen en die op te lossen dan op micro-niveau te optimaliseren. OntkoppeldDe technische details van externe systemen zijn ingekapseldCommunicatie verloopt via standaard protocollen (ook met clients)Ook het soort database zou daarbij van ondergeschikt belang moeten zijn.TestbaarKan worden getest met unit tests zonder dat er een database of extern systeem beschikbaar moet zijn.Gebruik Test Driven Development (TDD) om te streven naar een hoge mate van testbaarheid, hoge coverage en hoge kwaliteit.Veilig en betrouwbaarGebruikt altijd authenticatie om gebruikers te validerenToegang via autorisatie is op service-niveau in te stellen.Interne fouten worden afgeschermd tegen hackers.De status en crucialestappen in het bedrijfsproces van het systeemmoettevolgenzijnDe communicatie met externesystemen is tetracen/monitoren (b.v. timeouts, tijdelijkeuitval, e.d.)Hackers mogen het systeemnietkunnenplatleggen door incorrect data teversturenAgileIs makkelijk aanpasbaar aan nieuwe of gewijzigde functionele eisen NieuwetechnologievindtsneleenplaatsNiet alleen moet de impact snel te bepalen zijnDekwaliteit moetten alle tijden gewaarborgd blijven.
Service InterfacesIdealiter begin je met met het identificeren van de service contracten (services en methodes).Vrijwelmeteendaarna (of zelfstegelijkertijd) komendaar de ingaande en uitgaandeberichtenbij.Als je temakenhebt met herbruikbare data structuren (entiteiten of zogenaamde DTOs), identificeer die als data contracts.Uiteraardheb je ookeenimplementatieclassnodig die het service contract implementeert. Dit is overigensalleeneendoorgeefluik.En de host is verantwoordelijkvoor het aanbieden van de contracten op eenspecifiek endpoint en de WS-protocollen die daarbijgebruiktmoetenworden. Ditkan IIS zijn, in-process of WAS.Business LogicDe Service Implementations zijnnietmeerdandoorgeefluikenvooreenstap in het bedrijfsproces. De business actions zijnverantwoordelijkvoor de atomaireacties. Allebedrijfslogica is gevangen in eennetwerk van classes met entiteitenvoor elk concept uit het domein (conform Fowler’s domain model). Resource AccessDe entiteitenwordenuiteindelijk in de database opgeslagen, maar via repositories opgehaald. Dezeabstraheert de specifieke details van een database data model en regelenzakenalsenheritance mapping, koppeltabbellen, e.d..Toegang tot externesystemenwordenaltijdingekapseld in Service Agents. Dezeschermenalletechnische details af die met het externesysteemtemakenhebbenaf.Vanwege het feitdat de controlebij het aanroepen van externesystemenuithanden is, en ptoentieellangkanduren, zoutoegang tot externesystemen via een workflow moetenverlopen. Dezezorgtdatfoutenafgehandeldworden met compensating transactions.
Services moeten ontworpen worden met het bedrijfsproces in het achterhoofd. Het beste is om deze samen met de domeinspecialisten te bedenken. Let op, in de praktijk worden de eerste services vaak wel vanuit een specifieke applicatie bedacht. Mits de genericiteit is meegenomen, hoeft dat niet persee een slechte zaak te zijn. Vaak is dat de manier om een organisatie voor te bereiden op SOA.Identificatie van DTOs moet altijd verlopen o.b.v. een functionele sleutel, eventueel aangevuld met een versienummer. De services verzorgen de authenticatie van de aanroepende gebruikers. Windows Authenticatie heeft de voorkeur, maar hoe dit verloopt is afhankelijk van de WS-* protocollen van de service interfaces. Interne technische fouten worden altijd afgevangen door de servicelaag zodat technische details over de interne structuur nooit bij de aanroepende partij komt.
Services moeten gebouwd zijn met het netwerk als communicatiemedium. M.a.w. services zijn zo bedacht dat het aantal round-trips beperkt blijven. Eisen aan naamgeving van service operations, message contracts en data contracts moeten van te voren vastgelegd worden zodat consistentie bewaakt is. WCF ondersteunt geen mechanisme om textuele documentatie over services te publiceren, dus de naamgeving moet vanzelfsprekend zijn. Leg een centrale document of Wiki aan met een overzicht van de services en hun functionaliteit. .NET en WCF bieden hier eigenlijk geen goede functionaliteit voor. Definieer altijd een expliciet reques en response bericht, ook al zijn ze nog leeg. Het toevoegen van een nieuw attribuut aan een lege message is geen breakingchange Definieer tevens altijd een WCF wrapper (name en namespace) zodat het message contract altijd een container object bevat, ook al kent je bericht pas een enkel attribuut. Het toevoegen van de wrapper (vereist bij meerdere attributen) is breaking Alle functionele fouten die als SOAP Fault geretourneerd worden moeten een unieke code krijgen die ook beschreven worden. Alleen dan kan een client programmatische acties ondernemen.
Entities zijn gemodelleerd vanuit concepten, objecten en personen uit het domein. Ze bevatten alle bedrijfsregels en constraints die nodig zijn om de integriteit van het domein te bewaren. Overigens zullen simpele constraints vaak al door de database worden bewaakt. Een entiteit moet in principe altijd een functionele sleutel hebben zodat die gebruikt kan worden buiten de systeemgrenzen. Maar in de praktijk introduceer je die sleutel pas als de entiteit via een DTO via de service wordt aangeboden. 100% PI is in de praktijk erg lastig, maar in principe wil je geen database-afhankelijke code (b.v. ORM) in je domein model. Afhankelijkheden met andere lagen en componenten moeten altijd via interfaces en b.v. DI of IoC plaatsvinden. Een puur domein model kan gebruik maken van alle OO aspecten en design patterns om het functionele gedrag te realiseren, c.q. aanpasbaar te maken
Zie Applying Domain Driven Design & Patterns (Nillson). Ontwerp vanuit het OO-domein en niet vanuit het data model Modelleer je domein model als UML class diagram in het FO om de relaties en business rules in vast te leggen Denk goed na over welke entiteiten een root aggregrates representeren, oftewel, welke entiteiten zijn zelfstandig en tevens ‘parent’ van andere entiteiten. Deze bepalen de locatie van de belangrijkste business rules, versienummering en repository scope Een puur domein model heeft geen kennis van repositories, maar is vaak lastig in gebruik. In Active Record heeft elke entiteit toegang tot een repository en verloopt alle interactie vanuit een BA via de entity. In hybride is ook mogelijk: root aggregrates worden via repository opgehaald, maar entities mogen zelf ook gebruik maken van repositories (via een interface) Gebruik het VAB voor het vastleggen van business rules en constraints De aggregraties bepalen in grote mate ook het cascading gedrag Probeer unittesten te schrijven voor alle business rules waarbij repositoriesgemocked worden. De unittest op BA niveau testen puur de interactie.
Zie Applying Domain Driven Design & Patterns (Nillson). Ontwerp vanuit het OO-domein en niet vanuit het data model Modelleer je domein model als UML class diagram in het FO om de relaties en business rules in vast te leggen Denk goed na over welke entiteiten een root aggregrates representeren, oftewel, welke entiteiten zijn zelfstandig en tevens ‘parent’ van andere entiteiten. Deze bepalen de locatie van de belangrijkste business rules, versienummering en repository scope Een puur domein model heeft geen kennis van repositories, maar is vaak lastig in gebruik. In Active Record heeft elke entiteit toegang tot een repository en verloopt alle interactie vanuit een BA via de entity. In hybride is ook mogelijk: root aggregrates worden via repository opgehaald, maar entities mogen zelf ook gebruik maken van repositories (via een interface) Gebruik het VAB voor het vastleggen van business rules en constraints De aggregraties bepalen in grote mate ook het cascading gedrag Probeer unittesten te schrijven voor alle business rules waarbij repositoriesgemocked worden. De unittest op BA niveau testen puur de interactie.
BPA’s implementeren de functionaliteit van een service in een 1-op-1 verhouding. BPA’s bepalen de unit-of-work en alles daar binnen wordt in een enkele transactie uitgevoerd. Vaak zijn ze ook de scope van de unit tests (ze testen maximaal een enkele business process). In principe moeten ook de business entities (zie de sheets verderop) geunittest worden en dan kunnen de BPA testen beperkt worden tot b.v.een integratietest. BPA’s gebruiken PrincipalPermission attributen of de Role.IsInRole methode om toegang te controleren. Dit verloopt b.v. via een RoleMembershipProvider.Request en response berichten komen rechtstreeks uit de service interfaces. Dit wijkt af van de standaard architectuur, en introduceert een koppeling tussen BusinessLogic project en de MessageContracts en DataContracts projecten. Maar zou je dit niet doen, dan moet je een additionele vorm van conversie tussen die lagen introduceren. De BPA converteert tussen DTOs en entiteiten m.b.v. Translator classes
Gedistribueerde transacties brengen de schaalbaarheid omlaag en introduceren niet te beïnvloeden koppelingen tussen systemen. De BA moet zorgen dat de inkomende berichten gevalideerd worden zodat gebruikers nooit met ‘interne fouten’ geconfronteerd worden. Overigens mag dit gedelegeerd worden naar het domein model. De data die via DTOs binnenkomt wordt vaak doorgegeven aan een entiteit. Validatie gebeurt dus in principe al in de entiteit. In principe logging bij entry en bij exit. Het niveau (Info v.s. Verbose) is afhankelijk van hoe kritisch de service is. Een BA moet alleen business rules tussen entiteiten controleren. Alle andere logica behoort in het domein model.
Repositories regelen toegang tot de database (vaak via een ORM) en gedragen zich als een object collectie (interface is gebaseerd op die van ICollection).Repositories worden altijd via een interface opgehaald (b.v. via een factory)De scope van de unit-of-work wordt door de BA bepaald en niet door de repositories Idealiter ondersteunt de repository eigenschappen van TransparentPersistency, b.v. lazylaoding van relaties tussen entiteiten en het automatisch flushen van alle wijzigingen binnen een unit-of-work. Verzorgt optimalisaties om de database te ontlasten, zoals b.v. first en second-levelcaches, query caching, e.t.c Zorgt dat technische database-specifieke fouten afgeschermd worden en vervangen door functionele fouten
De meeste ORMs ondersteunen alle gewenste functionaliteit. Ik gebruik Nhibernate en Nhibernate.LINQ Definieer 1 repository voor elke aggregatie root Laat toegang tot repositories altijd verlopen via een interface zodat de repository altijd gemocked kan worden Implementeer Iqueryable (b.v. Nhibernate.LINQ) zodat de aanroepende code LINQ queries kan uitvoeren zonder dat dit performanceproblemen veroorzaken. Gebruik Query Object pattern of Specification om een enorme lijst van FindXXX methodes met verschillende argumenten te voorkomen.
Een service agent zit tussen het domein model of BA en een extern systeem (of subsysteem) en schermt alle technische afhankelijkheden af. Doel? De impact van externe wijzigingen minimaliseren. Ook kan een SA de verschillen tussen interne en externe accounts transparant maken (mapping tussen accounts) zodat single sing-on mogelijk is. Biedt optimalisatie aan zoals caching, retries, auditing, logging, e.t.c. Verzorgt de monitoring en tracing van de interactie met de externe systemen, en kan bijvoorbeeld actief signaleren als bepaalde operaties opvallen lang duren.
Service Agents altijd via interfaces aanroepen om unittesten te kunnen schrijven zonder het externe systeem. Ook toegang tot files of networklocaties en reporting engines zijn ‘extern’ en moeten via service agents verlopen. Aangezien een service agents van nature long-running zijn, moeten die in principe altijd via een WF verlopen. Let op, in de praktijk gebeurt dit niet zo vaak.
Verantwoordelijkheden Op het moment dat een business process langdurig is (meerdere uren, dagen, weken), dan moet dit opgelost worden door een business workflow. Het aanroepen van de bijbehorende service verloopt dan asynchroon.Workflowsorchestreren een logische gedistribueerde transactie over meerdere systemen, maar gebruiken geen echte locking. Transactie’s moeten dus gecompenseerd worden. Ook de communicatie met externe systemen moet in principe via workflows lopen omdat je nooit op externe systemen kunt vertrouwen. Aandachtspunten Tot .NET 3.5 was het erg lastig om de WF runtime te hosten in IIS en te exposen als WCF service, maar met de nieuwe ServiceWorkflowHost is dat beter opgelost. OOTB ondersteunt WF alleen SQL Server, maar er is een CodePlex project met een generieke implementatie voor meerdere databases. In WF is het gebruikelijk om de data die bij de workflow instantie hoort in de workflow op te slaan en zo mee te persisteren in de database. Maar het is beter om een functionele sleutel naar het domein model te gebruiken. Op die manier combineer je state en bedrijfslogica op de juiste manier en voorkom je workflow problemen als het domein model wijzigt.
Autonoom = niet afhankelijk van elkaar Geen gedistribueerde transactie’s, dus geen onnodige locking en dus vertragingen over meerdere databases of systemen Logica in .NET = .NET code in een applicatieserver is schaalbaarder dan een stored procedure in een databaseLoadtestso.b.v. VSTS Load Test of Team Test Load Agent
Ontkoppeld Service Agents om de buitenwereld af te schermen Web services om platformonafhankelijk te zijn Overleg interfaces om zo weinig mogelijk te moeten aanpassen (TDD helpt hier heel goed)
* FxCop en StyleCop hebben in principe niet direct iets met betrouwbaarheid te maken maar zorgen wel voor hoge codekwaliteit en dus minder kans op bugs
Ilities =maintainability, extensibility, testability Geen technische afhankelijkheid vanwege gebruik van ORM