Modyfikacja mutowalnego obiektu w metodzie.

Modyfikacja mutowalnego obiektu w metodzie.
O1
  • Rejestracja:ponad 14 lat
  • Ostatnio:około 8 godzin
0

Witam. Chciałbym się dowiedzieć jakie jest wasze podejście do modyfikacji obiektu wewnątrz metody. Załóżmy, że mamy klasę:

Kopiuj
class CalcModel {
	private long timeInActiveInMillis;
	private long timeInPauseInMillis;
	private int percentInActive;
	private int percentInPause;
	// inne zmienne i gettery, settery
}

Mam też metodę, która wykonuje obliczenia na tym obiekcie modyfikując jego właściwości, jednak ta metoda nic nie zwraca.

Kopiuj
public void calculate(CalcModel calcModel) {
	// tutaj wykonujemy różne operacje na modelu, którego go modyfikują, np.
	calcModel.setTimeInActiveInMillis(millis);
}

Czy takie podejście jest dobre czy lepiej zmodyfikować metodę aby coś zwracała?

Kopiuj
public CalcModel calculate(CalcModel calcModel) {
	// tutaj wykonujemy różne operacje na modelu, którego go modyfikują, np.
	calcModel.setTimeInActiveInMillis(millis);
	return calcModel;
}

Może operować na kopii obiektu w metodzie a zwróconą wartość przypisać do właściwego obiektu?

Kopiuj
public CalcModel calculate(CalcModel calcModel) {
	CalcModel modifiedCalcModel = new CalcModel(calcModel) // lub calcModel.copy();
	// tutaj wykonujemy różne operacje na modelu, którego go modyfikują, np.
	modifiedCalcModel.setTimeInActiveInMillis(millis);
	return modifiedCalcModel;
}

a potem:

Kopiuj
calcModel = calculate(CalcModel calcModel);

Jakie jest waszym zdaniem najlepsze podejście do takiego zagadnienia? Modyfikować przekazany argument i nic nie zwracać z metody? Modyfikować przekazany argument i go następnie zwracać? Czy może operować na kopii przekazanego argumentu a dopiero zwracany wynik po obliczeniach przypisywać do właściwego obiektu?

edytowany 6x, ostatnio: olek1
PI
  • Rejestracja:ponad 9 lat
  • Ostatnio:4 miesiące
  • Postów:2787
1

Tak naprawdę nie ma to aż tak wielkiego znaczenia - najbardziej istotnym elementem tutaj jest nazewnictwo metod. Jak nazwa metody dobrze opisze co w środku robi, to wtedy może zwracać bądź nie zwracać tego obiektu.

jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 7 godzin
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
2

Jeżeli jest tak jak myśle i obiekt początkowo ma ustawione **tylko **niektóre właściwości, a dopiero calc() ustawia pozostałe to taka klasa dowodzi wcielenia zła:

Kopiuj
//Wcielenie zła
class CalcModel {
    private long timeInActiveInMillis;
    private long timeInPauseInMillis;
    private int percentInActive;
    private int percentInPause;
    // inne zmienne i gettery, settery
}

Powinienes raczej mieć

Kopiuj
class Messdaten {
    private long timeInActiveInMillis;
    private long timeInPauseInMillis;
}
Kopiuj
class Ergebnisse {
 private int percentInActive;
    private int percentInPause;
}

oraz metodę

Kopiuj
public Ergebnisse calculate(Messdaten data) {
[...]
}

Wtedy wszystko będzie jasne.

Dodatkowo Ergebnisse może zawierać lub dziedziczyć po Messdaten.
Sorry za niemieckie nazwy- ale nie chciałem Ci narzucać nazw - nie wiem co tak naprawdę potrzebujesz( a dodatkowo kod po niemiecku ma +2 do bycia full professional.)

Ganeralnie obiekt po przejściu prze konstruktor powinien zawsze być "skonstruowany" - czyli wszystkie publiczne pola i i metody powinny być wywoływalne. Nie powinno być tak, że "puszczasz w świat" obiekt, który jest "w połowie zainicjalizowany" i niektórych metod i pól nie można używać, bo trzeba najpierw coś jeszcze wywołać. Bo ktoś o tym w końcu zapomni,
to jest po prostu kiepski/niebezpieczny kontrakt.

A poza tym polecam robienie gdzie się da niemutowalnych obiektów. To znacznie ułatwia życie.
Twój przykład idelanie do immutowalnego "ValueObjecta" pasuje.


jeden i pół terabajta powinno wystarczyć każdemu
edytowany 6x, ostatnio: jarekr000000
PI
niemieckie nazwy :OOO
O1
  • Rejestracja:ponad 14 lat
  • Ostatnio:około 8 godzin
0

Przykład jest totalnie abstrakcyjny. Ten obiekt początkowo w moim założeniu miał być zainicjalizowany a metoda calculate po prostu miała obliczać czas aktywności i w pauzie i %, ale tak jak napisałem przykład tylko na potrzeby tego posta. Chodziło mi bardziej o przekazywanie obiektu do metody, która może go modyfikować i jak najlepiej napisać taką metodę. Czy tworzenia metody, która modyfikuje oryginalny obiekt i nie zwraca nic nie jest mylące? Bo jakby nie patrzeć zmieniamy obiekt wykonujemy na nim operacje a nie zwracamy, żadnego wyniku.

jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 7 godzin
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
1

Czy tworzenia metody, która modyfikuje oryginalny obiekt i nie zwraca nic nie jest mylące?

Jest mylące. Najlepiej void-ów unikać - tak jak mutowalności.


jeden i pół terabajta powinno wystarczyć każdemu

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.