F# Bolero - A cóż to takiego? - wprowadzenie
Posty z tej serii:
- F# Bolero - A cóż to takiego? - wprowadzenie
- F# Bolero - A cóż to takiego? - HTML templates
- F# Bolero - A cóż to takiego? - view components
- F# Bolero - A cóż to takiego? - routing
- F# Bolero - A cóż to takiego? - routing - page models
- F# Bolero - A cóż to takiego? - remoting
Programowanie Webowe. Sposób wytwarzania oprogramowania, dzięki któremu produkt może zostać uruchomiony w przeglądarce internetowej. Zagadnienie jest bardzo obszerne. Możliwości realizacji można dzielić na różne kategorie, np. ze względu na miejsce generowania wyniku:
- Server Side - generowanie zawartości po stronie serwera, a następnie przesłanie do klienta - przeglądarki internetowej
- Client Side - generowanie zawartości po stronie klienta - przeglądarce internetowej
Inny podział to sposób generowania wyniku:
- Statyczny - pobieranie gotowej, wcześniej przygotowanej zawartości
- Dynamiczny - generowanie zawartości na żądanie, w momencie jej pobierania
Kategorie można łączyć ze sobą:
- Server Side / Statyczny - pierwsze strony internetowe
- Server Side / Dynamiczny - wyświetlanie strony internetowej w zależności od zapisanych danych
- Client Side / Statyczny - cache przeglądarki internetowej
- Client Side / Dynamiczny - początki języka JavaScript
Na bazie różnych kategorii powstało wiele podejść oraz technologii, które pozwalają realizować końcowe produkty.
Świat F# oferuje wiele z programowania webowego. Moją uwagę przykuło Bolero.
Jakbym miał zobrazować, na czym to polega to, zrobiłbym to tak:
Bolero umożliwia pisanie aplikacji webowych w języku F#. Kod konstruuje się w podejściu Elmish - implementacji architektury Model-View-Update, zapoczątkowanej wraz z pojawieniem się języka Elm. Wynikiem kompilacji jest program, który za pomocą Blazor oraz .NET uruchamiany jest w środowisku WebAssembly - alternatywy dla środowiska JavaScript.
Simple Program
Najszybszy sposób zapoznania się z możliwościami Bolero, to wygenerowanie przykładowego projektu, postępując wg wskazówek ze strony. Utworzony program zawiera implementację głównych feature’ów. Kod, generowany jest na podstawie Template’u, przygotowanego przez Loïc Denuzière - autora Bolero.
Template zawiera parametry, którymi można konfigurować końcowy efekt. Najprostszy program można wygenerować, postępując wg kroków:
- zainstalować Template
dotnet new -i Bolero.Templates
- utworzyć projekt
dotnet new bolero-app -o Simple --minimal=true --server=false
- uruchomić program
cd Simple
dotnet run -p src/Simple.Client
- otworzyć stronę wpisując w przeglądarkę adres wypisany na konsoli np.
http://localhost:5000
Najważniejsze elementy wygenerowanego programu to:
Main.fs
- plik z głównym kodemStartup.fs
- plik z konfiguracjąwwwroot
- katalog zawierający statyczne elementy
Główy kod programu wygląda tak:
module Simple.Client.Main
open Elmish
open Bolero
open Bolero.Html
type Model =
{
x: string
}
let initModel =
{
x = ""
}
type Message =
| Ping
let update message model =
match message with
| Ping -> model
let view model dispatch =
text "Hello, world!"
type MyApp() =
inherit ProgramComponent<Model, Message>()
override this.Program =
Program.mkSimple (fun _ -> initModel) update view
Przejdźmy przez poszczególne elementy:
Klasa MyApp
Komponent ładowany przy starcie. Plik Startup.fs
zawiera konfigurację uruchomienia:
builder.RootComponents.Add<Main.MyApp>("#main")
Klasa MyApp
dziedziczy po klasie ProgramComponent
, która w parametrach generycznych przyjmuje Model
oraz Message
. Uruchomienie następuje w momencie wywołania funkcji mkSimple
, która w parametrach przyjmuje opisane poniżej wartości.
Funkcja view
Renderuje widok, czyli to wszystko, co użytkownik widzi na ekranie. Posiada dostęp do aktualnego stanu programu w postaci parametru model
. Drugi parametr dispatch
pozwala wysyłać Message’e do programu, które umożliwiają kodowanie zachowania.
Funkcja update
Uruchamiana w momencie obsługi Message’a. Parametr message
określa jego rodzaj. Stan aktualizuje się, zmieniając wartości w parametrze model
.
Discriminated Union Message
Definiuje rodzaje Message’y, jakie można zgłaszać np. sygnalizacja naciśnięcia odpowiedniego przycisku na stronie.
Value initModel
Początkowy stan programu, inicjalizowany przez mkSimple
.
Record Model
Model reprezentujący aktualny stan programu.
Powyższy przykład zawiera najprostszą logikę działania - wypisanie tekstu na ekranie. Nie wykorzystuje on wszystkich wymienionych właściwości. Działanie kończy się na funkcji view
. Zmieńmy to implementując prosty licznik.
Simple Counter
Definiujemy Model
tak, aby przechowywał aktualną wartość licznika
type Model =
{
value: int
}
Ustawiamy początkową wartość
let initModel =
{
value = 0
}
Definiujemy Message’e
Increment
- przesuwa licznik do przoduDecrement
- przesuwa licznik do tyłuReset
- ustawia początkową wartość
type Message =
| Increment
| Decrement
| Reset
Aktualizujemy funkcję update
, ustawiając odpowiednią wartość licznika w zależności od Message’a
let update message model =
match message with
| Increment -> { model with value = model.value + 1 }
| Decrement -> {model with value = model.value - 1 }
| Reset -> { model with value = 0 }
Aktualizujemy funkcję view
tak, aby wyświetliła interfejs użytkownika zawierający:
- pokazanie aktualnej wartości licznika
- przyciski przesunięcia licznika w dwie strony
- zresetowanie licznika
Dodatkowo funkcja zgłasza odpowiedni Message w zależności od tego, który przycisk zostanie kliknięty.
Poniższy kod pokazuje jedną z właściwości Bolero - konstruowanie UI w kodzie F#:
let view model dispatch =
concat [
div [] [
button [on.click (fun _ -> dispatch Decrement)] [text "-"]
text (string model.value)
button [on.click (fun _ -> dispatch Increment)] [text "+"]
]
div [] [
button [on.click (fun _ -> dispatch Reset)] [text "Reset"]
]
]
Uruchamiamy program
dotnet run -p src/Simple.Client
Sprawdzamy efekt w przeglądarce internetowej
Zgodnie z implementacją przycisk +
zwiększa wartość licznika, a przycisk -
zmniejsza. Przycisk Reset
ustawia początkową wartość.
Istnieje jeszcze jeden, bardziej znany, sposób konstruowania UI - za pomocą standardowych znaczników HTML. Strona napisana w HTML reprezentowana jest w kodzie Bolero w postaci tzw. Templates.
Początek Serii
Spędziłem wiele miesięcy w poszukiwaniu sposobu programowania webowego, który najbardziej by mi odpowiadał. Taki sposób znalazłem w świecie F#. Obecnie zapoznaję się z różnymi możliwościami Bolero. Wyniki będę umieszczał na GitHub’e, a poszczególne elementy opisywał w serii, której pierwszy artykuł właśnie czytasz. Zachęcam Cię do własnych eksperymentów. Może taki sposób pisania kodu będzie odpowiadał również Tobie.
W następnym artykule zobaczymy, w jaki sposób używać wyżej wymienionych Templates.
=