Strona główna / Artykuły / Co to jest i jak korzystać z React Query w systemach produkcyjnych?

Co to jest i jak korzystać z React Query w systemach produkcyjnych?

Praktyczny przewodnik po tym, czym jest React Query i jak go używać w systemach produkcyjnych: umowy, sprawdzania oraz gotowe miejsca na kod dla zespołów wdrażających ten wzorzec.

2930 słów

Poniższe notatki przedstawiają praktyczną ścieżkę nauki od „Pierwsze kroki z React Query”. Nacisk kładziony jest na umowy, sprawdzenia oraz miejsca na kod do wstawienia, a nie na motywacyjne aspekty. Podczas przechodzenia przez etap przeglądu, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzuć możliwość cichego, częściowego ukończenia zadania.

Stan serwera vs stan klienta

Stosunek stanu serwera do etapu klienta działa najlepiej, gdy traktuje się go jako mierzalną wielkość. Zanim rozszerzysz zakres, zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian. Zapisz czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy przechodzi się z środowiska demonstracyjnego do współdzielonych środowisk. Utrzymuj koszty renderowania na niskim poziomie i odkładaj drogie operacje wyliczeniowe na później, dopiero po ich zmierzeniu. Przedwczesne stosowanie mechanizmów memoizacji może ukrywać błędy związane ze starymi danymi.

Tradycyjnie w ten sposób pobieramy dane

Zazwyczaj w ten sposób najlepiej funkcjonuje etap przetwarzania, gdy traktuje się go jako mierzalną powierzchnię. Zapisz jeden idealny przypadek, jeden przypadek awarii oraz notatkę o cofnięciu zmian, zanim rozszerzysz zakres pracy. Trzymaj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności przeglądania całej struktury. Utrzymuj koszty renderowania na niskim poziomie i odkładaj drogie operacje wyliczeniowe na później, dopiero po ich zmierzeniu. Przedwczesne stosowanie mechanizmów memoizacji może ukrywać błędy związane ze starymi wartościami.

