DOs & DONTs – część druga

Dzisiaj przyjrzymy się słowu kluczowemu var w C#. Słowo dodane wraz z premierą framework’a .NET 3.5 stało się jednym z najbardziej nadużywanych przez programistów. Jeśli chodzi o założenia, miało być pięknie:

foreach (var car in cars)
{
   // do something
}

var result = 
from c in cars 
where c.Brand == 'Ford'
select c;


a wyszło tak, że programiści zaczęli stosować var wszędzie, gdzie się tylko dało. I tu pojawiają się problemy:

var human = new Human(); // Ok, wiadomo, że human będzie typu Human
var settings = GetSettings(); // Ustawienia...hmmm - jakiego typu? co to za ustawienia?
var second = GetSecond(); // tragedia
var x = GetX(); // jakiego typu jest x?

I tak: przykład nr 1 ujdzie w tłumie, ponieważ mniej więcej wiadomo, czego możemy się spodziewać na wyjściu; przykład nr 2 – tutaj jest już dużo gorzej, ponieważ mamy jakieś ustawienia, w sumie nie wiemy co to za ustawienia, a nazewnictwo metody nam w tym nie pomaga. O ile łatwiej byłoby, gdyby otwierając kod, programista widział coś takiego:

ConcreteSettings settings = GetSettings(); 

Przykład nr 3 – tragedia!!! Jeśli w przykładzie nr 2 mogliśmy się domyślać o co chodzi, to tutaj nie mamy zielonego pojęcia. Może zarówno chodzić o to, żeby pobrać konkretną sekundę na podstawie jakichś danych, ale równie dobrze może pobierać obiekt, który będzie drugi (np. na jakimś wyjściu). Przykład nr 4 – znowu czarna skrzynka – widzimy metodę, która zwraca jakiś x oraz jakiegoś typu x, do którego przypisany jest wynik metody.

Używanie w odpowiednich miejscach var jest korzystne, ale nie może być ono nadużywane, ponieważ niestety zaciemnia kod i wymaga dodatkowych wysiłków (a co za tym idzie – kosztów).

