czwartek, 30 stycznia 2014

clean code 4

Praca z kodem czyli moje zajęcie :)
OK. Rozpoczynamy naszą  walkę o dobry kod.
Na sam początek zdefiniujemy sobie kilka terminów lub pojęć, które wypada znać.
Może inaczej,  bez ich znajomości nie można pisać dobrego kodu - takie jest moje zdanie. Są to głównie paradygmaty OO takie jak SOLID, GRASP etc.
Poniżej przygotowałem w skrócie prezentacje w xmind na której widać o co w tym wszystkim biega.


W poście tym, który jest kontynuacją poprzedniego który to mówił co należy zmienić w Twojej mentalności tak abyś stał się profesjonalistą w tym co robisz.
Teraz dowiesz się  jakie praktyki proponuje C.Martin. Jak należy dobrze programować w OO oraz inne pożyteczne wskazówki, które to mam nadziej wzbogacą Twój warsztat.


Ale co to jest czysty kod (według Uncle Boba)?
Czysty kod to kod elegancki, efektywny, prosty, pełen trafnych abstrakcji.
Łatwo sterowalny. Każdy o niego dba. Posiada i przechodzi testy jednostkowe i akceptacyjne. Jest wolny od powtórzeń. Powinien być maksymalnie minimalny objętościowo. Generalnie opiera się na wszystkich zasadach SOLID i GRASP.


TIP : @author (Javadoc) - kod bez jawnego autora, sprawia, że rozmywa się odpowiedzialność. Podpisany kod jest podatny na ocenę innych i o to w tym chodzi.


Prawo Demeter mówi, że metoda danego obiektu może odwoływać się jedynie do metod:
 - należących do tego samego obiektu,
 - metod dowolnego parametru przekazanego do niej,
 - dowolnego obiektu przez nią stworzonego,
 - dowolnego składnika klasy do której należała dana metoda.


W praktyce oznacza to, że obiekt powinien unikać wywołania metod klasy, której obiekt został mu dostarczony przez inny obiekt. np. w języku Java kod a.b.metoda() łamie prawo Demeter,  podczas gdy a.metoda() tego prawa nie łamie.
Tak więc prawo Demeter ogranicza długie łańcuchy wywołań.
Popularnie jest ono wyrażane: 'Nigdy nie rozmawiaj z obcymi'.

Stosowanie prawa Demeter, ułatwia pielęgnację, zmniejsza współczynnik błędów, ogranicza powiązania między obiektami, wzmacnia hermetyzację i abstrakcję
obiektów, a tak że powoduje przeniesienie odpowiedzialności za dostęp do metod i atrybutów klasy z obiektu odwołującego się do nich na ich właściciel

Loose coupling (luźne wiązania) - jest to własność systemu, która oznacza, że jego poszczególne moduły mogą być traktowane w dużym stopniu niezależnie i ich kody nie są ze sobą ściśle powiązane.

Cohesion -  miara powiązań funkcjonalnych metod w danej klasie. Należy dbać o utrzymanie wysokiej spójności (high cohesion).
Jeżeli jedna klasa odpowiada za zbyt wiele zagadnień (jest niespójna), z czasem nadmiernie się rozrośnie i będzie trudna do zrozumienia oraz pielęgnacji. Czasem należy przenosić odpowiedzialność do klas potomnych lub pomocniczych w celu zwiększenia ogólnej spójności.

TIP : LCOM4 , Metryki Kodu

Projektowanie pakietów










  Reguły SOLID :






























Zasady GRASP :



















Zdiagnozowane i zdefiniowane problemy: 








































Moje stare notatki :






































Zasady projektowania :
















Java class layout :
 1.Package statement
 2.Import statements
 3.Comments
 4. Class declaration {
          5. Variables
          6. Comments
          7. Constructors
          8. Methods
          9. Nested classes
         10. Nested interfaces
         11. Enum
 }

TIP : Sonar rules , PMD rules

Zalecenia uncle Boba :

TIP : Zasada skautów (The boy scout rule)
(leave the campground cleaner than you found it)

 - używaj nazw przedstawiających Twoje intencje. (Use Intention-Revealing Names)

