The linked "duplicate" question is an iffy match at best, because it's asking
- is
pattern XOK (YES/NO)
and I'm clearly already in the NO camp, and subsequently asking
- what is
pattern Xcalled - what steps can be taken to fix
pattern X
(neither of which are addressed by the linked question).
I recently did a code review on a block of code that looked something like this:
public class MyClass
{
private ISomething mySomething;
// ...Other variables omitted for brevity
public MyClass() { mySomething = new Something(); }
/// <summary>
/// Constructor - ONLY USE THIS FOR UNIT TESTING
/// </summary>
public MyClass(ISomething something) { mySomething = something; }
public void MyMethod()
{
// Gets called by the framework, and changes the internal state of the class by using mySomething...
}
// Other methods...
}
I'm concerned specifically with the overloaded constructor. It was added purely to test this class, and will make its way into production code.
Is there a name for this pattern/anti-pattern, and what can be done to solve it?
For clarification, the implementation of Something was added specifically for the purpose of being able to add an overloaded constructor to MyClass. It's used nowhere else. Its existence is an instance of the very issue I'm concerned about.
ISomething is very tightly coupled to MyClass. It needn't have been extracted. Implementation and interface might as well look like:
public interface ISomething
{
string GetClassName();
}
public class Something : ISomething
{
public string GetClassName() { return "MyClass"; }
}
That means that MyClass.MyMethod()'s body could just be replaced with return "MyClass";
However, the interface abuse/premature optimization seems like a separate issue and not in the spirit of the original question (i.e. consider it a given that the class/interface is structured like so and leave it as a separate [but valid] concern).
ISomethingbetter if we knew a little more about its design. Can it be used with many classes, or just this class? Does it have a sensible name? – Robert Harvey Nov 20 '14 at 16:45ISomethingimplementingGetClassName()seems perfectly reasonable. It's a lot of ceremony, but that's the price we pay for working in an object-oriented language. In a way, you're doing a poor man's form of Dependency Injection. – Robert Harvey Nov 20 '14 at 16:59MyClasshas no interface. ThusMyMethodshould never be called (in production) with an implementation ofISomethingother thanSomething- yet the overloaded constructor allows for this (invalid unless in a test context) possibility. – Michael Nov 20 '14 at 17:05public MyClass() : this(new Something()) { }– Dan Lyons Nov 21 '14 at 00:38MyClassimplements an interface and whether it should consume interfaces vs concrete classes – Ben Aaronson Nov 21 '14 at 15:50MyClassitself is not "injectible" anywhere - anywhere it's used, it's deliberate and its functionality is known. Because that's the case, it seems there's no need (in this simple example) to be able to have its functionality changed via the constructor in question. – Michael Nov 21 '14 at 16:22Loggerwhich usesILogWriter, the fact thatILogWritercould be aFileLogWriterorDbLogWriterorTraceLogWriteror whatever seems unrelated to the fact there's only a singleLogger. – Ben Aaronson Nov 21 '14 at 17:08#if Test? Should work maybe :) – Knerd Nov 24 '14 at 13:18