[StyleCop] od jakiego zestawu reguł wystartować

Korzystam ze StyleCopa od ładnych kilku lat. Zapewnia statyczną analizę kodu pod względem stylu (nie do końca tylko stylu ale to jest aspekt, na którym się skupiam). Jest to niezbędne narzędzie gdy stosuje się Code Review. Po prostu szkoda czasu i ludzkiej cierpliwości, żeby ręcznie wytykać komuś coś, co może wychwycić narzędzie. Preferowany sposób korzystania to poprzez StyleCop.Analyzers

Dzisiaj chciałbym podzielić się zestawem reguł, który w różnych projektach stosuję od lat. Pod to stworzyłem repozytorium https://github.com/kmorcinek/dotnet-tools-settings i plik StyleCopDefault.ruleset

example stylecop ruleset

Każda ignorowana reguła jest opisana, przykłady:

SA1611 - ElementParametersMustBeDocumented (no required documentation)
  • jeśli ktoś uważa, że przyda się komentarz to może dodać, ale nie można tego wymuszać, bo większość byłaby trywialnymi komentarzami, które nic nie wniosą.
SA1202 - ElementsMustBeOrderedByAccess, similar to SA1204 (assume couple of public methods in class, I want to have private methods used by a public method just below this public method, not below all other public methods)
  • zbyt na siłę, tak jak opisałem – nie sprawdza się.
SA1309 - FieldNamesMustNotBeginWithUnderscore (private fields should begin with underscore)
  • akurat w C# jest konwencja, żeby tak rozpoczynać od podkreślenia (a przynajmniej ja wolę to niż zaczynać prywatne pola od this)

Zostaję z dwoma pytaniami:
* czy wszystkie „Warning” przerobić na „Error” – zwracam się ku temu, ale na razie zostaje jak jest.
* czy dodać do pliku wszystkie, wszystkie reguły i ustawić na „Warning” („Error”) – będzie to może łatwiejsze w utrzymywaniu/zmienianiu w przyszłości i łatwiej będzie się włączało/wyłączało pojedyncze reguły.

Nie wszystko jest włączone z defaultu

Dotychczas myślałem (gdzieś przeczytałem) że wszystko co nie pojawia się w pliku konfiguracyjnym jest „włączone”, okazało się że nie wszystko, a prawie wszystko: StyleCopAnalyzers Status

To nie jest ostateczna wersja

Nie wszystkie te ustawienia są dla mnie ostatecznym wyznacznikiem co i jak robić. Pewnie w jeszcze innym projekcie coś włączę, coś wyłączę i to samo dotyczy Ciebie czytelniku. Jest to pierwsze miejsce gdzie się tym dzielę, więc zapraszam do podrzucania własnych ustawień i przemyśleń. A jeśli jeszcze nie masz wyrobionego stylu to znalazłeś gotowca:), daj mu szansę przez jakiś czas.

PS w kolejnych postach opiszę jak wprowadzać to w istniejący projekt, oraz jak ignorować czasem niektóre reguły.

[GIT] Screencast: Synchronizacja własnej pracy ze zdalnym repozytorium

Spotkałem się dzisiaj z Adrianem, aby nagrać screencast o tym jak dobrze synchronizować się ze zdalnym trunkiem/masterem/developem.

Nie powiemy o wszystkim co się dzieje w trakcie takiej pracy (bo za dużo jest ciekawych rzeczy jak na krótki odcinek). Skupimy się na porównaniu „rebase VS merge„.

Montaź: Adrian Wasielewski.

Na początku zarysujemy problem, potem pokazuję jedno podejście (rebase), następnie drugie podejście (merge) i na koniec podsumowujemy i wyciągamy wnioski.

Obrazek podsumowujący:

rebase vs merge final screencast

W kolejnych odcinkach opowiemy min o podejściu do rozwiązywania konfliktow, a także zaczniemy omawiać zasady SOLID.

Git commit jako ktoś inny

