GUI w skryptach – porównanie

Zadanie

zadanie jest proste – napisać GUI, które pozwoli wyłączyć maszynę w Azure z opcją force. tego normalnie z interfejsu zrobić się nie da, a operacja potrzebna. chodzi o przeniesienie zadania z 2giej czy 3ciej linii wsparcia do 1szej, czyli nie ma opcji na jakąkolwiek linię poleceń. musi być GUI.

 

poniżej dwa skrypty, które realizują to samo zadanie. jeden napisany w tym co PS daje [z małym wyjątkiem], drugi w Formsach. przykład ma posłużyć do porównania tych metod i pozwolić się zastanowić jakie są 'za’ i 'przeciw’ dla obu.

(prawie) natywny PowerShell

pełny skrypt można pobrać z GitHuba, poniżej omówienie fragmentów.

założeniem tej wersji jest szybkość działania i uniwersalność. nie korzystam póki co z wersji PS Core ale na pewno korzystanie z biblioteki forms nie będzie możliwe. dla Core można korzystać z XAML UI, którego również jeszcze nie testowałem. jak już pisałem – jedną z bolączek pisania skryptów z GUI jest już sam dobór bibliotek i decyzja 'gdzie ten skrypt będzie uruchamiany i przez kogo’ /:

dla tego 'natywne’ skrypty zachowują lepszą kompatybilność i uniwersalność.

niestety natywnych kontrolek jest niezmiernie mało. najważniejszą jest out-GridView, które umożliwia wyświetlenie listy lub obiektów w postaci interaktywnej tabeli, pozwalając na sortowanie, filtrowanie etc. pozwala również na wybranie pojedynczego lub wielu elementów – czyli może być przydatny również wtedy, kiedy chcemy pozwolić użytkownikowi wybrać obiektów do dalszego przetworzenia. i choć daje wiele możliwości, to równocześnie bardzo niewielką kontrolę.

fragment kodu do którego się odwołuję to:

function select-RG {
  param(
    $RGList 
  )
  write-host -ForegroundColor Yellow "Select Resource Group VM resides on"
  $RG=$RGList|out-gridview -title 'Select Resource Group' -OutputMode Single
  if([string]::isNullOrEmpty($RG)) {
    write-host 'cancelled by user. quitting' -foreground Yellow
    exit -1
  }
  write-host "$($RG.ResourceGroupName) chosen. reading VMs..."
  return $RG.ResourceGroupName
}

w szczególności linia pokazująca listę odczytanych Resource Groups w postaci interaktywnej. Out-GridView 'daje-to-co-daje’ czyli nie da się kontrolować wyglądu okna. to co możemy zrobić to:

  • title: ustawić tytuł okna. ponieważ nie jest to coś, co rzuca się specjalnie w oczy, staram się poprzedzać to dodatkowo odpowiednim komunikatem na ekranie. zwiększy to prawdopodobieństwo, że użytkownik tego nie przegapi i będzie widział po co w ogóle jakieś okno mu wyskaqje na ekran.
  • OutputMode: przyjmuje wartości 'single’ lub 'multiple’ dzięki czemu możemy kontrolować czy oczekujemy pojedynczego wyniku czy listy. np. jeśli piszemy skrypt, który usuwa pliki – chcemy mieć możliwość wybrania od razu wielu. tutaj użyte jest 'single’ co bloqje opcję multi-choice. dodatkowo ten parametr *zastępuje* passthru.
  • PassThru: to starsza wersja, nie jestem pewien w której wersji pojawiło się OutputMode… w każdym razie sam 'ogv’ [bo taki ma alias] po prostu wyświetla. można się pobawić i zamknąć. tyle. natomiast dodanie opcji PassThru [lub użycie OutputMode] spowoduje dodanie guzika wyboru 'OK’, po wybraniu którego wybrane elementy zostaną przesłane jako wyniki [pipelined].

siła tkwi w prostocie. chwilę później jednak można zobaczyć:

do {
  #choose RG
  $ResourceGroupName=select-RG -RGList $RGsInThisSub
  $VMlist=get-VMList -RGname $ResourceGroupName
  if([string]::isNullOrEmpty($VMlist)) {
    write-host "This Resource Group do not contain any VMs. Do you want to select another RG?"
    switch (
      [System.Windows.Forms.MessageBox]::show($this,"Choose another Resource Group?",'CONFIRM','OKCancel') 
    ) {
      'OK' {
        #do nothing - VMList is null which will trigger loop
      }
      'Cancel' {
        Write-Host -ForegroundColor Yellow "operation cancelled by the user. quitting."
        exit -1
        } 
    }
  }
} while( [string]::isNullOrEmpty($VMlist) )

