Na stronie 45 Czystego kodu Roberta C. Martina: Podręcznik do spraw zwinnego oprogramowania Martin pisze, że należy unikać argumentów wyjściowych. Mam problem ze zrozumieniem znaczenia „argumentu wyjściowego” i dlaczego należy go unikać.
Przykład Martina dla argumentu wyjściowego appendFooter(s);
wywołuje funkcję public void appendFooter(StringBuffer report)
. Jego poprawa kodu toreport.appendFooter();
Może wynika to z braku kontekstu kodu, ale nie rozumiem, jak używanie argumentów wyjściowych jest uważane za złe kodowanie. Czy ktoś mógłby wyjaśnić tę koncepcję lub podać dodatkowy przykład kodu, aby to zrozumieć?
Czy powyższa zasada byłaby również uważana za przykład nieczystego kodu na podstawie powyższej zasady?
int[] numberArray = {3, 5, 7, 1};
sortArray(numberArray);
Jeśli powyższe jest pogwałceniem zasady Martina, że nie używa argumentów wyjściowych, czy lepiej byłoby mieć obiekt, który ma tablicę jako pole i funkcję, którą można wywołać w celu posortowania tablicy?
ObjectWithArrayField numberArray = new ObjectWithArrayField(3, 5, 7, 1);
numberArray.sort();
źródło
sortArray(numberArray)
, oczywiście, układa sięnumberArray
na miejscu. Czy też tworzy kopięnumberArray
, sortuje kopię i zwraca posortowaną kopię bez żadnych zmiannumberArray
?sort()
metoda kontenera może również działać w miejscu, bez użycia „argumentu wyjściowego”. Zatem tylko dlatego,sortArray(numberArray)
że metoda na miejscu nie ma absolutnie żadnego powodu, który uzasadniałby „wyjściową formę argumentu”.sortArray(numberArray)
się dzieje. Może być oczywiste, że jeśli nie zwróci tego samego typu, który akceptuje, to musi być na miejscu. Ale bez zobaczenia typu zwracanego lub jeśli typ zwracany pasuje do typu wejściowego, jest niejasny bez patrzenia na definicję.Jest to kwestia użycia nieoczekiwanego mechanizmu do zwracania wartości z funkcji, co zwykle wynika z nadmiernego wykonywania funkcji lub niewłaściwej odpowiedzialności. Zdecydowanie najlepszym sposobem na przekazanie wyniku funkcji jest użycie wartości zwracanej. Mam nadzieję, że to oczywiste. W językach obiektowych drugą najlepszą metodą jest mutowanie obiektu.
Pomiędzy tymi dwiema opcjami istnieje tak wiele czystych, oczywistych sposobów komunikowania wyniku funkcji, że jeśli kiedykolwiek chcesz zmutować argumenty jako jedyny środek, coś poszło nie tak w twojej architekturze. Musisz zmienić swoje obowiązki klasowe, aby osoba dokonująca mutacji była w pierwszej kolejności danymi.
Jedynym wyjątkiem są bardzo ogólne algorytmy. Na przykład algorytm sortowania może słusznie być oddzielny od sortowanych kontenerów, jeśli można go ogólnie zastosować do dowolnego typu kontenera przy użyciu jego publicznego interfejsu. Funkcja jednego strzału
appendFooter
nie ma takiej wymówki.źródło