Najlepszym sposobem na zrozumienie jakiegoś zagadnienia, jest przestudiowanie przykładów je ilustrujących. W kilku ostatnich postach omówiłem podstawy TypeScriptu. Nadszedł czas, żeby wykorzystać tę wiedzę w bardziej praktycznym kontekście.
Dziś postaram się wykonać i opisać proste ćwiczenie programistyczne, przy użyciu TS’a. Chciałbym wykorzystać najważniejsze funkcje języka, które do tej pory opisałem.
W ramach ćwiczenia wykonam ćwiczenie, które zostało przedstawione w książce Kyle Simpsona „Tajniki języka JavaScript. Na drodze do biegłości”. Książkę tę recenzowałem jakiś czas temu i wspomniałem o tym, że zadanie to dobrze sprawdza podstawowe umiejętności programowania, niezależnie od użytego języka. Dlatego uznałem, że będzie ono dobrym przykładem użycia TSa na blogu.
Książka jest dostępna za darmo w wersji elektronicznej na githubie autora, więc chyba nikt nie obrazi się, że przedstawię tu trochę jej zawartości 🙂 . Na końcu rozdziału pierwszego znajduje się zadanie, które mnie interesuje. Nie jest ono wybitnie trudne, ale tak jak pisałem, w ramach prezentacji/treningu nada się idealnie.
treść ćwiczenia
Celem zadania jest napisanie programu, który obliczy koszt zakupów w sklepie z telefonami komórkowymi. Mając daną kwotę, program będzie kupował telefony dopóki starcza mu pieniędzy. Dopóki nie przekroczona zostanie pewna kwota pośrednia, do każdego telefony program dobierze jeszcze jakiś dodatek. Kwoty podawane są bez podatków, więc program musi do tego obliczyć jeszcze wydatek brutto. Na koniec program powinien wypisać ile kasy zostało wydane, informacja ta ma być odpowiednio sformatowana (znak dolara z przodu i dokładność dziesiętna kwoty do dwóch miejsc po przecinku).
rozwiązanie: kod
Zadanie nie powinno sprawić trudności nawet średnio zaprawionym programistom. Jednak przyznam się, że podczas pisania go w TSie, w paru miejscach musiałem się zastanowić. Oto ostateczne rozwiązanie:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
const SPENDING_THRESHOLD:number = 200; const TAX_RATE:number = 0.08; const PHONE_PRICE:number = 99.99; const ACCESSORY_PRICE:number = 9.99; const CANT_AFFORD_MSG:string = "You can't afford this purchase. :("; const BUY_PHONE_MSG:string = "Buying phone! :)"; const BUY_ACCESSORY_MSG:string = "Buying accessory! :)"; var bankBalance:number = 303.91; var initialAmount:number = 0; var calculateTax: (amount:number, tax:number) => number; var formatAmount: (amount:number) => string; var performePurchase: (balance:number,amount:number) => string; calculateTax = function(amount:number, tax:number) { return amount * tax; } formatAmount = function(amount:number) { let tempString:string = String(amount.toFixed(2)) return "$" + tempString; } performePurchase = function(balance:number,amount:number){ while (amount < balance) { amount = amount + PHONE_PRICE; console.log(BUY_PHONE_MSG); if (amount < SPENDING_THRESHOLD) { amount = amount + ACCESSORY_PRICE; console.log(BUY_ACCESSORY_MSG); } } amount = amount + calculateTax(amount,TAX_RATE); console.log("Your purchase: " + formatAmount(amount)); if(amount > balance){ return CANT_AFFORD_MSG; } } console.log(performePurchase(bankBalance,initialAmount)); |
rozwiązanie: opis
Na początku deklaruje wszystkie potrzebne mi zmienne. Ponieważ w TS mogę korzystać ze składni ES, do stworzenia zmiennych stały używam operatora const. W ten sposób zadeklarowane zmienne nie powinny być zmieniane, i jeżeli to zrobię, TS wyrzuci błąd.
Wśród stałych mam takie dane jak: koszt telefonu, koszt akcesoria, wysokość podatku i próg kwoty, do którego program ma kupować akcesoria. Do tego deklaruje trzy zmienne zawierające teksty, które będą wyświetlane przez program w odpowiednich momentach. Oczywiście wszystkie zmienne deklaruję z odpowiednimi typami.
Na koniec deklaruję też dwie zmienne, nie stałe. Są to: początkowy stan konta, oraz suma wydatków. Gdy zmienne są już gotowe, wypisuję deklarację trzech funkcji, na które składać będzie się program. Pierwsza z nich to: calculateTax, która do kwoty zakupu dodawać będzie podatek. Przyjmuje ona dwa argumenty typu liczbowego i zwraca wartość tego samego typu.
Kolejna funkcja to formatAmount. Przyjmuje ona jeden argument typu liczbowego, będzie to wydana kwota. Zwraca jednak łańcuch znaków.
Ostatnia funkcja, performPurchase, to główna część programu. To tutaj obliczane będą wartości zakupów. Przyjmuje ona dwie wartości liczbowe, początkowy stan konta, oraz początkową wartość wydanej kwoty. Typ wartości zwracanej to również łańcuch znaków.
Kiedy deklaracje są już gotowe, czas przejść do zdefiniowania zachowań tych funkcji. calculateTax jest zdecydowanie najprostsza z całej trójki. Po prostu zwraca otrzymane w argumentach wartości przemnożone przez siebie.
Kolejna funkcja, formatAmount jest już trochę bardziej złożona (ale wciąż bardzo prosta 😉 ). Najpierw w tymczasowej zmiennej zapisuję przekonwertowaną na łańcuch znaków wartość otrzymaną jako argument. Muszę to zrobić, ponieważ chcę parametr jest typu liczbowego, a ja chce wykorzystać go jako string 🙂 . Przy okazji używam tutaj operatora let, z ES6, który służy do tworzenia zmiennych w zakresie blokowym. Na koniec zwracam zmienną tymczasową z doklejonym z przodu znakiem dolara.
Ostatnia funkcja nie zawiera zbyt wiele smaczków TSowych. Logika w niej zawarta jest dość prosta. Przy pomocy pętli while, wykonuje opisane w ćwiczeniu zadanie. Z każdym obiegiem do wydanej kwoty dodaje cenę telefonu, jeżeli nie została przekroczona kwota zdefiniowana w SPENDING_THRESHOLD, dochodzi jeszcze cena akcesoria. Pętla zatrzymuje się gdy wydana kwota jest większa lub równa limitowi na koncie. Następnie do kwoty dodaję podatek, odpowiednią ją formatuję i zwracam jako łańcuch znaków.
Na koniec wywołuję funkcję performPurchase i zwracam jej wynik do konsoli.
Warto wykonać kilka prostych ćwiczeń tego typu, aby przywyknąć do nowej składni i nowych funkcjonalności TSa. Nie zajmuje to dużo czasu, a jednak stawia programistę przed pytaniami i zagwózdkami, o których sama teoria nie mówi.
I to tyle na dziś. Jeżeli chcesz być na bieżąco z postami na blogu zachęcam do polubienia mojej strony na facebooku. Zawsze zamieszczam tam informacje o wszystkich nowościach. Jest to też dobre miejsce na kontakt ze mną. Na wszystkie pytania zawsze odpowiem :). Do przeczytania.