Doszedłem do wniosku, że CreateDataFile
robienie jednej rzeczy polega na wykonaniu szybkiego pomiaru, a następnie zapisaniu danych, a wykonanie obu w tej samej metodzie jest bardziej intuicyjne dla kogoś innego, kto korzysta z tego kodu, niż konieczności wykonania pomiaru i zapisania do pliku jako osobne wywołania metod.
Myślę, że to właściwie twój problem. Metoda nie robi nic . Wykonuje dwie odrębne operacje, które dotyczą operacji we / wy na różnych urządzeniach , z których obie odciążają inne obiekty:
- Pobierz pomiar
- Zapisz ten wynik gdzieś w pliku
Są to dwie różne operacje we / wy. Warto zauważyć, że pierwszy z nich w żaden sposób nie powoduje mutacji systemu plików.
W rzeczywistości powinniśmy zauważyć, że istnieje domniemany środkowy krok:
- Pobierz pomiar
- Serializuj pomiar do znanego formatu
- Zapisz zserializowany pomiar do pliku
Twój interfejs API powinien dostarczyć każdy z nich osobno w jakiejś formie. Skąd wiesz, że dzwoniący nie będzie chciał wykonać pomiaru bez przechowywania go w dowolnym miejscu? Skąd wiesz, że nie będą chcieli uzyskać pomiaru z innego źródła? Skąd wiesz, że nie będą chcieli przechowywać go w innym miejscu niż urządzenie? Istnieje dobry powód, aby oddzielić operacje. Na gołej minimum, każdy poszczególny element powinien być dostępny dla każdego obiektu wywołującego. Nie powinienem być zmuszany do zapisywania pomiaru do pliku, jeśli mój przypadek użycia tego nie wymaga.
Na przykład możesz oddzielić takie operacje.
IMeasurer
ma sposób na pobranie pomiaru:
public interface IMeasurer
{
IMeasurement Measure(int someInput);
}
Twój typ pomiaru może być po prostu czymś prostym, na przykład a string
lub decimal
. Nie twierdzę, że potrzebujesz do tego interfejsu lub klasy, ale czyni to przykład bardziej ogólnym.
IFileAccess
ma jakąś metodę zapisywania plików:
interface IFileAccess
{
void SaveFile(string fileContents);
}
Następnie potrzebujesz sposobu serializacji pomiaru. Zbuduj to w klasie lub interfejsie reprezentującym pomiar, lub zastosuj metodę użyteczności:
interface IMeasurement
{
// As part of the type
string Serialize();
}
// Utility method. Makes more sense if the measurement is not a custom type.
public static string SerializeMeasurement(IMeasurement m)
{
return ...
}
Nie jest jasne, czy ta operacja serializacji została jeszcze rozdzielona.
Ten rodzaj separacji poprawia interfejs API. Pozwala to osobie dzwoniącej decydować, czego potrzebują i kiedy, zamiast wymuszać z góry przyjęte pomysły na temat tego, co należy wykonać we / wy. Dzwoniący powinni mieć kontrolę nad wykonywaniem dowolnej prawidłowej operacji, niezależnie od tego, czy uważasz, że jest to przydatne, czy nie.
Gdy będziesz mieć osobne implementacje dla każdej operacji, twoja CreateDataFile
metoda stanie się tylko skrótem
fileAccess.SaveFile(SerializeMeasurement(measurer.Measure()));
Warto zauważyć, że po wykonaniu tego wszystkiego twoja metoda wnosi bardzo niewielką wartość. Powyższy wiersz kodu nie jest trudny dla twoich rozmówców do bezpośredniego użycia, a twoja metoda jest najwyżej dla wygody. Powinno być i jest czymś opcjonalnym . I to jest poprawny sposób działania API.
Po uwzględnieniu wszystkich istotnych części i stwierdzeniu, że metoda jest jedynie wygodą, musimy ponownie sformułować pytanie:
Jaki byłby najczęstszy przypadek użycia dla Twoich rozmówców?
Jeśli chodzi o to, aby typowy przypadek użycia pomiaru i pisania na tej samej płycie był nieco wygodniejszy, wówczas sensowne jest po prostu udostępnienie go Board
bezpośrednio w klasie:
public class Board : IMeasurer, IFileAccess
{
// Interface methods...
/// <summary>
/// Convenience method to measure and immediate record measurement in
/// default location.
/// </summary>
public void ReadAndSaveMeasurement()
{
this.SaveFile(SerializeMeasurement(this.Measure()));
}
}
Jeśli to nie poprawi wygody, nie zawracałbym sobie głowy tą metodą.
Ta metoda wygody rodzi jeszcze jedno pytanie.
Czy IFileAccess
interfejs powinien wiedzieć o typie pomiaru i jak go serializować? Jeśli tak, możesz dodać metodę do IFileAccess
:
interface IFileAccess
{
void SaveFile(string fileContents);
void SaveMeasurement(IMeasurement m);
}
Teraz dzwoniący po prostu zrób to:
fileAccess.SaveFile(measurer.Measure());
który jest tak samo krótki i prawdopodobnie bardziej przejrzysty niż twoja metoda wygody przewidziana w pytaniu.