Instalowanie lintera

https://aie24.pl/

Najpopularniejszym linterem dla kodu JavaScript jest ESLint. Wykonaj poniższe kroki, aby zainstalować i wypróbować ESLint

  1. Jeśli jeszcze tego nie zrobiłeś, pobierz kod do rozdziału 7 ze strony internetowej tej książki pod adresem www.dummies.com/go/codingwithaifd. 2. Uruchom VS Code, a następnie otwórz folder chapter07.
  2. Otwórz nowe okno terminala w VS Code, wybierając Terminal ➪ Nowy terminal.
  3. Wpisz cd chapter07/react-linting-demo, aby zmienić katalog roboczy na folder react-linting-demo.

Folder react-linting-demo zawiera projekt napisany w React, w którym jest już zainstalowany ESLint.

  1. Wpisz npm install w oknie terminala, aby zainstalować zależności projektu React, w tym ESLint.
  2. Wpisz npm run lint w oknie terminala.

ESLint analizuje wszystkie pliki JavaScript w projekcie i wyświetla raport znalezionych błędów, jak pokazano na rysunku .

Jeśli nie znasz JavaScript ani React, niektóre błędy zgłaszane przez ESLint nie będą miały większego sensu. Ale nie martw się! Zrozumienie React i JavaScript nie jest ważne dla zrozumienia, jak używać lintera i jak rozszerzyć możliwości lintera za pomocą AI.

Zapobieganie błędom za pomocą lintingu

https://aie24.pl/

Ponieważ debugowanie może być frustrującym i czasochłonnym procesem, dobrym pomysłem jest zrobienie wszystkiego, co możliwe, aby wyeliminować potrzebę debugowania w pierwszej kolejności. W rozdziale 6 używasz Prettier do automatycznego formatowania kodu. Formatowanie kodu w spójny sposób jest ważnym krokiem w pisaniu wysokiej jakości kodu, ale to nie jedyna rzecz, którą możesz zrobić, aby zmniejszyć potrzebę debugowania.  Większość lintersów działa w podobny sposób jak narzędzia formatujące kod. Używają listy reguł do sprawdzania kodu przed jego skompilowaniem lub uruchomieniem. Podczas gdy formatery kodu zajmują się tabulatorami, spacjami i podziałami wierszy w kodzie, lintersy zajmują się składnią kodu i przestrzeganiem dobrych konwencji kodowania. Debugowanie naprawia problemy, które występują podczas działania kodu. Linting naprawia problemy w kodzie, które występują, gdy kod nie jest uruchomiony (dlatego lintersy są narzędziem do statycznej analizy kodu). W idealnym przypadku linting może wyeliminować potrzebę debugowania.

Zgłaszanie błędów wspomagane przez sztuczną inteligencję za pomocą Jam

https://aie24.pl/

Zgłaszanie błędów to sposób, w jaki programiści i zespoły programistyczne dokumentują i śledzą błędy i potencjalne błędy w oprogramowaniu. Zgłoszenia błędów zazwyczaj opisują bieżące funkcjonowanie pewnego aspektu oprogramowania i sposób, w jaki powinno ono działać. Poniżej przedstawiono niektóre cechy dobrego zgłoszenia błędu

»»Zawiera wizualne dowody defektu

»»Ma wystarczająco dużo szczegółów, aby programista mógł odtworzyć warunki, które doprowadziły do ​​zgłoszenia błędu

»»Opisuje tylko jeden błąd, zamiast łączyć kilka problemów

»»Jest składany w standardowy i zdefiniowany sposób (np. za pomocą narzędzia do śledzenia błędów)

