Pay to Roll Dice Game

In my recent dive into the world of the Lightning Network, I built a simple project—a React-based betting game. During the project, I learned a couple of things that I’d like to share in this post.

First of all, I was surprised by how supportive ChatGPT is from a technical point of view. It helped me scaffold the project, recommended specific technologies, and even suggested an appropriate editor. On the other hand, I was unpleasantly surprised by the Lightning Network—how unintuitive it still is from the user’s perspective. But first things first.

I had a rough idea for a one-evening project built on the Lightning Network, so I asked ChatGPT to generate a list of ideas. I chose a dice roll game where:

  • Players bet on a number by making an LN payment.
  • If they win, they take the entire pot by claiming it with LN.
  • If they don’t win, their sats contribute to the growing pot for the next round.

Simple enough—but since I didn’t have any experience with these kinds of technologies, I had to rely on ChatGPT again. It proposed using React and Vite as frontend frameworks, Alby or LNbits for integrating Lightning payments, Supabase or Firebase as a minimal backend solution, and Vercel, Replit, or Netlify for deployment.

Since I wanted to use a mobile wallet instead of a browser extension, the payment solution was narrowed down to LNbits. I also stripped out the need for a backend for the MVP and stuck with React useState only.

Bootstrapping the project was very easy. It basically involved installing a few dependencies via npm and adding an admin key for LNbits. That could be a security issue without proxying the calls through a backend, but I decided to accept the risk for the MVP and the small satoshi amounts in the demo wallet.

After picking a lightweight editor (I went with Zed since I didn’t want to use VSCode or WebStorm), we had to do a couple of iterations over the code to get it running and eliminate all the linting complaints. But it was running and accepting payments—all within an hour! One missing piece was adding support for claiming winnings, but we quickly solved that as well.

Here I’d like to pause: the user experience while using Lightning payments is still quite harsh, and I feel that’s something preventing broader adoption by regular users. I had been using the Phoenix wallet for a while—but only for sending payments. Now I needed the players to receive payments as well, which meant gaining a basic understanding of how Lightning actually works, including generating BOLT11 invoices. That’s quite easy with Phoenix, but still, the user has to request a specific amount—raising questions like, “What if I request too little or too much?”

So I decided to implement LNURL-withdraw, which removes the need for players to create invoices. After a bit of work, I had it running—players could now claim winnings by simply scanning a QR code! Again, not super intuitive, but functional. I can imagine a future where wallets have a single button (e.g., “Scan QR”) for both payments and withdrawals. That would improve the user experience dramatically. But with Phoenix, the user has to first tap “Receive” and then click a tiny icon in the corner—not very user-friendly.

Anyway, let’s move on. I had it running locally, linted, code-reviewed, and ready to deploy. From the options ChatGPT suggested (Replit, Netlify, Vercel), I chose Vercel (based purely on gut feeling, sorry 😄). It connected to the project’s GitHub repo and was able to fetch and deploy the code on demand or on push to a specific branch. So easy! That means the project is public and running—though it does have some security issues without a backend. But that’s a story for another time, if I ever get to it.

Conclusion

I used generative AI for ideating, implementing, and deploying a simple project. I was surprised by how easy it was—originally I wanted a weekend project, but I actually managed to finish it in a single evening. I can now easily imagine no-code or multimodal programming becoming a reality.

Still, user input is necessary—at least for reviewing, refining incorrect URL calls, and challenging odd bits of generated code (linting alone isn’t enough). As for the Lightning Network, I was disappointed by how unintuitive it still is, especially considering it aims for mass adoption. Perhaps it’s not the right protocol for widespread Bitcoin use—yet. Looking ahead, I hope it matures to the point where, like the internet today, people can use it without needing to understand the ISO/OSI model. The future looks bright!

Glass hackathon Brno 2014

Přestože jsem se spolupodílel na organizaci této akce, nebudu psát o slastech a strastech organizování, ale o tématu, které se přímo týká kódování a docela nepříjemně mě na této akci spálilo. Totiž o googlovském (dá se říci) házení klacků early adopterům a vývojářům pod nohy (hateposty dneska frčí, musím se trendu chytit!). Spolčil jsem se … Pokračovat ve čtení „Glass hackathon Brno 2014“

Přestože jsem se spolupodílel na organizaci této akce, nebudu psát o slastech a strastech organizování, ale o tématu, které se přímo týká kódování a docela nepříjemně mě na této akci spálilo. Totiž o googlovském (dá se říci) házení klacků early adopterům a vývojářům pod nohy (hateposty dneska frčí, musím se trendu chytit!).

Spolčil jsem se s Radkem Bartoňem z Trinerdisu, protože jsem měl náladu stvořit nějaký backend, více než drátovat pro brýle. Radek přišel s nápadem čtečky ebooků ne nepodobnou Spritzu, na který mě shodou okolností nedávno odkázal jeden známý. Idea byla taková, že uživatel na telefonu vybere knížku a nechá si ji poslat do brýlí. Tudíž nějaký „push to device“. Pojďme se podívat na možnosti, které pro tuto funkcionalitu připadají v úvahu.

Glglglass

Nejjednodušší možností je využít Mirror API a intent filter. Pomocí Mirror API se pushne na timeline speciální karta, která obsahuje volání URI definované ve výše zmíněném intent filteru. Pěkný příklad použití je uveden v jedné odpovědi na Stack overflow.

