Czytam o typowych zapachach kodu w książce Martin Fowler Refactoring . W tym kontekście zastanawiałem się nad wzorem, który widzę w bazie kodu i czy można obiektywnie uznać go za anty-wzór.
Wzorzec to taki, w którym obiekt jest przekazywany jako argument do jednej lub więcej metod, z których wszystkie zmieniają stan obiektu, ale żadna z nich nie zwraca obiektu. Opiera się więc na charakterze referencyjnym (w tym przypadku) C # / .NET.
var something = new Thing();
// ...
Foo(something);
int result = Bar(something, 42);
Baz(something);
Uważam, że (zwłaszcza gdy metody nie są odpowiednio nazwane) muszę przyjrzeć się takim metodom, aby zrozumieć, czy stan obiektu się zmienił. To sprawia, że rozumienie kodu jest bardziej złożone, ponieważ muszę śledzić wiele poziomów stosu wywołań.
Chciałbym zaproponować ulepszenie takiego kodu, aby zwracał inny (sklonowany) obiekt z nowym stanem lub cokolwiek, co jest potrzebne do zmiany obiektu w miejscu wywołania.
var something1 = new Thing();
// ...
// Let's return a new instance of Thing
var something2 = Foo(something1);
// Let's use out param to 'return' other info about the operation
int result;
var something3 = Bar(something2, out result);
// If necessary, let's capture and make explicit complex changes
var changes = Baz(something3)
something3.Apply(changes);
Wydaje mi się, że pierwszy wzór jest wybierany na podstawie założeń
- że jest to mniej pracy lub wymaga mniej wierszy kodu
- że pozwala nam zarówno zmienić obiekt, jak i zwrócić inną informację
- że jest bardziej wydajny, ponieważ mamy mniej przypadków
Thing
.
Ilustruję alternatywę, ale aby ją zaproponować, trzeba argumentować przeciwko oryginalnemu rozwiązaniu. Jakie argumenty można przedstawić, aby stwierdzić, że oryginalne rozwiązanie jest anty-wzorcem?
A co, jeśli w ogóle, jest nie tak z moim alternatywnym rozwiązaniem?