INŻYNIERIA OPROGRAMOWANIA IMPLEMENTACJA KODU
Najważniejszy jest efekt działania programu.a nie sam program
Cechy dobrego programu poprawność (jako zgodność z wymaganiami użytkownika/klienta) niezawodność ( dobre dane wejściowe gwarantują dobre wyniki) przenośność, łatwość konserwacji (prosto napisany program łatwo przystosować do różnych warunków pracy), prawidłowe wykorzystanie zasobów (pamięci, dyski, itp.), szybkość działania
Cechy dobrego kodu POPRAWNOŚĆ. Kod powinien działać prawidłowo na wszystkich oczekiwanych i nieoczekiwanych danych wejściowych WYDAJNOŚĆ. Kod powinien działać wydajnie pod kątem pamięci i czasu. Istotna jest zarówno wydajność asymptotyczna (notacja wielkie O ) i praktyczna. PROSTOTA 10 linijek kodu zamiast 100 jeśli się da. Programista powinien umieć napisać kod szybko CZYTELNOŚĆ. Łatwość zrozumienia dla innych programistów (czytanie, działanie) ŁATWOŚĆ KONSERWACJI dla Twórcy jak i innych Programistów (łatwość wprowadzenie zmian w cyklu życia) KOMPROMIS
Cechy dobrego kodu jak to osiągnąć? ROZWIĄZANIA OGÓLNE - CZYTELNOŚĆ 1. Unikaj programistycznej prowizorki (obejścia, rozwiązania tymczasowe: workaround) 2. Trzymaj się ustalonych, jednolitych standardów kodowania i nazewnictwa (np. nazwy klasy z dużej litery, prywatne składowe poprzedzane podkreśleniem _, nazwy interfejsów od litery I). 3. Pisz samodokumentujący się kod, dbaj o komentarze na etapie tworzenia kodu.
Cechy dobrego kodu jak to osiągnąć? ROZWIĄZANIA OGÓLNE PROSTOTA Książka jest skończona nie wtedy, gdy nie można do niej nic dodać, ale wtedy gdy nie można z niej nic usunąć. 1. Zasada KISS (Keep It Simple, Stupid) 2. Hermetyzacja klas przez najbardziej restrykcyjne (z możliwych!) modyfikatory dostępu do właściwości klas (private, protected), 3. Jeden uniwersalny mechanizm zamiast kilku podobnych 4. Zasada DRY (Dont Repeat Yourself). Wystrzeganie się kopiuj i wklej (przeniesienie kodu do osobnej funkcji, klasy bazowej). 5. Reguła Rule Of Three
Cechy dobrego kodu jak to osiągnąć? ROZWIĄZANIA OGÓLNE ŁATWOŚĆ KONSERWACJI Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification [Bertrand Meyer] 1. Zasada OPEN/CLOSE. Kod powinien być zamknięty na modyfikację i otwarty na rozszerzanie (rozwijając projekt, nie należy zmieniać istniejącego kodu, a jedynie go rozszerzać). Nawet drobna zmiana w istniejącym kodzie może w łatwy sposób zepsuć inną funkcjonalność, która z tego fragmentu kodu korzysta.
Cechy dobrego kodu jak to osiągnąć? ROZWIĄZANIA BARDZIEJ SZCZEGÓŁOWE 1. Stosowanie struktur danych 2. Powtórne wykorzystanie kodu 3. Modułowość 4. Elastyczny kod 5. Wykrywanie błędów
Cechy dobrego kodu jak je osiągnąć STOSOWANIE STRUKTUR DANYCH Zad: Napisać funkcje dodającą dwa wyrażenia matematyczne Ax a +Bx b Wyrażenia można zapisać w dowolnej strukturze danych, bez parsowania łańcuchów znaków. ZŁA IMPLEMENTACJA Zapisanie wyrażenia jako tablicy liczb zmiennoprzecinkowych o podwójnej precyzji, w której k-ty element odpowiada współczynnikowi dla członu x k : int[] sum(double[] expr1, double[] expr2) { }
Cechy dobrego kodu jak je osiągnąć STOSOWANIE STRUKTUR DANYCH Zad: Napisać funkcje dodającą dwa wyrażenia matematyczne Ax a +Bx b Wyrażenia można zapisać w dowolnej strukturze danych bez parsowania łańcuchów znaków. TROCHĘ LEPSZA IMPLEMENTACJA Zapisanie wyrażenia jako zbioru dwóch tablic: współczynników (coef) i z wykładnikami (exp). Człony wyrażenia zapisywane w dowolnej kolejności i dopasowywane tak że i-ty człon wyrażenia: coef[i]*x exp[i]??? sum(double[] coef1, double[] exp1, double[] coef2, double[] exp2 ) { }
Cechy dobrego kodu jak je osiągnąć STOSOWANIE STRUKTUR DANYCH Zad: Napisać funkcje dodającą dwa wyrażenia matematyczne Ax a +Bx b Wyrażenia można zapisać w dowolnej strukturze danych bez parsowania łańcuchów znaków. DOBRA IMPLEMENTACJA Zaprojektowanie własnej struktury danych reprezentującej wyrażenie: Class ExprTerm{ Double coef; Double exp; } ExprTerm[] sum(exprterm[] expr1, ExprTerm expr2) { }
Cechy dobrego kodu jak je osiągnąć MODUŁOWOŚĆ Umieszczenie odizolowanych fragmentów kodu w odrębnych metodach (łatwiejsza konserwacja, testowanie, większa czytelność) Zad: Napisać kod, który zamienia miejscami minimalny i maksymalny element w tablicy liczb całkowitych
public void swapminmax(int[] array){ int minindex=0; for(int i=1; i<array.length; i++){ if(array[i]<array[minindex]){ minindex=i; } } int maxindex=0; for(int i=1; i<array.length; i++){ if(array[i]>array[maxindex]){ maxindex=i; } } int temp=array[minindex]; Array[minIndex]=array[maxIndex]; Array[maxIndex]=temp; }
public static int getminindex(int[] array) { int minindex=0; for(int i=1; i<array.length; i++){ if(array[i]<array[minindex]){ minindex=i; }} return minindex; } public static int getmaxindex(int[] array) { int maxindex=0; for(int i=1; i<array.length; i++){ if(array[i]>array[maxindex]){ maxindex=i; }} return maxindex; } public static void swap(int[] array, int m, int n){ int temp=array[m]; array[m]=array[n; array[n]=temp; } public static void swapminmaxbetter(int[] array){ int minindex =getminindex(array); int maxindex =getmaxindex(array); swap(array, minindex, maxindex) }
Cechy dobrego kodu jak je osiągnąć ELASTYCZNE ROZWIĄZANIE rozwiązania ogólne.jeśli się to opłaca zmienne zamiast stałych wykorzystanie szablonów i typów generycznych
Cechy dobrego kodu jak je osiągnąć WYKRYWANIE BŁĘDÓW Odrzucanie założeń dotyczących danych wejściowych Przykład: Przekształcanie liczb o podstawie i (2 lub 16) na całkowite public int ConvertToBase(String number, int base) { if (base<2 II (base>10 && base!=16)) return -1; int value=0; for (int i=number.length()-1; i>=0,; i--) { int digit=digittovalue(number.charat(i)); if(digit<0 digit >=base) { return -1;} Int exp=number.length)() -1-i; value +=digit * Math.pow(base,exp); } return value; } // czy podstawa jest poprawna //czy każda cyfra należy do zadanego przedziału
Styl programowania nazwy zmiennych, wielkości stałe, liczba zmiennych globalnych (możliwie najmniejsza), deklaracje typów zmiennych, komentarze, sposób redagowania kodu (puste linie, odstępy poziome, akapity) podział na sekcje, podprogramy, uniwersalność i standaryzacja modułów, funkcjonalność i wygoda użytkowników, formułowanie celów, złożoność systemu.
Nazwy zmiennych Reguły skracania nazw: skraca się każde znaczące słowo w nazwie, pierwsza litera musi wystąpić, spółgłoski są ważniejsze od samogłosek, początek słowa jest ważniejszy niż koniec, tworzy się skróty na 6 do 15 liter Usuwa się od końca najpierw samogłoski potem spółgłoski, oprócz pierwszej litery, aż do osiągnięci pożądanej długości. Porządkowanie list zmiennych wg alfabetu znacznie ułatwia ich odszukiwanie i określenie typu.
Wielkości stałe Nie należy wprost używać stałych w całej treści programu, w jego wnętrzu. Najlepiej zadeklarować (zgłosić) je w części opisowej, specjalnie do tego przeznaczonej (w Pascalu słowo const) Zmiana sprzętu często powoduje idące za nią zmiany przybliżonych wartości różnych stałych.
Deklaracje typów zmiennych Wszystko, co tylko się da, należy umieszczać w deklaracjach typu, włączając w to podzakresy, definicje tablic oraz rekordów. Należy unikać deklarowania niejawnego.
Komentarze Na początku programu : opis działania programu, sposób wywołania, wykaz z opisem ważniejszych zmiennych, opis plików wejścia/wyjścia, nazwy używanych podprogramów, nazwy wszelkich specjalnych metod, które zostały użyte, wraz ze wskazaniem, gdzie można znaleźć dalsze informacje, wymagania sprzętowe i systemowe, opis specjalnych poleceń dla użytkownika, autor, data powstania (data modyfikacji/numer wersji).
Zadanie CZWARTEK 08:50-10:20 1. Napisz program który za pomocą jak najmniejszej liczby instrukcji zamienia miejscami sąsiadujące bity parzyste i nieparzyste (zerowy z pierwszym, drugi z trzecim itd
Na zakończenie. Skromny, działający program jest bardziej użyteczny niż program imponujący, ale niedokończony