Možností druhou je Google Cloud Messaging. Ten nabízí metody pushování notifikací dvě: pomocí HTTP a XMPP. HTTP volání je čistě synchronní, což vyplývá z podstaty protokolu – z mé aplikace (serveru) pošlu zprávu serverům GCM a čekám na odpověď o přijetí, což mě blokuje ve snaze odeslat zprávu další. Naproti tomu XMPP využívá GCM server jako broker, do kterého pere zprávy a odpovědi může až dodatečně (na základě id) vyhodnotit. Z toho je jasné, že pomocí HTTP je možné komunikovat pouze ve směru server->cloud->zařízení, kdežto v případě XMPP je díky držení otevřeného spojení možná obousměrná komunikace.

Protože byl na hákování vyhrazen celý den, zvolil jsem možnost b) Google Cloud Messaging a sice s využitím XMPP, abych neudělal během pěti minut servlet pro Mirror API a pak celý den jen neseděl a nekroutil palcama. Mimo jiné by potom bylo možné tento stejný přístup použít i pro mobilní aplikaci, která pushnutí iniciuje. Dokumentace je přehledná, dokonce je její součástí celý zdroják pro navázání komunikace s GCM. Existují i nějaké další poměrně detailní tutoriály. Kámen úrazu byl, že jsem (už po několikáté) přehlédnul nenápadný řádek „Note: To try out this feature, sign up using this form,“ takže jsem se nemálo divil odpovědi „Project 858xyz396 not whitelisted.“ Až po chvíli jsem daný formulář našel a zaregistroval do něj náš projekt pro hackathon. Bohužel, není to jenom robotem schvalovaná registrace, takže „lefuq“, zabil jsem spoustu času, tohle je jen pro vyvolené, až mi to někdy někdo schválí.

Po obědě jsem se pustil do GCM pomocí HTTP. Ovšem opět jsem to nedotáhl do konce, protože záhy mi Radek hlásí, že brýle nepodporují Google Play Services. To je teda fail, srsly, na co ty brejle jsou, opravdu jen na to pushování karet pomocí Mirror API? Nebo opět pouze pro vyvolené (to by mě zajímalo, kdo to je, když vývojáři zaplatili nemalé peníze za samotné pitomé brýle)?

Takže nakonec nouzovka v podobě jednoduchého REST rozhraní, kdy si brýle samy tahají seznam a odpovídající knížky. Škoda, teď by se hodil další den hackathonu, kdy bychom přidali to pushování pomocí Mirror API a k tomu appku pro telefon s tydlidrojdem (nebo tlačítko do prohlížeče – na pushnutí článku k pozdějšímu přečtení).

Poučení na závěr: důvěřuj, ale prověřuj se ve spojitosti s Googlem mění na: nedůvěřuj, ale prověř, neuvěř a radši to udělej jinak. Každopádně aspoň nějakým výstupem je zdroják k „serveru“ na GitHubu a běžící endpoint na OpenShiftu. Tak alespoň něco, mimo akce samotné a následných škopků.

Custom filesystem receiver for Alfresco

It’s really a long time since my last Alfresco post on this blog. And because of that I’d like to announce my comeback to Alfresco developing, because the year with mainly Android coding was long enough. Before that I’ve been working on content publisher for custom CMS based on Alfresco repository, which was able to … Pokračovat ve čtení „Custom filesystem receiver for Alfresco“

It’s really a long time since my last Alfresco post on this blog. And because of that I’d like to announce my comeback to Alfresco developing, because the year with mainly Android coding was long enough. Before that I’ve been working on content publisher for custom CMS based on Alfresco repository, which was able to publish through NATed networks.

My solution is based on Broker, which provides communication between publisher and endpoints, which both may be behind NAT. Each endpoint is subscribed to queue on broker and when request for publish comes, it locally compares published version and if published is newer, it sends request for content and content is transfered. Depublishing works the same way, data consistency is secured by ‚sync‘ mechanism – endpoint may send local file list to publisher, which checks its integrity and do appropriate actions.

Publisher/endpoint scheme
Publisher/endpoint scheme

First version was based on RabbitMQ and HSQLDB and had a lot of performance and security issues, but as I said – I’d like to resurrect it now, rewrite and open source it. I just need to be sure that there is no such a project, because I don’t want to do the same thing. If anyone knows similar stuff, please let me know!

Howto access recent query suggestions on Android and populate ListView with them

I’m working on search activity for Beermapa and because I did not find any topic covering reading access to SearchRecentSuggestions and I needed to load saved suggestions and fill a ListView with them, so I did some research and wrote this post. What I want to achieve is an input for writing search query, which … Pokračovat ve čtení „Howto access recent query suggestions on Android and populate ListView with them“

I’m working on search activity for Beermapa and because I did not find any topic covering reading access to SearchRecentSuggestions and I needed to load saved suggestions and fill a ListView with them, so I did some research and wrote this post.

What I want to achieve is an input for writing search query, which displays custom suggestions (based on searching query) and also ListView placed right under input box, which displays recent search queries.

SearchView with ListView
SearchView with ListView

My first try was with EditText and TextWatcher, which after each written character filtered my listAdapter backing ListView, something like this:

[code lang=“java“]
searchEditText.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {}

public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

public void onTextChanged(CharSequence s, int start, int before, int count) {
adapter.getFilter().filter(s);
}
});
[/code]

