Tym razem Dr. Ian Malcolm wraz z całym zespołem Parku Jurajskiego przygotowali dla Ciebie kluczowy briefing. Po kilku incydentach w parku, w tym słynnej awarii systemu i ucieczce dinozaurów, zespół opracował zestaw najlepszych praktyk programistycznych, które mogłyby zapobiec podobnym katastrofom w przyszłości.
Problem w parku: System nie sprawdzał poprawnie danych o temperaturze inkubatorów jaj dinozaurów, co doprowadziło do niekontrolowanego rozmnażania się welociraptorów.
Rozwiązanie:
1// Źle:
2function ustawTemperaturęInkubatora(temperatura) {
3 inkubator.temperatura = temperatura;
4 // Co jeśli temperatura będzie zbyt wysoka? Lub to będzie string zamiast liczby?
5}
6
7// Dobrze:
8function ustawTemperaturęInkubatora(temperatura) {
9 // Sprawdzamy czy temperatura jest liczbą
10 if (typeof temperatura !== 'number') {
11 throw new Error('Temperatura musi być liczbą');
12 }
13
14 // Sprawdzamy czy temperatura mieści się w bezpiecznym zakresie
15 if (temperatura < 20 || temperatura > 40) {
16 throw new Error('Temperatura poza bezpiecznym zakresem (20-40°C)');
17 }
18
19 inkubator.temperatura = temperatura;
20}Problem w parku: Nikt nie przetestował systemu ogrodzenia elektrycznego w warunkach ekstremalnych, takich jak tropikalna burza.
Rozwiązanie:
1// Zestaw testów dla systemu ogrodzenia
2describe('System ogrodzenia', () => {
3 test('powinien działać przy normalnym zasilaniu', () => {
4 const ogrodzenie = new SystemOgrodzenia();
5 ogrodzenie.włącz();
6 expect(ogrodzenie.czyAktywne()).toBe(true);
7 });
8
9 test('powinien przełączyć się na zasilanie awaryjne podczas burzy', () => {
10 const ogrodzenie = new SystemOgrodzenia();
11 ogrodzenie.włącz();
12 ogrodzenie.symulujPrzerwęWDostawieEnergii();
13 expect(ogrodzenie.czyAktywne()).toBe(true);
14 expect(ogrodzenie.źródłoZasilania).toBe('awaryjne');
15 });
16
17 test('powinien wysłać alert gdy baterie awaryjne są poniżej 20%', () => {
18 const ogrodzenie = new SystemOgrodzenia();
19 const alertMock = jest.fn();
20 ogrodzenie.onNiskiPoziomBaterii = alertMock;
21
22 ogrodzenie.ustawPoziomBaterii(15);
23
24 expect(alertMock).toHaveBeenCalled();
25 });
26});Problem w parku: Jeden system sterował zarówno drzwiami, jak i ogrodzeniami, kamerami oraz systemem bezpieczeństwa. Awaria jednego komponentu doprowadziła do kaskadowej awarii całego systemu.
Rozwiązanie:
1// Źle:
2class SystemParku {
3 kontrolujDrzwi() { /* ... */ }
4 zarządzajOgrodzeniem() { /* ... */ }
5 monitorujKamery() { /* ... */ }
6 sterujKlimatyzacją() { /* ... */ }
7 // Ten obiekt robi zbyt wiele!
8}
9
10// Dobrze:
11class SystemDrzwi {
12 otwórz(id) { /* ... */ }
13 zamknij(id) { /* ... */ }
14 sprawdźStan(id) { /* ... */ }
15}
16
17class SystemOgrodzenia {
18 włącz() { /* ... */ }
19 wyłącz() { /* ... */ }
20 sprawdźNapięcie() { /* ... */ }
21}
22
23class SystemMonitoringu {
24 włączKamerę(id) { /* ... */ }
25 wyłączKamerę(id) { /* ... */ }
26 nagrywaj(id) { /* ... */ }
27}
28
29class CentralnySterownik {
30 constructor(systemDrzwi, systemOgrodzenia, systemMonitoringu) {
31 this.systemDrzwi = systemDrzwi;
32 this.systemOgrodzenia = systemOgrodzenia;
33 this.systemMonitoringu = systemMonitoringu;
34 }
35
36 uruchomProcedurębezpieczeństwa() {
37 // Teraz koordynuje niezależne systemy
38 this.systemDrzwi.zamknij('wszystkie');
39 this.systemOgrodzenia.włącz();
40 this.systemMonitoringu.nagrywaj('wszystkie');
41 }
42}Problem w parku: System transportu jaj nie posiadał obsługi błędów, co doprowadziło do utraty cennego materiału genetycznego, gdy jeden z czujników przestał działać.
Rozwiązanie:
1// Źle:
2function przenieśJajo(idJaja, docelowaPozycja) {
3 const jajo = bazaDanych.pobierzJajo(idJaja);
4 ramięRobotyczne.przenieś(jajo, docelowaPozycja);
5 bazaDanych.aktualizujPozycję(idJaja, docelowaPozycja);
6 // Co jeśli którakolwiek z tych operacji się nie powiedzie?
7}
8
9// Dobrze:
10async function przenieśJajo(idJaja, docelowaPozycja) {
11 try {
12 // Pobieramy jajo z bazy
13 const jajo = await bazaDanych.pobierzJajo(idJaja);
14 if (!jajo) {
15 throw new Error(`Jajo o ID ${idJaja} nie zostało znalezione`);
16 }
17
18 // Przenosimy jajo za pomocą ramienia robotycznego
19 try {
20 await ramięRobotyczne.przenieś(jajo, docelowaPozycja);
21 } catch (błąd) {
22 console.error('Błąd podczas przenoszenia jaja:', błąd);
23 wyslijAlert('Błąd ramienia robotycznego', błąd.message);
24 return false;
25 }
26
27 // Aktualizujemy pozycję w bazie danych
28 await bazaDanych.aktualizujPozycję(idJaja, docelowaPozycja);
29
30 // Logujemy udaną operację
31 logOperacji.dodaj(`Jajo ${idJaja} przeniesione do ${docelowaPozycja}`);
32
33 return true;
34 } catch (błąd) {
35 console.error('Krytyczny błąd podczas przenoszenia jaja:', błąd);
36 wyslijAlert('Krytyczny błąd', błąd.message);
37 uruchomProcedurębezpieczeństwa();
38 return false;
39 }
40}Problem w parku: Po odejściu głównego inżyniera, nikt nie wiedział dokładnie jak działa system kontroli dostępu.
Rozwiązanie:
1/**
2 * Weryfikuje poziom dostępu pracownika do stref parku.
3 *
4 * @param {Object} pracownik - Obiekt zawierający dane pracownika
5 * @param {string} pracownik.id - Unikalny identyfikator pracownika
6 * @param {string} pracownik.imię - Imię pracownika
7 * @param {string} pracownik.nazwisko - Nazwisko pracownika
8 * @param {number} pracownik.poziomDostępu - Poziom dostępu pracownika (1-5)
9 * @param {string} strefa - Identyfikator strefy, do której pracownik próbuje uzyskać dostęp
10 * @returns {boolean} - Zwraca true, jeśli pracownik ma dostęp do strefy, false w przeciwnym razie
11 *
12 * @example
13 * // Sprawdź czy Dr. Wu ma dostęp do laboratorium
14 * const drWu = { id: '001', imię: 'Henry', nazwisko: 'Wu', poziomDostępu: 5 };
15 * const dostęp = sprawdźDostęp(drWu, 'laboratorium');
16 * console.log(dostęp); // true
17 */
18function sprawdźDostęp(pracownik, strefa) {
19 // Mapa wymaganych poziomów dostępu dla różnych stref
20 const wymaganyPoziom = {
21 'publiczna': 1,
22 'administracja': 2,
23 'zwierzęta roślinożerne': 3,
24 'drapieżniki': 4,
25 'laboratorium': 5
26 };
27
28 // Sprawdź czy strefa istnieje
29 if (!wymaganyPoziom.hasOwnProperty(strefa)) {
30 console.warn(`Nieznana strefa: ${strefa}`);
31 return false;
32 }
33
34 // Porównaj poziom dostępu pracownika z wymaganym dla strefy
35 return pracownik.poziomDostępu >= wymaganyPoziom[strefa];
36}Problem w parku: System kontroli klimatu używał globalnych zmiennych do przechowywania ustawień, co pozwoliło błędowi w module sterowania wentylacją wpłynąć na cały system klimatyzacji.
Rozwiązanie:
1// Źle:
2let globalnaTemperatura = 22;
3let globalnaWilgotność = 70;
4
5function ustawTemperaturęWDżungli() {
6 // Modyfikuje zmienne globalne
7 globalnaTemperatura = 28;
8 globalnaWilgotność = 90;
9}
10
11function ustawTemperaturęWLaboratorium() {
12 // Również modyfikuje te same zmienne globalne!
13 globalnaTemperatura = 20;
14 globalnaWilgotność = 50;
15}
16
17// Co się stanie, jeśli obie funkcje zostaną wywołane blisko siebie w czasie?
18
19// Dobrze:
20class KontrolerKlimatu {
21 constructor() {
22 this.strefy = new Map();
23 }
24
25 ustawParametryStefy(idStrefy, temperatura, wilgotność) {
26 this.strefy.set(idStrefy, { temperatura, wilgotność });
27 }
28
29 pobierzParametryStefy(idStrefy) {
30 return this.strefy.get(idStrefy);
31 }
32}
33
34const kontrolerKlimatu = new KontrolerKlimatu();
35
36kontrolerKlimatu.ustawParametryStefy('dżungla', 28, 90);
37kontrolerKlimatu.ustawParametryStefy('laboratorium', 20, 50);
38
39// Teraz każda strefa ma własne niezależne ustawieniaProblem w parku: Kod do sprawdzania stanu zagrożenia był powielony w kilku systemach, więc poprawka błędu w jednym systemie nie została wprowadzona w pozostałych.
Rozwiązanie:
1// Źle:
2function sprawdźZagrożenieWSystemieDrzwi() {
3 if (czujniki.ruch > 10 && czujniki.dźwięk > 80 && !jestDzień()) {
4 ogłośAlarm('Podejrzana aktywność przy drzwiach!');
5 }
6}
7
8function sprawdźZagrożenieWSystemieOgrodzenia() {
9 // Ten sam logika jest powtórzona!
10 if (czujniki.ruch > 10 && czujniki.dźwięk > 80 && !jestDzień()) {
11 ogłośAlarm('Podejrzana aktywność przy ogrodzeniu!');
12 }
13}
14
15// Dobrze:
16function wykryjPodejrzanąAktywność() {
17 return czujniki.ruch > 10 && czujniki.dźwięk > 80 && !jestDzień();
18}
19
20function sprawdźZagrożenieWSystemieDrzwi() {
21 if (wykryjPodejrzanąAktywność()) {
22 ogłośAlarm('Podejrzana aktywność przy drzwiach!');
23 }
24}
25
26function sprawdźZagrożenieWSystemieOgrodzenia() {
27 if (wykryjPodejrzanąAktywność()) {
28 ogłośAlarm('Podejrzana aktywność przy ogrodzeniu!');
29 }
30}Problem w parku: Kod genetyczny napisany przez Dr. Wu był tak zagmatwany, że nikt inny nie rozumiał jak dokładnie tworzono hybrydowe dinozaury.
Rozwiązanie:
1// Źle:
2function ms(d,g,s) {
3 const r = [];
4 for(let i=0;i<d.length;i++) {
5 if(d[i].g === g && d[i].t > s) {
6 r.push(d[i]);
7 }
8 }
9 return r;
10}
11
12// Dobrze:
13/**
14 * Filtruje dinozaury według gatunku i minimalnego poziomu siły
15 */
16function filtrujDinozauryPoGatunkuISile(dinozaury, gatunek, minimalnaSila) {
17 const wyfiltrowane = [];
18
19 for (let i = 0; i < dinozaury.length; i++) {
20 const dinozaur = dinozaury[i];
21
22 if (dinozaur.gatunek === gatunek && dinozaur.siła > minimalnaSila) {
23 wyfiltrowane.push(dinozaur);
24 }
25 }
26
27 return wyfiltrowane;
28}
29
30// Lub jeszcze lepiej, używając nowoczesnego JavaScript:
31function filtrujDinozauryPoGatunkuISile(dinozaury, gatunek, minimalnaSila) {
32 return dinozaury.filter(dinozaur =>
33 dinozaur.gatunek === gatunek && dinozaur.siła > minimalnaSila
34 );
35}Problem w parku: Zespół IT nie używał systemu kontroli wersji, więc po wprowadzeniu nowej funkcjonalności, która okazała się zawierać błędy, nie można było łatwo przywrócić poprzedniej działającej wersji.
Rozwiązanie:
1# Inicjalizacja repozytorium Git
2git init
3
4# Dodanie plików do repozytorium
5git add .
6
7# Pierwszy commit
8git commit -m "Początkowa wersja systemu Parku Jurajskiego"
9
10# Tworzenie nowej gałęzi na potrzeby rozwoju nowej funkcjonalności
11git checkout -b nowy-system-karmienia
12
13# Praca nad funkcjonalnością...
14
15# Zapisanie zmian
16git add zmodyfikowane-pliki
17git commit -m "Dodano automatyczny system karmienia dla drapieżników"
18
19# Łączenie zmian z główną gałęzią po testach
20git checkout main
21git merge nowy-system-karmienia
22
23# W przypadku problemów, można szybko wrócić do poprzedniej wersji
24git revert HEADProblem w parku: Dennis Nedry wprowadził tylne drzwi do systemu bezpieczeństwa, których nikt nie zauważył, ponieważ nie było procesu przeglądania kodu.
Podejście w zespole:
Jak już wiemy z historii Parku Jurajskiego, nieprzestrzeganie najlepszych praktyk programistycznych może prowadzić do katastrofalnych konsekwencji:
Wyobraź sobie, że jesteś głównym programistą w Parku Jurajskim. Zidentyfikuj wszystkie potencjalne problemy w poniższym kodzie i przepisz go zgodnie z najlepszymi praktykami:
1// System monitorowania dinozaurów w Parku Jurajskim
2var dinos = [];
3var alarmy = 0;
4
5function dodaj(name, type, area, dangerLvl) {
6 dinos.push({n: name, t: type, a: area, d: dangerLvl, h: 100});
7 console.log('dodano: ' + name);
8}
9
10function check() {
11 for (var i=0; i<dinos.length; i++) {
12 if (dinos[i].h < 50) {
13 console.log('UWAGA! Dinozaur ' + dinos[i].n + ' ma niski poziom zdrowia!');
14 alarmy = alarmy + 1;
15 }
16
17 if (dinos[i].a != dinos[i].lockArea && dinos[i].d > 3) {
18 console.log('NIEBEZPIECZEŃSTWO! Drapieżnik poza strefą!');
19 alarmy = alarmy + 1;
20 }
21 }
22
23 if (alarmy > 0) alert('Mamy problemy...');
24}
25
26// Przykład użycia
27dodaj('Rex', 'T-Rex', 'B5', 5);
28dodaj('Tri', 'Triceratops', 'A2', 2);
29dinos[0].h = 30;
30dinos[0].a = 'X3'; // Poza przypisaną strefą!
31check();Pamiętaj, w świecie programowania, tak jak w Parku Jurajskim - życie zawsze znajdzie sposób... na ujawnienie nieprzemyślanych rozwiązań! Dlatego stosuj najlepsze praktyki, aby twój kod był bezpieczny, utrzymywalny i efektywny.