Jakość zgłoszenia błędu często zależy od poziomu doświadczenia osoby zgłaszającej błąd w oprogramowaniu, czasu, jaki poświęca na dokładne opisanie problemu, oraz jej umiejętności pisania. Narzędzia do debugowania wspomagane przez sztuczną inteligencję mogą pomóc użytkownikom i testerom dokładnie opisać problem, a także pomóc programistom odtworzyć, a nawet naprawić zgłoszone błędy. Jam (https://jam.dev) to rozszerzenie przeglądarki Chrome, które upraszcza proces zgłaszania błędów w witrynach internetowych i aplikacjach internetowych. Integruje się z chatbotem AI, aby zapewnić programistom dodatkowe informacje o tym, jak rozwiązać błąd. Aby rozpocząć korzystanie z Jam, przejdź do https://jam.dev/jamgpt i zainstaluj wtyczkę do przeglądarki. Następnie kliknij ikonę Jam, która pojawi się w przeglądarce, aby wyświetlić ekran pokazany na rysunku

Aby rozpocząć zgłaszanie błędu na dowolnej odwiedzanej stronie internetowej, możesz wykonać zrzut ekranu, nagrać wideo aktywnej karty przeglądarki lub pulpitu i skorzystać z funkcji natychmiastowego odtwarzania, która dołącza zrzut ekranu ostatnich interakcji z aktywną kartą przeglądarki. Zgłoszenia błędów utworzone za pomocą Jam można udostępniać na kilka sposobów, w tym za pomocą łącza, za pośrednictwem poczty e-mail lub jako problem w repozytorium GitHub. Na rysunku 2 tworzę raport o błędzie w repozytorium jednej ze swoich stron internetowych.

Po użyciu rozszerzenia Jam do utworzenia raportu o błędzie możesz otworzyć raport na stronie internetowej Jam lub wysłać go do jednej z platform, z którymi Jam jest zintegrowany, np. GitHub, Asana, Jira lub Slack.  Jam dostarcza kilka typów danych o warunkach w przeglądarce, gdy zgłaszano błąd, w tym jakie działania podjął użytkownik, jakie żądania sieciowe doprowadziły do ​​ekranu, na którym zgłaszano błąd, a także informacje o przeglądarce internetowej i systemie operacyjnym użytkownika, jak pokazano na rysunku 3

Karta JamGPT, po prawej stronie ekranu, zapewnia dostęp do chatbota, który może uzyskać dostęp do wszystkich informacji o zgłoszeniu błędu. Po otwarciu karty JamGPT chatbot pyta, czy chcesz, aby przeanalizował raport o błędzie i przedstawił zalecenia, jak pokazano na rysunku 4.

Po poproszeniu JamGPT o pomoc, analizuje on raport o błędzie i sugeruje możliwe rozwiązanie. JamGPT nie może naprawić problemu za Ciebie, ale jego sugestie mogą być pomocne w zlokalizowaniu problemu, jak pokazano na rysunku 5.

Identyfikacja powszechnych typów błędów

https://aie24.pl/

Na Ziemi żyje około 6 do 10 milionów różnych typów błędów, które stanowią 90 procent form zwierzęcych. Na szczęście błędy oprogramowania nie występują w tak wielu różnych odmianach i w większości przypadków nie są tak wszechobecne. Oto najczęściej występujące typy błędów oprogramowania:

»»Błędy składniowe to nieprawidłowe lub brakujące znaki w kodzie, które uniemożliwiają kompilację lub uruchomienie programu.

»»Błędy czasu wykonania nie uniemożliwiają kompilacji programu, ale powodują jego awarię.

»»Błędy funkcjonalne występują, gdy coś w oprogramowaniu nie działa zgodnie z przeznaczeniem, na przykład pole wyszukiwania, które nie wyszukuje.

»»Błędy logiczne to problemy związane z logiką biznesową i są zazwyczaj wynikiem źle napisanego kodu, na przykład wartości przypisanej do niewłaściwej zmiennej.

»»Błędy przepływu pracy mają związek z nawigacją użytkownika w aplikacji oprogramowania. Jednym z przykładów błędu przepływu pracy jest łącze, które nie przenosi użytkownika na właściwą stronę w witrynie.

»»Błędy na poziomie jednostki to proste, łatwe do naprawienia błędy zawarte w pojedynczej jednostce kodu. Przykładem błędu na poziomie jednostki jest problem z walidacją danych wejściowych dla pola adresu e-mail.

»»Błędy integracji na poziomie systemu to bardziej złożone błędy, w których poszczególne jednostki kodu działają poprawnie, ale zachowują się nieoczekiwanie podczas współpracy. Tego typu błędy mogą być trudne i czasochłonne do wyśledzenia i naprawienia. Na przykład, jeśli dwa komponenty oprogramowania oczekują różnych formatów danych, mogą nie być w stanie poprawnie wymieniać danych.

»»Błędy wykraczające poza granice to problemy, które występują w wyniku niezamierzonej interakcji użytkownika z interfejsem użytkownika oprogramowania, na przykład gdy użytkownik wprowadza w polu wprowadzania większą wartość niż oczekuje system.

»»Błędy bezpieczeństwa to problemy, które sprawiają, że oprogramowanie jest podatne na złośliwe ataki lub inne rodzaje ryzyka, takie jak udostępnianie danych użytkownika nieautoryzowanym użytkownikom.

Choć luki w zabezpieczeniach niekoniecznie uniemożliwiają normalne korzystanie z oprogramowania, są to błędy o najwyższym priorytecie i należy je natychmiast naprawić.

CZY MOŻESZ PISAĆ OPROGRAMOWANIE BEZ BŁĘDÓW?

Większość błędów kodowania wynika z tego, co zwykliśmy nazywać błędem ludzkim. Wraz z pojawieniem się kodowania wspomaganego przez sztuczną inteligencję, asystenci AI mogą być równie prawdopodobną przyczyną błędów. Każde oprogramowanie o dowolnej złożoności ma błędy. Cel tworzenia oprogramowania bez błędów jest nierealny i doprowadzi do przekroczenia terminów i przekroczenia kosztów. Niektóre z najsłynniejszych projektów upadły z powodu niemożliwych do spełnienia wymagań jakościowych. Na przykład projekt Federalnej Administracji Lotnictwa mający na celu napisanie nowego oprogramowania kontroli ruchu lotniczego w latach 80. i 90. XX wieku został pierwotnie zaproponowany jako projekt, który miał rozpocząć się w 1982 r. i zostać ukończony w 1996 r. przy koszcie 2,5 miliarda dolarów. Do czasu anulowania projektu w 1994 r. szacunkowy koszt wzrósł do 7 miliardów dolarów, a niektóre segmenty projektu były opóźnione nawet o 8 lat. Jedną z wielu przyczyn niepowodzenia projektu było żądanie przez FAA niezawodności na poziomie 99,99999%, co wielu uważało za nierealne

Znajomość błędów

https://aie24.pl/

Zanim będziesz mógł usunąć błędy z kodu, musisz je zlokalizować, zidentyfikować i udokumentować. W tej sekcji dowiesz się, jak wykonać wszystkie trzy zadania.

Strategie wykrywania błędów

Do wykrywania błędów w oprogramowaniu stosuje się wiele różnych metod. Najbardziej skuteczne strategie wykrywania błędów to:

»»Przeglądy kodu: regularne przeglądanie kodu z kolegami często wyłapuje problemy, których pojedynczy programista pracujący w pojedynkę nie jest w stanie wyłapać.

»»Automatyczne testowanie: automatyczne testowanie zapewnia, że ​​nowa funkcjonalność nie psuje istniejącego kodu. Ten typ testowania pomaga wykryć błędy oprogramowania na wczesnym etapie cyklu rozwoju.

»»Statyczna analiza kodu: statyczna analiza kodu analizuje kod w trakcie jego pisania.

»»Narzędzia do debugowania: narzędzia do debugowania pozwalają programistom na przechodzenie przez kod i zmienne oraz ich sprawdzanie podczas działania programu. Są one niezbędne do ustalenia przyczyn źródłowych błędu. Debugowanie wspomagane przez AI jest omówione w sekcji „Wykrywanie błędów za pomocą AI”

»»Rejestrowanie i monitorowanie: rejestrowanie błędów i monitorowanie wydajności zapewniają twórcom oprogramowania szczegółowe informacje o tym, jak dobrze oprogramowanie działa po wdrożeniu w środowisku produkcyjnym.

Znajdowanie i eliminowanie błędów

https://aie24.pl/

Termin debugowania w odniesieniu do komputerów sięga czasów admirał Grace Hopper, która pracowała na Uniwersytecie Harvarda w latach 40. Jej koleżanka znalazła ćmę utkniętą w komputerze, która uniemożliwiała mu prawidłowe działanie, i zauważyła, że ​​„debugują” system. Chociaż usterki w systemach mechanicznych nazywano błędami już w 1887 r., kiedy Thomas Edison użył tego terminu, Grace Hopper przypisuje się wprowadzenie tego terminu w odniesieniu do komputerów i programowania komputerowego. Obecnie znacznie rzadziej napotykasz błędy fizyczne, które uniemożliwiają prawidłowe działanie programów, ale te defekty w kodzie są nadal tak samo uciążliwe, a czasami równie trudne do zauważenia. W tym rozdziale dowiesz się, jak używać narzędzi AI, które pomogą Ci w procesie debugowania kodu.

Ulepszenie gry AI w kółko i krzyżyk

https://aie24.pl/

Ostatnim problemem, z którym chciałem się zmierzyć w programie, było sprawdzenie, czy Copilot mógłby mi udzielić sugestii, jak ulepszyć GPT-4 w grze w kółko i krzyżyk. Otworzyłem plik zawierający program Node.js, który współpracuje z GPT-4, i wyświetliłem Copilotowi następujące polecenie:

Jak mogę zmodyfikować mój monit do GPT-4, aby lepiej radził sobie z grą w kółko i krzyżyk?

Drugi pilot zasugerował skorzystanie z następującego monitu:

Jesteś wysoce wykwalifikowaną sztuczną inteligencją wyszkoloną do gry w kółko i krzyżyk. Grasz z ludzkim przeciwnikiem. Twoim celem jest wygranie lub zremisowanie gry. Oczekuje się, że wykonasz optymalne ruchy w oparciu o aktualny stan planszy do gry. Pozycje na planszy są ponumerowane od 0 do 8, zaczynając od lewego górnego rogu i przechodząc w prawo, a następnie w dół. Plansza jest reprezentowana jako lista dziewięciu elementów, z których każdy może być „X”, „O” lub „” (dla pustego miejsca). Podekscytowany, że w końcu mogę zagrać z AI na remis, wdrożyłem sugestię i uruchomiłem serwer i klienta. Mój przeciwnik AI nadal nie był dobry w grze w kółko i krzyżyk, a ja wygrywałem każdą grę, bez względu na to, jak bardzo starałem się przegrać. Do diabła. W tym momencie czułem się dobrze z powodu refaktoryzacji, którą udało mi się wykonać, jeśli nie ze względu na zdolność AI do gry w kółko i krzyżyk. Cały program jest pokazany w Listingu.

Listing : Przebudowana gra w kółko i krzyżyk

class TicTacToeGame {

constructor(difficulty = 10) {

this.DEFAULT_DIFFICULTY = difficulty;

this.board = [”, ”, ”, ”, ”, ”, ”, ”, ”];

this.currentPlayer = ‘X’;

this.isGameOver = false;

this.messageHistory = [];

this.difficulty = this.DEFAULT_DIFFICULTY;

this.init();

}

/**

* Initialize the game by adding event listeners

to the DOM

*/

init() {

document.addEventListener(‘DOMContentLoaded’, (event) => {

let cells = document.querySelectorAll(‘.cell’);

cells.forEach((cell, i) => {

cell.addEventListener(‘click’, () => this.makeMove(i));

});

document

.getElementById(‘start’)

.addEventListener(‘click’, () => this.startNewGame());

});

let slider = document.getElementById(‘slider’);

document.getElementById(‘difficulty’).innerHTML =

‘Level of difficulty: ‘ + slider.value;

slider.addEventListener(‘change’, (e) => {

document.getElementById(‘difficulty’).innerHTML =

‘Level of difficulty: ‘ + e.target.value;

this.difficulty = e.target.value;

});

}

/**

* Start a new game by resetting the game state

and clearing the board

* Then post a new game message to the server

*/

async startNewGame() {

this.resetGameState();

this.clearBoardDisplay();

await this.postNewGameMessage();

}

/**

* Reset the game state

*/

resetGameState() {

this.board = [”, ”, ”, ”, ”, ”, ”, ”, ”];

this.currentPlayer = ‘X’;

this.isGameOver = false;

this.messageHistory = [{ role: ‘user’, content: ‘new’ }];

}

/**

* Clear the board display

*/

clearBoardDisplay() {

document.querySelectorAll(‘.cell’).forEach((cell) => (cell.innerHTML = ”));

}

/**

* Post a new game message to the server

*/

async postNewGameMessage() {

try {

const response = await fetch(‘http://localhost:3000/chat’, {

method: ‘POST’,

headers: { ‘Content-Type’: ‘application/json’ },

body: JSON.stringify({ messages: this.messageHistory }),

});

const data = await response.json();

this.updateMessageDisplay(data.response.choices[0].message.content);

} catch (error) {

console.error(‘Failed to post new game message:’, error);

this.updateMessageDisplay(‘Error starting a new game. Please try again.’);

}

}

/**

* Update the message display

* @param {string} message

*/

updateMessageDisplay(message) {

document.getElementById(‘message’).innerHTML = message;

}

/**

* Make a move on the board

* @param {number} index

*/

makeMove(index) {

if (this.board[index] === ” &&; !this.isGameOver) {

this.board[index] = this.currentPlayer;

document.getElementsByClassName(‘cell’)[index].innerHTML =

this.currentPlayer;

this.messageHistory.push({ role: ‘user’, content: index.toString() });

if (this.checkWin()) {

alert(this.currentPlayer + ‘ Wins!’);

this.isGameOver = true;

return;

}

if (this.checkDraw()) {

alert(‘Draw!’);

this.isGameOver = true;

return;

}

this.aiMove(); // Player is X, AI is O

}

}

/**

* Check whether someone has won the game

* @returns {boolean}

*/

checkWin() {

const winCombos = [

[0, 1, 2],

[3, 4, 5],

[6, 7, 8],

[0, 3, 6],

[1, 4, 7],

[2, 5, 8],

[0, 4, 8],

[2, 4, 6],

];

return winCombos.some((combo) => {

return (

this.board[combo[0]] &&;

this.board[combo[0]] === this.board[combo[1]] &&;

this.board[combo[0]] === this.board[combo[2]]

);

});

}

/**

* Check whether the game is a draw

* @returns {boolean}

*/

checkDraw() {

return this.board.every((cell) => cell !== ”);

}

/**

* Make a move for the AI

*/

async aiMove() {

let move = await this.getAIMove(this.messageHistory);

this.messageHistory.push({ role: ‘assistant’, content: move.toString() });

console.log(move);

this.board[move] = ‘O’;

document.getElementsByClassName(‘cell’)[move].innerHTML = ‘O’;

if (this.checkWin()) {

alert(‘O Wins!’);

this.isGameOver = true;

}

}

/**

* Get a move from the AI

* @param {array} message

* @returns {string}

*/

async getAIMove(message) {

/*

Use the value of difficulty to decide whether to

query the API for a move or use a random move.

If difficulty is 10, always query the API

If difficulty is 0, always use a random move

If difficulty is between 0 and 10, use a random move

10 – difficulty percent of the time

and use the best move difficulty percent of the time

*/

let randomNumber = Math.random();

if (randomNumber < this.difficulty / 10) {

const response = await fetch(‘http://localhost:3000/chat’, {

method: ‘POST’,

headers: {

‘Content-Type’: ‘application/json’,

},

body: JSON.stringify({

messages: message,

}),

});

const data = await response.json();

let messageElement = document.getElementById(‘message’);

messageElement.innerHTML = data.response.choices[0].message.content;

return data.response.choices[0].message.content;

}

let randomMove = Math.floor(Math.random() * 8);

while (this.board[move] !== ”) {

randomMove = Math.floor(Math.random() * 8);

}

document.getElementById(‘message’).innerHTML = move.toString();

return randomMove.toString();

}

}

