Jaký problém tím vyřešíme?

Minulý týden jsem kolegům přednesl revoluční návrh. Zaměstnanci začnou nosit výložky stejně jako vojáci. Programátoři by začínali u desátníka, architekti u rotmistra a manažeři u majora. Jak se dalo čekat, návrh vzbudil bouřlivou diskuzi. Nejdřív si vzal slovo kolega František. Jsme americká firma, výložky by měly být podle americké armády. Jindřich se přidal se zajímavým rozborem různých hodností ve světových armádách. Netušil jsem, že se v tom tak vyzná. Vladan navrhl vylepšení, výložky by měly být barevně odlišeny podle týmu, ve kterém daný člověk pracuje. To byla voda na Jindřichův mlýn, útvary se prý odjakživa odlišují pomocí insignií.

Pak se ozval Bedřich, známý potížista. Prý k čemu to bude dobré? To je snad jasné. Budeme vědět, kdo je na jaké pozici a když přidáme barvy nebo insignie, tak budeme i vědět, z kterého týmu daný člověk je. Petra se následně zeptala, jak to bude připevněné, že prý se bojí, že se budou kolegové převlékat ještě méně než dosud. Za pár minut jsme se shodli, že kombinace suchého zipu a spínacích špendlíků by to mohla vyřešit. I když František dál trval na lepidle a Jindřich na firemních košilích. Pak se zas ozval Bedřich. Prý jaký problém tím vyřešíme. Poprosil jsem ho, ať je konstruktivní a řekne mi, co konkrétně mám na svém návrhu vylepšit. Vypršel čas, poděkoval jsem všem za zpětnou vazbu, svůj návrh podle ní upravím.

No dobře, celý tento příběh jsem si vymyslel, nicméně jsem zažil pár podobných diskuzí. Obsah byl výrazně méně absurdní, ale průběh se moc nelišil. Někdo přijde s dobře míněným návrhem, rozpoutá se diskuze o detailech, ale nezazní to nedůležitější – jaký problém nám to vyřeší.

Proč je to tak důležité? Protože každá změna něco stojí a my máme omezené množství času, duševní energie, pozornosti a dalších zdrojů. Musíme si proto vybírat. Samozřejmě, pokud je to malá změna, třeba na úrovni týmu nebo jednotlivce, tak ji můžeme udělat bez většího přemýšlení. Když se rozhodnu, že mi větší úspěchy u žen zajistí nošení růžových ponožek, tak mě to moc nestojí. Ale i tak je dobré vědět, proč změnu dělám, abych mohl vyhodnotit jestli to pomohlo.

Horší je to s celofiremními aktivitami. Ty nemůžeme dělat jen tak. Ty jsou vždy nákladné už jen v komunikaci, vysvětlování, překonávání odporu, učení se novým věcem. U takovýchto změn nestačí vědět co zlepší, musíme vědět jaký problém vyřeší. Pokud chystáte velkou změnu jen kvůli drobnému zlepšení, tak je velká šance, že napácháte víc škody než užitku.

Takže u každé větší změny prosím ptejte „Jaký problém tím vyřešíme?“ před tím, než se vrhnete do řešení detailů. Pokud se vám nedaří na tuto otázku jednoznačně odpovědět tak se vám pravděpodobně změna nevyplatí. Ale pozor, jak už jsem tu kdysi psal, je jednoduché najít problém pro řešení, které mám zrovna v hlavě. Chci zavést výložky, tak najdu problém – nevím kdo má jakou roli a v jakém týmu dělá. Nemusím to dělat záměrně nebo se zlým úmyslem, tak prostě můj mozek pracuje. Proto je dobré se zamyslet, jestli se jedná o problém, který nás opravdu pálí natolik, že ho stojí za to řešit na celofiremní úrovni.

Converting RxJava Observables to Java 8 Completable future and back

I have been working on a small project that converts between different types of Java futures. The most challenging conversion is from/to RxJava observable. The reason is simple – RxJava observable is quite different than let’s say Java 8 CompletableFuture. Observable can produce multiple values, future can handle at most one, observable revolves around non-blocking push paradigm, futures mix blocking and non-blocking approach into one API. Nevertheless, the conversion is quite straightforward.

Let’s say that we want to create a CompletableFuture that handles first item of an bservable. It’s quite simple.

public class ObservableCompletableFuture<T> extends CompletableFuture<T> {
    private final Subscription subscription;
    public ObservableCompletableFuture(Observable<T> observable) {
        subscription = observable.single().subscribe(
                this::complete,
                this::completeExceptionally
        );
    }

    @Override
    public boolean cancel(boolean mayInterruptIfRunning) {
        subscription.unsubscribe();
        return super.cancel(mayInterruptIfRunning);
    }
}

