Styl akcesorów

2009-11-16 18:46

Ponieważ w C++ nie ma mechanizmu właściwości, do kontroli dostępu do pól w klasie wykorzystuje się metody dostępowe, czyli akcesory. Od kiedy zajmuję się programowaniem w tym języku, starałem się wynaleźć jakąś sensowną konwencję odnośnie tego, w jakiej postaci metody te zapisywać i jak je nazywać.
Niektórzy preferują na przykład utworzenie tylko jednej funkcji postaci:

  1. Typ SetX(Typ x);

która ustawia nową wartość pola i jednocześnie zwraca nam poprzednią. Takie rozwiązania realizuje chociażby funkcja set_new_handler, ustawiająca procedurę obsługi błędu braku pamięci dla operatora new. Nie akceptuję tego sposobu z jednego prostego powodu: bardzo częsta operacja pobrania wartości wymaga tutaj aż dwóch wywołań, które wyglądają co najmniej dziwnie.

Akcesory muszą więc być dwa (get/set). Pozostaje wtedy kwestia: jak je nazywać? Tutaj doszedłem do trzech możliwości:

  1. Skorzystać z przeciążenia funkcji i obie metody nazwać tak samo, czyli po prostu X. Dla kompilatora będą one z łatwością odróżnialne, jako że getter jest bezparametrowy, a setter oczywiście nie.
  2. Użyć nazw GetX i SetX.
  3. Metodę zmieniającą nazwać SetX, ale getter po prostu X.

Chyba każdy z tych trzech sposobów widziałem w użyciu w jakiejś popularnej bibliotece, więc nie są to tylko teoretyczne propozycje. Sam zresztą wypróbowałem po kolei każdą z nich.

I tak rozwiązanie pierwsze jest na pewno najkrótsze, ale sprawia, że wywołania setterów wyglądają dziwnie. Widząc:

  1. scene->Camera (camera);

można zastanawiać się, co autor miał na myśli, a interpretacja “ustaw obiekt kamery dla sceny” nie musi być wcale tą, która nasuwa się jako pierwsza.
Z kolei drugi sposób (z Get/Set) jest całkowicie jednoznaczny, lecz w zamian potrafi wyprodukować łańcuszki w rodzaju poniższego:

  1. game->GetSubsystem(SS_GFX)->GetSceneManager()->GetRenderer()->GetDevice()->Reset();

Wszystkie te Gety trudno uznać za potrzebne do szczęścia, chociaż javowcy pewnie by się kłócili ;)

Dlatego też sposób trzeci polega na pozbyciu się ich (Getów, nie koderów Javy :>). Tę właśnie konwencję (SetX/X) wykorzystuję obecnie i jak dotąd stwierdzam, że sprawdza się dobrze. Dla ostatecznych wniosków byłby jednak potrzebny dłuższy okres, by przekonać się, czy po upływie pewnego czasu nadal mogę patrzeć na swój kod z zachowaniem równowagi psychicznej ;]

Tags: ,
Author: Xion, posted under Programming »


5 comments for post “Styl akcesorów”.
  1. SirMike:
    November 16th, 2009 o 21:40

    Mysle, ze wybrales srednio dobra droge :) Get/Set jest jak najbardziej poprawne i doskonale ulatwia czytanie kodu. Co do nazewnictwa funkcji i ogolnie porzadku w kodzie polecam lekture “Clean Code” Roberta C. Martina.

  2. polymorph:
    November 17th, 2009 o 3:22

    Swego czasu próbowałem zasymulować akcesory makrami, wyglądało to tak:

    #define Accesor template struct
    #define set void operator=(const T& value)
    #define get operator T() const

    //…
    int param_x;

    Accesor ToParamX
    {
    set
    {
    cout << “Accesor set” << endl; param_x = value; } get { cout << “Accesor get” << endl; return param_x; } }; ToParamX ParamX; [/cpp] Ale nie pamiętam jak się to skończyło, czy nie działało(najprawdopodobniej), czy po prostu zdecydowałem że to mi zasyfi kod za bardzo, w każdym razie teraz używam rozwiązania 1.

  3. polymorph:
    November 17th, 2009 o 17:33

    Tak, jak teraz przejrzałem ten kod to okazuje się że to jednak nie działało… ale szperając po dysku znalazłem plik z rozwiązaniem działającym: Link. Ale jak widać jest to zbyt śmieciaste rozwiązanie, więc można to traktować tylko jako ciekawostkę, czy proof of concept że accesory(właściwości) w c++ są możliwe jak się człowiek uprze ^^

  4. Xion:
    November 17th, 2009 o 21:55

    polymorph: Na coś podobnego (do tego rozwiązania z linku) wpadłem już jakiś czas temu, ale nie pomyślałem o użyciu boost::bind przez co rzecz nie była nawet teoretycznie używalna (wymagałaby drugiego parametru w szablonie: typu klasy, w której zawarty jest akcesor).
    To, co pokazałeś, jest zdecydowanie lepsze – właściwie to już jest niemal to samo, co properties z Delphi (po niezbyt trudno uzupełnieniu o drugi szablon, ReadOnlyAccessor).

  5. Reg:
    November 22nd, 2009 o 15:02

    Jest jeszcze notacja put_X i get_X, stosowana w klasach COM AFAIR.

    Ja stosuję nazwy GetX i SetX. Jest taka zasada, która mówi, że nazwy metod powinny mieć czasownik jako że są to operacje, tak jak nazwy pól rzeczownik.

Comments are disabled.
 


© 2017 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.