17 uwag do wpisu “DOs & DONTs – część druga

  1. Moim zdaniem w Twoim przykładzie problemem są nazwy metod, a nie nadużywanie słowa kluczowego var. Odpowiednie nazywanie zmiennych i ich metod poprawia czytelność kodu wystarczająco aby nazwa typu przed deklaracją zmiennych nie była bardzo dużym DOSem
    var settings = sqlConnection.GetSettings(); //zapewne zwraca obiekt typu SqlConnectionSettings (pomijam konwencje nazewniczą rodem z Javy)
    Ja raczej nazwałbym to kwestią gustu.

  2. Tak jak kolega wcześniej napisał wydaje mi się że odpowiednie nazewnictwo najpierw metody i później samej zmiennej załatwiłaby sprawę. (Bronię sam siebie bo też prawie zawsze wrzucam var)

  3. Tak na moje skromne oko przy takim nazewnictwie metod duży projekt byłby koszmarem…
    Liczyłem na konkretniejsze przykłady a nie pokazanie, że nie wiemy co siedzi w środku :/
    Zresztą var zazwyczaj siedzi w czymś, i jeżeli te settingsy z przykładu są podpięte pod konkretny element z tego czegoś to wiemy czego w varze się możemy spodziewać. Chyba, że mówimy o kodzie spaghetti…

    1. Wszystko się zgadza, ale wlasnie o to m.in. chodzi w tym przykładzie – nie każdy kod jest sztuką, czasem lepiej od razu zobaczyć typ niż zastanawiać się co autor miał na myśli. Dzięki za uwagi, następnym razem postaram się skupić na konkretach, aczkolwiek w przypadku przykladu z GetSecond uważam, że trafnie obrazuje problem 🙂

  4. Ja stanę po stronie autora bloga 🙂 Też uważam, że var jest nadużywane. Otwierając plik chcę od razu przeczytać kod, a nie się domyślać, najeżdzać myszką itp. Znając dobrze projekt, konkretne typy dają mi więcej informacji co się dzieje w danym fragmencie kodu. Wiadomo, że w trakcie pisania kodu, to się wie co siedzi po var-em. Ale kolega obok, który zajrzy tam później już nie będzie wiedział. Ja prawie w ogóle nie stosuję var, a jak widze coś takiego to alt+enter z R# i jest ok 🙂

      1. Dokładnie. Dlatego jest tyle var, bo człowiek woli już sam to napisać niż później zmieniać.

  5. To nie var jest nadużywane w tym kodzie, tylko słaby kod. Bo cóż wnosi ConreteSettings gdy dostajemy je z jakiejś enigmatycznej metody GetSettings?

    1. W takiej sytuacji, gdy mamy do czynienia ze slabym kodem, czytelność jest dużo gorsza niż w przypadku jawnego typowania. Przykłady mają na celu pokazanie „smaczków” z codziennego życia. Co w przypadku Second, które wcale nie jest juz takie enigmatyczne?:)

  6. Jako, że widzę duże zainteresowanie, powiem jeszcze to:

    Absolutnie nie jestem przeciwnikiem używania var, jednak w odpowiednich miejscach. Wychodzę z założenia, że jeśli od razu widać czego możemy się spodziewać używajmy var, jednak w każdy m innym przypadku, użycie jawnego typowania będzie bardziej czytelne.

  7. Moim zdaniem jawne podawanie typów nie jest do niczego potrzebne. Kogo obchodzi czy to jest ConnectionSettings, ExtendedConnectionSettings czy MyCustomSettings. Ważne, że mamy jakieś obiekt settings z którego wybieramy interesujące nas wartości. Równie dobrze to by mogło być ISettings.Loosly couple code. Ważne jest co się dzieje, a nie kto to robi.
    A jeżeli za chwilę zmienię obiekt zwracany z metody to nie muszę zmieniać wszystkich miejsc korzystających z metody.

  8. var czasem się przydaje, ale jest nadużywane bardzo, zwłaszcza przez młodych programistów. Nie chce tracić czasu widząc var na domyślanie się co tam za tym siedzi. Ja jeśli wiem jaki konkretny typ ma znaleźć się w zmiennej to zawsze go podaje. Ms dodaje wiele do języka c#, ale nie każde jest warte używania…

  9. Słowo var zostało wprowadzone z NET 3.5 nie dlatego ze było jakoś szczególnie potrzebne tylko dlatego ze bez niego linq byłoby męczące w używaniu (tworzenie klas aby wykorzystać je w dwóch linijkach) – tak wiec zadny przykład nie jest w 100% poprawny. A co do złośliwości to wystarczy stworzyć klasę o nazwie var 😉

  10. var używam prawie wszędzie gdzie się da. Chociaż trochę razi mnie gdybym miał go używać np. zamiast int.

    Zupełnie nie rozumiem problemu z używanie var gdy zaraz obok jest new. Piszesz, że mniej więcej wiadomo jakiego typu będzie zmienna. Mniej więcej? 🙂

    Przykład z settings. Odpowiedz proszę po co ci znajomość konkretnego typu? Nie widzę tutaj żadnego problemu.

    W przypadku GetSecond() i GetX() możemy mieć tutaj problemy słabych nazw metod, albo nie mieć problemu wcale. Jeżeli GetSecond() jest metodą składową klasy Timer/Clock itp, a GetX składową klasy Point to wszystko jest pięknie.

    Dla mnie w moim (lubię o nim myśleć jako bardzo czystym :)) kodzie var ma same zalety.
    Dodatkowo pozwala na zmianę zwracanego typu bez konieczności zmiany typów deklarowanych zmiennych. Np. metoda zwracająca tablicę może zwracać IEnumerable i nie muszę nic zmieniać w kodzie – foreach działa nadal.

  11. Ostatnio przejechalem sie na uzywaniu var przy okazji robienia tdd kata http://www.mfranc.com/tdd/tdd-commit-by-commit-string-calculator-ii/ .

    Metoda miast zwracac ‚int’ zwracala ‚object’ (najprawdopodobniej wina nie umiejetnego wykorzystania R#). Test jednotskowy tego nie wychwicil wlasnie przez uzycie var. Assercja nie miala problemu.

    Zaczalem deklarowac teraz typ przy wartosciach oczekiwanych w testach. Dzieki temu zyskuje dodatkowe sprawdzenie, w czasie kompilacji czy zwracany typ jest poprawny.

Zostaw komentarz

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj /  Zmień )

Zdjęcie na Google+

Komentujesz korzystając z konta Google+. Wyloguj /  Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj /  Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj /  Zmień )

w

Connecting to %s