But since Android has pretty good Search Interface, I was wondering how to use it with my search (because of possible future use of voice search etc.). Adding recent query suggestion is described in tutorial, also custom suggestion is. But there is nothing about how to access saved queries another way then in SearchView whispering box. Saving is really easy:

[code lang=“java“]
SearchRecentSuggestions suggestions = new SearchRecentSuggestions(getApplicationContext(), MySuggestionProvider.AUTHORITY, MySuggestionProvider.MODE);

suggestions.saveRecentQuery(query, null);
[/code]

First solution which came on my mind was to implement own saveRecentQuery routine, which saves last queries to local database, but that’s not the way – why to write already written code again?

Finally – there is possibility to access those saved queries through ContentResolver, which returns Cursor:

[code lang=“java“]
ContentResolver contentResolver = getApplicationContext().getContentResolver();

String contentUri = „content://“ + MySuggestionProvider.AUTHORITY + ‚/‘ + SearchManager.SUGGEST_URI_PATH_QUERY;
Uri uri = Uri.parse(uriStr);

Cursor cursor = contentResolver.query(uri, null, null, new String[] { query }, null);
[/code]

Where query is String representing searching query, or null for returning all records. Now with received cursor it’s simple to populate ListView:

[code lang=“java“]
cursor.moveToFirst();

String[] columns = new String[] { SearchManager.SUGGEST_COLUMN_TEXT_1 };
int[] views = new int[] { R.id.name };

ListAdapter listAdapter = new SimpleCursorAdapter(this, R.layout.component_pub_row, cursor, columns, views, 0);
listView.setAdapter(listAdapter);
[/code]

Note that last parameter in SimpleCursorAdapter – it’s there because of deprecation of constructor with FLAG_AUTO_REQUERY, for more details see this Stack Overflow topic.

Vanitygen a import adresy do Bitcoin-QT na MacOS

Dlouho jsem nic nenapsal a protože jsem si právě vygeneroval novou krásnou (1SHM12iG4KPRs54CxjLsCwbvnMJp4bMh5) Bitcoinovou adresu (jo, mohlo to být lepší, ale není na to výkon) na Mackovi za pomocí Vanitygenu, poznamenám si tu postup. Zdrojáky Vanitygenu je možné stáhnout z GitHubu, kde by měl být i Makefile pro Macka. Problém je v tom, že Macek … Pokračovat ve čtení „Vanitygen a import adresy do Bitcoin-QT na MacOS“

Dlouho jsem nic nenapsal a protože jsem si právě vygeneroval novou krásnou (1SHM12iG4KPRs54CxjLsCwbvnMJp4bMh5) Bitcoinovou adresu (jo, mohlo to být lepší, ale není na to výkon) na Mackovi za pomocí Vanitygenu, poznamenám si tu postup.

Zdrojáky Vanitygenu je možné stáhnout z GitHubu, kde by měl být i Makefile pro Macka. Problém je v tom, že Macek má staré verze OpenSSL knihoven (na mém 10.7.5 je OpenSSL 0.9.8x 10 May 2012), takže je nutné použít ty z Homebrew. No a protože není dobrý nápad natvrdo zadávat cestu ke knihovnám a po změně kompilovat znovu, proč si pohodlně netapnout repozitář s Vanitigenem rovnou? Takže i s instalací OpenSSL a Vanitigenu následovně:

[code]bash-3.2$ brew install openssl && brew tap WyseNynja/bitcoin && brew install vanitygen[/code]

Teď už je možné si nechat vygenerovat adresu a privátní klíč:

[code]bash-3.2$vanitygen 1SHM1[/code]

Závěrečným krokem je import privátního klíče do peněženky – používám Bitcoin-QT 0.8.2. Takový nástřel je na bitcoin wiki, kterou doporučuju před akcí projít. Akce samotná sestává z následujících kroků:

  • spuštění Bitcoin-QT v režimu serveru (kdy naslouchá RPC na portu 8332),
  • odemknutí peněženky na dobu nezbytně nutnou k provedení importu,
  • provedení importu soukromého klíče,
  • …,
  • profit.

Aby bylo možné spustit Bitcoin-QT v režimu serveru, je nutné nastavit heslo pro uživatele rpcuser. Provede se to přidáním dvou řádků do konfiguračního souboru ~/Library/Application Support/Bitcoin/bitcoin.conf.

[code]rpcuser=bitcoinrpc

rpcpassword=***************[/code]

Bitcoin-QT je nutné spustit v režimu serveru – provede se tak v konzoli pomocí příkazu

[code]bash-3.2$ open Bitcoin-Qt.app –args -server[/code]

Jakmile naběhne, je možné posílat příkazy na port 8332 – např. pomocí curl. Protože se však takto budou zapisovat hesla a privátní klíče přímo do konzole, je vhodné zapisované příkazy potlačit v historii – před příkaz se do konzole přidá mezera. Sled příkazů je následující:

[code]bash-3.2$ curl –user bitcoinrpc –data-binary ‚{"method": "walletpassphrase", "params": ["heslo_do_penezenky", 120] }‘ http://127.0.0.1:8332/
Enter host password for user ‚bitcoinrpc‘:
{"result":null,"error":null,"id":null}
bash-3.2$ curl –user bitcoinrpc –data-binary ‚{"method": "importprivkey", "params": ["5_privatni_klic_pr_nove_vytvorenou_adresu_pomoci_vanitigenu", "popisek adresy"] }‘ http://127.0.0.1:8332/
Enter host password for user ‚bitcoinrpc‘:
{"result":null,"error":null,"id":null}
[/code]