Wybór odpowiedniej nazwy jest naprawdę ważną rzeczą - utrzymanie kodu)
     int k; // jest  niedopuszczalne 
  
TIP:  Avoid inconsistent naming  
 - unikaj dezinforamacji (Avoid Disinformation)

 - używaj nazw które można wymówić (Use Pronounceable Names)
 - używaj nazw łatwych do wyszukania (Use Searchable Names)
    (The length of a name should correspond to the size of its scope)

 TIP : Magic numbers (PMD rules ,  Sonar rules)
 TIP : new Syntactic sugar like :  binary literals, underscores in numbers, diamond syntax (lub Guava Static constructors)


   - klasy to rzeczowniki (unikaj takich nazw jak Manager, Info, Processor, Data)
   - metody są czasownikami
   - gdy konstruktory są przeciążone zastąp je metodą fabrykującą

   Uwaga: W konstruktorze nigdy nie może być metoda którą możesz przesłonić !  

   - wybieraj jedno słowo na pojęcie (Pick One Word per Concept
      (np fetch, get, retrieve etc) Nazwy funkcji powinny być niezależne i spójne.

  - korzystanie z nazw dziedziny rozwiązania  (Use Solution Domain Names)
   (np : AccountVisitor - zastosowany wzorzec visitor)

  - dodanie znaczącego kontekstu (Add meaningful context)
     Czasem warto dodać przedrostek by pokazać, że zmienna jest częścią większej struktury.

Funkcje

    - funkcje powinny być krótkie (small), najlepiej jak mają maksymalnie kilka linii < 20.
    - funkcje powinny wykonywać tylko jedno zadanie (Do One Thing), jeśli tak nie jest istnieje realna potrzeba dekompozycji funkcji na mniejsze logiczne kawałki
   - wartość zagnieżdżenia instrukcji warunkowych w jednej funkcji (Blocks and Indenting) nie powinna przekraczać 2 (<2). (czytelność, złożoność lokalna)
   - działanie funkcji powinno opierać się na jednym poziomie abstrakcji   (One Level of Abstraction per Function)

   - funkcje pisz tak aby łatwo można było je czytać od góry do dołu
     (Reading Code from Top to Bottom: The Stepdown Rule)

  - instrukcje switch (Switch Statements)
    Należy uważać na instrukcje typu switch ponieważ często są to duże byty, często naruszają zasadę SRP oraz OCP .

 TIP : użyj Abstract Factory

  - korzystaj z nazw opisowych (Use Descriptive Names) - aby dokładniej sprecyzować faktycznie znaczenie funkcji oraz czynności jaką ma za zadanie wykonać. (długa nazwa nie jest problemem)

 - argumenty funkcji (Function Arguments)
Generalnie trzymajmy się zasady im mniej tym lepiej bo jest ona wtedy łatwiejsza do analizy. Przyjmuje się, że funkcje powinny zawierać max do trzech argumentów. Argumenty sprawiają też, że taką funkcję jest trudniej przetestować. Funkcje z jedno-argumentowym typem boolean są złe, bo oznacz to, że funkcja wykonuje więcej niż jedną operację.
Jeśli funkcja wymaga więcej niż dwóch czy trzech argumentów użyj wrapper. Funkcje powinny być czasownikami lub tworzyć parę czasownik-rzeczownik. Jeśli już się zdarzy, że funkcja złamie zasadę SRP to Twoim obowiązkiem jest zasygnalizować to w nazwie funkcji.

 - argumenty wyjściowe (Output Arguments)
 Analiza wyniku argumentów wyjściowych z reguły trwa długo. Można odwoływać się do referencji this jako wyniku działania danej funkcji. Po prostu funkcja zmienia stan własnego obiektu i ma do tego prawo (OO).

 - stosowanie wyjątków zamiast kodów błędów (Prefer Exceptions to Returning Error Codes) prowadzi do powstawania głęboko zagnieżdżonych struktur (complexity) poprzez zastosowywanie instrukcji if. Zwracany kod błędu musimy natychmiast obsłużyć w ten czy inny sposób. Zastosowanie wyjątku odseparowuje prawdziwą ścieżkę wykonania od obsługi błędu przez co kod staje się prostszy. Ponadto wyrzucenie wyjątku z nieweryfikowalnego lub zdefiniowanego biznesowo znacznie uprasza strukturę i zrozumienie problemu.
Konstrukcje typu zamykanie kodów błędów w enum jest też słabe. Dodanie nowego wymaga ponownego przekomplilowania programu.



TIP :
       - Improved exception handling - redukcja kodu, enumerujesz wyjątki '|'
       - Try-with-resources (TWR) - nie martwisz się dłużej o zamykanie zasobów oraz eliminujesz brzydkie finally.
Uwaga : korzystając z TWR pamiętaj, że  zastosowaniu java.lang.AutoCloseable , bo właśnie na tym opiera się mechanizm TWR


W javie 7 wygląda to tak : - wyodrębnij blok try/catch (Extract Try/Catch Blocks)
Blok try/catch wygląda brzydko już sam w sobie. Narusza strukturę przepływu bo miesza przetwarzanie błędu ze zwykłym przetwarzaniem. Warto jest wyodrębnić poszczególne bloki try oraz catch czy finally do osobnych funkcji.
Obsługa błędów też jest operacją i powinna robić też tylko jedną rzecz.

Inne przydatne features java 7 :











TIP : TWR , AOP Throws Advice

- programowanie strukturalne (Structured Programming)
  Zawsze unikaj goto ! Uważaj na zwielokrotnianie instrukcji return. Dziel duże funkcje na małe.
 

 Komentarze

 - obecność komentarza sugeruje nieporadność programisty lub po prostu nieudany kod
 - zamiast pisać komentarz spróbuj napisać kod tak aby sam wyrażał swoje intencje (Explain Yourself in Code)
 - nie jesteśmy w stanie utrzymywać komentarzy, więc często są już nie aktualne.
 - duża liczba komentarzy wprowadza bałagan w kodzie.

 Dobre komentarze to (Good Comments):

  - komentarze prawne (Legal Comments)  np: licencje
  - komentarze informacyjne (Informative Comments)  ale w przypadkach gdzie faktycznie taki komentarz dużo pomaga dla czytającego kod. np (wyrażenia regularne)
   - wyjaśniające zamierzenia i postępowania (Explanation of Intent) np @SuppressWarnings (Eliminate unchecked warnings  J.Bloch)

   - ostrzeżenie o konsekwencjach (Warning of Consequences)
     np : Not thread safe
  
   - komentarze TODO  (TODO Comments) oznaczające zadania do wykonania, ale z jakiegoś powodu w danym momencie nie możemy zrobić tego od ręki.

   - wzmocnienie (Amplification)  - ukazujący wagę danej operacji.

   - komentarze do publicznego API (Javadocs in Public APIs)


Złe użycie komentarzy (Bad Comments) :

- bełkot (Mumbling) - to taki komentarz, który naprawdę  nic nie wnosi.
   
- powtarzające się komentarze (Redundant Comments) oraz komentarze które nic nie wnoszą (Noise Comments)
  np : wszystkie pola, konstruktory, metody getter oraz setter etc

- znaczniki pozycji (Position Markers)
 np : // Do something with user account ///////////////

- komentarze w klarach zamykających (Closing Brace Comments) oznaczające koniec bloków np for czy if

- atrybuty i dopiski  (Attributions and Bylines) używamy systemy kontroli wersji więcej tam możemy komentować różne rzeczy np kto dodał modyfikację

 - zakomentowany kod (Commented-Out Code) jeśli zobaczyć fragmenty lub sekcje zakomentowanego kodu po prostu go wywal. Jest przecież historia zmian w systemie kontroli wersji.

 - komentarze HTML (HTML Comments)  powinny być generowany - formatowe przez narzędzie do generacji dokumentacji.

- informacje nie lokalne (Nonlocal Information) - czasem spotyka się komentarz, który znajduje się w złym miejscu lub po prostu do tego miejsca nie pasuje. np informacje o konfiguracji trzymaj na WIKI.


cdn.

Brak komentarzy:

Prześlij komentarz