zasady Flashcards
TDD
TDD (Test-Driven Development) to podejście do tworzenia oprogramowania, w którym testy automatyczne są pisane przed implementacją kodu źródłowego. Proces TDD składa się z cyklu trzech kroków, który powtarza się dla każdej funkcji lub fragmentu kodu:
Napisz test:
Zanim zaczniesz pisać kod źródłowy, napisz test automatyczny, który określa, jak powinna działać funkcja lub fragment kodu. Test ten będzie początkowo nieprzechodzący (fail).
Napisz minimalną ilość kodu źródłowego:
Napisz tylko tyle kodu, ile jest niezbędne, aby spełnić warunki testu. W tym momencie twoja implementacja może być bardzo prosta i minimalna.
Uruchom testy automatyczne:
Uruchom wszystkie testy automatyczne, aby sprawdzić, czy nowy kod spełnia oczekiwania. Jeśli testy przechodzą, możesz kontynuować z kolejnymi testami lub rozszerzyć implementację. Jeśli testy nie przechodzą, musisz dostosować kod źródłowy, aby spełnić warunki testu.
Ten cykl (nazywany “czerwony, zielony, refactor”) jest powtarzany wielokrotnie podczas procesu tworzenia oprogramowania. Proces TDD ma kilka korzyści:
Zwiększa jakość kodu: Dzięki pisaniu testów przed kodem źródłowym, programista musi zastanowić się nad oczekiwanym zachowaniem kodu, co może prowadzić do lepiej zaprojektowanego i bardziej elastycznego kodu.
Ułatwia utrzymanie i rozwijanie kodu: Posiadanie zestawu testów automatycznych ułatwia wprowadzanie zmian w kodzie, ponieważ programista może szybko sprawdzić, czy wprowadzone modyfikacje nie powodują błędów.
Redukuje liczbę błędów: Testy automatyczne pomagają wychwycić błędy w kodzie wcześniej, jeszcze zanim trafi on do środowiska produkcyjnego.
Zwiększa pewność refaktoryzacji: Jeśli masz solidny zestaw testów, możesz być pewny, że refaktoryzacje (zmiany w kodzie mające poprawić jego jakość bez zmiany zachowania) nie wprowadzają nowych błędów.
Popularne narzędzia do TDD obejmują frameworki testowania takie jak JUnit (dla Javy), pytest (dla Pythona), NUnit (dla .NET) itp.
Polimorfizm
Polimorfizm to jedno z podstawowych pojęć w programowaniu obiektowym. Oznacza ono zdolność różnych obiektów do reagowania na te same operacje w sposób zrozumiały i spójny. Polimorfizm umożliwia tworzenie ogólnych interfejsów lub klas bazowych, które mogą być używane do manipulowania różnymi obiektami, niezależnie od ich konkretnego typu.
Istnieją dwa główne rodzaje polimorfizmu:
Polimorfizm ad hoc (polimorfizm dynamiczny): W tym rodzaju polimorfizmu różne obiekty potrafią reagować na te same operacje w sposób, który zależy od ich rzeczywistego typu w czasie wykonania programu. W językach programowania obiektowego, takich jak Java czy C++, polimorfizm ad hoc jest realizowany poprzez dziedziczenie, dynamiczne wiązanie i przesłanianie metod.
Przykład w Javie:
java
Copy code
public class Animal {
public void makeSound() {
System.out.println(“Animal makes a sound”);
}
}
public class Dog extends Animal {
@Override
public void makeSound() {
System.out.println(“Dog barks”);
}
}
public class Main {
public static void main(String[] args) {
Animal myDog = new Dog();
myDog.makeSound(); // Wywołuje metodę makeSound z klasy Dog
}
}
Polimorfizm uniwersalny (polimorfizm statyczny): Ten rodzaj polimorfizmu pozwala na obsługę różnych typów obiektów w ogólny sposób, niezależnie od ich konkretnego typu. Jest to często realizowane poprzez użycie interfejsów lub klas bazowych, które definiują wspólne operacje, które muszą być zaimplementowane przez różne klasy.
Przykład w Javie:
java
Copy code
interface Shape {
double calculateArea();
}
class Circle implements Shape {
double radius;
public Circle(double radius) { this.radius = radius; } @Override public double calculateArea() { return Math.PI * radius * radius; } }
class Square implements Shape {
double side;
public Square(double side) { this.side = side; } @Override public double calculateArea() { return side * side; } }
public class Main {
public static void main(String[] args) {
Shape circle = new Circle(5.0);
Shape square = new Square(4.0);
System.out.println("Circle area: " + circle.calculateArea()); System.out.println("Square area: " + square.calculateArea()); } } Polimorfizm umożliwia tworzenie bardziej elastycznego i rozszerzalnego kodu oraz ułatwia zarządzanie różnymi typami obiektów w programie.
Haszowanie
Haszowanie to proces przekształcania danych wejściowych, takich jak tekst, liczby czy inne dane, na krótki ciąg znaków o stałej długości, zwany “hashem” lub “wartością skrótu”. Haszowanie ma na celu wygenerowanie unikalnej reprezentacji danych, która jest trudna do odwrócenia, co oznacza, że nie da się odzyskać oryginalnych danych z wartości skrótu.
Główne cechy haszowania to:
Deterministyczność: Ten sam zestaw danych wejściowych zawsze generuje ten sam hash. W innym przypadku, hashowanie byłoby niewłaściwe, ponieważ nie można by było polegać na wynikach.
Jednokierunkowość: Nie da się odzyskać oryginalnych danych z wartości skrótu. Innymi słowy, nie można cofnąć procesu haszowania.
Równoważność: Różne dane wejściowe powinny generować różne wartości skrótu. Jednak w praktyce zawsze istnieje możliwość kolizji, czyli sytuacji, w której dwa różne zestawy danych generują ten sam hash.
Haszowanie jest szeroko stosowane w informatyce w różnych kontekstach:
Zabezpieczanie haseł: W przypadku przechowywania haseł użytkowników w bazach danych, zamiast przechowywać same hasła, przechowuje się ich hasze. Kiedy użytkownik próbuje się zalogować, system oblicza hash wprowadzonego hasła i porównuje go z haszem w bazie danych. Jeśli hasze są zgodne, użytkownik jest uwierzytelniany, a oryginalne hasło pozostaje niewidoczne.
Integrity Check: Haszowanie jest używane do sprawdzania integralności danych. Można obliczyć hash danych źródłowych i porównać go z hashem otrzymanym po transmisji lub przechowywaniu danych. Jeśli hasze nie pasują, oznacza to, że dane zostały zmienione.
Szyfrowanie: W pewnych systemach hasze są wykorzystywane w procesie szyfrowania lub do autoryzacji w systemach, takich jak uwierzytelnianie w procesie SSL/TLS w przeglądarkach internetowych.
Popularne algorytmy haszujące obejmują MD5, SHA-1, SHA-256 i wiele innych. Wybór odpowiedniego algorytmu zależy od zastosowania i poziomu bezpieczeństwa, który jest wymagany. Obecnie starsze algorytmy haszujące, takie jak MD5 i SHA-1, uważane są za przestarzałe ze względu na podatność na ataki kryptograficzne, i zaleca się stosowanie bardziej zaawansowanych i bezpiecznych algorytmów.
BDD
BDD (Behavior-Driven Development) to podejście do tworzenia oprogramowania, które rozszerza idee TDD (Test-Driven Development) o współpracę między różnymi rolami w zespole projektowym, takimi jak programiści, testerzy i przedstawiciele biznesu. BDD skupia się na opisie oczekiwanego zachowania oprogramowania w języku naturalnym, zrozumiałym dla wszystkich zainteresowanych stron.
Kluczowe elementy BDD to:
Specyfikacje w języku naturalnym:
Specyfikacje oprogramowania są pisane w formie prostych i czytelnych scenariuszy w języku naturalnym, zrozumiałym dla wszystkich członków zespołu, nie tylko dla programistów.
Gherkin:
Gherkin to język specyfikacji używany w BDD. Jest to język oparty na tekście, który pozwala opisać scenariusze w sposób formalny. Popularne słowa kluczowe w Gherkin to m.in. Given (Zakładając), When (Kiedy), Then (Wtedy), And (I), But (Ale).
Przykład Gherkin:
gherkin
Copy code
Feature: Logowanie użytkownika
Scenario: Poprawne logowanie
Given użytkownik jest na stronie logowania
When wprowadza poprawne dane logowania
Then powinien być zalogowany
Automatyzacja testów:
Scenariusze BDD są następnie automatyzowane, a testy automatyczne są generowane na podstawie specyfikacji. Narzędzia do BDD, takie jak Cucumber (wiele języków, w tym Java, Ruby, itp.) lub Behave (dla Pythona), pomagają w tym procesie.
Współpraca między zespołami:
BDD promuje współpracę między różnymi rolami w zespole projektowym, umożliwiając łatwiejsze zrozumienie wymagań przez wszystkich uczestników projektu.
Korzyści z BDD obejmują:
Lepsze zrozumienie wymagań: Dzięki użyciu języka naturalnego, specyfikacje są bardziej zrozumiałe dla przedstawicieli biznesu, testerów i programistów.
Wczesna detekcja błędów: Specyfikacje, które są jednocześnie testami, pomagają w identyfikacji problemów już na etapie pisania kodu.
Łatwiejsza współpraca: Dzięki zrozumiałym specyfikacjom, wszyscy członkowie zespołu mogą aktywnie uczestniczyć w procesie definiowania i weryfikowania wymagań.
BDD jest często używane w projektach Agile i jest ściśle związane z praktykami Scrum i Kanban, które również podkreślają współpracę i adaptację w trakcie rozwoju oprogramowania.