První příkaz odemkne peněženku na 120s, což by mělo pro provedení druhého příkazu postačovat – stačí jen jeho iniciace, rescan blockchainu může probíhat až po opětovném (automatickém) locknutí.

V tento okamžik (až doběhne import) se nová adresa objeví v adresáři, ne mezi adresami pro příjem. Tomu napomůže ukončení Bitcoin-QT a opětovné spuštění, tentokrát už jako „obyčejné“ aplikace.

Jak si (zase) nabíjím hubu

Už jsem psal o tom, co jsem udělal špatně u minulého projektu a protože mám rozjetý další, tak vidím, že je spousta věcí, které opět tak nějak dělám špatně. No a protože chybama se člověk učí, tak se (aspoň s těma nejzásadnějšíma) pochlubím a budu doufat, že třeba pomůžou i někomu dalšímu, aby se jich … Pokračovat ve čtení „Jak si (zase) nabíjím hubu“

Už jsem psal o tom, co jsem udělal špatně u minulého projektu a protože mám rozjetý další, tak vidím, že je spousta věcí, které opět tak nějak dělám špatně. No a protože chybama se člověk učí, tak se (aspoň s těma nejzásadnějšíma) pochlubím a budu doufat, že třeba pomůžou i někomu dalšímu, aby se jich vyvaroval. Ale známe to – každý si musí nejprve nabít hubu… 🙂 Jedná se o Androidí aplikaci Zasaď strom, ale myslím, že to jsou docela obecné věci, které se dají promítnout kamkoliv jinam. Nuže, pojďme na ně!

 

Drbání se s detaily

Aplikace je celá postavená na geolokaci, takže jsem si řekl, že když už, tak to udělám pořádně. Takže jsem několik dnů vytvářel a testoval sofistikovaný systém, který nežere moc baterku a snaží se co nejpřesnějším možným způsobem zjistit polohu uživatele. Pak jsem to pustil ven a zjistil, že je to celé úplně na ho*no – polovině uživatelů to blbne a ta druhá polovina nechápe, proč se to chová tak divně. Takže opět další čas zabitý měněním parametrů, dalším laděním… STOP! Všechno jsem vyházel a použil naprosto základní možnost zjištění polohy nabízený systémem – přece jenom to baterku zase tak nežere a já přece nebudu zabíjet veškerý čas laděním něčeho, o čem si ani nejsem jistý, jestli vůbec bude v takové složitosti potřeba – to ukáže až čas a způsob používání!

 

Neudržení se v rámci hranic nejmenší možné verze produktu (MVP)

Sice jsem si definoval, jak bude vypadat Minimum Viable Product, ale přesto jsem se neudržel a ještě než je hotový, pořád mi tam prosakují plánované gamifikační featury (ovšem z mnohem vyššího levelu – ne ty základní – a to jenom proto, že „teď by to bylo jednoduché implementovat“). Důsledkem je, že věci, které by měly být, stále nejsou, pořád v tom něco blbne a uživatelé (a často i já) jsou zmatení z nekompletních funkcí. STOP! Doladím základní plánovanou funkcionalitu a potom začnu postupně přidávat další věci – od těch nejjednodušších – časem se uvidí, jestli si uživatelé sami o něco neřeknou!

 

Snaha stále udržet zpětnou kompatibilitu

Spoustu času jsem věnoval hackování zpětné kompatibility. ActionBar je v Androidu od jisté verze a výš, Fragmenty taky existují od určité verze nahoru… Takže (dle obecných doporučení milovaného Gogolu) jsem ošetřoval, aby vše běželo i na prehistorických verzích systému. STOP! Na to se už příště můžu…!! Když jsem aplikaci zveřejnil, tak ty prastaré verze nemá jediný uživatel! A i kdyby – prostě vyvíjím aplikaci a mám nějaké minimální požadavky pro její běh – vždyť je to přece naprosto normální! Jednoduše to napíšu, jak je dneska v módě (jako prase) a až pokud zjistím, že je nemalé procento uživatelů nějaké starší verze systému a mají o aplikaci taky zájem, tak začnu přemýšlet o zpětné kompatibilitě.

Verzování a testování Android aplikací

Vrátil jsem se nedávno k jedné odložené aplikaci a začínám ji křísit s novými nápady a s trochu změněným konceptem (s detaily přijdu v brzké budoucnosti) a protože jsem se dostal k potřebě aplikaci testovat ve více lidech, kdy někteří mají ne zrovna aktuální verzi buildu a přesto reportují chyby, začal jsem používat systém číslování … Pokračovat ve čtení „Verzování a testování Android aplikací“

Vrátil jsem se nedávno k jedné odložené aplikaci a začínám ji křísit s novými nápady a s trochu změněným konceptem (s detaily přijdu v brzké budoucnosti) a protože jsem se dostal k potřebě aplikaci testovat ve více lidech, kdy někteří mají ne zrovna aktuální verzi buildu a přesto reportují chyby, začal jsem používat systém číslování verzí, který bych chtěl tímto postem popsat.