const [users, setUsers] = useState([])
const [loading, setLoading] = useState(false)
const [error, setError] = useState(null)
useEffect(() => {
  async function fetchUsers() {
    try {
      setLoading(true)      const res = await fetch(
        "https://jsonplaceholder.typicode.com/users"
      )      const data = await res.json()      setUsers(data)
    } catch (err) {
      setError(err)
    } finally {
      setLoading(false)
    }
  }  fetchUsers()

Z użyciem React Query powyższy kod staje się:

Z React Query ten etap funkcjonuje najlepiej, gdy traktowany jest jako mierzalna powierzchnia do analizy. Zapisz jeden idealny przypadek działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres. Zdokumentuj zarówno prawidłowy przebieg działania, jak i ścieżkę naprawczą. Próby ponownych działań, kontrola przez ludzi oraz obsługa wiadomości błędowych stanowią część produktu, a nie elementy dodawane później. Utrzymuj koszty renderowania na niskim poziomie i odkładaj drogie operacje obliczeniowe za pomocą memoizacji tylko po dokonaniu pomiarów. Przedwczesna memoizacja może ukrywać błędy związane ze starymi wartościami propów.

function Users() {
  const {
    data,
    isLoading,
    error
  } = useQuery({
    queryKey: ["users"],
    queryFn: fetchUsers
  })
  if (isLoading) {
    return <p>Loading...</p>
  }  if (error) {
    return <p>Something went wrong</p>
  }  return (
    <ul>
      {data.map(user => (
        <li key={user.id}>
          {user.name}
        </li>
      ))}
    </ul>
  )
}

Z React Query ten etap funkcjonuje najlepiej, gdy traktowany jest jako mierzalna powierzchnia do analizy. Zapisz jeden idealny przypadek działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres. Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzucaj ciche, częściowe ukończenie procesów.

Jak więc faktycznie go używamy?

Aby ustalić, jak przygotować scenariusz, zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu, operatorzy powinni móc ponownie uruchomić ten krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy rejestrować czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega nieoczekiwanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Stan powinien być umieszczany obok komponentu, który odpowiada za jego modyfikację. Umieszczanie wszystkiego w globalnym magazynie utrudnia wykrycie błędów związanych z czasem wykonywania.

1. Ustawienia

W fazie przygotowawczej nr 1 należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Konfigurację należy przechowywać poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Stan powinien być przechowywany razem z komponentem odpowiedzialnym za jego zmianę. Umieszczanie wszystkiego w globalnym magazynie utrudnia wykrycie błędów związanych z czasem wykonywania operacji.

npm install @tanstack/react-query
const queryClient = new QueryClient();

root.render(
<QueryClientProvider client={queryClient}>
    <App />
</QueryClientProvider>
);

2. Pobieranie danych za pomocą useQuery

Dla przypadku „Pobieranie danych z etapem” należy przed zmianą kodu zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia. Operatorzy powinni móc ponownie uruchomić ten krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy udokumentować zarówno prawidłowy przebieg działania, jak i ścieżkę naprawczą. Próby ponownych działań, kontrolne punkty ludzkie oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dodawane później. Stan powinien być przechowywany razem z komponentem, który odpowiada za dokonywanie modyfikacji. Umieszczanie wszystkiego w globalnym magazynie utrudnia wykrycie błędów związanych z czasem realizacji. Dla przypadku „Pobieranie danych z etapem” należy przed zmianą kodu zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia. Operatorzy powinni móc ponownie uruchomić ten krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nazwij poszczególne elementy, zdefiniuj kryteria sukcesu i odrzucaj ciche, częściowe ukończenie zadań.

const { data,
isPending,
error } = useQuery({
 queryKey: ["users"],
 queryFn: fetchUsers
 })

2.1. Funkcja zapytania

Podczas przechodzenia przez etap 2.1 Funkcja zapytania, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zapisz czasy wykonywania oraz koszt tokena lub zapytania obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Traktuj efekty jako synchronizację z otaczającym światem, a nie jako zamiennik wartości pochodnych podczas renderowania.

async function fetchUsers() {
  const res = await fetch("/api/users")

  if (!res.ok) {
    throw new Error("Failed to fetch users")
  }

  return res.json()
}
useQuery({
  queryKey: ["users"],
  queryFn: fetchUsers
})

2.2. Klucz zapytania

Gdy przechodzisz przez etap klucza zapytania 2 2, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Przechowuj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Traktuj efekty jako synchronizację z otaczającym światem, a nie jako zamiennik wartości wyliczanych podczas renderowania.

3. Cacheowanie

Gdy przechodzisz przez 3 etapy cacheowania, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zdokumentuj zarówno ścieżkę prawidłowego działania, jak i ścieżkę naprawczą. Próby ponowne, kontrola przez ludzi oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dopiero późniejszej optymalizacji. Traktuj efekty jako synchronizację z otaczającym światem, a nie jako zamiennik wartości wyliczanych podczas renderowania. Gdy przechodzisz przez 3 etapy cacheowania, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzucaj ciche, częściowe ukończenie zadania.

4. staleTime

Faza 4 staleTime działa najlepiej, gdy traktuje się ją jako mierzalną powierzchnię. Zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres badania. Zapisuj czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Utrzymuj koszty renderowania na niskim poziomie i odkładaj drogie operacje wywodzenia na później, dopiero po ich zmierzeniu. Przedwczesna memoizacja może ukrywać błędy związane ze starymi wartościami.

useQuery({
  queryKey: ["users"],
  queryFn: fetchUsers,
  staleTime: 60,000 // 60 seconds
})

Dlaczego potrzebujemy staletime??

Najlepiej funkcjonuje podejście oparte na zrozumieniu „dlaczego” potrzebne są poszczególne etapy, gdy traktuje się je jako mierzalną powierzchnię do analizy. Zapisz jeden idealny przykład działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres pracy. Trzymaj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, aby operatorzy mogli je sprawdzić bez konieczności przeglądania całej struktury. Utrzymuj koszty procesu renderowania na niskim poziomie i odkładaj drogie operacje obliczeniowe na później, dopiero po ich zmierzeniu. Przedwczesne stosowanie mechanizmów memoizacji może ukrywać błędy związane ze starymi wartościami.

Rozumienie staleTime

Faza Understanding staleTime funkcjonuje najlepiej, gdy jest traktowana jako mierzalna zmienna. Zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres. Zdokumentuj zarówno prawidłowy przebieg działania, jak i ścieżkę przywracania do normalnego stanu. Próby ponownych działań, kontrola przez ludzi oraz obsługa nieudanych wiadomości stanowią część produktu, a nie elementy dodawane później. Utrzymuj koszty przetwarzania na niskim poziomie i odkładaj drogie operacje wyliczeniowe na później, dopiero po ich zmierzeniu. Przedwczesne stosowanie mechanizmów memoizacji może ukrywać błędy związane ze starymi wartościami. Faza Understanding staleTime funkcjonuje najlepiej, gdy jest traktowana jako mierzalna zmienna. Zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzucaj ciche, częściowe ukończenie zadań.

User visits page
       ↓
Fetch users
       ↓
User navigates away
       ↓
User comes back
       ↓
Fetch users again
staleTime: 5 * 60 * 1000

5. gcTime

Dla etapu 5 gcTime należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy rejestrować czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega nieoczekiwanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Stan powinien być przechowywany razem z komponentem, który odpowiada za jego modyfikację. Umieszczanie wszystkiego w globalnym magazynie utrudnia wykrycie błędów związanych z czasem wykonywania.

useQuery({
  queryKey: ["users"],
  queryFn: fetchUsers,
  gcTime: 60000
})

Jaka jest różnica między staleTime a gcTime?

Na etapie „Jaka jest różnica?” należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Konfigurację należy przechowywać poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Stan powinien być przechowywany razem z komponentem, który odpowiada za jego modyfikację. Umieszczanie wszystkiego w globalnym magazynie utrudnia wykrycie błędów związanych z czasem wykonywania operacji.

6. Ponowne pobieranie danych

W fazie 6 Refetching należy zdefiniować dane wejściowe, osobę odpowiedzialną za daną czynność oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić tę czynność na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy udokumentować zarówno prawidłowy przebieg działania, jak i ścieżkę naprawczą. Próby ponownych działań, kontrola przez ludzi oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dodawane później. Stan powinien być przechowywany razem z komponentem, który odpowiada za jego modyfikację. Umieszczanie wszystkiego w globalnym magazynie utrudnia wykrycie błędów związanych z czasem realizacji. W fazie 6 Refetching należy zdefiniować dane wejściowe, osobę odpowiedzialną za daną czynność oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić tę czynność na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nazwij poszczególne elementy, zdefiniuj kryteria sukcesu i odrzucaj ciche, częściowe ukończenie zadań.

const { refetch } = useQuery(...)
refetch()
useQuery({
  queryKey: ["users"],
  queryFn: fetchUsers,
  refetchInterval: 30,000
})

7. Mutacje — Tworzenie, aktualizacja, usuwanie

Gdy przechodzisz przez etap 7 Mutacji: Tworzenie i Aktualizacja, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zapisz czas wykonywania oraz koszt tokena lub zapytania obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega nieoczekiwanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Traktuj efekty jako synchronizację z otaczającym światem, a nie jako zamiennik wartości pochodnych podczas renderowania.

async function createUser(user) {
  const response = await fetch(
    "https://jsonplaceholder.typicode.com/users",
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(user),
    }
  );

  if (!response.ok) {
    throw new Error("Failed to create user");
  }

  return response.json();
}
import { useMutation } from "@tanstack/react-query";

function CreateUser() {
  const mutation = useMutation({
    mutationFn: createUser,
  });

  return (
    <button
      onClick={() =>
        mutation.mutate({
          name: "John Doe",
          email: "john@example.com",
        })
      }
      disabled={mutation.isPending}
    >
      {mutation.isPending ? "Creating..." : "Create User"}
    </button>
  );
}

export default CreateUser;
Button click
    ↓
mutation.mutate(user)
    ↓
createUser(user)
    ↓
POST request
    ↓
Server

7.1. Stany mutacji

Gdy przechodzisz przez etap 7 1 Mutation States, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Trzymaj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Traktuj efekty jako synchronizację z otaczającym światem, a nie jako zamiennik wartości pochodnych podczas renderowania.

const {
  mutate,
  isPending,
  isSuccess,
  isError,
  error,
  data,
} = useMutation({
  mutationFn: createUser,
});
<button
  onClick={() => mutate({ userName: "delfina ghimire" })}
  disabled={isPending}
>
  {isPending ? "Creating..." : "Create user"}
</button>

8. Klient zapytań

Podczas przechodzenia przez 8 etapów Query Client najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zdokumentuj zarówno ścieżkę prawidłowego działania, jak i ścieżkę naprawczą. Próby ponowne, kontrola przez ludzi oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dodawane później. Traktuj efekty jako synchronizację z otaczającym światem, a nie jako zamiennik wartości pochodnych podczas renderowania. Podczas przechodzenia przez 8 etapów Query Client najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzucaj ciche, częściowe ukończenie zadania.

9. Unieważnianie zapytań

Faza unieważniania 9 zapytań działa najlepiej, gdy traktuje się ją jako mierzalną powierzchnię do analizy. Zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres badania. Zapisuj czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Utrzymuj koszty renderowania na niskim poziomie i odkładaj drogie operacje wyliczeniowe na później, dopiero po ich zmierzeniu. Przedwczesne stosowanie mechanizmów memoizacji może ukrywać błędy związane ze starymi danymi.

[
  { id: 1, userName: "delfina ghimire" },
  { id: 2, userName: "spiderman ghimire" },
]
mutation.mutate({
  userName: "ironman ghimire",
});
const queryClient = useQueryClient();
const mutation = useMutation({
  mutationFn: createUser,
  onSuccess: () => {
    queryClient.invalidateQueries({
      queryKey: ["users"],
    });
  },
});
Create Users (Mutation)
     ↓
Server data changes
     ↓
Invalidate ["users"]
     ↓
Query becomes stale
     ↓
Refetch
     ↓
UI gets fresh data

Unieważnianie vs. ponowne pobieranie

Faza Invalidate vs Refetch działa najlepiej, gdy traktuje się ją jako mierzalną powierzchnię do analizy. Zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres badania. Trzymaj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny haseł oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Utrzymuj koszt renderowania na niskim poziomie i odkładaj drogie operacje obliczeniowe na później, dopiero po ich zmierzeniu. Przedwczesne stosowanie mechanizmów memoizacji może ukrywać błędy związane ze starymi wartościami propów.

Wniosek

Faza zakończenia działa najlepiej, gdy traktuje się ją jako mierzalną powierzchnię. Zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres. Zdokumentuj zarówno prawidłowy przebieg, jak i ścieżkę odzyskiwania. Próby ponownych działań, kontrolne punkty ludzkie oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dodawane później. Utrzymuj koszty przetwarzania na niskim poziomie i odkładaj drogie operacje wywodzenia na później, tylko po dokonaniu pomiarów. Przedwczesne stosowanie mechanizmów memoizacji może ukrywać błędy związane ze starymi danymi. Faza zakończenia działa najlepiej, gdy traktuje się ją jako mierzalną powierzchnię. Zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzucaj ciche, częściowe ukończenia.

TL;DR

W fazie TL DR należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Obok wyników funkcjonalnych należy zapisywać czas trwania oraz koszt tokena lub zapytania. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Stan powinien być przechowywany razem z komponentem, który odpowiada za jego modyfikację. Umieszczanie wszystkiego w globalnym magazynie utrudnia wykrycie błędów związanych z czasem trwania operacji.

Lista kontrolna operacyjna

W fazie listy kontrolnej operacyjnej należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu.

Należy preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok zawiedzie, błąd powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji.

Umieszczaj stan w tym samym komponencie, który zarządza mutacją. Przenoszenie wszystkiego do globalnego magazynu utrudnia wykrycie błędów związanych z czasem wykonywania operacji.

Napisz krótki przewodnik: jak rotować klucze, jak opróżnić kolejkę z zadań, jak cofnąć ostatnie zadanie.

Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi danymi wyjściowymi. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzucaj ciche, częściowe ukończenie procesu.

Umieszczaj stan w tym samym komponencie, który zarządza mutacją. Przenoszenie wszystkiego do globalnego magazynu utrudnia wykrycie błędów związanych z czasem wykonywania operacji.

Zanim uruchomisz cały stack, zamroź wersje, utwórz dokładny zapis dla kluczowych etapów realizacji oraz potwierdź kroki odwracania zmian. Środowiska współdzielone wymagają ograniczeń szybkości, weryfikacji przynależności użytkowników oraz wyraźnego właściciela odpowiedzialnego za rotację haseł. Wolimy nudną niezawodność od pomysłowych, jednorazowych demonstracji.

Uwaga dotycząca 1aa45226c385: trzymaj klucze dostawcy poza repozytorium, ustaw ograniczenie liczby tokenów na sesję oraz przechowuj zapisy obok plików testowych, aby późniejsze zmiany modeli pozostawały porównywalne.