Zakładając interfejs IReader, implementację interfejsu IReader ReaderImplementation oraz klasę ReaderConsumer, która zużywa i przetwarza dane z czytnika.
public interface IReader
{
object Read()
}
Realizacja
public class ReaderImplementation
{
...
public object Read()
{
...
}
}
Konsument:
public class ReaderConsumer()
{
public string location
// constructor
public ReaderConsumer()
{
...
}
// read some data
public object ReadData()
{
IReader reader = new ReaderImplementation(this.location)
data = reader.Read()
...
return processedData
}
}
Do testowania ReaderConsumer i przetwarzania używam makiety IReadera. Czytnik ReaderConsumer staje się:
public class ReaderConsumer()
{
private IReader reader = null
public string location
// constructor
public ReaderConsumer()
{
...
}
// mock constructor
public ReaderConsumer(IReader reader)
{
this.reader = reader
}
// read some data
public object ReadData()
{
try
{
if(this.reader == null)
{
this.reader = new ReaderImplementation(this.location)
}
data = reader.Read()
...
return processedData
}
finally
{
this.reader = null
}
}
}
W tym rozwiązaniu kpina wprowadza zdanie produkcyjne do kodu produkcyjnego, ponieważ tylko konstrukt kpiąca dostarcza instancje interfejsu.
Pisząc to, zdaję sobie sprawę, że blok try-last jest w pewnym stopniu niezwiązany, ponieważ ma za zadanie obsłużyć użytkownika zmieniającego lokalizację podczas działania aplikacji.
Ogólnie wydaje się śmierdzący, jak można sobie z tym poradzić lepiej?
ReaderConsumer
niezależnymReaderImplementation
?