Problém je následující: vypustím testovací verzi mezi testery a mezitím vývoj nezamrznu, ale pokračuju v opravách, úpravách a (přiznám se k tomu) někdy i nových featurách. Často se stane, že tester pošle stacktrace starší verze, nebo přijde aktuální verze, jenomže po úpravách už nesedí čísla řádků, či díky refactoru je daný fragment někde úplně jinde a podobně. Jak teda zkontrolovat, jestli už chyba byla odstraněna, nebo tam je pořád? Poměrně jednoduše, stačí pár nástrojů.

Celý řetězec sestává z IDE Eclipse, Pivotal Trackeru, PT-mylyn connectoru a nějakého systému zprávy verzí (používám Git na Bitbucketu). Základem je si navyknout odklepávat aktivní tasky zadané pomocí Pivotal Trackeru v Mylynu, měnit odpovídající čísla patchů v Manifestu a commity provádět s daným identifikátorem (ideálně do vlastního branche, který se po release zmerguje, ale kdo by se s tím sr…l, žejo :)). Pojďme ale postupně, ukážu to na konkrétním příkladě – tasku. (Pozn. používaná skladba číslování verzí vychází z následujícího schématu, uvedeného např. na wikipedii).

Schéma číslování verzí
Schéma číslování verzí

Veškeré změny, požadavky a bugy zadávám pouze skrze Pivotal Tracker (nebudu tu rozebírat nástroj samotný, ani jak iteruju – to je každého věc :)). Důležité je, že každá story má jednoznačný identifikátor, jak je vidět na následujícím screenshotu.

Identifikátor story v Pivotal trackeru
Identifikátor story v Pivotal trackeru

V Eclipse mám PT napojený skrze mylyn-connector (návod jak na to je přímo na stránkách projektu) na Task list, kdy pracuju na aktuální vybrané úloze. Na následujícím screenshotu už je story finishnutá, takže je přeškrtnutá.

Zobrazení story v Task listu
Zobrazení story v Task listu

Když potom dané změny commitnu, nechávám jako title dané změny identifikátor a popisek, který je v PT – při commitu jsou už automaticky předvyplněné. V přehledu verzovadla je potom jednak vidět interní identifikátor daného commitu, ale v rámci popisku i identifikátor z PT.

Hotový commitnutý task v přehledu na bitbucketu
Hotový commitnutý task v přehledu na bitbucketu

A teď ono celkové propojení: když aktivuju task v IDE, změním daným identifikátorem z PT i build verzi v manifestu, společně s versionCode.

Čísla verzí v AndroidManifest.xml
Čísla verzí v AndroidManifest.xml

Když tedy následně distribuuju danou verzi testerům, tak je možné v rámci vlastností aplikace přehledně zkontrolovat verzi, kterou testují.

Zobrazení čísla verze ve vlastnostech aplikace
Zobrazení čísla verze ve vlastnostech aplikace

A pokud někdo nahlásí chybu, o které si nejsem jistý, zda byla opravená, jednoduše se vrátím ke konkrétní verzi z repozitáře a můžu zkontrolovat, o co vlastně šlo a případně si zadat novou story (bug by mohl být zadán číslem revize a build verze se neměnit).

Je mi jasné, že asi znovuobjevuju kolo, ale připadlo mi to celé tak geniálně jednoduché a praktické, že mi nedalo se o to nepodělit. Také mi nedá se nepodělit o očekávání testovacího frameworku Testflight pro Android. Věřím, že předchozí tipy skvěle doplní a posune na ještě vyšší level!

Sbohem a šáteček!

Končím s ubytovníčkem, konec, šlus, adie! V lean kanvasu jsem měl zaznačený zisk jediný – zkušenost. A té jsem dosáhl – udělal jsem špatný úkrok stranou, takže pryč s tím, soustředit se na jiné věci. Ještě bych ale tímto posledním postem rád shrnul věci, o kterých jsem chtěl původně psát (resp. když jsem na nich … Pokračovat ve čtení „Sbohem a šáteček!“

Končím s ubytovníčkem, konec, šlus, adie! V lean kanvasu jsem měl zaznačený zisk jediný – zkušenost. A té jsem dosáhl – udělal jsem špatný úkrok stranou, takže pryč s tím, soustředit se na jiné věci. Ještě bych ale tímto posledním postem rád shrnul věci, o kterých jsem chtěl původně psát (resp. když jsem na nich dělal, připadalo mi dobré o nich průběžně psát na blog, protože by mohly přitáhnout pozornost). Jenže jsem o nich nepsal. Teda psal, ale hrozně pomalu. Plán byl – jeden týden, jeden blogpost. A kdy že se objevil první? Pche! Proč dělat tisíc věci na 1/1000? Navíc některé „jakodělat“? To je radši zrušit úplně!

Chyba číslo jedna: myslet ti, že to mám ověřený. Chybělo něco jako „move your fucking ass out of the building.“ Nedávno jsem vytáhl nápad ubytovníčku a lidé na mě koukali jako na blázna: „Jak jako spát s někým v pokoji? My si s drahou polovičkou bereme dvoulůžko!“ Následovalo přemýšlení nad pivotem – udělat rezervační systém pro ubytovací zařízení. Nojo, ale proč? Copak mám nějaké ubytovací zařízení? A i kdyby!

Ubytovníček
Ubytovníček

Chyba číslo dva: myslet si, že mám pěkně rozvrhnutý projekt. Neměl jsem konkrétní cíl, neměl jsem konkrétní čas, kdy bych ho měl dosáhnout, neměl jsem vlastně spoustu věcí, hlavně, že jsem měl doménu :).

