Imagine some SOA. We have a few different services, of which the OperationContext is extended by some SecureOperationContext which makes sure certain security demands are met.
Assume furthermore that sometimes we might need to know a certain property from this SecureOperationContext somewhere else, in a place where there is and won't be this SecureOperationContext. For example a username for some sort of logging purpose.
Currently we're using something that looks and smells plain dirty. The fat's dripping of in my opionion.
Now, in some 'Common' library, there is a class defined with a ThreadStatic property: Username. I guess you can catch my drift: the security stuff sets this static global variable and lo and behold we have it available for logging puproses.
This thing bugs me, but on the other hand what else to do? I was thinking about creating a method that takes a string as parameter to handle this, but then all my methods need to still read that username property, which is non-dry.
So on one hand, this way everything is handled on the background, but I'm not just quite happy having to maintain some (global) class just to achieve this.
Any tips?
I'm not sure how to put it in less abstract terms, but here goes (in pseudo).
public WebService
{
public Save(Car car)
{
// Some SecurityCOntext is known here, this holds top secret info,
// like the username
// and sets this into the golbal helper class UserNameManagemer
// car has for example a CreatedDate property (from an Interface),
//but I don't want handle do this propertyin every Create method can handled in some general piecei of code.
efcontainer.AddObjcect(car)
e.SaveChanges() ->
//Now savechanges will check the objects in the ObjectSatateManager
//and sets the apppriopriate property via the global thing.
}
}
Now what to do to rid myself of this global variable!. Passing a username to SaveChanges is undesirable ass well, since we'd then still have to manually repat this for everything, which blows.
Encapsulate the global property in a service. Define an interface for that service. Now, depend on that interface everywhere you need the data by having a constructor parameter of that type.
This is called dependency injection and is a very important concept when you want to avoid problems as the one you currently have. A dependency injection container such as Autofac can help if you have a big application, but is not strictly required.
The most important thing is to understand dependency injection and have a well-defined composition root, no matter whether you use a DI container or do it yourself.
The security stuff sets this static global variable and lo and behold we have it available for logging puproses.
This sounds like the data is determined dynamically. Note that you can still use a service to track the value. That service also knows whether the value is available or not. This way, you can better manage the temporal coupling that you have at the moment.
Edit: You can further improve the design by creating the client objects through a factory. That factory can ensure that the value is available, so it couples the lifetime of the client objects to the availability of the value. This way, you are sure to always act in a context where the value can be safely accessed.
Related
I'm working on a domain model writing my software all DDD and stuff doing a great job, when I suddenly bump into the same problem I have been facing over and over again and now it's time to share some insights. The root of the problem lies in the uniqueness of data.
For example, let's say we're writing this awesome domain model for a user. Obviously the username is unique and just to be as flexible as possible we want the user to be able to change his name, so I implemented the following method:
public void SetUsername(string value)
{
if (string.IsNullOrWhiteSpace(value))
{
throw new UserException(UserErrorCode.UsernameNullOrEmpty,
"The username cannot be null or empty");
}
if (!Regex.IsMatch(value, RegularExpressions.Username))
{
throw new UserException(UserErrorCode.InvalidUsername,
"The username {value} does not meet the required ");
}
if (!Equals(Username, value))
{
Username = value;
SetState(TrackingState.Modified);
}
}
Again, this is all fine and fancy, but this function lacks the ability to check if the username is unique or not. So writing all these nice articles about DDD, this would be a nice use-case for a Domain Service. Ideally, I would inject that service using dependency injection but this ruins the constructor of my domain model. Alternatively, I can demand an instance of a domain service as a function argument like so: public void SetUsername(string value, IUsersDomainService service) and to be honest I don't see any solid alternatives.
Who has faced this problem and maybe came up with a nice rock-solid solution?
I agree with #TomTom. But as most times with software decisions, it depends, there is almost always a tradeoff. As a rule of thumb, you gain more by not injecting a domain service into an entity. This is a common question when one is starting with DDD and CQRS+ES. And has been thoroughly discussed in the CQRS mailing list here
However, there are some cases where the approach you suggested (known as method injection) might be beneficial it depends on the scenario. I’ll try and drive some analysis points next.
Consider the case where you want to make some validation before creating an entity. Let's think of a hypothetical and way oversimplified international banking context, with the following entity:
public class BankNote
{
private BankNote() {}
public static FromCurrency(
Currency currency,
ISupportedCurrencyService currencyService)
{
currencyService.IsAvailable(currency);
}
}
I am using the factory method pattern FromCurrency inside your entity to abstract the entity creation process and add some validation so that the entity is always created in the correct state.
Since the supported currencies might change overtime, and the logic of which currencies are supported is a different responsibility than the bank note issuing logic, injecting the ISupportedCurrencyService in the factory method gives us the following benefits:
By the way, the method dependency injection for domain services is suggested in the book: Hands-On Domain-Driven Design with .NET Core
By Alexey Zimarev. Chapter 5 "Implementing the Model" page 120
Pros
The BankNote is always created with a supported Currency, even if the currencies supported change overtime.
Since we are depending on an interface instead of a concrete implementation, we can easily swap and change the implementation without changing the entity.
The service is never stored as an instance variable of the class, so no risk of depending on it more than we need.
Cons
If we keep going this way we might add a lot of dependencies injected into the entity and it will become hard to maintain overtime.
We still are adding a loosely coupled dependency to the entity and hence the entity now needs to know about that interface. We are violating the Single Responsibility Principle, and now you would need to mock the ISupportedCurrencyService to test the factory method.
We can’t instantiate the entity without depending on a service implemented externally from the domain. This can cause serious memory leak and performance issues depending on the scenario.
Another approach
You can avoid all the cons if you call the service before trying to instantiate the entity. Say having a different class for the factory instead of a factory method, and make that separate factory use the ISupportedCurrencyService and only then call the entity constructor.
public class BankNoteFactory
{
private readonly ISupportedCurrencyService _currencyService;
private BankNoteFactory(
ISupportedCurrencyService currencyService)
=> _currencyService = currencyService;
public BankNote FromCurrency(
Currency currency)
{
if(_currencyService.IsAvailable(currency))
return new BanckNote(currency);
// To call the constructor here you would also need
// to change the constructor visibility to internal.
}
}
Using this approach you would end with one extra class and an entity that could be instantiated with unsupported currencies, but with better SRP compliance.
I have a scenario that i have a Client of webAPi that need base url in it's constructor and An configuration manager class that reads configuration from web.config.
interface IConfigManager
{
string baseurl {get;}
}
class ConfigManager:IConfigManager
{
public string baseurl => system.configuration.ConfigruationManager.AppSettings["URL"];
}
and i have a client class that calls the web api
interface IApiClient
{
List<Products> GetProducts(string addresssufix);
}
public class ApiClient:IApiClient
{
public ApiClient(string baseUrl)
{
//----
}
List<Products> GetProducts(string addresssufix)
{
//....
}
}
so i require Url in APiClient
in simple injector while registration of components.
container.Register<IConfigManager, ConfigManager>();
var config= container.GetInstance<IConfigManager>();
container.Register<IApiClient<(()=> new ApiClient(config.baseurl));
but it said i can't register after calling GetInstance
Simple Injector blocks any calls to Register after the first call to GetInstance to force strict registration between registration and resolve. This design prevents strange, hard to debug, and hard to verify behaviour as explained in more detail here in the documentation.
But just as you want to separate the registration phase from the phase where you start resolving from the container, you should do the same when reading configuration values. Configuration values should only be loaded at application start-up, before or during the time of the registration phase. Delaying the reading of configuration values causes applications to become brittle and forces you to go through the complete application to find out whether or not the application is configured correctly, while this can easily be prevented by loading the configuration at start-up (and thus letting the application fail fast).
This means, that in your situation it doesn't make much sense to have an IConfigManager abstraction, since it's only goal is to delay the loading of base URL from the app settings, while again, this should be done directly at start-up (and should preferably fail in case that value is missing or malformed).
With that in mind, I would like to propose the following improvement and simplification to your design:
var container = new Container();
string baseUrl = System.Configuration.ConfigruationManager.AppSettings["URL"];
if (string.IsNullOrEmpty(baseUrl))
throw new ConfigurationErrorsException("appSettings/URL is missing.");
container.RegisterSingleton<IApiClient>(new ApiClient(baseUrl));
See how the configuration is read directly at startup and checked immediately whether the value exists. After that the baseUrl is used directly in the ApiClient constructor. Also note that ApiClient is registered as Singleton. I assume here that ApiClient is stateless and immutable (which is a good practice).
Note that you did the right thing by letting your ApiClient depend on the string baseUrl configuration value, instead of injecting the IConfigManager. Using ConfigManager as an abstraction in application code is typically problematic. Such configuration abstraction will typically grow indefinitely during the lifetime of the application, since every time a new configuration value is added to the configuration, this abstraction (and its implementation and possible fake implementations) need to be updated. Consumers of that abstraction will typically only depend on one or a few configuration values, but never on all. This is an indication of a Interface Segregation Principle violation. Problem with that is that it becomes harder to test consumers of that interface, because you typically want to be sure that they use the correct configuration values. Another problem is that from the definition of such a consumer (its type name and its constructor with required dependencies) it becomes impossible to see which configuration values are actually required.
All these problems go away completely when you let consumers depend directly on the configuration value they require. But again, this even removes the need to have this IConfigManager abstraction in the first place.
Do note that although register-resolve-register is not permitted, you would be able to do the following instead:
container.Register<IConfigManager, ConfigManager>();
container.Register<IApiClient>(() =>
new ApiClient(container.GetInstance<IConfigManager>().baseurl));
What is going on here is that GetInstance<IConfigManager> is called as part of the delegate for IApiClient. This will work because in that case the GetInstance<IConfigManager>() is called while resolving the IApiClient and thus after the registration process. In other words, resolving IConfigManager is delayed.
Big warning about this though: This practice is typically not advised. As explained before, when it comes to configuration values, we don't want to load them lazily. But even in other cases, we typically don't want to do this, because this construct blinds Simple Injector's verification and diagnostic system. Since Simple Injector uses statically available information (such as constructor arguments) to analyse your object graphs, such dynamic call will disallow Simple Injector to find common problems such as Lifestyle Mismatches. In other words, this construct should only be used in rare cases were you're sure that misconfigurations won't occur.
Pass the dependent object to ApiClient, instead of just a property of it. If that object has too many properties in which ApiClient is not interested, do interface segregation.
container.Register<IConfigManager, ConfigManager>();
container.Register<IApiClient, ApiClient>();
public ApiClient(IConfigManager configManager)
{
this.baseurl = configManager.baseurl;
}
container.GetInstance<ApiClient>();
I have some global components I am not sure how to put them in design. Such as:
Settings class: it is interfacing the initial settings of the program, it could be app.config(1way), web.config(1way), hard coded values(1way), or sqldb(2way) behind the scenes.
Language class: it contains different language sets, and again, I could have some resx files(1way), hard coded values(1way) or sqldb(2way) behind it.
First question is, should I make these classes setter properties in dependency injection (I use Windsor):
public ISettings Settings {set;}
public ILanguage Language {set;}
Or should I make them ambient context:
string DoSomethingAndReportIt() {
//do something ...
var param = Settings.Current.SomeParam;
//report it ...
return Language.Current.SomeClass_SomeMethod_Job_Done;
}
I notice there are a few components in .net library that actually use ambient context pattern, e.g. System.Security.Principal, System.Web.ProfileBase, System.Thread.CurrentCulture ...
Do you think it is no harm to make my global classes such as Settings and Language to be ambient context classes? If not, why DI is preferred? Do they take more advantage in unit testing compare to ambient?
Second question is, if DI is better, (I have a feeling that the DI pattern is preferred), what is a good way to proxy the existing ambient classes such as Security.Principal or Profile to follow the DI pattern?
Ambient context is OK when you need to implement functionality that spans across multiple layers. (In your case you say that the two objects are global) This functionality is known as crosscutting concerns. As you noticed many classes in .NET are implemented as ambient context, like IPrincipal. In order to get a working version of your implementation of ambient context, you will need to have some default value provided to your Settings and Language objects if they are developed as ambient context. My assumption is that you will provide some default implementation of ILanguage and ISettings, and considering that you will use them globally they are good candidates for ambient context.
On the other hand, how often do you plan to use those objects that implement these two interfaces? And, is the existence of the two objects crucial, meaning Settings != null and Language != null? If you really intend to use them in one or two classes, and/or if the existence of the objects is not really important, you might want to go with the setter injection. The setter injection does not really need a default value, so your object can be null.
Personally I am not a fan of ambient context. However I would use it if it turns out to be the most acceptable solution. In case of your implementations I would do something like this: because you will need to initialize objects which implement the two interfaces once and in one location only, you could start with the ambient context. If you realize that you are using it in a very small number of locations, think about refactoring it as a setter injection. If the existence of objects is important think about constructor injection implementation.
Question:
Normally, one accesses the session object like this:
Session["foo"] = "bar";
I have written a wrapper over it, which is generic, and which checks whether a session has expired or not, and throws a SessionExpiredException if that is so.
In order to use my session access, I have to access sessions over my class like this
WebApplications.SessionAccess.Set<string>("foo", "bar");
Now, obviously, despite the presence of the class SessionAccess, one could still access the session via the normal session object. This is not desirable, and additonally, I want to later include it in a larger old project which has been written using the normal Session, which would mean I would have to replace all calls to session (a number in the low thousands) with my wrapper.
Is there a way I can overwrite the System.Web.HttpSessionStateBase.Controller.Session - Property with my own ?
The thing is, without a custom session handler defined in web.config, because there sometimes already is one for using the database for sessions (one could still initialize a module in Global.asax).
Those NULL-Reference exception YSODs on SessionTimeout are hyper-disturbing.
If possible, a solution that works on classical ASP.NET web-forms as well as on MVC.
I don't think that there will be any full-proof solution as you wants it but few tricks can make your life easier.
Create yet another wrapper that provides indexer property so that you can easily substitute calls such as Session["key"] = "name" to your wrapper property;
You need to inherit all your pages (i.e. code-behind classes) from a common base page class (that itself has inherited indirectly from System.Web.UI.Page). If you already have such base page then you are really in good situation. Inherit your common page base class from an internal base class that itself inherited from System.Web.UI.Page.
In the common page base, add a new Session property that would return your wrapper object created in #1. Similar trick has to be done for UserControl (and custom control) if you have many of them. This will save you from replacing the most of Session["key"] = "name" kind of calls.
Finally, override Session property in the internal base page class to add a debug assertion. You may choose to return null but that would break production usage. Debug assertion is a lot better to find session usage that will be escaped from #3.
As said, this is not a full-proof solution as one can still access the session state via HttpContext. But it should make the migration of legacy code to your session accessor object easier.
I have a c# factory object which creates objects through factory methods, using a list of objects as a source.
The list of objects is created like this:
public WidgetFactory()
{
widgetLibrary = new List<WidgetModel>();
//Add all widgets
widgetLibrary.Add(new ClientsWidget());
widgetLibrary.Add(new InstallationsWidget());
etc.
and various parts of my application access this list in different ways to get the type of object it needs.
But I now have a requirement that one of the objects in the list(i.e. a widget) needs to make use of the widget factory itself. Clearly this causes a circular reference.
How can I alter my design to accomodate this need?
But I now have a requirement that one of the objects in the list(i.e. a widget) needs to make use of the widget factory itself. Clearly this causes a circular reference.
How can I alter my design to accomodate this need?
Typically, objects should not rely on the factory that creates them for construction, as it causes exactly this problem. If you can push in the reference to the factory, but not use it until it's needed, it may solve the issue.
If you absolutely need to do this, then the best approach may be to lazily instantiate the objects within the factory. Instead of having your WidgetFactory contain a List<WidgetModel> internally, you could use a List<Lazy<WidgetModel>>. This would allow the individual "widgets" to only evaluate as needed, which would mean that, when the widget in question tries to reference the factory, it'll be fully loaded.
But I now have a requirement that one of the objects in the list(i.e. a widget) needs to make use of the widget factory itself. Clearly this causes a circular reference.
How can I alter my design to accomodate this need?
Your model is wrong. Once a car has left the assembly line at the NUMMI plant, it doesn't depend on the plant to operate properly.
Also, I question the design of your factory. Why are you new instances the constructor. What purpose is that serving?
You should probably tell us a little bit more about your model and why you think you need this. Odds are, properly done, you don't.
The constructor for the WidgetFactory should not be calling the constructers of the things that it is building. Instead, the WidgetFactory should have a method (BuildWidgets) that does all of the work.
Then the other objects can make some use of the factory without causing this cascade of activity to start over again.
For starters, move Widget creation out of the WidgetFactory's constructor. This should happen either in an initialization method or on-demand in a CreateWidget(Type) method.
To make the factory instance available to the Widget instances, you can do one of a few different things:
Have WidgetFactory pass 'this' when it creates the Widget
Use the singleton pattern: add a static property WidgetFactory.Instance and initialize it once; have all WidgetFactory users access the property rather than create a new instance.
Use the dependency injection pattern -- difficult to provide a short description here.