// Create a new game

new TicTacToeGame();

Brak komentarzy

https://aie24.pl/

Ostatnią rzeczą, w której chciałem uzyskać pomoc od Copilota, była dokumentacja i komentarze w moim programie. Ponieważ wiedziałem już, że program potrzebuje więcej dokumentacji, postanowiłem wypróbować narzędzie Copilota do generowania dokumentów. Wybrałem pierwszą metodę w mojej klasie, kliknąłem ją prawym przyciskiem myszy i wybrałem Copilot ➪ Generuj dokumenty. Copilot napisał opis metody, ale użył nieprawidłowego symbolu, aby oznaczyć ją jako komentarz, i był rozwlekły i powtarzalny, jak pokazano na rysunku .

Przy drugiej próbie Copilot wykonał lepszą robotę, ale nadal nie oznaczył poprawnie tekstu jako komentarza. Przełączyłem się na Copilot Chat i zadałem następujące pytanie:

Napisz komentarze JDoc do tego programu.

Przykładowy kod, który otrzymałem, był w formacie JSDoc, ale nie był tym, co uważałbym za odpowiednie. Przy trzeciej próbie przejrzałem swój program i rozpocząłem blok kodu przed każdą z funkcji i zacząłem wpisywać własne komentarze, aby zobaczyć, jakie sugestie da mi Copilot. To podejście dało mi zdecydowanie najlepsze wyniki ze wszystkich trzech podejść. Im więcej pomocy udzielisz AI, tym bardziej ona może pomóc tobie.