Konkrétní čas
Konkrétní čas

Chyba číslo tři: technologie? Ta ne, za její volbou si stojím. Jen bych příště nešel cestou RADu ve formě Roo. Ovšem i zde je namístě otázka – je to tím, že za tu předlouhou dobu, co jsem na tenhle projekt nemákl, jsem se všechno, co Roo nabízelo, naučil sám a zautomatizoval? Že jsem se naučil psát testy, že už si připadám Spring intermediate a výš, že si radši model vytvořím sám a bez aspektů, že i ty query si napíšu radši ručně a lépe… Zase na druhou stranu – podíval jsem se hlouběji na webflow, tiles a dojo. Aspoň na chvíli jsem se cítil být frontenďákem :).

Grafické znázornění webflow
Grafické znázornění webflow

Chyba číslo čtyři: chtěl jsem psát všechno a obsáhle na blog. Chtěl. Jenomže než jsem se k tomu vždycky dokopal, tak se mi to, co jsem chtěl popisovat, vykouřilo z hlavy. A cucat si to z prstu se mi prostě nechce, stejně tak to celé dělat znovu jenom kvůli popisu. Takže základem je – napsat to hned! A napsat to stručně. Pokud někdo má zájem o bližší informace, ozve se a může se případně navázat dalším dílem. Proč sepisovat něco, co vlastně ani nikoho nezajímá a nikdo to nejspíš ani nečte? Zbytečná ztráta času! Samozřejmě je také nutné uvažovat cílové publikum – proč jsem sakra na blog související s ubytováním psal věci ohledně vývoje? Copak to je blog s tématem „jak rozjet (nemám to slovo rád – ) startup?“ Příště striktně oddělit témata a takovéhle posty nepsat vůbec, nebo je psát do tech části.

Jaké je cílové publikum blogu?
Jaké je cílové publikum blogu?

Chyba číslo pět: „i cesta může být cíl“ – rozdělat projekt a učit se na něm. Jenomže když to učení nakonec převažuje nad cílem jako takovým, tak to nebude to pravé ořechové a zůstanu trčet ve vzduchoprázdnu. Vlastně to souvisí s předchozím bodem – příliš jsem se soustředil na to, co napíšu, jak to napíšu a jak to ještě rozvedu, aby to vydalo na víc, než pár řádků. Takže jsem chystal sáhodlouhej článek o propojení Pivotal Trackeru s „mojí pružnou metodikou“ (teď nově vydáno s menší obměnou a imho mnohem praktičtější)…nehledě na to, že mezitím u Good Data přestalo fungovat reportovadlo/analýza pro Pivotal Tracker. Mu!

V nekonečnu přímka však se Vždycky ve kruh schoulí
V nekonečnu přímka však se Vždycky ve kruh schoulí

Sečteno a podtrženo: příště si definuju nejenom konkrétní cíl (konkrétně specifikovaný MVP), ale i nějaký náznak představy o čase, kdy ho chci dosáhnout. A díky známému „každý úkol zabere přesně přesně tolik času, na kolik ho odhadneme,“ budu odhady zaokrouhlovat dolů – budu mít hotovo dřív! 🙂 Brzkého nákupu domény nelituju, i tu příští koupím velmi brzo – přece jenom to není nijak extra vysoká částka a když ji využiju pro landing page (použil jsem Launchrock) se základními informacemi a možností registrace zájemců (jako tomu bylo teď) a na subdoménu vrznu opět nějaký blog, snad Posterous úplně neumře, jak je teď slibováno. A především – budu se věnovat něčemu, čemu se opravdu chci věnovat a v čem vidím smysl. Nebudu násilně vymýšlet blbovinu, o které se někdo zmínil v hospodě u píva, že by mohla být fajn. Takže nashle příště u dalšího začátku!

PS pokud má někdo zájem o doménu ubytovnicek.cz, twitter účet stejného jména a fb fanstránku, tak se mi ozvěte s nástinem plánu. Tomu, co mě nejvíce zaujme to všechno milerád (zdarma) přenechám!

(Repost z blog.ubytovnicek.cz)

Pozadí ubytovníčku: platforma

Konečně se dostáváme do trochu techničtější fáze, o které měl původně tento seriál celý být. Ovšem pro některé souvislosti a nasměrování i na trochu potřebné teorie byla odbočka směrem k Running lean nezbytná. Tato fáze vychází z některých polí v Lean canvasu a sice pole cena a pole zisk. Nejsem si jistý, zda tento způsob … Pokračovat ve čtení „Pozadí ubytovníčku: platforma“

Konečně se dostáváme do trochu techničtější fáze, o které měl původně tento seriál celý být. Ovšem pro některé souvislosti a nasměrování i na trochu potřebné teorie byla odbočka směrem k Running lean nezbytná. Tato fáze vychází z některých polí v Lean canvasu a sice pole cena a pole zisk. Nejsem si jistý, zda tento způsob zadání je možné považovat za korektní vyplnění těchto polí, ale popravdě – je mi to docela jedno.