We extend CompletableFuture and then we just subscribe to the observable. Subscribe method accepts two actions. The first will be called when an item is produced, the other one upon error. By calling single() method on Observable we make sure that at most one item will be produced.

The only thing missing is to unsubscribe upon cancel.

What about the opposite direction, if we want to convert CompletableFuture to Observable? It’s simple as well.

public class CompletableFutureObservable<T> extends Observable<T> {
    CompletableFutureObservable(CompletableFuture<T> completableFuture) {
        super(onSubscribe(completableFuture));
    }

    private static <T> OnSubscribe<T> onSubscribe(final CompletableFuture<T> completableFuture) {
        return subscriber -> {
            completableFuture.thenAccept(value -> {
                if (!subscriber.isUnsubscribed()) {
                    subscriber.onNext(value);
                    subscriber.onCompleted();
                }
                }).exceptionally(throwable -> {
                if (!subscriber.isUnsubscribed()) {
                    subscriber.onError(throwable);
                }
                return null;
            });
        };
    }
}

We just have to describe what to do if someone subscribes to the observable. We just register two callbacks on the CompletableFuture. The first one using thenAccept calls onNext and onCompleted when the CompletableFuture value is ready. The other one calls onError in case of error. Please note that we do not cancel the future if the subscriber unsubscribes. We can not do it, since we do not know how many subscriptions are registered. And even if we knew, we do not know how the future will be used.

Apart from that, the implementation is pretty straightforward. Please note how helpful the lambdas and method references are, without them the code would be much more verbose. If you are interested in the details, do not hesitate to check the code.

Práce = úkoly + kaizen

Na tento vzorec jsem nedávno narazil v knížce Lead with Respect. I když je to takový překladatelský oříšek, v originále job = work + kaizen, tak myšlenka za ním je jednoduchá. Naše práce se skládá ze dvou stejně důležitých částí. Jednou je plnění úkolů, samotná pracovní činnost, to za co nás platí. U programátorů je to programování. To je jasné. Na co se ale často zapomíná, je druhá část, neustálé zlepšování se – kaizen. To by také mělo být nedílnou součástí pracovního dne. Důvod je jednoduchý. Věci mají tendenci se samy od sebe zhoršovat. Náš skvělý kód se nějakým zázračným způsobem přes noc zkazí. Technologie se posouvají vpřed. Lidi zapomínají. Co včera platilo, dneska už neplatí. Co včera fungovalo, dneska už nefunguje. Proti těmto tendencím musíme vědomě, systematicky, dennodenně bojovat.

I když ten vzorec platí stejně dobře pro jednotlivce jako pro celé firmy, chtěl bych se zamyslet nad tím, co to znamená pro scrumový tým.

Co jsou úkoly je jasné. To jsou věci z backlogu, věci, které po týmu někdo chce. Kde je ale ten kaizen? Je to ta retrospektiva jednou za čtrnáct dnů? Těžko. Smutnou pravdou je, že kaizen v mnoha týmech chybí. Není se čemu divit, ono je to takové nehmatatelné a těžko popsatelné. Vždyť na to ani nemáme pořádné slovo. Je ohromě snadné sklouznout do stavu, kdy tým jenom plní úkoly, které mu přichazí z backlogu. Vždyť to je důvod, proč ten tým vůbec existuje.

Takže se nemůžeme divit, když si někdo myslí, že by úplně všechna práce měla být v backlogu. Včetně refaktoringu, vylepšování infrastruktry nebo zlepšování testů.

Mě připadá, že je to lepší dělat jinak. Je mnohem jednoduší zařídit, aby měl tým na kaizen čas. Dá se snížit zátěž (velocity) týmu tak, aby měl ve většině sprintů časovou rezervu a tím pádem čas na kaizen. Co si ve zbylém čase bude tým dělat, je jen na něm. Může refaktorovat, zlepšovat automatizaci, něco si zkoušet, učit se. Je to oddělená část rovnice, product owner rozhoduje o úkolech, o kaizenu si rozhoduje tým sám. Proč? Protože tým nejlíp ví, kde ho tlačí bota. Je to samoorganizující se tým, proč by mu měl někdo kecat do toho, jak se má zlepšovat?

Snížení zátěže týmu je ta jednodušší část. Ta těžší část je naučit se to zlepšování samotné. Většina lidí to jednoduše neumí (mě nevyjímaje). U refaktoringu je to jednoduché, z ošklivého kódu udělám hezčí. Co ale takové to zlepšovaní procesu, toho jak fungujeme jako tým, ten původní význam slova kaizen? To jsme nikdy nedělali, nikdo nás to nikdy neučil a ošklivě v tom tápeme. Plnění úkolů je mnohem jednodušší a uspokojivější. Proto si musíme neustále připomínat, že práce = úkoly + kaizen.