Naprawianie niespójnego nazewnictwa

https://aie24.pl/

Miałem duże nadzieje co do tego, jak model języka mógłby poprawić moje nazewnictwo zmiennych i funkcji. Poleciłem Copilotowi następujące:

Jak mogę przebudować ten program, aby zachować spójność nazewnictwa?

Sztuczna inteligencja odpowiedziała kilkoma ogólnymi wskazówkami i najlepszymi praktykami oraz trzema konkretnymi sugestiami, jak pokazano na rysunku

Zgodziłem się z dwiema z trzech sugestii i wdrożyłem je, a następnie ponownie zadałem pytanie. Za drugim razem, gdy zapytałem, zwróciła dwie różne sugestie. Zgodziłem się z jedną z nich i wdrożyłem ją, a następnie ponownie zadałem pytanie. Za trzecim razem zwróciła tę samą poradę dotyczącą najlepszych praktyk, ale zasugerowała, abym zmienił nazwy dwóch zmiennych, dla których już podała sugestie (ale z innymi i, moim zdaniem, gorszymi sugestiami). Wydawało się, że osiągnąłem punkt malejących korzyści z moim powtarzającym się pytaniem. Moim następnym działaniem było przejrzenie kodu i sprawdzenie, czy są jakieś dodatkowe nazwy, które moim zdaniem można by poprawić. Uznałem, że wszystkie pozostałe nazwy są odpowiednie. Jeśli zadajesz pytanie naprowadzające, takie jak „Co jest nie tak z moim kodem?” lub „Jak mogę naprawić mój kod?”, model języka często odpowie odpowiedzią, która zakłada, że ​​coś jest nie tak z Twoim kodem, zamiast powiedzieć Ci, że nie ma w nim nic złego. Nie zaszkodzi zapytać, ale ostatecznie zaufaj swojemu osądowi.

