When thinking of agile software development and all the principles (SRP, OCP, ...) I ask myself how to treat logging.Is logging next to an implementation a SRP violation?I would say yes because the implementation should be also able to run without logging. So how can I implement logging in a better way? I've checked some patterns and came to a conclusion that the best way not to violate the principles in a user-defined way, but to use any pattern which is known to violate a principle is to use a decorator pattern.Let's say we have a bunch of components completely without SRP violation and then we want to add logging.component Acomponent B uses AWe want logging for A, so we create another component D decorated with A both implementing an interface I.interface Icomponent L (logging component of the system)component A implements Icomponent D implements I, decorates/uses A, uses L for loggingcomponent B uses an IAdvantages:- I can use A without logging- testing A means I don't need any logging mocks- tests are simplerDisadvantage:- more components and more testsI know this seem to be another open discussion question, but I actually want to know if someone uses better logging strategies than a decorator or SRP violation. What about static singleton logger which are as default NullLogger and if syslog-logging is wanted, one change the implementation object at runtime?
Is logging next to an implementation a SRP violation?
design patterns;logging;single responsibility;decorator
Yes it is a violation of SRP as logging is a cross cutting concern.The correct way is to delegate logging to a logger class (Interception) which sole purpose is to log - abiding by the SRP.See this link for a good example:https://msdn.microsoft.com/en-us/library/dn178467%28v=pandp.30%29.aspxHere is a short example:public interface ITenantStore{    Tenant GetTenant(string tenant);    void SaveTenant(Tenant tenant);}public class TenantStore : ITenantStore{    public Tenant GetTenant(string tenant)    {....}    public void SaveTenant(Tenant tenant)    {....}} public class TenantStoreLogger : ITenantStore{    private readonly ILogger _logger; //dep inj    private readonly ITenantStore _tenantStore;    public TenantStoreLogger(ITenantStore tenantStore)    {        _tenantStore = tenantStore;    }    public Tenant GetTenant(string tenant)    {        _logger.Log(reading tenant  + tenant.id);        return _tenantStore.GetTenant(tenant);    }    public void SaveTenant(Tenant tenant)    {        _tenantStore.SaveTenant(tenant);        _logger.Log(saving tenant  + tenant.id);    }}Benefits include You can test this without logging - true unit testingyou can easily toggle logging on / off - even at runtimeyou can substitute logging for other forms of logging, without ever having to change the TenantStore file.