W Git można dodać autora commitu jakiego się chce. Domyślnie jest to brane z pliku konfiguracyjnego i będzie to nasza kombinacja username/email. Można to jednak prosto nadpisać:

git commit --author="Konrad Dzwinel <kdzwinel@gmail.com>" -m "Commited as the Konrad for fun."

Na GitHubie w naszym commit pojawi się nawet odpowiednia twarz osoby, którą sobie losowo wzięliśmy z GitHuba.

Git, Commited as somebody else
Po prostu się pod kogoś podszyłem

W git osoba która wykonała push do repozytorium, a osoba która jest jako author commita to moga być różne osoby i warto o tym pamiętać. Nie jest to jakieś złe (takie commity nie pojawia się u Konrada w „latest commits”), w ten sposób możemy zaznaczyć że tę dobrą robotę wykonał ktoś inny i dla niego zarezerwowane sa credits.

GIT: Release branch w podejściu Trunk Based Development

Nagrałem screencast, gdzie tłumaczę jak podchodzić do release’owania kolejnych paczek gdy korzystamy z Gita (a w szczególności z Trunk Based Development).

Strona, z której korzystałem to https://learngitbranching.js.org/. Można na niej pouczyć się branchowania bo ma interaktywne tutoriale. Ja korzystam z tej opcji bez tutoriali czyli https://learngitbranching.js.org/?NODEMO

(wiem, że są szumy, ale „Done is better than nothing”, kupię mikrofon)

trunk based development i release branches
Tak wygląda historia na końcu

Komendy, które były wpisywane w „konsoli”:

git checkout -b develop
git commit
git tag ver-2.1
git branch rel-2.1 // drogi się rozchodzą, QA testuje, team dev’ów tworzy kod
git commit // kolejny feature
// bug
git commit
git tag fix-1
// bug 2
git commit
git tag fix-2
git checkout rel-2.1
git cherry-pick C4
git cherry-pick C5
git checkout develop
git commit // kolejny feature
// Minął miesiąc(2), a może sprint. Decydujemy się na kolejny release
git commit
git tag ver-2.2
git branch rel-2.2
git commit // kolejny feature
// QA znalazł buga
git commit
git tag fix-3
git checkout rel-2.2
git cherry-pick C9
// gdy 2.2 poszło na produkcję to
git branch -D rel-2.1
commity bez opisu oznaczają ze tu się dużo mogło dziać.

Wstępna konfiguracja gita

Powiedzmy, że przypadkiem szykujesz się do DevWarsztatów z gita 😉 i coś tam trzeba zainstalować.

Konsola

Konsolę ściągamy ze strony https://git-scm.com/downloads dla odpowiedniego systemu. Klikamy wszędzie „Dalej” 🙂

Podstawowe ustawienia

Ustawiamy swoje dane

git config --global user.name "Krzysztof Morcinek"
git config --global user.email "your-email@gmail.com"

Domyślnym edytorem jest vim, którego wiele osób nie zna. Polecam więc zmienić na np notepad.

git config --global core.editor notepad

GitHub

Zakładamy konto na GitHubie https://github.com/join

Source Tree

Nieobowiązkowe, można ściągnąć z https://www.sourcetreeapp.com/ (trzeba zarejestrować email, to jedyne wymaganie). Wersje tylko dla Mac i Windows.

Kdiff3

Instalujemy: https://www.google.com/?q=kdiff3+download

Konfiguracja (zrobimy też to na warsztatach):

Na Windowsie dodajemy na dole pliku. ~/.gitconfig (może trzeba ścieżkę dostosować):

[merge]
    tool = kdiff3
[mergetool "kdiff3"]
    path = c:/Program Files/KDiff3/kdiff3.exe
[diff]
    tool = kdiff3
    guitool = kdiff3
[difftool "kdiff3"]
    path = c:/Program Files/KDiff3/kdiff3.exe

Na Linuxie dodajemy na dole pliku. ~/.gitconfig:

[merge]
    tool = kdiff3