czemu nagle pojawia się Forms? to niestety sqcha twórców PowerShell – o ile WScript dysponował prostym okienkiem OK/Cancel, o ile jest OGV w PS… o tyle nie ma takiego prostego okienka OK/Cancel w PS.

co ciekawe, można takie okienko wyświetlić bez Forms! w taki sposób:

Add-Type -AssemblyName PresentationFramework
[System.Windows.MessageBox]::show("Choose another Resource Group?",'CONFIRM','OKCancel')

pomimo, że wyglądają bardzo podobnie, i dają niemal ten sam efekt, pod spodem wydarzają się trochę inne rzeczy. jeden jest częścią PresentationFramework drugi Forms, mają inne konstruktory. lepiej używać Formsowego z dwóch powodów:

  • zazwyczaj to nie będzie jedyny element GUI, więc jeśli importujesz biblioteki .NET, lepiej już wybrać tą bardziej rozbudowaną w tym kierunq
  • wersja z PF nie pozwala w konstruktorze na zdefiniowanie okna nadrzędnego – magiczne '$this’ na pierwszej pozycji show($this,”Choose another Resource Group?”,’CONFIRM’,’OKCancel’)  – a w efekcie takie okienko często lądowało pod spodem czegoś aktywnego.

a co z readKey?!

jak już coś pisaliście co wymaga interakcji, powinniście zadać pytanie – czemu nie użyć readKey? natywne, nie wymaga importu bibliotek, szybsze … i tak dalej.