V poli cena mám pouze dvě položky – platba za doménu a čas. Od toho se bude odvíjet veškerý návrh technické části. Všimněte si, že nikde není uvedena cena za hosting či virtuál, ceny za licence na ten který použitý software, cena za grafiku a další. Opravdu jedinou investicí by měl být můj čas.

Lean canvas
Lean canvas

Jaké technické řešení teda zvolit, když má být zdarma? Mohl bych si vybrat nějaký free hosting s podporou třeba php, ale vzhledem k mému odporu k tomuto jazyku to nehrozí. Jsem Javista a přestože mám v plánu pustit se do učení se nějakého dalšího nového jazyka, nemyslím si, že tohle je vhodná příležitost, takže zůstanu u té Javy. Možností běhu javy zdarma (alespoň několika instancí) na serverech je dneska už taky poměrně velké množství (Amazon Elastic Computing Cloud, Google App Engine, Heroku, Cloudbees, CloudFoundry a další), zkušenost mám pouze s Google App Enginem a Cloud Foundry, takže budu volit z nich. Volba je poměrně jasná, protože GAE je uzavřený (nejenom, svého času mě pěkně vytočil, když jsem se snažil udělat abstrakty pro persistentní objekty), navíc mi neumožní zdarma běh většího množství instancí a (jako bonus) můj odpor vůči této společnosti v poslední době docela stoupá, začínám na ni koukat jako na „evil one“.

O Cloud Foundry jsem mluvil už už minulý rok v Ostravě na Dev Skillz. A protože už o tomto řešení bylo napsáno více než dost kdekoliv jinde, tak se čtenář bude muset spokojit se základní informací, že se jedná o  PaaS řešení zaštítěné VmWare, které běží na jejich infrastruktuře, infrastrukturách jiných (AppFog, Uhuru), případně je možné sáhnout po komunity forku tohoto projektu a rozjet si jej na vlastních serverech. Spíše než o jazycích je vhodnější mluvit spíše o podporovaných frameworcích, kterýchž škála je poměrně pestrá: Spring, Grails, Lift, Play, Node.JS, Rails a Sinatra, persistence je zajištěna databázemi relačními (MySQL, vFabric Postgres) i NoSQL (Redis, MongoDB) a pro komunikační mezivrstvu je možné použít RabbitMQ.

Zásadní výhoda je tedy následující: s CloudFoundry mám možnost běhu aplikace zdarma, pokud bych vyžadoval více instancí, větší dostupnost nebo nějaké perličky, můžu si připlatit, nebo přímo přesunout aplikaci na EC2, či na vlastní infrastrukturu!

Jak jsem zmínil, Cloud Foundry přímo umožňuje využití některého z množství oblíbených frameworků, což rozhodně využiju, protože jsem člověk líný, abych začínal od píky. A jsem líný tak, že využiju nějaký RAD, v mém případě Spring ROO, protože nově podporovaný Play v době návrhu ubytovníčku ještě CF nebyl nabízen.

Roo nabízí využití některého ze dvou frameworků pro tvorbu view – Google Web Toolkit a Apache Tiles, takže sahám po Tiles v kombinaci s  jQuery a čistými JSP. Opět nepůjdu do detailů, zájemce odkážu na některý z mnoha tutoriálů na ovládání roo.

V poli zisk mám nejzásadnější položku – zkušenost. V praxi rád testuju různé nápady na lidech, jak se co ujme, jestli to vyhovuje…na malých částech, dalo by se to nazvat uživatelský prototyping. Nejinak tomu je i u tohoto projektu. Chci zkusit, jaký bude poměr registrovaným uživatelům ku uživatelům pouze využívajícím službu (jsem zastáncem možnosti anonymního využívání aplikací na webu, jako tomu bývalo odjakživa – před všemožnými facebooky a unifikovanými loginy v podobě openId a dalších) a prozkoumat zájem potencionálních zákazníků (provozovatelů ubytování), jak se budou stavět k nabídce využívání tohoto systému – vyzkoušet svoje „social skills“, totiž jak s „nepočítačovníky“ správně a slušně komunikovat.

Dalším pokusem (ziskem v podobě informace) bude sestavit vůbec funkční aplikaci nad Cloud Foundry – předchozí byly jenom pokusy v podobě helloworld a drobností pro zábavu – a získat pro ni nějaké reálné uživatele, na kterých se budu moci učit – ať už komunikovat jakožto „já projekt“, nebo ladit přivětivost systému, „zážitek“ z použití služby a další.

V neposlední řadě taky aplikaci zařadím do kategorie svých „pet projektů“, ke kterým se můžu uchýlit k odreagování se, když mě všechno ostatní točí a rád bych se jednorázově alespoň na chvíli věnoval něčemu jinému.

PS Jako side-project vznikl Air Cargo Forwarder, což je aplikace pro Android pro monitorování a ovládání aplikací běžících na platformě Cloud Foundry.

(Repost z ubytovnicek.cz)

Pozadí ubytovníčku: validace

Co mám: mnoho nápadů Výstup: nejjednodušší možné řešení, kterým jsem schopen vyřešit zákazníkův problém Co budu dělat: mluvit s potenciálními zákazníky, pivotovat, hledat nejjednodušší možnou funkcionalitu Co pro to použiju: lean canvas (případně jiný canvas či způsob validace, pokud je vhodnější) Minule jsem psal o něčem, co by se dalo nazvat blitím nápadů. Podstatnější než … Pokračovat ve čtení „Pozadí ubytovníčku: validace“

