Czysty kod

Jestem na krótko po przeczytaniu Czystego Kodu od Wujka Boba i chciałbym się podzielić kilkoma wrażeniami z książki. Jest to zbiór przypowieści o tym, jak pisać kod, pozostał on czysty i czytelny. Aby utrzymanie kodu nie było karą za złe zachowanie, a pisanie testów nie było piekłem dla programistów. Poza tym testy piszemy przed napisaniem kodu – rajt?

Wszystkie złe rzeczy, które przez przypadek mogliśmy wyprodukować są opatrzone przykładowym kodem, rozwiązania także przedstawiają kod. Wskazówki sugerowane przez wujka, są dobre dla początkujących programistów jak i dla wypasionych developerów – nawet jako forma przypomnienia.

Poniżej kilka przykładów, które sobie zanotowałem, część z nich to oczywistość. Uważam jednak, że warto wracać do podstaw, kod pochodzi z książki.
Nazwy zmiennych
Dobrze aby nazwy było tak dobrane, aby dało się je wymówić. Ułatwia to zapamiętywanie struktury kodu, komunikację w projekcie oraz czytelność. Dotyczy to nazw klas/struktur, metod oraz zmiennych. Jak pisze wuj Bob: jeśli piszesz komentarz aby opisać zmienną, usuń komentarz i popraw nazwę zmiennej.
ZŁY KOD DOBRY KOD
class DtaRcrd102 
{
    private DateTime genymdhms;
    private DateTime modymdhms;
    private string pszqint = „102”;
};
class Customer 
{
    private DateTime generationTimestamp;
    private DateTime modificationTimestamp;
    private string recordId = „102”;
};
Magiczne wartości
Omijamy je z daleka, jeśli musisz wpisać gdzieś ‚7’, to utwórz zmienną, która swoją nazwą powie, że ‚7’ to jest dni w tygodniu.
ZŁY KOD DOBRY KOD
for (int j=0; j<34; j++) 
{
    s += (t[j]*4)/5;
}
int realDaysPerIdealDay = 4;
const int WORK_DAYS_PER_WEEK = 5;
int sum = 0;
for (int j=0; j < NUMBER_OF_TASKS; j++) 
{
    int realTaskDays = taskEstimate[j] * realDaysPerIdealDay;
    int realTaskWeeks = (realdays / WORK_DAYS_PER_WEEK);
    sum += realTaskWeeks;
}

Tworzenie obiektów
Nie ograniczaj się tylko do konstruktorów i ich ciągłego przeciążenia, skorzystaj z wzorca metoda wytwórcza.
MOŻNA LEPIEJ
Complex fulcrumPoint = new Complex(23.0);

Complex fulcrumPoint = Complex.FromRealNumber(23.0);
Krótko zwięźle i na temat
Ilość przekazywanych argumentów do funckji powinna być możliwie najmniejsza:
1 – spoko
2 – jeśli musisz
3 – zastanów co robisz 
4 – WTF? 
5 – link
Może któryś z parametrów uda się przenieść na stałe do klasy, co zmniejszy ich ilość w sygnaturze funkcji. Jeśli nie, to zaproponuj strukturę przechowującą tą ogromną ilość parametrów i przekazuj taką strukturę.
Pamiętacie wpis o SOLID, otóż wyobraźcie to sobie, że SRP (single
responsibility principle) można też zastosować wobec metod i funkcji.
Niech będę zwięzłe, krótkie, monotematyczne i nie posiadają efektów ubocznych.
ZŁY KOD, ZŁY
public boolean checkPassword(String userName, String password) 
{
    User user = UserGateway.findByName(userName);
    if (user != User.NULL) 
    {
        String codedPhrase = user.getPhraseEncodedByPassword();
        String phrase = cryptographer.decrypt(codedPhrase, password);
        if („Valid Password”.equals(phrase)) 
        {
            Session.initialize();
            return true;
        }
    }
    return false;
}

Rozdzielenie odpowiedzialności
CQS (command query separation)- Bob zaleca odseparowanie polecenia od zwracania wartości:
STARE NAWYKI NOWE NAWYKI
if (set(„username”, „unclebob”))
{…}
if (attributeExists(„username”))
{

     setAttribute(„username”, „unclebob”);

}

Trochę więcej o CQS można znaleźć na wiki.