[diff]
    guitool = kdiff3

Gdzie chowasz swoje hacki?

Jest bug! 😦

function foo(){
    applyResultToDataTable();
    // more code
}

Wywołanie takiej funkcji powoduje błąd w rozmwiarze stylowania i tabelka z danymi jest niewidoczna. Na jednym środowisku działa na innym nie działa. Bug trudny do zlokalizowania/zrozumienia/naprawienia.

Ale można przyhaczyć 🙂 Okazuje się, że „malutki” timeout załatwia sprawę:

setTimeout(function(){
    applyResultToDataTable();
    // more code
}, 100);

Hacki się mszczą, ale teraz musimy dostarczyć paczkę

Dzisiaj zakładamy, że takie hacki się mszczą (dlaczego to osobny ciekawy temat). Kolejne założenie to takie, że w tym akurat momencie tak już zrobimy. Brak czasu lub skilla nie pozwala. Co więć dalej zrobić?

Na pewno można dodać opis:

// Workaround for columns width = 0px; after loading data to DataTables
setTimeout(function(){
    applyResultToDataTable();
    // more code
}, 100);

Kolejny tydzień, kolejny ten sam bug

Kod żyje, innego dnia dowiadujemy się że testy na innym widoku znalazły ten sam problem. I znów w innym miejscu dopisujemy:

// Workaround for columns width = 0px; after loading data to DataTables
setTimeout(function(){
    applyResultToDataTable();
    // more code
}, 100);

Wróc! Najczęściej tak się nie zdarza, najczęściej inny developer nie zna akurat „tego” hacka. Brak komunikacji i przesunięcie w czasie sprawiły, że nikt mu o nim nie powiedział. Więc dopisuje na nowo tego samego (po straceniu czasu na rozkminę), albo znajdzie nowy sposób załatania (i znowu straci czas). Kolejny smutny hack 😦

Bądź EXPLICIT

Ja sugeruję aby takie drogi na skróty od razu opisywać osobnymi metodami.

/*
 * Workaround for columns width = 0px; after loading data to DataTables
 */
function addTimeoutToFixNarrowDataTables(action){
    setTimeout(function(){
        action();
    }, 100);
}
function foo(){
    addTimeoutToFixNarrowDataTables(function(){
        applyResultToDataTable();
        // more code
    }
}

Czy nazwa addTimeoutToFixNarrowDataTables() jest właściwa? Tutaj będzie bardzo wiele opinii. Ja wychodzę z założenia, że lepiej wpisać tutaj wiele rzeczy, bo ktoś szukając rozwiazania swojego problemu w przyszłości znajdzie przynajmniej jedno słowo (korzystając z Search Everywhere). Zgadzam się, że w normalnym kodzie nie chciałbym takich dużych metoda, ale to jest właśnie Hack.

A gdzie umieścić taką metodę? Można gdzieś w klasie z której jest wołana, może jest bazowy kontroller lub serwis z którego kod potrzebujący może wywołać hacka. Ja bym jednak stworzył osobną klasę nazywającą się YouNameItHacks (ControllerHacks, DataTablesHacks, itd). Takich rzeczy nie należy ukrywać. Ktoś może zmarnować dużo czasu zanim znajdzie „dlaczego nowo pisany moduł na takiego dziwnego buga…”.

explicit hacks in visual studio solution

Jak nazwać? Gdzie umieścić? Podzielcie się waszymi pomysłami w komentarzach.

[Git] Czasem dopiero po chwili wiesz jak dobrze nazwać

Tak najpierw nazwałem commity:
Install angular
AngularJS TypeScript typings
Update jQuery definitions for TypeScript

A później samo do mnie doszło że lepszymi nazwami będzie:
Install angular with TypeScript typings (z połączenia dwóch pierwszych)
Update jQuery definitions for TypeScript

Dzięki funkcjonalności rebase interactive możemy pozmieniać nazwy (posklejać commity), aby było to bardziej sensowne. Opisuję jak to wyklikać z GUI.