Co mám: mnoho nápadů
Výstup: nejjednodušší možné řešení, kterým jsem schopen vyřešit zákazníkův problém
Co budu dělat: mluvit s potenciálními zákazníky, pivotovat, hledat nejjednodušší možnou funkcionalitu
Co pro to použiju: lean canvas (případně jiný canvas či způsob validace, pokud je vhodnější)

Minule jsem psal o něčem, co by se dalo nazvat blitím nápadů. Podstatnější než to je však validace těchto nápadů, v tom pomůže svatá trojice. Tou se rozumí trojice uživatel, uživatelův problém a moje řešení tohoto problému. Nejlepší situace je ta, když sám vidím v něčem problém a chci jej řešit (neboli sám sobě jsem zákazníkem). Potom můžu přistoupit k onomu blití nápadů z minula a mám nápadů na řešení přehršel, protže vím, o čem mluvím. Ovšem i přesto můžu být sám sobě zákazníkem jediným a to je špatně, proto přichází na řadu výše zmíněná validace.

Validace problému/řešení
Validace problému/řešení (zdroj: http://market-by-numbers.com)

Proč jsem zvýraznil spojení uživatelův problém? Protože musím vycházet z problému, který uživatele opravdu trápí, ne z problému, o kterém si myslím já, že uživatele pálí. Proto je třeba se ptát, ne někde v ústraní dumat nad možnými problémy. Je potřeba sehnat potencionální zákazníky, lidi, kteří do dané problematiky vidí a věčné skeptiky (mě :-)) a předložit jim různé scénáře s problémovými situacemi a způsoby jejich řešení a postupně se s nimi dopracovávat k jedinému konkrétnímu výsledku, nebo klidně i několika různým důležitým cílům, z nichž vykrystalizuje výsledný produkt (lépe řečeno Minimal Viable Product).

Postupná krystalizace nápadu (kombinace problém/řešení)
Postupná krystalizace nápadu (kombinace problém/řešení) (zdroj: http://theagni.com/)

Tohle dopracovávání se k výslednému nápadu, který bude mít cenu realizovat, by mělo probíhat iterativně – tedy postupně by se měl nápad doplňovat připomínkami, validovat, doplňovat, validovat…třeba i v několika paralelních větvích, které budou validovány dále ještě jinými způsoby, aby byla vybraná ta nejlepší. Nejlepším výběrem je myšlen kompromis mezi užitnou hodnotou pro uživatele a mojí schopností tuto věc co nejrychleji realizovat. Tím myslím především finanční stránku věci, protože když je čas a peníze, realizovat se dá cokoliv :-).

Lean canvas
Lean canvas (zdroj: http://www.ashmaurya.com/)

V hledání tohoto kompromisu pomůže nástroj zvaný lean canvas. Lépe řečeno – mnoho canvasů, protože co canvas, to kombinace uživatel/problém. Není možné napasovat stejné uživatele na různé problémy, protože je prostě nemusí vůbec pálit. Canvas má několik polí, která se vyplňují postupně a samozřejmě canvas samotný se dále vyvíjí na základě komunikace s potenciálními klienty/zákazníky, díky čemuž mohou nevyhovující canvasy zanikat i vznikat nové. Prvotní vytvoření canvasu zabere okolo 20 minut, delší koumání je ztráta času, jak píše autor této techniky, Ash Maurya, v knize Running lean. Když nevím, nevyplňuju, nebo ani vyplnit nemůžu, protože to zatím není jasné – též budeme iterovat a dopracovávat se k nejvhodnějšímu řešení. Lean canvas vychází z Business model canvasu a vhodně jej rozšiřuje pro začínající projekty, dle slov autora: Business canvas na příkladech ukazoval zajeté instituce, jako apple, nebo skype… Lean canvas se soustředí na začínající projekty a na mnoha příkladech ilustruje tuto techniku na vlastním rozjížděném projektu. Nebudu to dále rozmazávat, stojí to za přečtení – druhé vydání je k sehnání na Amazonu za nějakých $16, první vydání bylo možné předplatit v rámci psaní knihy a dostávat je na etapy (nebo zkuste napsat přímo autorovi, je to člověk otevřený ;-)).

Pivotování
Pivotování (zdroj: http://steveblank.com/)

Ale zpátky k validacím: v této fázi se bude určitě hodně pivotovat, protože mám představu, kdo jsou mými zákazníky, oni jimi však většinou nebudou, musí sami sebe identifikovat s mým produktem. Proto se budou cíle velmi často měnit a v této fázi je to výhodné a také velice vhodné, protože nic reálného zatím neexistuje a měním pouze myšlenky a nahlížení na ně. Jen se k tomu musím přinutit, je to jako u zubaře – včasný zásah bolí mnohem méně. Časem se to nějak ustálí a najednou bude vše „nad slunce jasné“.

Teď už by mohl být pomalu čas na nákup domény, dočkali jsme se! Taky je možné začít vytvářet profil pro aplikaci na sociálních sítích, (nejenom) abychom se dostali uživatelům pod kůži a vytvořili si nějaké publikum. Ale o tom zase až příště, konečně se to stočí k techničtějším věcem, o kterých měla tato série původně celá být!

(Repost z blogu Ubytovníčku.)