Dobrą zasadą jest, aby nazwy metod były czasownikami lub predykatami, tak aby obiekt, do którego je wywołujesz ( self
w standardowej konwencji Pythona, this
w większości innych języków) stał się tematem.
Zgodnie z tą zasadą file.close
jest trochę źle, chyba że zastosujesz model mentalny, że plik sam się zamyka lub że file
obiekt nie reprezentuje samego pliku, a raczej uchwyt pliku lub jakiś obiekt proxy.
Worek treningowy nigdy się nie uderza, więc i tak punchingBag.punch()
jest źle. be_punched()
jest technicznie poprawny, ale brzydki. receive_punch()
może działać, lub handle_punch()
. Innym podejściem, dość popularnym w JavaScript, jest traktowanie takich wywołań metod jako zdarzeń, a konwencja polega na tym, że nazwa zdarzenia poprzedzona jest prefiksem „on”, więc będzie to on_punched()
lub on_hit()
. Alternatywnie, możesz przyjąć konwencję, że imiesłów bierny wskazuje głos pasywny, a zgodnie z tą konwencją nazwa metody byłaby sprawiedliwa punched()
.
Innym aspektem do rozważenia jest to, czy worek treningowy rzeczywiście wie, co go uderzyło: czy ma to znaczenie, czy uderzysz go, uderzysz kijem, czy wpadniesz na niego ciężarówką? Jeśli tak, jaka jest różnica? Czy potrafisz sprowadzić różnicę do argumentu, czy potrzebujesz różnych metod dla różnych rodzajów otrzymywanej kary? Pojedyncza metoda z parametrem generycznego jest prawdopodobnie najbardziej eleganckie rozwiązanie, ponieważ utrzymuje stopień łączący niskie, a taka metoda nie powinna być wywołana punched()
albo handle_punch()
, ale raczej coś bardziej ogólne jak receive_hit()
. Dzięki takiej metodzie możesz wdrożyć różnego rodzaju aktorów, którzy mogą uderzać worki treningowe, bez zmiany samej torby treningowej.
Hitable
.Myślę, że jest to kwestia konceptualna (jak myślimy o świecie). Można powiedzieć:
door.close()
paper.fold()
file.close()
Dziwnie jest powiedzieć:
bag.punch()
Musiałby w pierwszej kolejności mieć coś do uderzenia (np. Ramiona). Prawdopodobnie powiedziałbyś:
punching_bag.move()
Jest w porządku, że obiekty programistyczne robią rzeczy, które normalnie inni robią z nimi / w nich (w „prawdziwym świecie”). Ale myślę, że zawsze powinno to mieć przynajmniej jakiś sens, że coś robi to samo z sobą . Powinieneś być w stanie sobie to łatwo wyobrazić, nie pozostając niejasnym (jak w przypadku
punching_bag
).źródło
Myślę, że to kwestia gustu.
Punching bag
„spunch()
metoda jest co najmniej zgodne zfile.close()
lubframe.move()
w sensie przeżywania działanie na sobie. Większe pytanie brzmiałoby: dlaczego wBoxer
ogóle istniejepunch(something)
metoda?źródło
Coach.sayPunchToBoxer()
,Boxer.punchNearestBag()
iBag.punch()
. W przeciwnym razie musisz zgadnąć, co się stanie za każdym razem, gdy zadzwoniszCoach.punch()
. Ogólna zasada brzmi: jeśli obiekt, który doświadcza akcji, nie jest określony w nazwie metody, wówczas odbiorcą jest ten obiekt.Masz dwa różne komunikaty: jeden z poleceniem wybicia obiektu i jeden z informowaniem obiektu, że został on uderzony. Weź pod uwagę, że obiekt Boxer prawdopodobnie będzie musiał odpowiedzieć na oba . Różnie . To naprawdę dobry powód, aby nadać im różne nazwy.
Chciałbym zachować
punch(boxer, object, strength)
i zmienić nazwę metody przeciwnej dopunched
. Możesz to nazwaćhandle_punch
lub coś w tym rodzaju, ale nadal nie jest jasne, czy ma to być polecenie polecenia ciosu, czy powiadomienie, że został uderzony.źródło
defend
w tym konkretnym przypadku). Ale worek treningowy nigdy nie będzie tak dwukierunkowy. I jest już ten plik.close () ...defend
to polecenie. Jest to jedno z możliwych działań, które obiekt może podjąć w odpowiedzipunched
, ale nie chcesz, aby inne obiekty wywoływałydefend
bezpośrednio.Twoje podejście ostatecznie doprowadzi do powstania bardzo sprzężonego kodu.
Podsumowując idealnie Erica Lipperta tutaj, chciałbyś, aby bokser był w stanie uderzyć bardzo wiele rzeczy. Posiadanie worka bokserskiego jako sygnatury funkcji boksera oznacza, że bokser jest tworzony z natychmiastową znajomością wszystkiego (to jest możliwe do wykrawania). Plus dać cios i otrzymać cios to dwie BARDZO różne rzeczy, dlatego nie powinny mieć tej samej nazwy.
Wolałbym modelować to jako bokser, który tworzy cios (inny obiekt zawierający siłę atrybutu ciosu, zasięg, kierunek itp.).
Następnie mieć worek treningowy za pomocą metody takiej jak onPunch, który odbiera ten obiekt uderzenia, aby obliczyć wpływ stempla na siebie.
Pamiętając o tym, nazwa rzeczy ma duże znaczenie. Musi pasować do twojego mentalnego modelu sytuacji. Jeśli próbujesz wyjaśnić, jak może się zdarzyć coś, co na pierwszy rzut oka nie ma sensu, lub jeśli masz trudności z nazwaniem czegoś, być może twój model jest zły i musi się zmienić.
Po rozpoczęciu ciężko jest zmienić model, ludzie zazwyczaj naginają rzeczywistość, aby dopasować do modelu. Problem polega na tym, że kiedy zginasz rzeczy, aby dopasować (na przykład worek treningowy, który może wykrawać rzeczy), świat, który tworzysz, staje się coraz bardziej złożony, a interakcje stają się coraz trudniejsze do wdrożenia. W końcu osiągniesz punkt, w którym dodanie nawet najbardziej trywialnej rzeczy stanie się koszmarem zmian i błędów. Ten koncepcyjny dług techniczny może mieć bardzo wysoką cenę, nawet jeśli początkowy koszt był wówczas postrzegany jako najtańszy.
źródło
Jest to problem, który nazywam zamieszaniem „obiekt / przedmiot” i jest dość powszechny.
Zdania na ogół mają podmiot, który wykonuje czasownik na swoim obiekcie docelowym .
Jeśli chodzi o programowanie, jedyną rzeczą, która faktycznie robi rzeczy, jest komputer. Lub praktycznie proces, nić lub włókno. Obiekty nie są domyślnie animowane. Nie mają własnych wątków, więc nie mogą nic zrobić.
Oznacza to, że działają na nich metody, są one celem akcji, a nie kto ją wykonuje. Dlatego nazywamy je „przedmiotami”, a nie „podmiotami”!
Kiedy mówisz,
File.close
że to nie plik sam się zamyka, to bieżący działający wątek zamyka plik. Jeśli powieszArray.sort
, bieżący działający wątek sortuje tablicę. Jeśli powieszHttpServer.sendRequest
, bieżący działający wątek wysyła żądanie do serwera (nie odwrotnie!). Podobnie powiedzeniePunchingBag.punch
oznacza, że bieżący wątek przebija torbę.Oznacza to, że jeśli chcesz
Boxer
być w stanie dziurkować, musi to być podklasaThread
tak, aby mogła robić rzeczy takie jak dziurkowanie worków w funkcji wątku.Czasami jednak sensowne jest stwierdzenie, że worek bokserski przebija się sam w przypadku, gdy każdy obiekt ma swój własny wątek, możesz chcieć uniknąć warunków wyścigu i zaimplementować wywołania metod jako przekazywanie wiadomości: przebijasz torbę, wysyłając jej
punch
wiadomość, to dziurkuje wątek następnie odsyłapunch successful
wiadomość, ale to tylko szczegół implementacji.źródło
Zgadzam się, że „cios” jest dobrą nazwą metody dla klasy Boxer, ponieważ (z pewnymi poprawkami) może być ponownie użyty przeciwko innym obiektom. Dokładnie opisuje również, że obiekt klasy wykonuje akcję na innym obiekcie. Chociaż zmieniłbym nazwę metody na „doPunch”, aby jaśniej pokazać związek.
Jednak w przypadku klasy PunchingBag nazwa metody jest albo zbyt niejasna, albo trochę niedokładna w stosunku do tego, co dzieje się w metodzie. Kiedy widzę „uderzenie”, myślę, że coś uderza coś innego. Jednak w tym przypadku obiekt PunchingBag reaguje na uderzenie obiektu (w tym przypadku obiekt Boxer). Chciałbym więc zmienić nazwę metody na „isPunched”, aby zilustrować, że obiekt reaguje na uderzenie.
Jest to jednak moja interpretacja tego, jak nazwałbym metody. Wszystko zależy od gustu i standardów, których przestrzegasz.
źródło
isPunched
jest naprawdę mylące (mniej więcej, w zależności od schematu nazewnictwa ram).punch()
?hmmmm. Pytam worek treningowy jako klasę, ponieważ tak naprawdę nie zależy ci na worku treningowym - zależy ci na uderzeniu i sile pięści bokserów. więc metody powinny dotyczyć wszystkiego, co mierzy i raportuje wpływ ciosu. nawet jeśli pochodzi z „worka treningowego”, nazwa powinna wciąż ujawniać odpowiedzialność - jak punchImpactMeter itp.
źródło
Bokser uderza pięścią worek treningowy -> bokser. Poncz
Worek treningowy zostaje uderzony przez boksera -> punchingbag.get_punch
źródło