Communication between Bounded Contexts - winforms

I have a WinForms application that I am hopefully going to be refactoring to be utilizing a DDD architecture. First, I am trying to really wrap my head around the architecture itself, I have Evans' book and I have Vernon's book and I find myself struggling with three scenarios I would face rather immediately in my application. I am afraid I might be over thinking or being too strict in my conceptual design process.
1.) Utilizing an example provided inside a Pluralsight tutorial on DDD the speaker made a point that different bounded contexts should be represented by their own solution. However, if I have a winforms app that is not service oriented (this will eventually change and a lot of this question becomes moot) this doesn't seem feasible. I am therefore operating under the assumption I'll be separating these into different projects/namespaces being vigilant there are no interdependencies. Is this the right way to think about it or am I missing something obvious?
2.) I have a navigation UI that launches other modules/windows that would belong in separate presentation layers of different bounded contexts. Think of the first window that would be open when you launched an ERP application. Since this doesn't fit cleanly within any particular BC how would something like this be properly implemented. Should this fall within a shared kernel?
3.) I have a Job Management bounded context and a Rating/Costing bounded context. It is part of the business process that when a Job is created its details are then rated. This has its own UI, etc, which I feel pretty good that this presentation still adequately falls inside the Job Management context. However, the actual rating process of these details definitely should not. I am not entirely sure how to communicate with the Rating/Costing context since bc's are to be kept separate from one another. I realize I could do messaging, but that seems to be overkill for a non distributed app. Each BC could feasibly self host some kind of API but again this seems overkill, although this would set the team up nicely for migrating to a distributed architecture later on. Finally, my last idea is having some kind of shared dependency that is an event store of sorts. I don't know if this is the same as Domain Events as those seem to have a separate concern in and of themselves. So, does that mean this would fall under a shared kernel as well or some other type of solution?
Thank you in advance.

1) Guidance about BCs corresponding to solution is only guidance, not a hard rule. However, it does provide much needed isolation. You can still have this with a WinForms project. For example, suppose you have a BC called Customers. Create a solution for it and within it, create an additional project called Customers.Contracts. This project effectively houses the public contract of the BC which consists of DTOs, commands and events. External BCs should be able to communicate with the Customers BC using only the messages defined in this contracts project. Have the WinForms solution reference Customers.Contracts and not the Customers project.
2) A UI often serves a composing role, orchestrating many BCs - a composite UI. A stereotypical example is the Amazon product page. Hundreds of services from different BCs are required to render the page.
3) Again this seems like a scenario calling for a composite UI. The presentation layer can mediate between different BCs. BCs are loosely coupled, but there still are relationships between BCs. Some are downstream from others, some are upstream, or even both. Each has an anti-corruption layer, a port, to integrate with related BCs.

The feeling I get from these questions can be summarized as: "What is a sane approach to BC boundaries from a code artifact perspective? and How do I build a UI that both queries and commands several BCs?". It depends ...
Another, not yet mentioned approach could be to regard the UI as a seperate context. I doubt it's a very popular POV, but it can be useful at times. The UI could dictate what it needs using e.g. its own interfaces and data structures, and have each BC implement the appropriate interfaces (doing an internal translation). The downside is the extra translation going on, but then again it only makes sense when there is sufficient value to be reaped. The value is in keeping things simple on the UI side and not having to worry how and where the data is coming from or how changes affect each BC. That can all be handled behind a simple facade. There are several places this facade could sit (on the client or on the server). Don't be fooled though, the "complexity" has just moved behind yet another layer. Coordination and hard work still needs to be done.
Alternatively you may also want to look into what I call "alignment" of a UI with use cases exposed by a BC. As Tom mentioned, workflow or saga implementations might come in handy to pull this off when coordination is required. Questioning the consistency requirements (when does this other BC need to know about given information?) might bring new insight into how BCs interoperate. You see, a UI is a very useful feedback loop. When it's not aligned with a BC's use case maybe there is something wrong with the use case or maybe there is something wrong with how it was designed in the UI or maybe we just uncovered a different use case. That is why UI mockups make such a great tool for having discussions. They offer an EXTRA view on the same problem/solution. Extra as in "this is not the only visualization you should use in conversations with a domain expert". UX requirements are requirements too. They should be catered for.
Personally I find that when I'm discussing UI I'm wearing another hat than when I'm discussing pure functionality (you know, things that don't require a UI to explain what the application is doing/should do). I might switch hats during the same conversation just to find out malalignment.

