سؤال

I have an ASP.NET Core 1.1 application which uses dependency injection and is splitted in 3 layers (web, business logic and data access).

I'd like to access to some values of the configuration file in some methods of the business logic layer. Which way would be more correct to keep a clean architecture?

  • Pass the config values as method-parameters while calling the method in the web layer
  • Pass/inject the configuration as constructor-parameter to the class of my business logic layer
هل كانت مفيدة؟

المحلول

In any situation where information needs injecting into part of an app, remember the "tell, don't ask" principle.

If you pass configuration into the business logic layer directly, then you are creating a coupling between the two. It becomes difficult to change the configuration without breaking the business logic layer. Further, you potentially create the need to have to mock the configuration for testing purposes.

However, having to pass individual configuration values as parameters into every business layer method call from the web layer creates other problems. It adds extra complexity to those method signatures and ceremony to using them and it also necessitates exposing all of the configuration to all of the web layer. Again, remember "tell, don't ask": parts of the web layer should only be told about those aspects of configuration that they need to know about.

So I'd suggest a third approach. Inject the configuration values required by each class within the business logic layer, as parameters to their constructors. That way it becomes the responsibility of your IoC framework, if you are using one (or your dependency mapping code at app start if you are using pure DI) to route individual values to just those classes that need them.

نصائح أخرى

You can declare the configuration per module and have it provided/injected on creation:

package: Accounts
   + AccountService
   + // internal classes
   + AccountConfig
package: Users
   + UserService
   + // internal classes
   + UserConfig
package: Config
   + IConfigProvider
   + XMLConfigProvider
   + RemoteConfigProvider

Let each module declare an interface (with getters for config values), for its own configuration data. The implementation of this interface must be passed to each module on initialization/construction. You can further break down module config interface for more fine mapping.

Now you implement a configuration provider that provides implementations for each of such interfaces whenever required. The provider might be parsing actual values from a JSON/XML file or from other sources.

When you add another config value to any config interface, the provider interface and implementations have to be updated.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى softwareengineering.stackexchange
scroll top