GUT Intel 2015/16 1/1 Inżynieria Wytwarzania Systemów Wbudowanych Wykład 2 Iwona Kochańska Katedra Systemów Elektroniki Morskiej WETI PG October 11, 2018
Dobre praktyki GUT Intel 2015/16 2/1
Łatwość pielęgnacji (maintainability) - wysiłek, który musi być włożony w lokalizację błędów i ich naprawę Kiedy potrzebna jest zmiana programu, który został już dostarczony klientowi, np.: w wyniku znalezienia błędu gdy zaistnieje potrzeba dodania nowej funkcjonalności Dobre praktyki: pamiętaj, że inni będa czytać twój kod, pisz w taki sposób, by zmniejszyć prawdopodobieńtwo błędu podczas modyfikacji, pisz prosto, pisz w jednolitym stylu, pisz w taki sposób, by móc łatwo opracować testy. GUT Intel 2015/16 3/1
Kod w komentarzu Jeśli umieszczasz fragment kodu w komentarzu, wyjaśnij, dlaczego to robisz Możesz również umieszczać taki nieużywany kod w dyrektywie #if 0 - #endif (taki kod nie zostanie skompilowany). GUT Intel 2015/16 4/1
Deklaracje wielu zmiennych 1. W jednej instrukcji deklaruj tylko jedn a zmienn a 2. Możesz zadeklarować w jednej instrukcji zmienne tego samego typu i przeznaczenia, jednak nie mieszaj zmiennych zainicjalizowanych ze zmiennymi niezainicjalizowanymi GUT Intel 2015/16 5/1
Przyrostki przy stałych stałe całkowite to zwykle domyślnie typ int, stałe zmiennoprzecinkowe - typ double jeśli chcesz użyć innego typu, musisz to zapisać za pomoca odpowiedniego przyrostka używaj wielkich liter jako przyrostków. GUT Intel 2015/16 6/1
Długi łańcuch znaków w wielu liniach kodu Długi łańcuch znaków podziel na wiele składowych łańcuchów. Nie umieszczaj jednego łańcucha znaków w wielu liniach kodu (taka konstrukcja jest bardziej czytelna). GUT Intel 2015/16 7/1
użycie instrukcji switch, gdy możliwe sa tylko 2 przypadki używaj instrukcji switch tylko wtedy, gdy liczba możliwych przypadków jest większa od 2 switch jest obarczony większym prawdopodobieństwem błędu, niż if (nieprawnie zdefiniowany przypadek default, brak polecenia break) GUT Intel 2015/16 8/1
Brak jawnie określonego typu zawsze jawnie określaj typ zmiennej i funkcji. Jeśli tego nie zrobisz, domyślnym typem będzie int, ale taki kod jest mniej czytelny w standardzie C99 pominięcie typu zmiennej lub funkcji powoduje bł ad kompilacji GUT Intel 2015/16 9/1
Nawiasy w wyrażeniach logicznych Używaj nawiasów ( ) by zwiększyć czytelność wyrażeń logicznych GUT Intel 2015/16 10/1
Nawiasy a operatory dwuargumentowe Używaj nawiasów ( ) by jasno zaznaczyć, jaka jest kolejność wykonywania operacji GUT Intel 2015/16 11/1
Użycie nazwy funkcji bez nawiasów ( ) W języku C zawołanie nazwy funkcji bez nawiasów oznacza pobranie adresu (referencji) tej funkcji Taki kod trudno odróżnić od pomyłki polegajacej na pominięciu nawiasów podczas wywołania funkcji Używaj operatora & do sprawdzania referencji do funkcji! GUT Intel 2015/16 12/1
Jawne porównanie z wartościa 0 Jawnie porównuj wartość zmiennej z wartościa 0 (lub true/false) GUT Intel 2015/16 13/1
Jedna zmienna = jedno przeznaczenie Nie używaj tej samej zmiennej do różnych zadań GUT Intel 2015/16 14/1
Używaj różnych nazw zmiennych jeśli zmieniasz zakres/kontekts (scope) GUT Intel 2015/16 15/1
Nie używaj nazw istniejacych w standardowych biblitekach GUT Intel 2015/16 16/1
Nie używaj nazw rozpoczynajacych się od znaku _ Nazwy rozpoczynajace się od _ i wielkiej litery zarezerwowane sa w języku C do operacji na plikach. GUT Intel 2015/16 17/1
Makra Nie używaj makr do definiowania podstawowych elementów języka GUT Intel 2015/16 18/1
0 przed liczba całkowita Nie stawiaj 0 przed liczba całkowita w celu jej wyrównania. 0 przed liczba całkowita jest rozumiane jako poczatek liczby w systemie ósemkowym. GUT Intel 2015/16 19/1
Wyjaśnienie nietypowych konstrukcji Jeśli używasz nietypowych konstrukcji języka C/C++, zawsze opisuj je za pomoca komentarza lub makra Jeśli używasz nieskończnych instrukcji iteracyjnych, b adź konsekwentny: tylko for(;;) lub tylko while(1) GUT Intel 2015/16 20/1
Stałe Nie używaj wartości stałych w kodzie programu. Definiuj je za pomoc a makr. GUT Intel 2015/16 21/1
Obszary pamięci tylko do odczytu Obszary pamięci tylko do odczytu oznaczaj jako const GUT Intel 2015/16 22/1
Ulotność zmiennych Zmienna lub obszar pamięci, które moga być zmienione przez inne fragmenty programu powinny byc oznaczone jako volatile. W przeciwnym razie kompilator optymalizujac program może zaniechać odczytu zmiennej/obszaru pamięci. GUT Intel 2015/16 23/1
Opisywanie instrukcji Zawsze opis wszystkie elementy kodu, nawet jeśli nie s a one kompilowane GUT Intel 2015/16 24/1
Struktura danych inicjujacych tablicę Podczas inicjalizacji wartości tablicy struktura danych powinna być wyrażona za pomoca nawiasów { }. Podczas inicjalizacji tablicy wszystkie jej wartości powinny być jawnie podane GUT Intel 2015/16 25/1
Nawiasy { } a pojedyncza instrukcja W przypadku, gdy w instrukcji warunkowej lub iteracyjnej znajduje się tylko jedna instrukcja nie ma potrzeby używania nawiasów { }. Jednak jeśli kod będzie w przyszłości modyfikowany i lista instrukcji wydłuży się, istnieje prawodopodbieństwo, że nikt nie będzie pamiętał o dodaniu nawiasów { }. Dlatego warto ich używać w każdym przypadku. GUT Intel 2015/16 26/1
Zmienne używane tylko wewnatrz funkcji Zmienne używane tylko wewnatrz funkcji powinny być deklarowane w ciele tych funkcji Jeśli wartość takiej zmiennej ma być pamięta po wyjściu z funkcji i powrocie do niej, warto oznaczyć taka zmienna jako static GUT Intel 2015/16 27/1
Typ enum W celu zdefiniowania stałych stanowiacych zbiór wartości używaj typu wyliczeniowego zamiast dyrektywy #define. Nazwy określone w typie enum sa przetwarzane przez kompilator w przeciwienstwie do nazw określonych przez #define - ławiej o bład w tym drugim przypadku. Zmienne typu enum moga być debugowane. GUT Intel 2015/16 28/1
Instrukcja goto Nie należy używać instrukcji goto Jeśli już instrukcja goto musi być użyta, etykieta, do której ma być wykonany skok, powinna znajdować się PO instrukcji goto. GUT Intel 2015/16 29/1
Break w instrukcji switch Każdy przypadek case, włacznie z default, powinien być zakończony intrukcja break. GUT Intel 2015/16 30/1
Przecinek Przecinek nie powinien być używany Dopuszcza się użycie przecinka w instrukcji iteracyjnej for GUT Intel 2015/16 31/1
Definicja instrukcji for W definicji instrukcji for powinny się znaleźć tylko instrukcje dotyczace zmiennej sterujacej GUT Intel 2015/16 32/1
Modyfikacja zmiennej sterujacej pętla for Zmienna steruj aca powinna być modyfikowana tylko w kodzie definicji pętli for GUT Intel 2015/16 33/1
Używaj maksymalnie 2-krotnego wskaźnika Wskaźnik potrójny jest trudny do interpretacji GUT Intel 2015/16 34/1
Trzymaj się jednolitej konwencji zapisu: pozycji nawiasów { } wcięcia na poczatku linii kodu spacji. Dlaczego warto używać spacji? GUT Intel 2015/16 35/1
Trzymaj się jednolitej konwencji: przenoszenia linii kodu do nowej linii tekstu GUT Intel 2015/16 36/1
Przykładowe style kodowania 1. Styl K&R - używany w The C programming language (pol. Język Ansi C ) - D. Ritchie i B. Kernighan nawiasy { } na poczatku nowej linii - jeśli definicja funkcji nawiasy { } w pozostałych przypadkach w tej samej linii wcięcie = 1 tab (4 spacje) 2. Styl BSD (Allman style) wszystkie nawiasy { } w nowej linii, wyrównane do poczatku poprzedniej linii wcięcie = 8 lub 4 spacje 3. Styl GNU - zdefiniowany w GNU Coding Standards - R. Stallman wszystkie nawiasy { } w nowej linii, wcięcie 2 spacje w stosunku do poczatku poprzedniej linii wcięcie = 2 spacje GUT Intel 2015/16 37/1
GUT Intel 2015/16 38/1
Trzymaj się jednolitej konwencji pisania komentarzy Używaj // dla komentarza na końcu linii kodu (tylko 1 linia tekstu!) Używaj /* */ dla bloku komentarzy Trzymaj się jednolitej konwencji nazw GUT Intel 2015/16 39/1
Konwencja nazw Indian Hill Nazwy rozpoczynajace sie od _ sa zarezerwowane dla wywołań systemowych i nie powinny być używane przez programistę jako nowe nazwy Stałe definiowane przez #define powinny być pisane wielkimi literami Nazwy w typie wyliczeniowym powinny mieć co najmniej pierwsza wielka literę Unikaj par nazw, które różnia się tylko wielkościa liter Nazwa pliku z kodem powinna mieć co najwyżej 8 znaków alfanumerycznych. Pierwszy znak powinien być litera alfabetu Nie należy nazywać plików z kodem tak, jak nazywaja się pliki bibliotek GUT Intel 2015/16 40/1
Konwencja nazw GNU Używaj sugestywnych nazw zwiazanych ze znaczeniem zmiennej lub funkcji Nazwy w języku angielskim Używaj _ do rozdzielania słów w nazwach Wielkie litery zarezerwowane dla makr i typów wyliczeniowych GUT Intel 2015/16 41/1
Nie używaj par nazw, które różnia się jedynie: obecnościa podkreślenia _ litera O i cyfra 0 litera I i litera l lub cyfra 1 litera S i cyfra 5 litera Z i cyfra 2 litera n i litera h GUT Intel 2015/16 42/1
Struktura pliku nagłówkowego GUT Intel 2015/16 43/1
Struktura pliku z kodem programu GUT Intel 2015/16 44/1
Prototyp funkcji W prototypie funkcji nie używaj nazw zmiennych, jedynie typy. W definicji funkcji używaj nazw zmiennych Jeśli w prototypie występuja nazwy zmiennych, powinny być takie same GUT Intel 2015/16 45/1
Przecinek przed nawiasem } w inicjalizacji wielu elementów jednocześnie istnieja dwie szkoły: 1) nie stawiamy przecinka przed }, 2) stawiamy przecinek przed }. Stosuj jednolita konwencję. GUT Intel 2015/16 46/1
Wartość NULL Wartość NULL powinna być stosowana jedynie dla null pointer, choć bezpieczniej jest używać wartości 0. GUT Intel 2015/16 47/1
Pamięć dynamiczna - jeśli alokujesz pamieć w sposób dynamiczny, musisz pamiętać o ryzyku zwiazanym z: odwołaniem do nieprawidłowej przestrzeni adresowej przecieków pamięci Problem zwiazane z dynamiczna alokacja pamięci Przepełnienie bufora (Buffer overflow) - kiedy odwołujesz się do pamięci spoza zaalokowanego. Problem ten ujawni się dopiero podczas odwołania do pamięci, która została zapisana przez pomyłkę Brak inicjalizacji (Forgetting to initialize) - kiedy pamięć alokowana jest za pomoca new, ale nie dla obiektu klasy C++, pamięć nie jest automatycznie inicjalizowana. GUT Intel 2015/16 48/1
Problem zwiazane z dynamiczna alokacja pamięci (c.d.) Przeciek pamięci (Memory leak) - kiedy zapominamy o zwalnianiu pamięci. Nie dotyczy to programów, ktore uruchamiane sa raz i kończa dziłałanie po jednokrotnym wykonaniu. Problem dotyczy programów, które działaja długo i iteracyjnie. Odwołanie po zwolnieniu pamięci (Use after return) - kiedy odwołujemy się do pamięci zwolnionej przez wcześniejsze wywołanie delete GUT Intel 2015/16 49/1
Literatura GUT Intel 2015/16 50/1