Argumenty pola vs metody [zamknięte]

9

Właśnie zacząłem pisać nową klasę i przyszło mi do głowy, że dodałem wiele argumentów metod, które nie są ściśle potrzebne. Jest to zgodne z nawykiem unikania posiadania stanu w klasach, który jest specyficzny dla niektórych wywołań metod, a nie ogólnej konfiguracji lub zależności klasy.

Takie postępowanie oznacza, że ​​wiele metod, które nie mogą mieć argumentów, kończy się na jednym, dwóch lub trzech.

Chciałbym usłyszeć twoje opinie na temat tego, co myślisz o tym kompromisie i jak decydujesz, które podejście wybrać w jakiej sytuacji?

Ponieważ opis kodu jest często łatwiejszy do zrozumienia niż angielski, stworzyłem małą treść, która zawiera oba warianty: https://gist.github.com/JeroenDeDauw/6525656

Jeroen De Dauw
źródło
Argumenty używane tylko jako zmienna lokalna (nie globalna przez cały okres istnienia obiektu) powinny być objęte zakresem, o ile ma to sens ... Uważam, że jest to bardzo irytujące, gdy deweloperzy przechowują stan nieinstancyjny jako stan instancji, ponieważ jest to wygodne ... Ale tylko moja opinia. Utrudnia zobaczenie, jak przebiega proces wykonywania.
Maks.
Używanie parametrów i pozwalanie klasie zadbać o to, czy może być konieczna zmiana stanu podczas wykonywania metody, ładnie łączy się z zasadą „nie pytaj” . Pamiętaj, że Tell nie pytaj nie oznacza, że ​​nie możesz zapytać obiektu o jego stan ( rażąca wtyczka )
Marjan Venema

Odpowiedzi:

2

Ponieważ jedyną widoczną z zewnątrz metodą w twoim przykładzie jest updateTable, myślę, że dobrze jest używać pól zamiast parametrów metody.

Jeśli jest to część bardziej ogólnej klasy (np. TableTools), Przenosiłbym metody pomocnicze, które potrzebują stanu, do ukrytej klasy wewnętrznej.

Przykład pseudokodu:

class TableTools {
    ...
    public void updateTable(currentTable, newTable) {
        TableUpdater u = new TableUpdater(schemaModifier, currentTable, newTable);
        u.removeRemovedFields();
        u.addAddedFields();
     }

     private class TableUpdater { ... }
}

W ten sposób unikniesz pól używanych tylko przez jedną metodę publiczną. Ponadto kod jest bezpieczny dla wątków w tym sensie, że każde wywołanie updateTable używa własnej kopii TableUpdater, a zatem zmiennych instancji TableUpdater.

Heinzi
źródło
7

Korzystanie z pól pozwala na korzystanie z wielowątkowości dla metod wykorzystujących te pola.

Używanie takich pól jest tylko nieznacznie lepsze niż używanie globałów z punktu widzenia wielokrotnego użytku i konserwacji, kluczowym punktem tutaj jest to, że złożone konfiguracje wymagają starannej i aktualnej dokumentacji na temat tego, które metody używają i / lub zamykają, które pola; coś, czego nie musisz robić, używając argumentów.

maniak zapadkowy
źródło
Wielowątkowość nie ma znaczenia w moim przypadku użycia, tak jak w PHP. Zgadzam się, że takie podejście jest złe, jeśli sposób wykorzystania pól nie jest trywialny. W takim przypadku są one zapisywane tylko (i zawsze są zapisywane) z jedynej publicznej metody. Nie przewiduję, że to spowoduje problemy. Co do takich pól, które są tylko nieco lepsze od globalnych, nie jestem pewien, co masz na myśli. Czy możesz rozwinąć?
Jeroen De Dauw,
7

Słowami laika:

  • metody powinny mieć możliwie najmniej argumentów (czysty kod Martina)
  • jedną z cech obiektów jest to, że mogą one (i powinny) mieć stan
  • metody niestatyczne, które nie działają na stanie obiektu, tj. odbierają wszystko jako parametry, nie są spójne
  • metody niespójne można równie dobrze uczynić statycznymi i pogrupować w klasę użyteczności

Ponownie, moim skromnym zdaniem, niespójne metody należą do klasy użyteczności, a nie do klasy o nazwie domeny.

Tulains Córdova
źródło
1

Nie używaj pól w bieżącym przypadku! Dwa „wątki”, które jednocześnie używają obiektu, poważnie się pomieszają. Nie muszą też być rzeczywistymi, oddzielnymi wątkami (stąd cytaty). Jeśli skonfigurujesz obiekt dla jednej tabeli, a następnie wywołaj metodę, która używa go dla innej tabeli, a następnie spróbuj użyć oryginalnej konfiguracji, masz problem. Na razie trzymaj się parametrów.

To, co chcesz tutaj zrobić, to utworzyć nową klasę aktualizacji, która będzie używana tylko w jednym przypadku. Oryginalna klasa może mieć metodę tworzenia instancji w razie potrzeby. Nowa klasa miałaby pola. Masz to, co najlepsze z obu światów. Czasami łatwiej jest trzymać się parametrów, ale w twoim przykładzie już docierasz do miejsca, w którym oddzielna klasa byłaby lepsza.

RalphChapin
źródło
0

Myślę, że wybór powinien być zgodny z rzeczywistą sytuacją, tak jak ją widzisz. Jeśli element należy do instancji, powinien być postrzegany jako jego pole. Jeśli element jest zewnętrzny względem instancji, powinien zostać przekazany jako parametr metody.

W tym przypadku powinniśmy się kierować nie efektywnością (różnica i tak jest nieznaczna), czy (Boże chroń!) Łatwością pisania, ale zrozumiałością i naturalnością kodu.

Gangnus
źródło
0

Moim zdaniem, jeśli piszesz kod, który coś robi, to powinien on przyjmować parametry, które określają, do czego powinien to robić, a jego nazwa powinna określać, na ile to możliwe, co ma z tym zrobić.

Jeśli piszesz kod, który pakuje akcję do wykonania na czymś , powinieneś owinąć rzeczy, które powinny zostać wykonane w obiekcie i przekazać je swojej rzeczy, która coś robi .

Ta akcja staje się następnie rodzajem meta-opisu wywołań metod pierwszego, które możesz następnie wykonać później, ustawiając w kolejce, a nawet z jakiegoś powodu zrezygnować.

Twoje pytanie przekłada się więc na działanie lub funkcję ? Akcja może być przełożone lub odwołane, a zatem należy ująć to, co działa na. Funkcja dzieje się natychmiast, więc nie ma potrzeby top zachować swoje parametry.

Możesz cofnąć i wykonać akcję, ale nie funkcję .

OldCurmudgeon
źródło