This is more like a good practise question. I want to offer different generic libraries like Logging, caching etc. There are lots of third party libraries like MS enterprise library, log4Net, NCache etc for these.
I wanted to know if its a good practise to use these directly or create wrapper over each service and Us开发者_运维百科e a DI to inject that service in the code.
regards
This is subjective, but also depends on the library.
For instance, log4net or NHibernate have strictly interface based API's. There is no need to wrap them. There are other libraries which will make your classes hard to test if you don't have any interfaces in between. There it might be advisable to write a clean interface.
It is sometimes good advise to let only a small part of the code access API's like for instance NHibernate or a GUI library. (Note: This is not wrapping, this is building abstraction layers.) On the other side, it does not make sense to reduce access to log4net calls, this will be used in the whole application.
log4net is probably a good example where wrapping is just overkill. Some people suffer of "wrappitis", which is an anti-pattern (sometimes referred to as "wrapping wool in cotton") and just produces more work. Log4net has such a simple API and is highly customizable, they made it better then your wrapper most probably will be.
You will find out that wrapping a library will not allow you to just exchange it with another product. Upgrading to newer versions will also not be easier, rather you need to update your wrapper for nothing.
If you want to be able to swap implementations of those concepts, creating a wrapper is the way to go.
For logging there already is something like that available Common.Logging.
Using wrapping interfaces does indeed make unit testing much easier, but what's equally important, it makes it possible to use mocks.
As an example, the PRISM framework for Silverlight and WPF defines an ILoggerFacade
interface with a simple method named Log
. Using this concept, here's how I define a mocked logger (using Moq) in my unit tests:
var loggerMock = new Mock<ILoggerFacade>(MockBehavior.Loose);
loggerMock.Setup(lg => lg.Log(It.IsAny<string>(), It.IsAny<Category>(), It.IsAny<Priority>()))
.Callback((string s, Category c, Priority p) => Debug.Write(string.Format("**** {0}", s)));
Later you can pass loggerMock.Object
to the tested object via constructor or property, or configure a dependency injector that uses it.
It sounds like you are thinking of wrapping the logging implementation and then sharing with different teams. Based on that here are some pros and cons.
Advantages of Wrapping
- Can abstract away interfaces and dependencies from implementation. This provides some measure of protection against breaking changes in the implementation library.
- Can make standards enforcement easier and align different project's implementations.
Disadvantages of Wrapping
- Additional development work.
- Potential additional documentation work (how to use new library).
- More likely to have bugs in the wrapping code than mature library. (Deploying your bug fixes can be a big headache!)
- Developers need to learn new library (even if very simple).
- Can sometimes be difficult to wrap an entire library to avoid leaking implementation interfaces. These types of wrapper classes usually offer no value other than obfuscation. e.g. MyDbCommand class wraps some other DbCommand class.
I've wrapped part of Enterprise Library before and I didn't think it added much value. I think you would be better off:
- Documenting the best practices and usage
- Providing a reference implementation
- Verifying compliance (code reviews etc.)
This is more of a subjective question but IMO it's a good thing to wrap any application/library specific usage into a service model design that has well thought out interfaces so you can easily use DI and later if you ever need to switch from say EntLib Data Application Block to NHibernate you don't need to re-architect you're whole application.
I generally create a "helper" or "service" class that can be called statically to wrapper common functionality of these libraries.
I don't know that there is a tremendous amount of risk in directly referencing/calling these, since they are definitely mature projects (at least EntLib and Log4Net), but having a wrapper isolates you from the confusion of version change, etc. and gives you more options in the future, at a fairly low cost.
I think it's better to use a wrapper, personally, simply because these are things you don't want to be running when your unit tests run (assuming you're unit testing also).
Yes if being able to replace the implementation is a requirement now or in a reasonable future.
No otherwise.
Defining the interface that your application will use for all logging/enterprising/... purposes is the core work here. Writing the wrapper is merely a way to make the compiler enforce use of this interface rather than the actual implementation.
精彩评论