First things first, as I saw you talking about a message bus, I think we need to talk about BC integration first.
You do not need a message bus to communicate between BC's; here is an explanation on how I integrate different BC's:
I expose some public interfaces on each BC (similar to domain commands, - queries and - events), and have an intermediate layer in my infrastructure that translates this call to the other BC.
Here is an example interface for exposed commands in a BC:
public interface IHandleCommands
{
void DoSomething(Guid SomeId,string SomeName);
}
I also have a similar one for exposed events
public interface IPublishEvents
{
void SomethingHappened(Guid SomeId,string SomeName);
}
Finally for my exposed data (i.e. the Queries in CQ(R)S) I have another interface, please note that this allows you to remove coupling between your domain model and query code at any given time.
public interface IQueryState
{
IEnumerable<SomeData> ActiveData(DateTime From=DateTime.Minvalue, ... );
}
And my implementation looks like this:
public class SomeAR:IHandleCommands
{
IPublishEvents Bus;
public SomeAr(IPublishEvents Bus)
{
this.Bus = Bus;
}
public void DoSomething(Guid x,string y)
{
Bus.SomethingHappened(SomeId: x,SomeName: y);
}
}
After all, when you think about it: things like domain events can be done without the messaging as well; just replace the message classes by interface members, and replace the handlers by interface implementations that get injected into your BC.
These handlers then invoke commands on other BC's; they are like the glue that bind together different BC's (think workflows/stateless saga's etc).
This could be an example handler:
public class WorkFlow : IPublishEvents
{
public void SomethingHappened(Guid SomeId,string SomeName)
{
AnotherBC.DoSomething(SomeId,SomeName);
}
}
This is an easy approach that does not require a lot of effort, and I have used this with great success. If you want to switch to full-blown messaging later on, it should be easy to do.
To answer your questions about the UI:
I think you are being too rigid about this.
As long as my domain is (or can be easily) decoupled from your UI, you can easily start with a single UI project, and then split it up the minute you start experiencing pain somewhere. However, if you do split up code, you should split it up per BC, so project structures match.
I find building a UI this way to be the most efficient way for me...

Related

Clean Architecture: Sequence Flow Among Frameworks

I have been trying to learn more about Uncle Bob's Clean Architecture from blogs, article, and videos.
If I were to use a database in this architecture, then what should the UI (as a framework such as web or form) know about the database? Or more generally, how should data flow between two or more pieces/parts that are in the same layer?
For example, The UI would talk to my adapter(s)/gateway(s) to interact with the business entities. To Read/Write, I can see that the UI could call whatever class/classes that can access the database and pass in the adapter(s)/gateway(s), so that it can interact with the business entities.
public class SomeUI
{
public static void Main(string[] args)
{
SomeAdapter adapter = new SomeAdapter();
SomeDataAccess db = new SomeDataAccess();
db.Save(adapter);
}
}
public class SomeDataAccess
{
public void Save(SomeAdapter adapter)
{
//Interact with database
}
}
public class SomeAdapter
{
//properties
}
Many of the articles barely vary off of this one (https://subvisual.co/blog/posts/20-clean-architecture). I have not found a good article that covers how pieces that are in the same layer should work with each other. So, articles referring to that would be an acceptable answer.
This does not appear to violate the Dependency Rule, but it feels like I am not doing something right, since I am making a dependency between my UI and database. I believe that I may be over-thinking the concept, and I believe it may be from hammering away at learning the 3-tier architecture (UI -> BLL -> DAL).
You ask:
If I were to use a database in this architecture, then what should the UI (as a framework such as web or form) know about the database? Or more generally, how should data flow between two or more pieces/parts that are in the same layer?
There is no such term as UI component in Clean Architecture. In Clean Architecture terms, the UI would be the presentation layer or the delivery mechanism, decomposed in the following components:
The view model generator (or the presenter to use Uncle Bob's terms), which is in charge of encapsulating the business rules for the UI. This should access the business model in order to generate the view model from it. The business model is passed to the presenter's method inside the interactor response object by its caller, the interactor.
The view model which holds data for the view and passed to the view indirectly via for example an event.
The dumb view which is now decoupled from the domain model and all layers, displays data of the view model.
Decomposing that this way insures better testability, better SRP and more decoupling with application, domain and infrastructure layers.
So your presentation layer should know absolutely nothing about the infrastructure layer.
Maybe you got confused by examples using some kind of Web Form component/library? This kind of component propose interconnected functionalities each in relation with several architecture layers: domain, application and presentation… So Web Form components are particularly delicate to adapt satisfactory in a Clean Architecture. Due to this inflexibility, I'm still struggling figuring out what is the best way to integrate a Web Form component in my Clean Architecture implementations...
Finally, to make it clear, you said:
For example, The UI would talk to my adapter(s)/gateway(s) to interact with the business entities. To Read/Write, I can see that the UI could call whatever class/classes that can access the database and pass in the adapter(s)/gateway(s), so that it can interact with the business entities.
It's not UI's responsibility to interact with your entities but as its name suggest it's interactor's responsibility (interactor = use case). Interactor are meant to encapsulate application business rules, they represent the application layer. They can CRUD your entities via the Entity Gateway which is your adapter to the infrastructure layer which could be an ORM, a REST API or whatever...
Edit #1:
Since a picture worth a thousand words here is Uncle Bob's UML class diagram representing the structure (and the data flow between the concerned components) of the Clean Architecture:
Edit #2:
It seems to me that your representation of the flow of control in a Clean Architecture is kind of reversed. Taking as reference the above diagram and Uncle Bob's analogy:
If you don't want your code to be dependent of a thing, make this thing a plugin.
(Said otherwise, make that thing the client of your code that you want independent from it.)
In a Clean Architecture, you want the presentation layer, or more contextually, the delivery mechanism (Controller + Presenter + ViewModel + View) to be a plugin of your business layer (which is composed of components on the right side of the communication channel boundary).
I have been doing more research into other examples of clean architecture.
(source).
From the diagram above, it looks like App (business entities and use cases) talks back and forth with Delivery (Externals: UI). The Delivery is used to talk to External (Externals: DAL).
Delivery is where you implement the delivery mechanism of your application itself. Delivery is where your app is integrated with external data sources and shown to the user. This means in simplest terms the UI, but it also means creating concrete versions of the external objects, such as data jacks, and also calling the actions of the app itself.
-Retro Mocha
So, that leads me to believe that yes the code example at the top is valid, but I am still open to hear if anyone else has more to provide on the answer.

How can I avoid first retrieving aggregate root for optimizations in DDD friendly way?

I have written an application and tried to use DDD as far as possible. I have run into a problem that I am not sure how to address. Most of the system is driven through users via a web front end, the volume of requests that the application is pretty low and quite CRUDy in nature. However there is one part of the system that integrate into other online systems and the volume of requests will be substantial. We already know from previous experience that we have to streamline this as much as possible.
The scenario is that we want to add create an entity if it doesn't exist but add to the aggregate root if it does exist.
var foo = fooRepo.Get(id);
if (foo != null)
{
foo.Bars.Add(new Bar("hello"));
fooRepo.Add(foo);
}
else
{
var foo = new Foo();
foo.Bars.Add(new Bar("hello"));
fooRepo.Add(fooo);
}
If the action is initiated by a user we don't mind because it is low volume. But the system generated ones it is an extra trip to the DB to determine if it exists. We have already determined that this is a bottle neck for us.
How do I do the above in a DDD way but avoiding the extra trip to the database. I started looking into CQRS because I thought that part of the pattern was to not have repositories so that I could execute commands. But I see that most CQRS examples still use repos and in most examples are still performing get operations for the aggregate roots and then manipulating them and then saving them back.
Clearly repositories don't work in my scenario because I can't treat the problem like an in memory collection of items. (In fact there is just way to much data to even cache everything). Best thing for performance is a straight write to the DB.
Is there anything that can be done in this scenario? Or should I just code an exception?
You could have a FooRepository.AddOrUpdate(foo, bar) method implemented as a direct INSERT INTO ... IF NOT EXISTS or MERGE INTO SQL statement if the extra round-trip is really a concern (which I'm not really sure why it would).
ETL or mass import processes rarely obey the same rules or go through the same layers as UI-based ones. The Application layer will typically be a separate one, and you might even want to bypass the Domain layer in some cases.
It could be a good idea to think about this second input flow in terms of transactions (do these system generated changes come in batches or units, do you want to isolate them the same way you isolate two concurrent end user transactions, etc.?) and create a specific Application layer based on that.
If it turns out that even like this you're too constrained by your aggregate design, you might want to short circuit the domain layer altogether.

How can i do Error Handling in a MVC/MVVM Windows Form app

i'm building an application using a pattern similar to the MVC. The situation is the next: in the context of the model making changes to the associated repository. If the change throw an exception what is the correct way to present the information about the error to the user?
In the previous version of my program when i have spaguetti code organization (model, view, controller overlaped), launching a messagebox telling the user about the error wasn't weird because i was doing almost everything from the views. Now in this new version i want to do the things correctly, so i guess that is bad doing anything that has a visual representation in the model layer.
Some time ago i ask what is the correct way to capture exceptions. The specific point i was refering was to scale up exceptions from an inner code to an upper layer vs capture them in the most upper layer. Almost all the response were that isnt a good approach scale exceptions(capture and throwing again to be captured by a responsable entity), and is better to capture in the most upper layer.
So i have this conflict in my head. I was thinking that is inevitable to maintain the separation of concerns to scale up, but that is in conflict with those previous advices.
How can i proceed?
A common pattern is to have a generic place to put errors in your existing model.
One easy way to do this is to have your model classes all inherit from a base model class that has a property of type IEnumerable<ErrorBase>, or some other type of your choosing.
Then, in your presenter, you can check the error collection and display as necessary.
As far as having exceptions bubble up, the approach I use (almost regardless of what type of application I'm building) is to only handle exceptions at lower levels if you are going to do some special logging (like logging important local variables), or if you can do something intelligent with that exception. Otherwise, let it bubble.
At the layer right before your presenter (or web service class, or whatever), that's when you can capture your exceptions, do general logging, and wrap them (or replace them with) a "sanitized" exception. In the case of the UI, you just make sure you don't reveal sensitive data and perhaps display a friendly message if possible. For web services, you turn these into some kind of fault. Etc.
The upper most layers aren't "responsible" for the bubbled exceptions, they're simply responsible for making sure those don't show up to the end users (or web service client, or whatever) it a form you don't want them to... in other words, you're "presenting" them appropriately.
Remember, separation of concerns is a paradigm that you should follow as a rule of thumb, not an edict that owns all. Just like leaky abstractions, there are leaky paradigms. Do what makes sense and don't worry about it too much. :)

How to do logging with WPF?

I'm writing a WPF application using a MVVM pattern and using Prism in selected places for loose coupling, and I'd like to have logging messages shown in a window and written to a file. The subset of messages going each way may not be the same.
I think I should publish a message through the EventAggregator (MS-Prism implementation of observer pattern) and have two objects subscribe: one that updates the LogWindowViewModel and one that logs using the Enterprise Library logger. Is this a good idea or am I duplicating something that's already implemented?
The fact that the log message will be different in each output is the limiting factor.
Extending the block may suffice and defining a CustomTraceListener or ILogFilter may work out for you. This would avoid needing to use the EventAggregator.
It boils down to who has the knowledge of what and where to log. Are the differences driven off values within the logging engine such as severity? Are they instead driven by the consumer of the logging engine and therefore tightly coupled to the class itself? These types of questions will dictate your choice.
Leveraging the extension points in the logging block would be my first choice before having to rely on using the EventAggregator.
I think an idea is fine. There is not so much functionality to be duplicated it seems
I used Common.Logging as data collector, filter and distributor for something comparable and wrote a custom appender for my own processing and ui-output.

Using VCL for the web (intraweb) as a trick for adding web interface to a legacy non-tiered (2 tiers) Delphi win32 application does make sense?

My team is maintaining a huge Client Server win32 Delphi application. It is a client/server application (Thick client) that uses DevArt (SDAC) components to connect to SQL Server.
The business logic is often "trapped" in Component's event handlers, anyway with some degree of refactoring it is doable to move the business logic in common units (a big part of this work has already been done during refactoring... Maintaing legacy applications someone else wrote is very frustrating, but this is a very common job).
Now there is the request of a web interface, I have several options of course, in this question i want to focus on the VCL for the web (intraweb) option.
The idea is to use the common code (the same pas files) for both the client/server application and the web application. I heard of many people that moved legacy apps from delphi to intraweb, but here I am trying to keep the Thick client too.
The idea is to use common code, may be with some compiler directives to write specific code:
{$IFDEF CLIENTSERVER}
{here goes the thick client specific code}
{$ELSE}
{here goes the Intraweb specific code}
{$ENDIF}
Then another problem is the "migration plan", let's say I have 300 features and on the first release I will have only 50 of them available in the web application. How to keep track of it? I was thinking of (ab)using Delphi interfaces to handle this. For example for the User Authentication I could move all the related code in a procedure and declare an interface like:
type
IUserAuthentication= interface['{0D57624C-CDDE-458B-A36C-436AE465B477}']
procedure UserAuthentication;
end;
In this way as I implement the IUserAuthentication interface in both the applications (Thick Client and Intraweb) I know that That feature has been "ported" to the web. Anyway I don't know if this approach makes sense. I made a prototype to simulate the whole process. It works for a "Hello world" application, but I wonder if it makes sense on a large application or this Interface idea is only counter-productive and can backfire.
My question is: does this approach make sense? (the Interface idea is just an extra idea, it is not so important as the common code part described above) Is it a viable option?
I understand it depends a lot of the kind of application, anyway to be generic my one is in the CRM/Accounting domain, and the number of concurrent users on a single installation is typically less than 20 with peaks of 50.
EXTRA COMMENT (UPDATE): I ask this question because since I don't have a n-tier application I see Intraweb as the unique option for having a web application that has common code with the thick client. Developing webservices from the Delphi code makes no sense in my specific case, so the alternative I have is to write the web interface using ASP.NET (duplicating the business logic), but in this case I cannot take advantage of the common code in an easy way. Yes I could use dlls maybe, but my code is not suitable for that.
The most important thing that you have to remember is this:
Your thick client .EXE process is used by one person at a time (multiple persons will have multiple instances of that .EXE).
Your intraweb .EXE process will be used by many persons at a time. They all share the same instance of the process.
That means your business logic must not only be refactored out into common units, the instances of the business logic must be able to reside into memory multiple times, and not interfere.
This starts with the business logic that talks to the database: you must be able to have multiple database connections at the same time (in practice a pool of database connections work best).
In my experience, when you can refactor your business logic into datamodules, you have a good starting point to support both an Intraweb and a thick client version of your app.
You should not forget the user interface:
Thick clients support modal forms, and have a much richer UI
Web browsers support only message dialogs (and then: those are very limited), all fancy UI stuff costs a lot of development time (though for instance, TMS has some nice components for Intraweb)
Then, to top it off, you have to cope with the stateless nature of the HTTP protocol. To overcome this, you need sessions. Intraweb will take care of most of the session part.
But you need to ask yourself questions like these:
what should happen if a user is idle for XX minutes?
how much session state can I store in memory? and what if it doesn't fit?
what do I do with the session state that does not fit into memory?
This is just a start, so let use know when you need more info.
If it gets very specific to your app, you can always contact me directly: just google me.
--jeroen
I think if you move your application to n-tiers will be a better solution, it will be easier after that to be used by the desktop and web applications.
you already made the first part by decoupling the business logic from the presentation, you can use RemObject SDK or DataSnap that bundled with Delphi.
after that you will have working desktop application, and you can use Intrawebm Asp.net or what ever for web part, and in this way you will not have to duplicate the business logic again for the web part.
usually converting desktop application to web not easy as you thought, because they work in different environment, and you need to build each one as it's nature.

Resources