2009-03-10 18 views
5

Piszę API do tworzenia geometrycznych kształtów i mam pewne problemy z nazwaniem moich metod.Potrzebujesz porady na temat skutecznego nazewnictwa metod?

Weźmy prosty przypadek: Tworzenie okręgu. Większość z nas może być zaznajomiona z metodą taką jak graphics.drawEllipse(x, y, w, h). Aby narysować okrąg, musisz znać lewą górną współrzędną oraz szerokość i wysokość koła.

Moje API ma na celu ułatwić programistom rysowanie kształtów przy użyciu różnych informacji, bez wykonywania wielu zadań matematycznych - co jest banalne dla kręgów, ale bardziej skomplikowane dla innych kształtów. Na przykład powinieneś być w stanie narysować okrąg, biorąc pod uwagę jego współrzędne i promień środkowy, lub górną lewą i dolną prawą współrzędną.

Więc mam Circle klasy z metod fabrycznych, takich jak:

Circle.createWithCenterAndRadius(cx, cy, r) 
Circle.createWithBoundingBox(x1, y1, x2, y2) 
Circle.createWithWidthAndHeight(x, y, w, h) 

Czuję, że może być „zapachy kodu” tutaj, ale nie jestem pewien. Z jednej strony te metody fabryczne są z konieczności opisowe. Z drugiej strony, mogę przewidzieć, że nazwy tych metod wymykają się spod kontroli. Na przykład, jak powinienem nazwać metodę fabularną Triangle, która tworzy trójkąt, biorąc pod uwagę punkt, długość jednej strony, kąt i długość innej strony? Triangle.createWithPointSideAngleAndSide(x, y, side1, angle, side2)? Czy to tylko zło?

Jeśli miałbyś używać tego API, czy nazwy metod byłyby w porządku dla Ciebie? Czy masz porady, w jaki sposób mogę uczynić nazwy metod bardziej rozsądnymi?

+0

z czym się podzieliłeś? – eglasius

+0

Zmieniam metody nazywane "od", tak jak w poście Jason. Usuwam niektóre niepotrzebne komentarze "i", za komentarz Joe_M do wpisu kevchaddera. Rozważałem twój płynny pomysł na interfejs; Używam Java, więc nie mam nazwanych parametrów. Lubię pomysł Slim'a, sprawdzając, czy jest to wykonalne. –

+0

I, planuję kontynuację, kiedy skończę szkic mojego interfejsu API, który powinienem wkrótce. –

Odpowiedz

0

Tak, to jest bardziej meta-odpowiedź, ale sugeruję, abyś zerknął na sposób nazywania nazw w Apple's Cocoa.

11

Jest w porządku w każdym języku, który nie obsługuje nazwanych parametrów. Jeśli język obsługuje parametry nazwane, bardziej podoba mi się skrót Utwórz i po prostu mają oczywiste nazwy parametrów.

dla języka z wymienionych parametrów, byś:

Circle.Create(
    centerX = cx, 
    centerY = cy, 
    radius = r 
); 

Innym bardziej zaangażowani opcją byłby płynny interfejs podobny (ale to chyba za dużo):

circleBuilder.Center(cx,cy).Radius(r) 
circleBuilder.Center(x,y).Width(w).Height(y) 
circleBuilder.BoundWith().Left(x1,y1).Right(x2,y2) 

Centrum powraca instancja klasy pośredniej, która zezwala tylko na promień lub szerokość. I BoundWith zwraca jeden, który zezwala tylko na lewo.

+0

To bardzo dużo kodu do stworzenia. Myślę, że marnowałbyś dużo czasu na tworzenie tego kodu, a następnie próbujesz go uogólnić, więc działa on również podczas tworzenia prostokąta lub trójkąta. – jmucchiello

+0

@Joe, zaktualizował go z "ale to może być zbyt dużo" na "ale to chyba za dużo". – eglasius

14

może zmienić swoje metody okręgu do

Circle.FromCenterAndRadius(...) 
Circle.FromBoundingBox(...) 
Circle.FromWidthAndHeight(...) 

Oznacza to, że tworzysz okręgi z ich różne reprezentacje w rodzaju zwięzły sposób ...

+0

+1 Podoba mi się ulepszenie :) – eglasius

1

przypadku języków, które nie obsługują nazwane parametry, czy byłoby czysto, aby nazwa metody była bardzo prosta, jak np. Circle.create, a następnie po prostu dodaj dodatkowy flagowy ciąg znaków (np. "środek" lub "obramowanie"), który wskazywał, w jaki sposób wartości wejściowe powinny być interpretowane dla sprawy trudne do rozróżnienia na podstawie danych wejściowych v żywa liczba i typ? Wadą tego jest to, że wymaga dodatkowej logiki wewnątrz metody do obsługi różnych typów argumentów wejściowych, a także wymaga, aby użytkownik pamiętał opcje flagi.

1

Chciałbym mieć metody CreateTriangle i mieć przeciążenia pokazać różne wymagane informacje.

E.g.

Circle.CreateCircle(cx, cy, r) 
Circle.CreateCircle(point1, point2) 
Circle.CreateCircle(point, width, height) 
+0

+1: Uzgodnione. Tak też bym to zrobił ... Niech przeciążone parametry mówią same za siebie. – Cerebrus

+0

er, masz tu dwie metody o tych samych parametrach (zakładając, że wszystkie parametry są typami całkowitymi). – slim

+0

jesteś prawidłowa, lepiej byłoby użyć rdzenia klasy Point niż dwóch int, aby rozróżnić – cjk

8