zgoda. ale celem nadrzędnym jest wygoda endusera i założenie, że nie jest bystrym inżynierem (; kiedy zrobiłem readKey, a skrypt miał mieć GUI, sam łapałem się na tym, że czekałem i czekałem… aż zorientowałem się, że to skrypt czeka na mnie, a nie odwrotnie. załamanie logiki – tutaj interfejs a tu linia poleceń – jest bardzo złym podejściem. albo decydujemy się robić skrypt tak, albo inaczej – ale musi być spójnie. inaczej ani nie jest łatwy w użyciu ani prosty w strukturze.

readKey to nie GUI tylko metoda na interakcję bez GUI.

wersja Forms

całość do pobrania z GitHub . kilka uwag n00ba dotyczących pisania PS+Forms.

pierwszą rzeczą jaka rzuca się oczy to narzut ilości kodu. do wykonania mamy jedno polecenie (jedna linijka). w wersji opisywanej wcześniej wyszło 126 linii kodu, tutaj mamy już prawie 19o. jasne się staje że podstawowym problemem będzie możliwy bałagan wynikający z samej ilości. dla tego części dotyczące rysowania samego interfejsu warto oddzielić od reszty. niektórzy decydują się na utworzenie projektu, w ramach którego jest kilka oddzielnych pliqw, i definicje interfejsu wyrzuca się do takiego oddzielnego pliq. spoko, ale ze względu na spójność, przy takich małych toolach wolę trzymać wszystko w pojedynczym pliq. łatwiej go przesłać do niedoświadczonych użytkowników, wytłumaczyć że to taki plik i już, niż kazać tworzyć jakąś strukturę, czy martwić się, że ktoś kawałek usunął czy nie skopiował. ale to oczywiście kwestia wyboru – ważne, żeby sobie oczyścić kod i możliwie mocno oddzielić logikę od definicji.

nie jest to oczywiście do końca możliwe, bo tak, jak opisywałem poprzednio, logika jest de facto związana z interfejsem – trigger-action. klikniemy guzik to uruchomi się jakiś kawałek. całą sekwencyjność szlag trafia.

ja póki co przyjąłem metodę tworzenia regionów – widać znaczniki #region i #endregion które dzielą skrypt na bloki – tutaj 3 bloki – interfejs, akcje interfejsu i cała reszta. zaleta jest taka, że większość edytorów rozpoznaje ten znacznik i pozwala zwinąć tą część kodu żeby nie pasqdziła widoq.

na koniec

niewątpliwie pisanie skryptów z GUI jest dużo trudniejsze i dużo bardziej czasochłonne. tak, jak przy zwykłym skrypcie 6o-8o% czasu to praca nad logiką działania, tak tutaj, ok. 9o% czasu zjadło mi badanie reguł interakcji między poszczególnymi elementami. ok, uczę się więc potem będzie łatwiej, ale nawet przy tak banalnym skrypciq sprawdzenie czy odpowiednio wyczyszczą się wartości konkretnych kontrolek, czy finalnie ustawiona/przeczytana zmienna jest prawidłowa, czy może pozostało coś z klikania usera, czy guziki są aktywne kiedy trzeba, do tego jak to zoptymalizować, że nie ładowało w kółko po pół minuty…

do tego commandlety Az są… hmm.. nie działają zbyt dobrze q: connect-AzAccount się regularnie [niedeterministycznie] zawiesza po zabiciu okna logowania [cancel], zawiesza się dużo bardziej w Vistual Studio Code, a get-AzContex nie implementuje prawidłowo ErrorAction SilentlyContinue…. żeby tak podać najważniejsze. ogólnie to dość trudna biblioteka do współpracy, bez względu na GUI.

eN.

ITD – garść informacji

już za tydzień ITechDay. zastanawiałem się, jak to będzie wyglądało organizacyjnie, a ponieważ jestem po spotkaniu z organizatorem, garść informacji. jeśli jesteś zarejestrowanym uczestnikiem to pewnie już dostałeś instrukcje, ale IMHO najważniejsze:

 

  • SESJE NIE BĘDĄ NAGRYWANE. ideą jest utrzymanie klimatu konferencji. nie chodzi wyłącznie o wiedzę [choć oczywiście jest priorytetem] ale również o pewną ideę, jaka stoi za takimi eventami – wspólne spotkanie, networking, wymiana myśli na żywo.
  • czy to dobrze czy źle – każdy oceni sam, ale muszę powiedzieć, że przygotowanie całego środowiska wygląda bardzo ciekawie – już samo obejrzenie jak to można zorganizować za pomocą Teams/TLE będzie na pewno ciekawym doświadczeniem.
  • warto również zapoznać się od razu z agendą i ustalić sobie co chcecie zobaczyć – bo równocześnie będzie toczyć się kilka sesji, a jak to w starym sucharze z żabą – raczej się nie rozdwoicie.
  • każdy z uczestników oraz prelegentów dostanie konto konferencyjne – anonimowe logowanie będzie niemożliwe. a to oznacza, że bez rejestracji się nie wbijesz – jeśli więc jeszcze chcesz dołączyć, sugerowałbym się pospieszyć.

w dobie 'wszystko zdalnie’ uczestniczyłem już w różnych eksperymentach – ten niewątpliwie będzie największym/najbardziej rozbudowanym. jedną z najcenniejszych funkcji konferencji jest networking, i ta formuła ma go umożliwić. podobnie do realnego wydarzenia będą 'stoiska partnerów’ czyli oddzielne breakout rooms gdzie można będzie zapoznać się ofertami sponsorów i dowiedzieć czegoś na temat ich produktów, hydepark aka „wirtualna pizza” – miejsce, gdzie będzie można swobodnie sobie chatować z innymi i kilka innych ciekawych pomysłów.

…reszta już w rękach uczestników.

PS. a w tym tygodniu virtualny Ignite. tak dla porównania q:

eN.

ITechDay 2o2o

ITD2o’

już 29.IX, [przekornie] ostatni wtorek miesiąca, odbędzie się konferencja ITechDay. również będę miał zaszczyt poprowadzić jedną z sesji. niestety, nadal w atmosferze covidowym, czyli zdalnie, w postaci Teams Live Events, ale co najważniejsze – live. modne ostatnio robi się ogłaszanie 'konferencji’, które okazują się spreparowanym portalem z sesjami offline…. nie tutaj (:

…bardzo nie lubię sesji zdalnych, brak kontaktu z publiką nie daje feedbacku… ale cóż. znak czasów. mam nadzieję, że ITD21′ odbędzie się już w pełni na żywo. jest opcja komentowania, co prawda z opóźnieniem ~3osec, ale zawsze. przynajmniej nie ma problemu z wejściówkami (;

eN.

OFICJALNA NOTKA

Społeczność WGUiSW.org wraz z Partnerami gorąco zapraszają na kolejną konferencję z cyklu ITechDay.

Wydarzenie odbędzie się w formule online z wykorzystaniem platformy Microsoft Teams.

Tematami wiodącymi konferencji będą:

  • rozwiązania chmury publicznej i prywatnej,
  • aspekty gromadzenia i bezpiecznego przechowywania danych,
  • zapewnienie wysokiej dostępności,
  • automatyzacja zadań w środowiskach IT,
  • analiza i ocena zabezpieczeń infrastruktury IT.

Sesje będą odbywały się równolegle w sześciu ścieżkach tematycznych:

  • Cybersecurity
  • Cloud IT
  • Case study
  • Innovation IT
  • Modern Workplace
  • Data & Dev

Sesje poprowadzą znani prelegenci posiadający bardzo bogate doświadczenie praktyczne poparte wieloma certyfikatami zawodowym.  

Udział w konferencji ITechDay jest bezpłatny.

GUI w skryptach – wstęp

GUI w skryptach?

zasadniczo jestem przeciwny takiemu pomysłowi. celem skryptów jest automatyzacja, a ich największą zaletą jest przetwarzanie potokowe – wyjście jednego skryptu staje się wejściem dla innego. dodanie GUI łamie te zasady – przede wszystkim zakłada interakcję, podczas gdy punktem wyjścia dla skryptu jest podanie parametrów 'up front’ dające automatyzację danego zadania. 

GUI jest oczywiście niezbędny dla 1szej/2giej linii, ale również pojedyncze zadania łatwiej przeważnie wyklikać. można też wyobrazić sobie rozwiązanie 'hybrydowe’ [takie modne słowo w dzisiejszych czasach… od paznokci poprzez samochody aż po architekturę IT] – skrypt przyjmuje parametr [np. nazwę pliq wejściowego], a kiedy go nie ma, pokazuje jakiś file-picker czy coś… nie jest to koszerne, ale koniec-końców decyduje zamawiający.

w ostatnim czasie musiałem wrócić do poważnego skryptowania [yyyeeeeey! (= ] właśnie z myślą o narzędziach dla 1szej linii. w zwizq z tym musiałem zmierzyć się z pisaniem pełnego GUI w PowerShell. w związq z tym kilka wniosków i spostrzeżeń.

GUI w PS – możliwości

w oprogramowaniu GUI jestem n00bem. ostatnie aplikacje okienkowe pisałem w Javie na studiach. do tego jeszcze moja ogólna niechęć do takiego pisania… a więc wpis cenny dla tych, którzy są na tej samej drodze. 

są trzy podstawowe metody uzyskania interfejsu dla skryptów:

  • natywne metody PS – jest ich oczywiście niezmiernie mało i są bardzo ograniczone. tak na prawdę ogranicza się do albo sczytywania z linii poleceń [nie bardzo GUI, ale jest interakcja) albo out-GridView – który jest genialną metodą do zrobienia szybkiego 'pickera’ wartości. dodałbym też tutaj funkcję
    [System.Windows.MessageBox]::Show(MessageBody,Title,ButtonType,Image)
    która natywna dla PS nie jest, ale dobrze uzupełnia możliwości.
  • wykorzystanie obiektu DCOM wscript.shell  który daje możliwość wyświetlenia prostego okienka podobnie do .NET. osobiście mierzi mnie łączenie tak odległych technik jak PS i WScript – IMHO to błąd i zamieszczam wyłącznie żeby napisać: „nie korzystać! to jest legacy crap
  • no i oczywiście pełnoprawne GUI – albo poprzez biblioteki Forms lub WPF. 

dokładniejszy opis w przyszłości, co kiedy jak i z jakim efektem, a póki co

narzędzie dla skryptów na poważnie

zwykłe ISE przestaje wystarczać – nie tyle z powodu samego GUI, co ogólnie tego, że ostatnio piszę więcej. zacisnąłem zęby i po raz kolejny przesiedziałem nad odpaleniem VSCode. VSC niestety jest makabrycznym narzędziem, jednak jego potencjał i choćby możliwości integracyjne są na tyle ważne, że cóż.. płaczę, ale walczę. kiedy to było tylko hobby, odpuszczałem zniechęcony, ale kiedy trzeba bardziej na poważnie, musiałem się złamać

  • VSC jest uniwersalnym narzędziem developerskim. dwa kluczowe słowa: uniwersalne i developerskie – w zasadzie wskazują jego wady. uniwersalne – wszystkiego jest za dużo, 8o% opcji jest zbędne przy pisaniu w PS. po instalacji dostajemy coś, czego do pisania w PS nie da się używać – a więc czeka nas czytanie serii artykułów i wpisów na forum, które pluginy zainstalować, jak skonfigurować, które z tysięcy opcji jak ustawić żeby uzyskać jakiś sensowny efekt.
    to co kiedyś było potęgą produktów MS – integralność i trzymanie się pojedynczych standardów – załamało się wraz z „powszechną linuxyzacją”. dziś wszystko trzeba wybrać z pośród dziesiątek lub setek różnych dodatków i zaczynają się problemy że 'ten dodatek jest szybszy a tamten ma taką opcję, a inny gryzie się z tamtym ale ma tą funkcję..’ .. i tak zaczyna się żmudna żonglerka dobrania sobie zestawu pluginów tak, aby mieć maksymalnie dużo wymaganych funkcji, równocześnie nie przeciążyć środowiska zbytecznymi śmieciami …
  • …które doprowadzą do niestabilności. podstawowe zastrzeżenie jakie mam do VSC to niestabilność, a zwłaszcza inteliSens, który regularnie przestaje działać w trakcie pisania. skrót „alt-ctrl-p, reload” już mi wszedł w krew /: [muszę poszukać pluginu, który mi doda tą operację pod jednym guzikiem q:]. o ile ISE zawieszało się w bardzo szczególnych przypadkach [np. korzystając z commadletów Exchange] o tyle VSC wywala się jak archetypiczny open source. poprawki wydawane typowo agile – czyli update za updatem i trzymanie kciuków, czy dziś będzie się wywalać się bardziej….  welcome to open source .. and agile.    

czemu warto pocierpieć? przy pewnej wielkości czy skomplikowaniu skryptu, nie mówiąc o projekcie w którym tych skryptów jest wiele, ale nawet kiedy po porostu trzeba przy nich popracować więcej – ISE to za mało. lepsze wyświetlanie składni, czy masy skrótów klawiszowych, znacznie przyspieszają pracę. integracja z repo, projekty… jest wiele dodatków, bez których byłoby więcej ręcznej pracy – czyli to co jest wadą, przy zainwestowaniu czasu, staje się podstawową przewagą.

jeśli więc czeka cię przesiadka – zarezerwuj sobie przynajmniej tydzień nieskończonej cierpliwości. będzie za to nagroda w postaci dużych możliwości i jeszcze większego potencjału. jeśli jednak nie korzystasz z repo, piszesz hobbystycznie lub okazjonalnie – ISE to wszystko co potrzebne i szkoda czasu i stresu. 

pisanie GUI

niestety VSC nie pomaga zbytnio w pisaniu GUI. może są dodatki, których jeszcze nie znalazłem, ale ogólnie – oprogramowanie GUI w edytorze nie-wizualnym to porażka. kilka elementów i robią się setki linii kodu ciężkie do ogarnięcia. ustawianie guzików zmieniając ich położenie wartościami X/Y na czuja – makabra. interfejs najlepiej się rysuje w interfejsie, dla tego najsensowniej jest mieć coś wizualnego. chciałoby się powiedzieć Visual Studio… huh, ale VS do pisania skryptów PS, to jak instalacja Exchange on prem w pełnej redundancji do wysyłania kilq emali. 

w skrócie – cały czas jestem w trakcie poszukiwania jakiegoś lekkiego designera interfejsu. te, które testowałem online były … jak to aplikacje online – siermiężne i ograniczone. 

forms vs UWP vs WPF

już sam wybór tego w czym ten interfejs ma być napisany nie jest łatwy. formsy wygrywają ilością dostępnych przykładów, UWP [chyba] umiera, WPF niby jest trendem, nowsze, nowocześniejsze i bardziej uniwersalne… ale czy przyszłościowe? no właśnie – nawet po przeczytaniu kilq artów, jeśli nie siedzi się w temacie, sam dobór biblioteki nie jest trywialny. jeśli się uczyć, chciałoby się nauczyć czegoś, co choć przez kilka lat się przyda. a to w obecnym tempie zmian niełatwe zadanie. 

osobiście póki co zdecydowałem się na formsy – stare, dobre, oklepane, dużo przykładów, a póki Microsoft nie zrezygnuje z Windows na rzecz jakiejś hybrydowej dystrybucji [chciałoby się powiedzieć Lindows, ale to już było] , zgromadzona wiedza powinna żyć przez jakiś czas.

zmiana logiki

ciekawym aspektem jest zmiana paradygmatu całej logiki działania. skrypty, poniekąd z samej definicji skryptu – przetwarzane są sekwencyjnie linia po linii. tak też logika pisania jest 'liniowa’. GUI to z kolei 'rozproszona logika’ pozaczepiania pod elementy interfejsu. całość nie jest już jak opowiadanie:

begin { początkiem }
process { rozwinięciem }
end { i końcem }

w zamian staje się fragmentarycznym kodem, sterowanym akcjami z kliknięć czy innych list. dla skrypciarza z krwi i kości to jest inny świat. dziwny i nie do końca logiczny. 

GUI + skrypt

na tym etapie nie mam jeszcze wyrobionych 'best practice’ więc poszuqję. jednym z pomysłów było zadziałanie tak, jak to przez pewien czas projektował Microsoft [i co mi się bardzo podobało] – interfejs służył do zebrania informacji, wizualizacji elementów, ale ostateczna akcja to był po prostu skrypt uruchomiony z parametrami, których wartości były zebrane z interfejsu.

takie podejście jest świetne jednak w momencie kiedy pisze się duże, rozbudowane narzędzie, aplikację pozwalającą na wykonanie wielu zadań. jednak drobny tool, którego celem jest właśnie ograniczenie wyborów i dostosowanie do konkretnego zadania w konkretnym środowisq powoduje, że rozdzielenie na dwa niezależne skrypty [jeden to GUI do zebrania parametrów, drugi do wykonania akcji] tworzy dużą nadmiarowość. ponadto takie podejście choć 'ładne’ i logiczne, utrudnia uruchomienie osobom, które tych skryptów się już i tak boją. to te niuanse – łatwiej komuś nieqmatemu przesłać jeden plik do uruchomienia, niż kilka, z opisem jak zrobić bibliotekę, czy jak przygotować środowisko. w regularnej aplikacji załatwia to instalator, przy skrypcie to już nie takie proste. 

z kolei zaletami oddzielenia GUI od logiki jest łatwiejsze panowanie nad samym wykonaniem, no i dla osób, które GUI nie potrzebują – od razu jest narzędzie. większa uniwersalność. mam nadzieję pokazać przykłady za jakiś czas.

praktyka pokaże który sposób wygra, choć widzę coraz więcej zalet rozbicia tego monolitycznego podejścia na rzecz bardziej uniwersalnej metody…

kompromis

skoro skrypty nie są do pisania GUI, przesiadka jest trudna, to czemu po prostu nie zacząć pisać np. w C#? 

proste: mimo-wszystko łatwiej nauczyć się oprogramowania samych Formsów, niż całego języka. na drugi dzień byłem w stanie narysować prosty interfejs, podpiąć logikę i zbudować jakiś działający skrypt. a to dla tego, że cała faktyczna logika, aktywna część działania była tym, co znam, w postaci commandletów. nauczenie się napisania tego w C# i poznanie całej specyfiki samego języka, zajęła by znacznie więcej czasu. choć podobny do PS – jest czyś zupełnie innym. no i podstawowa rzecz – nie zamierzam być developerem [może kiedyś, hobbystycznie] a tego rodzaju zadania są 'szybkim wsparciem’, a nie moim codziennym zajęciem. póki co nauka C# byłaby stratą czasu. 

jak mawiają: 'życie składa się z kompromisów’. kompromisem jest tutaj wyważenie efektu i czasu. pozostają zalety skryptu: kod nie jest kompilowany, łatwo go przeczytać a w razie potrzeby zmodyfikować 'gdziekolwiek’, bo bez konieczności rekompilacji, commandlety dają obszerne biblioteki o olbrzymich możliwościach, a równocześnie można dopiąć kawałek GUI – i to wszystko w bardzo krótkim czasie.

może Frankenstein, ale żywy i myślący. 

eN. 

 

wf-refresh

w-files’om strzeliła w tym rokq piętnastka… czas w IT liczy się trochę inaczej – 15 lat to kilka epok. jeśli przypomnieć sobie jak wyglądał ten świat w 2oo5… trochę sobie przypomniałem przeglądając stare artyqły… długa droga to była i wyboista ale jakże emocjonująca.  praca (i po części hobby) zajmuje większość życia – więc ten nLog, choć przez pryzmat technologii i zawodu, ale opowiada ciekawą historię – zarówno o ewolucji technologii jak i mnie samego.

<chwila nostalgii>

wszystkiego naj, wfilesowicze! z tej okazji drobny refresh strony – lżejszy, kompatybilny z aktualnymi wersjami i wyświetla się prawidłowo na mobilu… które w czasach tworzenia poprzedniego szablonu nie służyły za codzienne narzędzie do oglądania treści w Internecie. no i bezpieczniejszy. mam nadzieję, że wytrzyma następną epokę.

pro publico bono.

eN.