๐๏ธ ๐๐ก๐๐ซ๐ ๐ฒ๐จ๐ฎ๐ซ ๐ญ๐ก๐จ๐ฎ๐ ๐ก๐ญ๐ ๐๐๐จ๐ฎ๐ญ ๐๐๐๐ ? ๐๐๐๐ is a pattern initially articulated by Greg Young. Essentially, it revolves around the idea that updating information can employ a different model than reading information. While this separation can be advantageous in specific scenarios, it's important to be cautious, as, for the majority of systems, implementing CQRS introduces a potentially risky level of complexity. The main idea of CQRS is to introduce a split of the conceptual model into separate models for update and display. Many implementations involve the Mediator Pattern and database duplication in addition. Here's some ๐๐ฒ๐ป๐ฒ๐ณ๐ถ๐ ๐ฎ๐ป๐ฑ ๐ฐ๐ผ๐ป๐๐ถ๐ฑ๐ฒ๐ฟ๐ฎ๐๐ถ๐ผ๐ป ๐ฏ ๐ฆ๐ฐ๐ฎ๐น๐ฎ๐ฏ๐ถ๐น๐ถ๐๐ CQRS allows the read and writes operations to be scaled independently, since they are handled by separate models. This means that read-heavy applications can be scaled more easily without impacting the write operations, and vice versa. ๐ฏ ๐ฃ๐ฒ๐ฟ๐ณ๐ผ๐ฟ๐บ๐ฎ๐ป๐ฐ๐ฒ By optimizing each model for its specific use case, CQRS can lead to significant performance improvements. The query model can be designed for fast data retrieval, while the Command model can be optimized for consistency and durability. ๐ฏ ๐ฆ๐ฒ๐ฝ๐ฎ๐ฟ๐ฎ๐๐ถ๐ผ๐ป ๐ผ๐ณ ๐๐ผ๐ป๐ฐ๐ฒ๐ฟ๐ป๐ CQRS provides a clear separation of concerns, making the codebase easier to understand and maintain. Developers can more easily reason about how changes to the codebase will affect the overall system. ๐ฏ ๐๐น๐ฒ๐ ๐ถ๐ฏ๐ถ๐น๐ถ๐๐ CQRS allows each model to evolve independently, since they are not tightly coupled. This means that changes to one model can be made without impacting the other model. โ ๏ธ ๐๐ป๐ฐ๐ฟ๐ฒ๐ฎ๐๐ฒ๐ฑ ๐๐ผ๐บ๐ฝ๐น๐ฒ๐ ๐ถ๐๐ CQRS can increase the complexity of the application, since there are now two distinct models to maintain. This can lead to a steeper learning curve for developers and a more complex codebase overall. โ ๏ธ ๐๐๐ฒ๐ป๐๐๐ฎ๐น ๐๐ผ๐ป๐๐ถ๐๐๐ฒ๐ป๐ฐ๐ Since the Command and Query models are separate, there may be a delay between when data is written and when it becomes available for reading. This delay is known as eventual consistency and must be accounted for in the application design. โ ๏ธ ๐๐ฎ๐๐ฎ ๐๐๐ฝ๐น๐ถ๐ฐ๐ฎ๐๐ถ๐ผ๐ป Since the Command and Query models are separate, there may be some duplication of data between them. This can lead to increased storage requirements and may require additional effort to keep the data in sync. #cqrs #design #pattern #programming #software #softwareengineering Source : Romain Ottonelli Dabadie
SmartIPlaceโs Post
More Relevant Posts
-
SDET at Infosys | Full Stack.NET Developer | Youtuber | Hustler | An avid learner and obsessive seeker of IT knowledge | I make things.
๐๏ธ ๐๐ก๐๐ซ๐ ๐ฒ๐จ๐ฎ๐ซ ๐ญ๐ก๐จ๐ฎ๐ ๐ก๐ญ๐ ๐๐๐จ๐ฎ๐ญ ๐๐๐๐ ? ๐๐๐๐ is a pattern initially articulated by Greg Young. Essentially, it revolves around the idea that updating information can employ a different model than reading information. While this separation can be advantageous in specific scenarios, it's important to be cautious, as, for the majority of systems, implementing CQRS introduces a potentially risky level of complexity. The main idea of CQRS is to introduce a split of the conceptual model into separate models for update and display. Many implementations involve the Mediator Pattern and database duplication in addition. Here's some ๐๐ฒ๐ป๐ฒ๐ณ๐ถ๐ ๐ฎ๐ป๐ฑ ๐ฐ๐ผ๐ป๐๐ถ๐ฑ๐ฒ๐ฟ๐ฎ๐๐ถ๐ผ๐ป ๐ฏ ๐ฆ๐ฐ๐ฎ๐น๐ฎ๐ฏ๐ถ๐น๐ถ๐๐ CQRS allows the read and writes operations to be scaled independently, since they are handled by separate models. This means that read-heavy applications can be scaled more easily without impacting the write operations, and vice versa. ๐ฏ ๐ฃ๐ฒ๐ฟ๐ณ๐ผ๐ฟ๐บ๐ฎ๐ป๐ฐ๐ฒ By optimizing each model for its specific use case, CQRS can lead to significant performance improvements. The query model can be designed for fast data retrieval, while the Command model can be optimized for consistency and durability. ๐ฏ ๐ฆ๐ฒ๐ฝ๐ฎ๐ฟ๐ฎ๐๐ถ๐ผ๐ป ๐ผ๐ณ ๐๐ผ๐ป๐ฐ๐ฒ๐ฟ๐ป๐ CQRS provides a clear separation of concerns, making the codebase easier to understand and maintain. Developers can more easily reason about how changes to the codebase will affect the overall system. ๐ฏ ๐๐น๐ฒ๐ ๐ถ๐ฏ๐ถ๐น๐ถ๐๐ CQRS allows each model to evolve independently, since they are not tightly coupled. This means that changes to one model can be made without impacting the other model. โ ๏ธ ๐๐ป๐ฐ๐ฟ๐ฒ๐ฎ๐๐ฒ๐ฑ ๐๐ผ๐บ๐ฝ๐น๐ฒ๐ ๐ถ๐๐ CQRS can increase the complexity of the application, since there are now two distinct models to maintain. This can lead to a steeper learning curve for developers and a more complex codebase overall. โ ๏ธ ๐๐๐ฒ๐ป๐๐๐ฎ๐น ๐๐ผ๐ป๐๐ถ๐๐๐ฒ๐ป๐ฐ๐ Since the Command and Query models are separate, there may be a delay between when data is written and when it becomes available for reading. This delay is known as eventual consistency and must be accounted for in the application design. โ ๏ธ ๐๐ฎ๐๐ฎ ๐๐๐ฝ๐น๐ถ๐ฐ๐ฎ๐๐ถ๐ผ๐ป Since the Command and Query models are separate, there may be some duplication of data between them. This can lead to increased storage requirements and may require additional effort to keep the data in sync. #cqrs #design #pattern #programming #software #softwareengineering ___________ If you found this post helpful ๐ Like ๐ Repost ๐
To view or add a comment, sign in
-
๐๏ธ ๐๐ก๐๐ซ๐ ๐ฒ๐จ๐ฎ๐ซ ๐ญ๐ก๐จ๐ฎ๐ ๐ก๐ญ๐ ๐๐๐จ๐ฎ๐ญ ๐๐๐๐ ? CQRS is an intriguing pattern I often saw misuse or misunderstood, let's streamline the concept. ๐๐๐๐ is a pattern initially articulated by Greg Young. Essentially, it revolves around the idea that updating information can employ a different model than reading information. While this separation can be advantageous in specific scenarios, it's important to be cautious, as, for the majority of systems, implementing CQRS introduces a potentially risky level of complexity. The main idea of CQRS is to introduce a split of the conceptual model into separate models for update and display. Many implementations involve the Mediator Pattern and database duplication in addition. Here's some ๐๐ฒ๐ป๐ฒ๐ณ๐ถ๐ ๐ฎ๐ป๐ฑ ๐ฐ๐ผ๐ป๐๐ถ๐ฑ๐ฒ๐ฟ๐ฎ๐๐ถ๐ผ๐ป ๐ฏ ๐ฆ๐ฐ๐ฎ๐น๐ฎ๐ฏ๐ถ๐น๐ถ๐๐ CQRS allows the read and writes operations to be scaled independently, since they are handled by separate models. This means that read-heavy applications can be scaled more easily without impacting the write operations, and vice versa. ๐ฏ ๐ฃ๐ฒ๐ฟ๐ณ๐ผ๐ฟ๐บ๐ฎ๐ป๐ฐ๐ฒ By optimizing each model for its specific use case, CQRS can lead to significant performance improvements. The query model can be designed for fast data retrieval, while the Command model can be optimized for consistency and durability. ๐ฏ ๐ฆ๐ฒ๐ฝ๐ฎ๐ฟ๐ฎ๐๐ถ๐ผ๐ป ๐ผ๐ณ ๐๐ผ๐ป๐ฐ๐ฒ๐ฟ๐ป๐ CQRS provides a clear separation of concerns, making the codebase easier to understand and maintain. Developers can more easily reason about how changes to the codebase will affect the overall system. ๐ฏ ๐๐น๐ฒ๐ ๐ถ๐ฏ๐ถ๐น๐ถ๐๐ CQRS allows each model to evolve independently, since they are not tightly coupled. This means that changes to one model can be made without impacting the other model. โ ๏ธ ๐๐ป๐ฐ๐ฟ๐ฒ๐ฎ๐๐ฒ๐ฑ ๐๐ผ๐บ๐ฝ๐น๐ฒ๐ ๐ถ๐๐ CQRS can increase the complexity of the application, since there are now two distinct models to maintain. This can lead to a steeper learning curve for developers and a more complex codebase overall. โ ๏ธ ๐๐๐ฒ๐ป๐๐๐ฎ๐น ๐๐ผ๐ป๐๐ถ๐๐๐ฒ๐ป๐ฐ๐ Since the Command and Query models are separate, there may be a delay between when data is written and when it becomes available for reading. This delay is known as eventual consistency and must be accounted for in the application design. โ ๏ธ ๐๐ฎ๐๐ฎ ๐๐๐ฝ๐น๐ถ๐ฐ๐ฎ๐๐ถ๐ผ๐ป Since the Command and Query models are separate, there may be some duplication of data between them. This can lead to increased storage requirements and may require additional effort to keep the data in sync. #cqrs #design #pattern #programming #software #softwareengineering
To view or add a comment, sign in
-
Senior Software Engineer | Backend | Full Stack | Java | C# | Go | Python | TypeScript | JavaScript | ABAP
๐ก๐ A Software Engineering Pill from Marcelo ๐ปโจ ๐ CQRS is an architectural pattern that separates read and write operations into different models. This approach can greatly enhance performance, scalability, and security in your applications. ๐ Key Characteristics of CQRS: ๐งฉ Separation of Concerns: CQRS splits the operations for reading data (queries) and modifying data (commands) into separate models. This separation allows for more fine-tuned optimization of each operation. ๐ Scalability: Since the read and write models are separated, you can scale them independently. This is particularly useful for applications with high read or write loads. ๐ ๏ธ Flexibility: The read model can be optimized for queries, while the write model can be focused on consistency and validation. This separation also allows for different data storage technologies for reads and writes. ๐ Improved Security: By having separate models, you can apply different security measures for read and write operations, ensuring a more robust security posture. ๐ Here's a simple example demonstrating the CQRS pattern in Go: package main import ( "fmt" ) // Command model for updating financial plans type FinancialPlanCommand struct { UserIDย ย int PlanName string Amountย ย float64 } func (fpc *FinancialPlanCommand) Execute() { fmt.Printf("Updating financial plan for user %d: %s with amount $%.2f\n", fpc.UserID, fpc.PlanName, fpc.Amount) // logic to write data to the database } // Query model for retrieving financial plans type FinancialPlanQuery struct { UserID int } func (fpq *FinancialPlanQuery) Execute() { fmt.Printf("Fetching financial plans for user %d\n", fpq.UserID) // logic to read data from the database } func main() { // Example usage cmd := &FinancialPlanCommand{UserID: 1, PlanName: "Retirement Fund", Amount: 10000.00} cmd.Execute() query := &FinancialPlanQuery{UserID: 1} query.Execute() } ๐ฏ CQRS is a powerful pattern that can help you design more efficient and scalable systems by clearly separating read and write concerns. Implementing CQRS in your projects can lead to better performance, enhanced scalability, and improved security. #CQRS #SoftwareArchitecture #Go #SoftwareDevelopment #SoftwareEngineering
To view or add a comment, sign in
-
๐๏ธ ๐๐ก๐๐ซ๐ ๐ฒ๐จ๐ฎ๐ซ ๐ญ๐ก๐จ๐ฎ๐ ๐ก๐ญ๐ ๐๐๐จ๐ฎ๐ญ ๐๐๐๐ ? ๐๐๐๐ is a pattern initially articulated by Greg Young. Essentially, it revolves around the idea that updating information can employ a different model than reading information. While this separation can be advantageous in specific scenarios, it's important to be cautious, as, for the majority of systems, implementing CQRS introduces a potentially risky level of complexity. The main idea of CQRS is to introduce a split of the conceptual model into separate models for update and display. Many implementations involve the Mediator Pattern and database duplication in addition. Here's some ๐๐ฒ๐ป๐ฒ๐ณ๐ถ๐ ๐ฎ๐ป๐ฑ ๐ฐ๐ผ๐ป๐๐ถ๐ฑ๐ฒ๐ฟ๐ฎ๐๐ถ๐ผ๐ป ๐ฏ ๐ฆ๐ฐ๐ฎ๐น๐ฎ๐ฏ๐ถ๐น๐ถ๐๐ CQRS allows the read and writes operations to be scaled independently, since they are handled by separate models. This means that read-heavy applications can be scaled more easily without impacting the write operations, and vice versa. ๐ฏ ๐ฃ๐ฒ๐ฟ๐ณ๐ผ๐ฟ๐บ๐ฎ๐ป๐ฐ๐ฒ By optimizing each model for its specific use case, CQRS can lead to significant performance improvements. The query model can be designed for fast data retrieval, while the Command model can be optimized for consistency and durability. ๐ฏ ๐ฆ๐ฒ๐ฝ๐ฎ๐ฟ๐ฎ๐๐ถ๐ผ๐ป ๐ผ๐ณ ๐๐ผ๐ป๐ฐ๐ฒ๐ฟ๐ป๐ CQRS provides a clear separation of concerns, making the codebase easier to understand and maintain. Developers can more easily reason about how changes to the codebase will affect the overall system. ๐ฏ ๐๐น๐ฒ๐ ๐ถ๐ฏ๐ถ๐น๐ถ๐๐ CQRS allows each model to evolve independently, since they are not tightly coupled. This means that changes to one model can be made without impacting the other model. โ ๏ธ ๐๐ป๐ฐ๐ฟ๐ฒ๐ฎ๐๐ฒ๐ฑ ๐๐ผ๐บ๐ฝ๐น๐ฒ๐ ๐ถ๐๐ CQRS can increase the complexity of the application, since there are now two distinct models to maintain. This can lead to a steeper learning curve for developers and a more complex codebase overall. โ ๏ธ ๐๐๐ฒ๐ป๐๐๐ฎ๐น ๐๐ผ๐ป๐๐ถ๐๐๐ฒ๐ป๐ฐ๐ Since the Command and Query models are separate, there may be a delay between when data is written and when it becomes available for reading. This delay is known as eventual consistency and must be accounted for in the application design. โ ๏ธ ๐๐ฎ๐๐ฎ ๐๐๐ฝ๐น๐ถ๐ฐ๐ฎ๐๐ถ๐ผ๐ป Since the Command and Query models are separate, there may be some duplication of data between them. This can lead to increased storage requirements and may require additional effort to keep the data in sync. #cqrs #design #pattern #programming #software #softwareengineering ___________ If you found this post helpful ๐ Like ๐ Repost ๐ Follow :ย Romain Ottonelli Dabadie Stay tuned ๐
To view or add a comment, sign in
-
๐ Excited to share my latest article on Medium about "CQRS, Repository, and MediatR" in software development! In this piece, I delve into the effective design practices of CQRS (Command and Query Responsibility Segregation), exploring how it enhances code structure and facilitates maintenance and scalability. The article provides insights into the Repository pattern and the MediatR library in the .NET environment, showcasing their roles in implementing CQRS principles. ๐ Discover how these methodologies can transform your approach to building complex, efficient software architectures. Read the full article here: https://lnkd.in/ddtxDieH Subscribe for more: https://lnkd.in/dTKy_B8S https://t.me/SharpAssembly #SoftwareDevelopment #CQRS #MediatR #DDD #InWestMan
To view or add a comment, sign in
-
I had an interesting question about serializing the complex domain model - I receive such questions almost daily. So, I gave my default answer which is: You don't serialize the domain model; it's not meant for that! It's purpose is to model the business rules, and the business data are of secondary interest to it. But now, this commenter today went a step further and it eventually came that by "serialization" he appears to mean "persistence". I guess it is some form of document persistence, which boils down to persisting the serialized model. When that is the case, then my extended answer is that you still wouldn't serialize the full domain model, because of a few unpleasant consequences if you do: - It must remain the same in the long term, which is almost impossible; - It would be needlessly complex for the data it contains; - Object mappers might require too much configuration to work; - Some data might be private and inaccessible to the mapper; - Deserialization might require a protocol; etc. Either way, I think the most one should do is to produce a DTO out of the model and then leave transforms and JSON to the infrastructural code. The trick is in understanding that infrastructural code is by definition not burdened with domain rules. Now, I'd like to hear your opinions on this topic. It is a very important part of software development, so please add your thoughts especially if you think I forgot to cover some angle.
To view or add a comment, sign in
-
Today, I'm sharing a piece of a real project Iโm currently developing, which is heading into production soon! ๐ฏ ๐จ๐ป What is the Repository Pattern? The Repository Pattern is a way to abstract the data access layer. Encapsulating the logic for fetching and persisting dataย simplifies future changes and promotes code reusability. ๐ก Why am I using it in production? - Separation of Concerns: It separates the business logic from data access, allowing cleaner code and easier testing. - Flexibility: Want to swap out your database? No problem! By using repositories, your code interacts with interfaces, not implementations. - Transaction Control: In the future, the transactions in this project are expected to become complex. By using the Repository Pattern in conjunction with the Unit of Work pattern, I will have more control over these operations, ensuring atomicity and consistency across multiple repositories. - Easier Testing: By mocking the repository in tests, you can focus on testing your business logic without relying on the actual database. - CQRS Implementation: The class shown is named WriteMemberRepository because it handles the write operations in my CQRS pattern setup. There is also a ReadMemberRepository that reads data from a NoSQL database, ensuring optimized and separated read/write operations. In the image (at the end), Iโm implementing a WriteMemberRepository using Clean Architecture principles for this production-ready project. Notice how I am keeping operations like Create, Delete, and Update isolated in this repository class. This setup ensures that my applicationโs business logic remains decoupled from the database access details. Here's a quick breakdown of the repository's key methods: - Create: Adds a new member to the database. - Delete: Removes a member. - Update: Updates an existing memberโs information. By leveraging these patterns, my project will stay agile and adaptable to future requirements, ensuring long-term maintainability while keeping transaction complexity manageable and well-controlled. ๐ As I continue working on this project, Iโll be sure to share more insights and patterns I find interesting with the community. Stay tuned for more updates! Are you also using the Repository and Unit of Work patterns in your projects? Letโs discuss how these patterns help improve software architecture! ๐ฌ #CleanArchitecture #RepositoryPattern #UnitOfWork #CQRS #CodeQuality #SoftwareEngineering #SOLIDPrinciples #dotnet #EntityFramework #ProductionReady
To view or add a comment, sign in
-
-
Back End Developer Asp core & Senior SQL Server DBA & Developer | Replication |Backup & Recovery | Query Optimization | Committed to optimizing database performance and scalability
Doing CQRS+ES the wrong way is easy. CQRS stands for command query responsibility segregation and it is a way of separating reads from a database from writes to it. ES stands for event sourcing. Together they offer some technical opportunities: * put the business logic on the write path, resulting in a less diluted domain model * optimize the read path for speed * using caches and cache invalidation becomes easier What often happens though is that the development team makes the events (for ES) too fine grained. Example of a fine grained event stream: * LastNameChanged * StreetChanged * StreetNumberChanged * AddressAdditionChanged What is actually happening when those database fields have changed? Where is the business value? The answer: nowhere. What you need to do instead is to apply systems thinking, or like I call it - use-case thinking. And issue only one appropriate event, or multiple appropriate events in case of use-case composition. Example of a better event stream: * ProspectiveCustomerMarried And from there, the event can be picked up and acted on according to business needs. This kind of thinking leads to many benefits: * a crisper, less diluted domain model * a domain model that is easier to test * simpler code, which is easier to understand It also leads to better products because you foster product thinking also in the minds of the developers, but that's just one of the side effects. I want to clarify: sometimes really just the street number changes, because the user mistyped his address upon registration. The point is: the business needs to send a selection of baby products to potential new mothers, not to anyone making typos. By focusing more on business needs, you end up with a better architecture, simpler code, systems thinking and an overall better product. Advice: talk to and empathize more with the "devil", the business people. You gain an important tool - systems thinking - a tool you can use to grow your technical prowess. #domaindrivendesign #softwarearchitecture #cqrs #microservices #testdrivendevelopment
To view or add a comment, sign in
-
-
One of the Most Followed Voices in AI/ML/Data (60K+)| Developer Evangelist | Tech Content Creator | 26k Newsletter Subscribers
It is hard to build a #CI workflow for #MachineLearning projects. There are some key challenges..BUT...It is possible. Unlike traditional software, ML applications do not only impact by a change in the code but also the data on which the model is trained. Another key challenge is regarding quality control. In software projects, the unit/integration/regression tests ensure whether a change is safe to be integrated and delivered. If all tests are passed, it does, otherwise, it doesnโt. This isnโt suitable with an ML model due to several reasons. First, the mapping between input and output can be dynamic as some types of ML models have a non-deterministic behavior. Second, the input of ML models could be in an extremely complicated format such as a high-dimensional vector or an image. Generating the input like the way developers normally do when they write tests will be very inefficient and exhausting(if possible). Well, for data versioning, there are open-source tools available that can be used. One the author suggested is Data Version Control(DVC). The quality control is trickier because it isnโt a passed-or-failed question anymore. But keeping everything in mind, here is a proposed CI pipeline for ML applications. โค Developer branches out from main. โค Developer makes changes and runs experiments on a local machine(or a remote server) until get the desired result. โค Developer creates a PR targeting the main branch. โค CI server re-runs the experiment branch to ensure reproducibility. โค CI server compares the performance metrics with the main branch and reports back to the PR page on GitHub so other members can review it. โค If approved, the code is then merged to main. โค CI server reruns the experiment again but this time the model is pushed to the remote storage for future deployment as well as a performance report for comparison. Read the full article here: https://lnkd.in/gh3svbg5
To view or add a comment, sign in
-
-
"Doing CQRS the wrong way is easy" proceed to misunderstand CQRS completely. CQRS is about something other than databases, despite being a fundamentally shared misunderstanding across the industry. You can still do CQRS with the same database. CQRS is not a system design concern. CQRS is about data modeling and data structures if you wish. Does CQRS play well with Event-sourced systems? Most definitely. But because I am a good driver, it doesn't make me a car! Two completely different things that play nice together, but they are not required to go along. #KnowledgeIsNotUnderstanding
Doing CQRS+ES the wrong way is easy. CQRS stands for command query responsability segregation and it is a way of separating reads from a database from writes to it. ES stands for event sourcing. Together they offer some technical opportunities: * put the business logic on the write path, resulting in a less diluted domain model * optimize the read path for speed * using caches and cache invalidation becomes easier What often happens though is that the development team makes the events (for ES) too fine grained. Example of a fine grained event stream: * LastNameChanged * StreetChanged * StreetNumberChanged * AddressAdditionChanged What is actually happening when those database fields have changed? Where is the business value? The answer: nowhere. What you need to do instead is to apply systems thinking, or like I call it - use-case thinking. And issue only one appropriate event, or multiple appropriate events in case of use-case composition. Example of a better event stream: * ProspectiveCustomerMarried And from there, the event can be picked up and acted on according to business needs. This kind of thinking leads to many benefits: * a crisper, less diluted domain model * a domain model that is easier to test * simpler code, which is easier to understand It also leads to better products because you foster product thinking also in the minds of the developers, but that's just one of the side effects. I want to clarify: sometimes really just the street number changes, because the user mistyped his address upon registration. The point is: the business needs to send a selection of baby products to potential new mothers, not to anyone making typos. By focusing more on business needs, you end up with a better architecture, simpler code, systems thinking and an overall better product. Advice: talk to and empathize more with the "devil", the business people. You gain an important tool - systems thinking - a tool you can use to grow your technical prowess. #domaindrivendesign #softwarearchitecture #cqrs #microservices #testdrivendevelopment
To view or add a comment, sign in
๐ช Proud husband & dad | ๐ป Software Engineer | .NET Enthusiast
7moThanks for sharing