Nie chodzi tylko o POLA, ale także o zapobieganie nieprawidłowemu stanowi jako możliwemu źródłu błędów.
Zobaczmy, jak możemy wprowadzić pewne ograniczenia do Twojego przykładu bez konkretnej implementacji:
Pierwszy krok: nie zezwalaj na wywołanie czegokolwiek przed otwarciem pliku.
CreateDataFileInterface
+ OpenFile(filename : string) : DataFileInterface
DataFileInterface
+ SetHeaderString(header : string) : void
+ WriteDataLine(data : string) : void
+ SetTrailerString(trailer : string) : void
+ Close() : void
Teraz powinno być oczywiste, że CreateDataFileInterface.OpenFile
należy wywołać, aby pobrać DataFileInterface
instancję, w której można zapisać rzeczywiste dane.
Drugi krok: upewnij się, że hedery i przyczepy są zawsze ustawione.
CreateDataFileInterface
+ OpenFile(filename : string, header: string, trailer : string) : DataFileInterface
DataFileInterface
+ WriteDataLine(data : string) : void
+ Close() : void
Teraz musisz podać wszystkie wymagane parametry z góry, aby uzyskać DataFileInterface
: nazwę pliku, nagłówek i zwiastun. Jeśli ciąg zwiastuna nie jest dostępny, dopóki nie zostaną zapisane wszystkie wiersze, możesz również przenieść ten parametr do Close()
(ewentualnie zmienić nazwę metody WriteTrailerAndClose()
), aby przynajmniej pliku nie można było zakończyć bez ciągu zwiastuna.
Aby odpowiedzieć na komentarz:
Lubię separację interfejsu. Ale jestem skłonny myśleć, że twoja sugestia na temat egzekwowania (np. WriteTrailerAndClose ()) ogranicza się do naruszenia SRP. (Jest to coś, z czym zmagałem się wiele razy, ale twoja sugestia wydaje się być możliwym przykładem.) Jak byś zareagował?
Prawdziwe. Nie chciałem koncentrować się bardziej na przykładzie, niż jest to konieczne, aby wyrazić swoje zdanie, ale to dobre pytanie. W tym przypadku myślę, że nazwałbym to Finalize(trailer)
i twierdzę, że nie robi to zbyt wiele. Napisanie zwiastuna i zamknięcie są jedynie szczegółami implementacyjnymi. Ale jeśli się nie zgadzasz lub masz podobną sytuację, w której jest inaczej, oto możliwe rozwiązanie:
CreateDataFileInterface
+ OpenFile(filename : string, header : string) : IncompleteDataFileInterface
IncompleteDataFileInterface
+ WriteDataLine(data : string) : void
+ FinalizeWithTrailer(trailer : string) : CompleteDataFileInterface
CompleteDataFileInterface
+ Close()
Tak naprawdę nie zrobiłbym tego na tym przykładzie, ale pokazuje, w jaki sposób przeprowadzić technikę.
Nawiasem mówiąc, założyłem, że metody muszą być wywoływane w tej kolejności, na przykład, aby sekwencyjnie zapisywać wiele wierszy. Jeśli nie jest to wymagane, zawsze wolałbym budowniczego, jak zasugerował Ben Cottrel .