Naprawianie długich funkcji

https://aie24.pl/

Funkcja startNewGame() ma więcej niż jedno zastosowanie. Obecnie resetuje zmienne globalne, resetuje siatkę kółka i krzyżyka, wysyła wiadomość do interfejsu API OpenAI, aby nakazać mu rozpoczęcie nowej gry, i zapisuje odpowiedź serwera na ekranie przed zwróceniem odpowiedzi. Poprosiłem czat Copilot o naprawienie funkcji startNewGame(), aby nie miała zbyt wielu zadań. Rozwiązaniem, z którym się zwrócił, było podzielenie startNewGame() na trzy funkcje, ale jego rozwiązanie odrzuciło najważniejszą część funkcjonalności startNewGame(), czyli rozpoczęcie nowej gry. Następnie zadałem to samo pytanie GPT-4, który dał mi znacznie lepszą sugestię, jak rozdzielić funkcję. Kod wygenerowany przez GPT-4 dla startNewGame() po prostu wywołuje trzy inne funkcje, takie jak ta:

async startNewGame() {

this.resetGameState();

this.clearBoardDisplay();

await this.postNewGameMessage();

}Jeśli jeden model językowy nie daje oczekiwanych rezultatów, wypróbuj inny. Jeśli żaden z nich nie pomaga, być może musisz zmienić polecenie lub podzielić zadanie na mniejsze części.