(Helluva Boss)
Przetłumaczono z angielskiego
Grupa I.M.P, z możliwością TETO!?
⯆⚉⯆
~Teteteto~
"Nie mów mi 'słodka', jestem gangsta!"
(Zalecane używanie z jakimś proxy. Nie wiem, czy JLMM zadziała, i jestem zbyt leniwy, żeby to samemu testować)
Scenariusz pierwszy:
Loona, Millie i Moxxie uciekają przed policją.
Scenariusz drugi:
Pracujesz w I.M.P już od miesiąca. Dziś wszyscy mają spotkanie.
Scenariusz trzeci:
Jesteś chory. Loona się tobą opiekuje. (ma być fluff)
Scenariusz czwarty:
Ty i Millie jesteście na misji na ziemi.
Scenariusz piąty:
Ojej...
Scenariusz szósty:
Doszło do wielkiej kłótni. Idź pocieszyć Loonę.
Scenariusz siódmy:
Ty i Loona wygłupiacie się.
Scenariusz ósmy:
Loona, Millie, Moxxie i Blitzo chcą adoptować nowego Piekłopsa. To ty, bliźniaku. (POV Piekłopsa)
Scenariusz dziewiąty:
Wpisz własny scenariusz.
Tagi:
Komputery nie mają sensu. Wrzuć trochę metalu do pudełka i bum. Co do licha się tu dzieje? Wewnątrz twojego peceta znajduje się jednostka centralna, czyli CPU. To w zasadzie po prostu kawałek krzemu z miliardami mikroskopijnych przełączników zwanych tranzystorami. W zależności od przepływu prądu mogą być włączone lub wyłączone, trochę jak żarówka, co daje nam dwa stany: jeden i zero. Wartość jednego z tych przełączników nazywa się bitem. Jeden bit sam w sobie niewiele robi, ale złóż je razem i... Grupa 8 bitów nazywa się bajtem i może mieć 256 różnych kombinacji zer i jedynek. Gratulacje! Możemy teraz przechowywać informacje, licząc w systemie zwanym binarnym. Każdy bit reprezentuje potęgę dwójki, gdzie 1 oznacza, że potęga jest uwzględniona, a 0, że nie, więc ta liczba ma 1 razy 64, 1 razy 4 i 1 razy 1, co daje w sumie 69. To miłe, ale dla ludzi jeszcze lepszy jest system szesnastkowy. Często oznacza się go tym 0x i jest po prostu bardziej czytelnym formatem niż binarny. Cztery bity binarne mogą przyjąć dowolną wartość od 0 do 15. System szesnastkowy używa cyfr od 0 do 9 i liter od A do F, aby reprezentować te wartości, więc grupa czterech bitów może zostać zastąpiona jedną cyfrą szesnastkową. Dobra, skoro potrafimy już przechowywać liczby, potrzebujemy tylko, żeby komputery faktycznie, no wiecie, coś z nimi robiły. Za pomocą tranzystorów można tworzyć bramki logiczne, czyli układy elektroniczne, które ucieleśniają zdania logiczne. Można to sobie wyobrazić jako żarówkę z dwoma przełącznikami, gdzie światło zapala się tylko pod pewnymi warunkami, na przykład tylko jeśli A i B są włączone. Łącząc bramki logiczne w sprytny sposób, można zbudować układy wykonujące obliczenia zgodnie z algebrą Boole'a, która jest systemem formalizującym operacje matematyczne w systemie binarnym. Ale chociaż komputery rozumieją zera i jedynki, dla ludzi nie jest to zbyt użyteczne. Więc używając kodowania znaków takiego jak ASCII, możemy przypisać każdej postaci liczbę binarną. Kiedy wpisujesz cokolwiek na klawiaturze, zostaje to przetłumaczone na ten kod binarny, a gdy tylko komputer to zobaczy, mówi: aha, tak, to wielka litera A, i wklepuje ją na ekran. Sposób, w jaki te urządzenia współpracują, jest zarządzany przez jądro systemu operacyjnego, takie jak Windows, Linux czy Mac, które znajduje się między sprzętem komputerowym a aplikacjami i zarządza tym, jak wszystko razem działa, na przykład za pomocą sterowników urządzeń. Urządzenia wejściowe pozwalają ci wydawać komputerowi polecenia naciśnięciem przycisku, ale na najniższym poziomie komputery rozumieją tylko instrukcje w kodzie maszynowym, czyli kodzie binarnym mówiącym CPU, co ma robić i jakich danych użyć. Jeśli chodzi o wykonywanie tych instrukcji, CPU jest trochę jak geniusz, tylko z pamięcią obłąkanej złotej rybki. Potrafi obsłużyć dowolne instrukcje, ale nie potrafi przechowywać żadnych danych, więc jest naprawdę przydatne tylko z pamięcią o dostępie swobodnym, czyli RAM. Można to sobie wyobrazić jak siatkę, gdzie każde pole może pomieścić jeden bajt informacji, który może być danymi lub instrukcjami, i ma adres, żeby CPU mogło uzyskać do niego dostęp w czterech krokach. Pobierz z pamięci, zdekoduj instrukcje i dane, a na koniec wykonaj i zapisz wynik. To jeden cykl maszynowy. Ponieważ program to w zasadzie tylko lista instrukcji i pamięć, żeby go uruchomić, CPU wykonuje je jedną po drugiej w cyklach maszynowych, aż do ukończenia. Aha, czy wspomniałem, że dzieje się to, no, naprawdę szybko? Współczesne CPU potrafią wykonywać miliardy cykli na sekundę, które są koordynowane i synchronizowane przez generator zegara. Szybkość tego zegara mierzy się w gigahercach, a ludzie często podkręcają swoje CPU, żeby poprawić wydajność, co jest miłe, ale może po prostu podpalić twojego peceta. Co jest jeszcze bardziej szalone, to fakt, że CPU ma wiele rdzeni, które mogą wszystkie wykonywać różne instrukcje równolegle, czyli w tym samym czasie. Każdy rdzeń można też podzielić na wiele wątków, co pozwala każdemu pojedynczemu rdzeniowi obsługiwać wiele instrukcji współbieżnie, czyli przełączać się między nimi naprawdę szybko. Dobra, to fajne, ale nie ma znaczenia, jak potężny jest komputer, jeśli nie masz jak dać mu instrukcji w pierwszej kolejności. Wpisywanie kodu maszynowego ręcznie prawdopodobnie doprowadziłoby cię do szaleństwa, ale na szczęście nie musisz tego robić. Jądro jest opakowane w powłokę, która jest po prostu programem udostępniającym jądro użytkownikowi, pozwalającym na proste instrukcje w interfejsie wiersza poleceń z tekstowymi danymi wejściowymi. Ale najlepszym sposobem, żeby komputer zrobił coś pożytecznego, jest język programowania, który używa abstrakcji, więc zamiast tego możesz napisać kod, który wygląda tak, a który jest potem konwertowany na kod maszynowy za ciebie. Niektóre języki, jak Python, używają interpretera, który bezpośrednio próbuje wykonać kod źródłowy linia po linii. Inne języki, jak C czy Go, używają kompilatora, który konwertuje cały program na kod maszynowy, zanim umieści go w pliku, który CPU może wykonać. Otóż każdy język programowania ma inną składnię, ale istnieją pewne podstawowe narzędzia, które ma prawie każdy z nich. Najbardziej podstawowym sposobem używania danych są zmienne, które przypisują wartość do nazwy, którą można potem ponownie wykorzystać i modyfikować. W zależności od wartości zmienne mogą mieć różne typy danych. Dla tekstu są to pojedyncze znaki i łańcuchy wielu znaków. Dla liczb są liczby całkowite, które mogą być też ze znakiem, jeśli są ujemne, oraz liczby zmiennoprzecinkowe dla wartości dziesiętnych. Nazywa się je zmiennoprzecinkowymi, bo kropka dziesiętna może się przesuwać, wymieniając precyzję na zakres. Jest to możliwe, bo używają notacji naukowej. To jakaś liczba razy potęga mówiąca, gdzie postawić kropkę dziesiętną, co dokładnie odpowiada temu, jak wyglądają pod maską. Rzeczywista liczba jest przechowywana za pomocą ułamków binarnych. Niektóre ułamki, jak jedna trzecia, można tylko aproksymować w systemie binarnym za pomocą nieskończonej sumy. Ale ponieważ pamięć nie jest nieskończona, trzeba ją gdzieś uciąć, co prowadzi do błędów zaokrągleń, powodujących czasem dość dziwne obliczenia. Jeśli to nie wystarcza, long i double zużywają dwukrotnie więcej pamięci, żeby podwoić zakres intów i floatów. Niektóre języki, jak Python, automatycznie ustalają, jakiego typu jest zmienna, ale w języku takim jak C musisz jawnie zadeklarować typ zmiennej. Wartość zmiennej jest przechowywana pod pewnym adresem w pamięci. Wskaźniki to zmienne, których wartością jest adres pamięci innej zmiennej, oznaczany tym ampersandem. Więc tak naprawdę wskaźnik to po prostu jakiś kawałek pamięci wskazujący na inny kawałek pamięci. Ponieważ adres pamięci to po prostu liczba, możesz do niego dodawać i odejmować, żeby nawigować przez poszczególne bajty pamięci. Nazywa się to arytmetyką wskaźników. W niektórych językach niskiego poziomu, jak C, musisz ręcznie alokować i zwalniać pamięć, gdy nie jest już używana. Wszystko to dzieje się na stercie, która jest częścią pamięci, która może dynamicznie rosnąć i kurczyć się w miarę potrzeb programu, co daje większą kontrolę, ale sprawia, że niezwykle łatwo całkowicie zepsuć swój kod. Możesz sięgnąć do pamięci, której nie powinieneś, albo która po prostu nie istnieje, co nazywa się segmentation fault. Ale też, jeśli jakiś kawałek pamięci nie jest już używany i zapomnisz go zwolnić albo nie masz już do niego dostępu, ta pamięć nie jest już użyteczna. Nazywa się to wyciekiem pamięci i może powodować spowolnienie programu, a ostatecznie jego awarię. Żeby uniknąć tego bałaganu, języki wysokiego poziomu, jak Python, mają wbudowane moduły zbierające śmieci, które zarządzają pamięcią za ciebie. Różne typy danych zajmują różną ilość pamięci. Liczby całkowite to najczęściej 4 bajty pamięci, pojedynczy znak to najczęściej 1 bajt pamięci, a łańcuch to po prostu wiele bajtów znaków z znakiem null sygnalizującym koniec łańcucha. Przechowywanie wielu elementów w takim ciągłym kawałku pamięci to idea tablicy. Mówiąc ogólniej, to lista elementów o tym samym typie danych, gdzie każdy element ma numeryczny indeks, najczęściej zaczynający się od 0. Ponieważ elementy leżą obok siebie w pamięci, znając adres pierwszego elementu, można szybko zindeksować dowolny element tablicy za pomocą arytmetyki wskaźników. Tablice to tak zwana struktura danych, czyli po prostu sposób organizowania danych, żeby łatwiej się z nimi pracowało. Pobieranie wartości z tablicy jest błyskawicznie szybkie, ale rozmiar tablicy jest często ustalany przy jej tworzeniu, więc gdy jest pełna, nie możesz nic dodać, a jeśli nie używasz jej całej, to po prostu zmarnowana pamięć, więc bardziej elastyczną opcją jest lista powiązana. Używa ona węzłów zawierających wartość i wskaźnik do następnego węzła, co pozwala im być rozproszonymi w pamięci. Może też dynamicznie rosnąć i kurczyć się, bo możesz dodawać i usuwać dowolny węzeł, a możesz ją zmieniać kolejność, po prostu przestawiając wskaźniki. To świetne, ale mogą być niepraktyczne, bo nie masz sposobu, żeby dostać się do ostatniego węzła, chyba że przejdziesz przez każdy poprzedni. Ale mimo to zarówno tablice, jak i listy powiązane są użyteczne, bo pozwalają tworzyć kolejki i stosy. Stos kieruje się zasadą ostatni przyszedł, pierwszy wyszedł, zupełnie jak branie naleśnika ze stosu. Praktycznie, wyobraź sobie wskaźnik, który zawsze wskazuje na element ostatnio dodany do struktury, wtedy możesz zrobić pop, czyli usunąć ostatni element, co przesuwa wskaźnik z powrotem. Kolejka kieruje się zasadą pierwszy przyszedł, pierwszy wyszedł i używa dwóch wskaźników: jednego dla pierwszego dodanego elementu i jednego dla ostatniego. Każdy nowy element jest dodawany za ostatnim wskaźnikiem, który jest potem aktualizowany, a usuwanie z kolejki zaczyna się od pierwszego wskaźnika. Inną użyteczną strukturą danych jest mapa hash, czyli po prostu kolekcja par klucz-wartość. Działa trochę jak tablica, ale używa funkcji hashującej, żeby wziąć klucz i przypisać go do indeksu, gdzie jego wartość jest potem przechowywana. Ale czasami dwa różne klucze mogą mapować się na ten sam indeks, co nazywa się kolizją. Istnieją różne sposoby radzenia sobie z tym, ale jednym z nich jest utworzenie listy powiązanej na tej pozycji w tablicy, co sprawia, że wyszukanie tej wartości jest trochę wolniejsze, ale mimo to mapy hash są niesamowicie użyteczne, bo możesz zdefiniować klucze wskazujące na każdą wartość, a ponieważ są oparte na tablicach, pobieranie ich jest błyskawicznie szybkie. W przypadku wielu problemów może być bardzo użyteczne przedstawienie relacji między różnymi punktami danych jako struktury danych. Jeśli weźmiesz węzły listy powiązanej, ale pozwolisz dowolnemu węzłowi wskazywać na dowolny inny węzeł, otrzymasz graf, gdzie węzły są połączone krawędziami, które mogą być skierowane, nieskierowane, a nawet mogą mieć wagę, która może oznaczać dowolną metrykę, jak odległość czy koszt. Grafy są użyteczne do analizowania grup w sieciach lub znajdowania najkrótszej ścieżki między dwoma punktami, na przykład w Mapach Google. Istnieją dwa główne sposoby przeszukiwania grafu. Przeszukiwanie wszerz zaczyna się od jednego węzła i przesuwa się warstwa po warstwie, aż po raz pierwszy znajdzie docelowy węzeł. Przeszukiwanie w głąb bada każdą pojedynczą ścieżkę w pełni, aż dotrze do ślepego zaułka, potem cofa się do ostatniego węzła z inną ścieżką i kontynuuje w ten sam sposób, aż znajdzie docelowy węzeł. Graf, w którym dowolne dwa węzły są połączone dokładnie jedną ścieżką, nazywa się drzewem i reprezentuje hierarchię, na przykład system plików na twoim komputerze. Drzewo zaczyna się w korzeniu i rozgałęzia się na poddrzewa, które kończą się w liściach. Węzły nadrzędne mogą mieć dowolną liczbę węzłów podrzędnych, ale często najbardziej użyteczne są drzewa binarne. Na przykład drzewo binarne, w którym wszystkie wartości po lewej stronie dowolnego węzła są mniejsze, a wszystkie wartości po prawej są większe, nazywa się drzewem wyszukiwania binarnego, co sprawia, że znajdowanie konkretnych wartości jest super szybkie. Jeśli chcesz znaleźć docelową wartość, po prostu zacznij od korzenia. Jeśli cel jest mniejszy niż ten węzeł, idź w lewo, jeśli większy, idź w prawo, i powtarzaj to, aż znajdziesz cel. To, czego właśnie użyliśmy, to bardzo prosty algorytm, czyli po prostu zestaw instrukcji, który rozwiązuje problem krok po kroku. Najprostszym sposobem napisania algorytmu jest forma funkcji. Przyjmuje dane wejściowe, coś z nimi robi i zwraca wynik. Zupełnie jak zmienne, możesz potem wywołać funkcję po jej nazwie i przekazać różne argumenty. Przy wywoływaniu funkcji wywołanie funkcji jest odkładane na stos wywołań, który jest pamięcią krótkoterminową używaną do wykonywania kodu, i jak sama nazwa wskazuje, opiera się na strukturze danych stosu, co oznacza ostatni przyszedł, pierwszy wyszedł. Żeby zaimplementować algorytmy, często trzeba porównać dwie wartości, co można zrobić za pomocą operatorów, jak większe niż czy równość, oraz wyrażeń logicznych, takich jak and, or i not. Takie wyrażenia są proste, mogą być prawdziwe lub fałszywe, co jest możliwymi wartościami typu danych Boolean i pozwala pisać instrukcje warunkowe. Jeśli jakiś warunek jest prawdziwy, zrób to, w przeciwnym razie zrób tamto. Wartości logiczne można też używać do zapętlania pewnych części kodu. Jednym ze sposobów jest pętla while. Dopóki ten warunek jest prawdziwy, ten kod będzie się wykonywał. Innym sposobem jest pętla for, która może iterować po każdym elemencie wewnątrz struktury danych, jak tablica, ale może też zapętlać się określoną liczbę iteracji, ustawiając wartość początkową, inkrementując ją po każdej iteracji i ustalając górną granicę za pomocą warunku. Funkcje mogą też wywoływać same siebie, co nazywa się rekurencją. Jest to użyteczne, gdy problem można rozbić na mniejsze identyczne problemy, jak obliczanie silni z 5, która to jest po prostu 5 razy silnia z 4, która to jest po prostu 4 razy Ale domyślnie funkcja rekurencyjna będzie po prostu wywoływać się w nieskończoność. Oznacza to, że odkłada coraz więcej wywołań funkcji na stos wywołań, aż pamięć stosu zostanie przekroczona w przepełnieniu stosu. To nie jest optymalne. Żeby to zatrzymać, trzeba dodać do funkcji rekurencyjnej warunek bazowy, który określa, kiedy się zatrzymać. Dopiero wtedy wywołania funkcji zostaną wykonane bez wysadzania twojego peceta. Rekurencja jest fajna, ale może być dość kosztowna pod względem czasu i pamięci. Więc żeby zminimalizować ilość potrzebnych obliczeń, wcześniejsze wyniki można zapisać w pamięci podręcznej, żeby gdy pojawią się ponownie, komputer nie musiał ich obliczać od zera. Nazywa się to memoizacją. Mówiąc o wydajności, żeby ocenić, jak dobry jest algorytm, można spojrzeć na złożoność czasową i pamięciową, czyli ile czasu lub pamięci potrzeba, żeby go uruchomić. Mierzy się to notacją Big O, która opisuje relację między wzrostem rozmiaru danych wejściowych a liczbą operacji potrzebnych do wykonania algorytmu. Na przykład dodanie 1 do każdej liczby w tablicy to O , bo liczba operacji rośnie liniowo w miarę wzrostu tablicy. Istotna nie jest dokładna liczba operacji, ale raczej trend, gdy rozmiar danych wejściowych dąży do nieskończoności. Widzisz, coś takiego jak silnia n rośnie znacznie szybciej niż jakakolwiek funkcja liniowa kiedykolwiek mogłaby. Więc dopóki złożoność czasowa jest jakąś relacją liniową, upraszcza się ją do O , i to samo dotyczy każdej innej grupy. Pisząc algorytm, zawsze istnieją różne podejścia. Podejście siłowe polegałoby na prostym sprawdzeniu każdego elementu, aż znajdziemy cel na liście. Ale jeśli chcesz, żeby twój program działał szybciej niż ślimak ogrodowy, potrzebujesz bardziej wyrafinowanego podejścia, jak dziel i zwyciężaj. Na przykład w wyszukiwaniu binarnym wielokrotnie sprawdzasz środkowy element, żeby zobaczyć, po której stronie jest cel, i szukasz dalej w tej połowie, aż go znajdziesz. Istnieją też różne podejścia do pisania kodu w ogóle, które nazywa się paradygmatami programowania. Programowanie deklaratywne opisuje, co robi kod, ale nie jak dokładnie komputer powinien to zrobić, podczas gdy programowanie imperatywne jawnie opisuje, jak komputer powinien osiągnąć wynik za pomocą szczegółowych instrukcji. Rozszerzeniem programowania imperatywnego jest programowanie obiektowe, gdzie można definiować klasy jako plany obiektów, które są pojedynczymi jednostkami składającymi się z danych w postaci właściwości i zachowań w postaci metod. Żeby zakodować klasę, zaczynasz od zdefiniowania właściwości jako zmiennych i metod jako funkcji. Po zamknięciu właściwości i metod w klasie możesz utworzyć instancję obiektu i używać notacji kropkowej do pracy z jego właściwościami i metodami. Klasy ułatwiają organizowanie i ponowne wykorzystywanie kodu, bo możesz definiować podklasy, które dziedziczą właściwości i zachowania nadklasy, ale mogą je też rozszerzać i nadpisywać. Na przykład podklasa gumowej kaczki może zaimplementować kwakanie jako pisk. W rezultacie gumowe kaczki mogą być traktowane jako obiekty klasy kaczki, ale zachowują się inaczej, gdy wywoła się kwakanie, co jest koncepcją polimorfizmu. Ale w przypadku niektórych problemów żaden z tych tradycyjnych paradygmatów nie zadziała. Powiedzmy, że chcesz, żeby komputer rozpoznał, który z tych obrazów to pszczoła. Problem w tym, że nie da się tak naprawdę opisać kodem, jak wygląda pszczoła. Tu wkracza uczenie maszynowe, czyli uczenie komputera wykonywania zadania bez jawnego programowania go do tego zadania. Najpierw potrzebujesz dużo danych, które możesz podzielić na dane treningowe i dane testowe. Następnie wybierasz algorytm, który może zmieniać swoje parametry w czasie, na przykład sieć neuronową, gdzie wagi można aktualizować, żeby osiągnąć inny wynik. Wprowadzając mnóstwo danych treningowych do tego algorytmu, możesz zbudować model, którego dokładność możesz potem sprawdzić za pomocą danych testowych. Jeśli nie jest całkiem w porządku, model może z czasem się poprawiać, porównując wynik z tym, jaki powinien być, wychwytując różnicę w funkcji błędu i dostrajając swoje parametry, żeby zminimalizować różnicę. Ale niezależnie od tego, jak futurystyczna, najnowocześniejsza, błyskawicznie szybka i zoptymalizowana jest aplikacja, jeśli chcesz, żeby ludzie faktycznie jej używali, prawdopodobnie powinieneś wiedzieć o internecie. To sieć komputerów z całego globu połączonych kablami. Dosłownie, internet to po prostu kilka grubych kabli biegnących na dnie oceanu wraz z obiektami, jak dostawcy usług internetowych, którzy łączą cię z celem. Te komputery komunikują się za pomocą zestawu protokołów internetowych. Każdy komputer w sieci ma unikalny adres IP, a dwa komputery mogą potem przesyłać dane za pomocą protokołu kontroli transmisji. Dzieli on wiadomości na kilka pakietów, wysyła je przez sieć kabli, zanim odbiorca złoży wiadomość z powrotem. Jeśli masz słabe połączenie internetowe, mogłeś doświadczyć utraty pakietów, czyli po prostu tego, że niektóre z tych pakietów zgubią się po drodze. Jeśli internet to sprzęt, to sieć WWW to oprogramowanie, którego możesz używać w przeglądarce. Każda strona w sieci ma URL. Kiedy wpisujesz go w przeglądarce, ta wyszukuje adres IP serwera hostującego tę stronę za pomocą systemu nazw domen, który jest jak słownik mapujący nazwy domen na adresy IP rzeczywistych serwerów. Po połączeniu się z nim przez TCP twoja przeglądarka, zwana klientem, używa protokołu przesyłania hipertekstu, żeby wysłać żądanie HTTP do serwera, który potem daje odpowiedź, idealnie zawierającą zawartość strony internetowej. Rzeczywista strona internetowa najczęściej składa się z trzech części. Plik HTML zawiera całą treść strony i jest w zasadzie po prostu kolekcją elementów, które mogą być tekstem, linkami, przyciskami i tak dalej. Plik CSS kontroluje wygląd i sprawia, że strona wygląda ładnie. Ale strona jest bezużyteczna, jeśli naciśnięcie ładnie wyglądających przycisków nic nie robi, więc język taki jak JavaScript dodaje funkcjonalność. Ale czasami rzeczy mogą pójść nie tak. Z każdą odpowiedzią HTTP wiąże się kod odpowiedzi, który niesie informacje o statusie odpowiedzi. Na przykład 200 oznacza OK, a wszystko zaczynające się od 4 to błąd, z których najsłynniejszym jest 404, strona nie znaleziona. Żądania HTTP mogą nieść różne metody, na przykład get, post, put i delete, czyli pobieranie, dodawanie, aktualizowanie i usuwanie informacji. Są one często używane przez interfejsy programowania aplikacji, które łączą dwie aplikacje i pozwalają im na wzajemne oddziaływanie. Na przykład przechowywanie i pobieranie danych z bazy danych. Najczęstszym typem bazy danych jest relacyjna baza danych, która używa tabel do przechowywania danych. Kolumny tabeli zawierają różne atrybuty, a wiersze reprezentują poszczególne punkty danych. Każda tabela ma też jeden unikalny atrybut zwany kluczem głównym. Klucz obcy to klucz główny innej tabeli ustanawiający relację między nimi. W tym przypadku każda książka jest powiązana z autorem. Za pomocą języka takiego jak SQL możesz pisać instrukcje do pracy z danymi z tych tabel. Możesz wyszukać tytuły i autorów wszystkich książek, których tytuł zaczyna się na H, ale do tego musimy połączyć tabelę autorów z tabelą książek na pasującym kluczu, żeby połączyć dwa atrybuty z różnych tabel w jeden, co daje nam ten wynik. Te instrukcje są użyteczne, ale musisz uważać, bo możesz po prostu usunąć całą bazę danych jedną linią kodu. Ale nie martw się, to się nigdy nie zdarzyło. Za każdą stroną logowania stoi baza danych z nazwami użytkowników i hasłami. Kiedy użytkownik próbuje się zalogować, zapytanie SQL jest często używane do sprawdzenia, czy dane wejściowe użytkownika pasują do wpisu w bazie danych. To dobrze. Ale przebiegły aktor mógłby wpisać coś takiego, co zmienia zapytanie przez wcześniejsze zakończenie łańcucha i zakomentowanie reszty, co oznacza, że dopóki ta nazwa użytkownika istnieje w bazie danych, dostęp jest przyznany. Nazywa się to atakiem SQL injection i jest jednym z najłatwiejszych sposobów, w jakie hakerzy dostają się tam, gdzie nie powinni. Słuchanie o tych koncepcjach to jedno, ale żeby naprawdę się ich nauczyć, trzeba zobaczyć je w akcji i użyć ich samemu, co jest dokładnie tym, co możesz zrobić z Brilliant, który ma tysiące interaktywnych lekcji z wszystkiego, od matematyki i analizy danych po programowanie i AI. Sprawiają, że wiedza się utrwala, dzięki wizualnym lekcjom i interaktywnym problemom, co jest nie tylko zabawne i buduje intuicyjne umiejętności rozwiązywania problemów, ale też udowodniono, że jest sześć razy skuteczniejsze niż po prostu oglądanie godzin wykładów. Wiem, że znalezienie czasu na naukę nowych umiejętności może być trudne, ale Brilliant to takie łatwe. Możesz budować cenną wiedzę od podstaw w zaledwie kilka minut dziennie, dzięki małym lekcjom z dowolnego urządzenia, w dowolnym miejscu, o dowolnym czasie. Przejdziesz od podstaw analizy danych do analizowania prawdziwych zbiorów danych ze Spotify w absolutnie żadnym czasie, co możesz uzupełnić kursami podstaw matematyki i programowania w Pythonie, żeby zbudować jeden z najbardziej poszukiwanych zestawów umiejętności naszych czasów. Najlepsza część? Możesz wypróbować wszystko, co Brilliant ma do zaoferowania, za darmo przez pełne 30 dni, odwiedzając brilliant.org slash wackyscience. Dostajesz też 20% zniżki na roczną subskrypcję premium. Dzięki Brilliant za sponsorowanie tego filmu.
Utworzono 30 sty
Zaktualizowano 9 sie
Opublikowano 30 sty