Myślę, że nie ma nic złego w metodach opisowych - są one zwarte i opisują dokładnie to, co się dzieje. Użytkownicy biblioteki nie będą mieli wątpliwości co do funkcji twoich metod, ani programistów obsługi.

Można również zastosować wzór projektu, jeśli naprawdę martwisz się o ujawnienie dużej liczby metod fabrycznych - takich jak posiadanie metod fabrycznych z klasami właściwości. Możesz mieć klasę CircleProperties z właściwościami takimi jak CenterX, CenterY, Radius, (bool) UseCenterX, (bool) UseCenterY itd., A następnie przekazujesz to do publicznej metody fabrycznej, która określi, która (prywatna) metoda fabryczna do użycia.

Zakładając C#:

var circleProperties = new CircleProperties() 
{ 
    CenterX = 10, 
    CenterY = -5, 
    Radius = 8, 
    UseCenterX = true, 
    UseCenterY = true, 
    UseCenterRadius = true 
}; 

var circle = Circle.Create(circleProperties); 
+0

Czy naprawdę potrzebujesz właściwości "UseX"? Nie możesz po prostu sprawdzić, które właściwości zostały ustawione (czy nie są zerowe)? Lub ustawić je w ustawieniach dla innych właściwości (np. SetCenterX() ustawia UseCenterX)? – TMN

+0

TMN: Możesz, ale naprawdę musisz wybrać poprawne liczby magiczne ... Oczywiście 0.0 jest całkowicie poprawną współrzędną. Ustawienie tych wartości logicznych automatycznie w odpowiednim ustawiaczu jest jednak dobrym pomysłem. –

6

Moim pierwszym odruchem jest mieć więcej typów, które pozwoliłyby na bardziej intuicyjne metody przeciążeniem.

// instead of Circle.createWithCenterAndRadius(cx, cy, r) 
Circle.create(new Point(cx,xy), r); 

// instead of Circle.createWithBoundingBox(x1, y1, x2, y2) 
Circle.create(new Point(x1,y1), new Point(x1,y1)); 
// or even... 
Circle.create(new Box(p1,p2)); 

// instead of Circle.createWithWidthAndHeight(x, y, w, h) 
Circle.create(new Point(x,y), w, h); 

Jak również punkt, można określić odległość (który pozwoliłby na różnych jednostkach)

Jeśli odpowiada Ci ten styl, dlatego trzeba rozważyć metodę fabryki zamiast konstruktora.

Circle c = new Circle(new Point(cx,xy), r); 
-1

Wiem, wiem. To brzmi dla ciebie zupełnie szalenie C/C++/Java, ale przykłady podane w pytaniu i we wszystkich tych odpowiedziach wyraźnie pokazują, jaka jest zła, zła konwencja CamelCaseNaming.

Chodźmy przyjrzeć się oryginalnym przykład:

Circle.createWithCenterAndRadius(cx, cy, r) 
Circle.createWithBoundingBox(x1, y1, x2, y2) 
Circle.createWithWidthAndHeight(x, y, w, h) 

A teraz pozbyć takim przypadku camel notacji

Circle.create_with_center_and_radius(cx, cy, r) 
Circle.create_with_bounding_box(x1, y1, x2, y2) 
Circle.create_with_width_and_height(x, y, w, h) 

To może wydawać się strasznie unfamilar, ale szczerze: która wersja jest łatwiej czytać?

+0

Nie jest to zły przykład - w rzeczywistości jest nieco łatwiejszy do odczytania - ale zupełnie nieistotny. To nie tak, że ktoś się zmienia lub cokolwiek (i MAN byłoby źle, gdyby ktoś zrobił !!) Więc co próbujesz osiągnąć? –

+0

Uwaga: Kiedy jestem w Javie używam składni Java, gdy jestem w Ruby użyłem składni Ruby. Nie czułem potrzeby przełączania użytkowników jednego na drugiego - oba są całkiem czytelne. ps. Chociaż rubin jest nieco łatwiejszy do odczytania, java jest znacznie łatwiejsza do wpisania. –

0

Twój instynkt jest prawidłowy - cały wzór tworzenia rzeczy w ten sposób jest - niepewny.

O ile te nie zostaną użyte tylko raz lub dwa razy, staną się nieuporządkowane. Jeśli tworzyłeś kształt z 5 okręgami i 3 trójkątami, byłby to bałagan.

Cokolwiek poza trywialnym przykładem byłoby najlepiej zrobione przy użyciu implementacji opartej na danych.

Dążenie do tych końców, biorąc pod uwagę ciąg znaków, hasz lub XML, aby zdefiniować kształty, może być bardzo przydatne.

Wszystko zależy od tego, w jaki sposób można je wykorzystać.

Mam takie same problemy z tworzeniem elementów sterujących Swing w Javie. Kończy się wiersz po wierszu "nowego przycisku()", po którym następuje szereg wywołań właściwości .set, a także wiersz kodu, który służy do kopiowania wartości do obiektu (lub dodawania odbiornika), oraz wiersz do resetowania wartość..

Tego rodzaju zestaw znaków nigdy nie powinien się zdarzyć w kodzie, więc zwykle próbuję znaleźć sposób na napędzanie go danymi, wiążąc kontrolki z obiektami dynamicznie - iw tym celu opisowy język oparty na łańcuchach znaków byłby bardzo pomocny.

+0

Twoja sugestia zdecydowanie ma zalety. Czy możesz podać krótki przykład implementacji opartej na danych? W przypadku "łańcucha znaków" sugerujesz coś takiego jak język specyficzny dla domeny (DSL)? –

Powiązane problemy