Błędy i wyjątki
Preferuj wyjątki zamiast zwracania kodu błędu:
ŹLE DOBRZE
if (deletePage(page) == E_OK) 
{
    if (registry.deleteReference(page.name) == E_OK) 
    {
        if (configKeys.deleteKey(page.name.makeKey()) == E_OK)
        {
            logger.log(„page deleted”);
        }
         else 
        {
            logger.log(„configKey not deleted”);
        }
    } 
    else 
    {
        logger.log(„deleteReference from registry failed”);
    }

else 
{
    logger.log(„delete failed”);
    return E_ERROR;
}
try
{
deletePage(page);
registry.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey()
}
catch(…)
{
}

Obsługę błędów i wyjątków separuj od logiki kodu:

RAZEM OSOBNO
try 
{
    deletePage(page);
    registry.deleteReference(page.name);
    configKeys.deleteKey(page.name.makeKey());
}
catch (Exception e) 
{
    logger.log(e.getMessage());
}
public void delete(Page page) 
{
    try 
    {
        deletePageAndAllReferences(page);
    }
    catch (Exception e) 
    {
        logError(e);
    }
}

private void deletePageAndAllReferences(Page page) throws Exception 
{
    deletePage(page);
    registry.deleteReference(page.name);
    configKeys.deleteKey(page.name.makeKey());
}

private void logError(Exception e) 
{
    logger.log(e.getMessage());
}

Komentarze
Nie powtarzaj się i nie opisuj kodu w komentarzach:
SAMO ZŁO
assertTrue(a.compareTo(a) == 0); // a == a
assertTrue(a.compareTo(b) != 0); // a != b
assertTrue(ab.compareTo(ab) == 0); // ab == ab
// if the timeout is reached.
public synchronized void waitForClose(final long timeoutMillis) throws Exception
{
    if(!closed)
    {
        wait(timeoutMillis);
        if(!closed)
            throw new Exception(„MockResponseSender could not be closed”);
    }
}

Formatowanie kodu
Ustal formatowanie w projekcie i się go trzymaj, popraw czytelność stosując wcięcia, odstępy.
GORZEJ LEPIEJ
void foo()
{
    int zmiennaA;
    int zmiennaB;
    int zmiennaC;
    operacjaA()
    operacjaB()
    operacjaC()
    operacjaD()
}
void foo()
{
    int zmiennaA;
    int zmiennaB;
    int zmiennaC;

    
    operacjaA()
    operacjaB()

    
    operacjaC()
    operacjaD()
}
Abstrakcja i interfejsy
Udostępniaj tylko tyle informacji o klasie i jej stanie wewnętrznym ile potrzeba. Zasada ograniczonego zaufania w programowaniu też ma sens, korzystaj z interfejsów i abstrakcji
OK OKIEJEJ ( w sensie, że lepiej)
public interface Vehicle 
{
    double getFuelTankCapacityInGallons();
    double getGallonsOfGasoline();
}
public interface Vehicle 
{
    double getPercentFuelRemaining();
}

Zastanów się nad tym co udostępniasz innym:

🙁 🙂
List<int> getList()
{…}
IEnumerable<int> getList()
{…}

Chyba że lubisz (lub chcesz), sytuację gdy klient może wywołać getList().Clear();

Tam sięgaj gdzie ręka dosięga:

Klasy powinny korzystać ze swoich zmiennych, otrzymanych jako parametr, lub stworzonych przez siebie. Jeśli musisz stworzyć  okrutne połączenia, lepiej jest rozbić wszystkie wyniki na poszczególne wywołania. Wyjątkiem jest sytuacja, gdy dostęp następuje przez publiczne pola struktur. Choć i tak najlepiej jest kazać klasie odpowiedzialnej zrobić wszystko za nas:
ZŁE LEPIEJ SUPERAŚNIE
final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();
final String outputDir = ctxt.options.scratchDir.absolutePath;
output.ctxt.GetAbsolutePathToScratchDir()
//sposób na uratowanie honoru
Options opts = ctxt.getOptions();
File scratchDir = opts.getScratchDir();
final String outputDir = scratchDir.getAbsolutePath();

Law of Demeter

Obiekty NULL
O ile to możliwe zamiast NULL postaraj się zwracać neutralne obiekty, takie które nie wywalą kodu a jednocześnie nie spowodują jego zmiany:
BRZYDKO ŁADNO
List employees = getEmployees();
if (employees != null) {
    for(Employee e : employees) {
        totalPay += e.getPay();
    }
}
List employees = getEmployees();
for(Employee e : employees) {
    totalPay += e.getPay();
}

getEmployess() zamiast NULL zwraca pustą kolekcję.

To tylko część z tego co proponuje Martin. Jeśli jesteście zainteresowani to jeszcze raz zachęcam do przeczytania. Czyta się szybko i przyjemnie. Jedyny minus (taki na siłę) to przykłady są w JAVA – ale niech będzie. 

Uwagi i komentarza zawsze chętnie przyjmę.

Początki raz jeszcze

Jest taka książka Accelerated C# 2010 którą postanowiłem przeczytać, aby utrwalić swoją wiedzę z C#. W polskiej księgarni można znaleźć za około 120 nowych polskich złotych.
Jest przyjaźnie napisana i tłumaczy w lekki (dla mnie) sposób C#. Jej dużym plusem jest to, że nie jest ona dla początkujących programistów, a raczej dla osób które posiadają wiedzę z C++/Java (czy innego języka) i teraz chcieli by się nauczyć szarpa. Dlaczego tak się zajarałem? Książki które czytałem wcześniej nie wspominały nic o destuktorach (ani o tym, że w zasadzie nie powinno się z nich korzystać) w C# czy konstruktorach statycznych.
Te statyczne konstruktory to dla mnie w ogóle faza, w javie też niby są, ja tam nie wiem, javą się nie interesowałem. Poza tym gostek (w sensie autor), pisze też trochę o ILDASM, jak to wygląda w środku i czego się nie powinno używać. Myślę sobie, że to dobra książka na powtórzenie podstawowych wiadomości o tym języku w wersji 4.0.
Przy okazji będę mógł, wreszcie uczciwie napisać z której książki nauczyłem się podstaw.

Słówka kluczowe:
Konstuktor statyczny
Destruktory
params (tego też nie znałem)

Uwagi do mojej wybrakowanej wiedzy, słownictwa i prostactwa proszę zamieszczać w komentarzach.
A korzystając z okazji zapraszam na:

Geeks on tour (spotkania trzech grup społecznościowych, związanych z technologiami Microsoft)
wrocnet (wrocławska grupa .net)

C# nauka, materiały, etc

Każdy chciałby się szybko, przyjemnie i w interesujący sposób uczyć nowych technologi, języków czy bibliotek.
Nie da się tego wszystkiego tak łatwo osiągnąć, albo ja nie znalazłem jeszcze sposobu. Jeżeli wiecie to będę wdzięczny za podzielenie się taką informacją.
Nie ustając się w poszukiwaniu idealnego sposobu na naukę znalazłem jeden, który można uznać za prosty. Trzeba tylko posiedzieć przed monitorem i pooglądać kilka prezentacji przygotowanych przez ziomali z microsoft i firm z nimi współpracujących.

Ale first things first – podstawy:
Każdy porządny i szanujący się programista, powinien przebrnąć przez trochę książek  (przynajmniej jedną) i napisać trochę linii kodu, aby w miarę płynnie posługiwać się językiem którego chce używać. Część z nas czyta wszystko od A do Z w oficjalnych książkach wydanych przez MS, inni lecą po łebkach i korzystają z różnego rodzaju kursów dostępnych na blogach. Rozumiem, każdy przyswaja wiedzę w inny sposób. Ważne jednak jest aby każdy rozróżniał klasę od obiektu, wskaźnik od referencji, czy inne słowa.
Próbowałem obu podejść (łebki vs książki) i moim skromnym zdaniem lepiej przeczytać książkę, tak aby dobrze opanować podstawy. Ja przeczytałem i mocno polecam (ten post dotyczy c#) Charles Petzold Programming MS Windows with C#, wcześniej czytałem też programowanie dla Win32 i też jest to dobra pozycja. Najmocniej przepraszam, ale nie mogę sobie przypomnieć nazwy książki, którą czytałem aby poznać podstawy C#.

Opanowałem podstawy i co dalej?
Namiętnie oglądam ostatnio serię „How do I” dla WPF i ogólnie C#. Wcześniej przejrzałem kilka dłuższych prezentacji z PDC i muszę powiedzieć, że dzięki temu w szybki sposób można poznać to co nowe (przynajmniej dla mnie, bo wciąż jestem początkującym programistą C#), oraz nauczyć się jak zrobi ficzera X.
PDC2008
PDC2009
PDC2010
How do I (wpf)
Naprawdę polecam zainteresowanie się tymi materiałami.

Czy coś jeszcze? Można się zapisać do różnych lokalnych grup wsparcia dla anonimowych programistów i tam się dalej rozwijać do czego także namawiam. Ja jak tylko znajdę czas i chęci to też się zapisze.

Pozdro
JS

ps.
Dzisiaj jakoś tak bez drwin.

SDJ za free

Dużo na głowie i nie mam czasu na naukę i kodowanie.

Teraz taki szybki wpis o Software Developer’s Journal – otóż można już to czasopismo legalnie ściągać za darmo ze strony wydawcy. Dla użytkowników AdBlock uwaga, wyłączcie blokowanie reklam, link do zaciągnięcia .pdf ma nie fortunna nazwę i jest blokowany. Oprócz najnowszego numeru można sięgnąć na kilka wydać wstecz.

Całkiem miła sprawa z tym SDJ.

android, programowanie, ksiązki

Z czego się uczyć? To dobre pytanie, można czytać developer.android.com, można szukać na google, można zapytać kolegi, lub zobaczyć co jest np na amazon do przeczytania i kupić sobie książkę. Ja przejrzałem to co oferuje apress, na google book można znaleźć sporą część książki, zdecydowanie nie polecam. Jak dla mnie jest pisana zbyt chaotycznie, jakoś źle mi się to czytało. Natomiast ponownie jestem pod wrażeniem wydawnictwa wrox i takiej książki autorstwa Reto Meier. Wszystko jest tłumaczone, przykłady pisze się samodzielnie, a nie ściąga ze strony wydawnictwa. Wcześniej czytałem coś o programowaniu w c# i .net framework 3.5 i również uważam, że książka była dobrze napisania.
Nauka na przyszłość jak będzie potrzeba przeczytania i nauczenia się jakiejś nowej technologi napewno zacznę naukę od sprawdzenia co oferuje wrox

ps
Post niestety nie jest sponsorowany.