Já tvořím aneb od nápadu k realizaci za jeden den

Právě čtu knihu The Long Tail, která je o tom, jak jsou zajímavé trhy na chvostu poptávky, jak je zajímavé to, že čím dál tím víc lidí aktivně tvoří, místo toho aby jen pasivně čuměli na televizi. Taky jsem tak nějak trochu záviděl všem těm, co se pokoušejí rozjet vlastní internetové podnikání, nemluvě o těch, kterým se to povedlo.

Měl jsem několik nápadů, ale postupně jsem je zavrhl nebo selhali při realizaci. Až mě nakonec napadlo udělat komunitní web pro amatérské výtvarníky. Něco jako Flickr, ale pro lidi, kteří kreslí, malují, dělají si vlastní náušnice a podobně. Originální, že? No abych se přeci jen trochu odlišil, tak se chci zaměřit hlavně na český trh. Proč? Pro tuto cílovou skupinu je důležitá lokalizace do jejich jazyka. Často jsou to lidé, kteří si s počítačem nebo angličtinou moc nerozumí. Nedivil bych se, kdyby byla klasickou zástupkyní ne už mladá žena, která si s počítačem zas tak úplně nerozumí a Facebook zná jen z televize. Ale to je jen odhad, je pravděpodobné, že se pletu. Na druhou stranu lidé, kteří něco dělají rukama jsou ideální cílová skupina. Prostě se chtějí pochlubit a to nejlépe lidem, kteří mají podobné zájmy. Znám to z vlastní zkušenosti. Není nic horšího než se chlubit lidem, které to nezajímá. Navíc tu může docela fungovat šeptanda mezi kamarádkami. Prostě to znělo docela zajímavě.

Nápad ve mně uzrál včera ráno, tak jsem strávil nějakou hodinku na internetu hledáním, jestli něco podobného už neexistuje. A nic takového se mi nepodařilo najít! Alespoň ne v ČR. Pak přišla ta nejtěžší a nejdůležitější fáze. Vymyslet jméno. Nejlépe takové s volnou CZ doménou. Další hodina přemýšlení a hlavně zkoušení. Nakonec vyhrálo „Já tvořím!“. Jméno nic moc, ale lepší mě prostě nenapadlo. Postupně si na něj začínám i zvykat.

Takže máme jméno, teď už zbývá jen ta realizace. Původně jsem si chtěl vyzkoušet Scalu, Google App engine, Amazon S3 a podobně. Nakonec ale asi převážili zkušenosti a odolal jsem pokušení zavřít se na měsíc do sklepa a kódovat. Nejdřív jsem se podíval na internet, jestli bych nemohl využít nějaký existující projekt. Strávil jsem další hodinku na Google a SourceForge a našel jsem pár vhodných kandidátů. Pak jsem si ale vzpomněl, že existuje projekt Ning, v kterém už to všechno je, včetně hostingu. Stačí to jen naklikat. Což popravdě řečeno byla záležitost na půl hodinky. S výsledkem se můžete seznámit sami zde.

Velikou výhodou Ningu je lokalizace. Češtinu už tam prostě mají. Sice bylo a bude potřeba některé překlady upravit, ale to jde snadno přes administrátorské rozhraní. Ning má samozřejmě i své nevýhody. Hlavní nevýhodou je, že od 20. července nebude zadarmo. Verze, které by mi stačila stojí $20 za měsíc. Ale to je cena, kterou jsem ochoten platit. Popravdě řečeno, kdybych si měl jako programátorovi platit komerční cenu, tak jeden můj člověkoden vydá alespoň na rok provozu.

Další nevýhodou je, že nemám tu svobodu, kterou bych měl, kdybych si to napsal sám. Přizpůsobivost hotové platformy má své meze. Na druhou stranu je pravděpodobné, že kdybych to měl všechno programovat, tak bych to asi stejně nedokončil.

Největší nevýhoda ale je, že to samé může klidně udělat kdokoliv jiný (opovažte se!). Jenže to by mohl, i kdybych se na ten měsíc do sklepa zavřel. V dnešní době se člověk musí odlišit na jiné úrovni než technologické.

A jsme u největšího oříšku, kde sehnat lidi? Na tom to celé stojí a padá. Komunitní web bez komunity nemůže fungovat. Jedna věc je šeptanda, ale na tu člověk potřebuje určitou kritickou masu. Dokud jí nedosáhne, tak nemá kdo šeptat. Včera jsem cvičně hodil dvě věty na Facebook a už tam nejsem sám, přidaly se dvě kamarádky. Mám ještě jeden nápad, který by mohl být úspěšnější, ale je ještě v plenkách, tak mi určitě prominete, že si ho nechám pro sebe. Alespoň se pocvičím v marketingu.

Takže proč to vlastně dělám. No jo, proč vlastně? Určitě nečekám, že mě to bude živit. Popravdě řečeno, počítám s tím, že to bude naopak. Taky se na tom evidentně nenaučím programování. Možné se ale naučím spoustu dalších věcí. Hlavní je ale to, že mě to baví. Je to neuvěřitelný zážitek, když vás ráno něco napadne a odpoledne máte prvního uživatele. To za to stojí. Člověk si připadá, že opravdu něco tvoří.

Samozřejmě, pokud ve vás dříme umělec, neváhejte se přidat. Horší než být nemůžete.

Writing fluent API

In recent weeks I have been working with Arjen Poutsma on a brand new testing support for Spring Web Services. At least Arjen has been working, I have been just generating crazy ideas and he kept explaining me why we can’t use them.

But it was quite interesting experience and I have learned a lot about fluent API design. Since it was my first fluent API and I am not an API expert, please take everything I mention here with grain of salt.

The task is simple. We need a way how to configure a mock. This mock has to validate that requests generated by our application are correct and after that the mock has to return some response. We want to write something like this:

Computer, when someone is trying to send a request, verify that the request contains value “a”, has header “header” and then respond with value “b”.

The requirements for the API are following:

  • It has to be simple for users. Mainly it has to be friendly to GUI addicts like me, that rely on code-completion all the time.
  • The library itself has to be simple
  • The API should be as fluent as possible
  • It has to be extensible

In the next part, I will try to describe several variants of the solution, each of them fulfilling the requirements differently. Please keep in mind that the code is simplified, it focuses solely on the API, not on the implementation. Moreover, the classes have been renamed to show what their main purpose is.

All characters appearing in this work are fictitious. Any resemblance to real persons, living or dead, is purely coincidental.

Interface based version

code
The first variant is based mainly on interfaces. The test itself looks like this

	@Test
	public void testMock()
	{
		Mock mock = new Mock();
		mock.whenConnecting().expectValue("a").and().expectHeader("header").andRespondWithValue("b");
		
		//test code
		
		mock.verify();
	}

There is one entry point, class Mock

public class Mock {

	public RequestExpectations whenConnecting()
	{
		return new MockInternal();
	}
	
	public void verify()
	{
		//do something
	}
}

It just returns an internal class that implements RequestExpectations interface.

public interface RequestExpectations {
   
    ResponseActions expectValue(String value);
    
    ResponseActions expectHeader(String name);
}

All methods of this interface return ResponseActions interface

public interface ResponseActions {
	
	RequestExpectations and();
    
	void andRespondWithValue(String value);
    
	void andRespondWithError();

}

Please note that and() method allows chaining of request expectation.

This API is really IDE friendly. Code completion works like a charm. It’s quite simple both from outside and inside. But this API has one big flaw. It’s not extensible. Imagine that we would like to add an expectation that verifies a digital signature. We would have to add a method to the RequestExpectations interface. It is not possible neither for third parties nor for us, since this change would break backward compatibility.

Static factory

code
We can split the functionality and allow others to provide their own validators and response generators. We just have to change the interfaces

public interface RequestExpectations {
   
    ResponseActions expect(RequestMatcher matcher);
}

and

public interface ResponseActions {
	
	RequestExpectations and();
    
	void andRespond(ResponseCallback callback);
}

Now we have made the API extensible, but we have to provide an easy way how to create RequestMatchers and ResponseCallbacks. One way how to do it is a statically imported static factory.

public class StaticFactory {
	public static RequestMatcher value(String value)
	{
		return new RequestMatcher() {
			public void match(Object someParams) {
				//do something
			}
		};
	}
	public static ResponseCallback withValue(String value)
	{
		return new ResponseCallback() {
			public void doWithResponse(Object someParams) {
				//do something
			}
		};
	}
}

The test then can look like this.

import static net.javacrumbs.fluentapi2.StaticFactory.*;

public class MockTest {

	@Test
	public void testMock()
	{
		Mock mock = new Mock();
		mock.whenConnecting().expect(value("a")).and().expect(header("header")).andRespond(withValue("b"));
		
		//test code
		
		mock.verify();
	}
}

Such API is also fluent. It even resembles EasyMock API. The issue here is that code completion does not work as well as before. In Eclipse you have to type first letter of the method name before Ctrl+Space starts working. In Idea you have to press Ctrl+Shift+Space. But the advantage is that everyone can provide their own factory and extend the library seamlessly and consistently.

Super-static variant

code
We can go event further. We can get rid of RequestExpectations interface, remove Mock class and do statically most of the stuff. The test can look like this

import static net.javacrumbs.fluentapi3.StaticFactory.*;

public class MockTest {

	@Test
	public void testMock()
	{
		expect(value("a")).andExpect(header("header")).andRespond(withValue("b"));
		
		//test code
		
		verify();
	}
}

It’s simple and elegant. We even got rid of the strange and() method. The downside is that we usually have to use some ThreadLocals internally. But it looks almost like EasyMock. Cool.

Inheritance

code
Some people (like me) do not like static methods. It does not feel right, it’s not object oriented programming. Can we do something similar, but dynamic? Yes, we can.

We just have to use inheritance. Just delete static keywords from the methods in StaticFactory class. We will also rename the class itself because it’s not static any more.

We get

public class MockTest extends MockFactory{

	@Test
	public void testMock()
	{
		expect(value("a")).andExpect(header("header")).andRespond(withValue("b"));
		
		//test code
		
		verify();
	}
}

The downside is, that we have to extend our class from MockFactory. Sometimes it’s not possible. No problem, we can use a trick I have seen in Apache Camel DSL.

public class MockTest{
	@Test
	public void testMock()
	{
		MockFactory mockFactory = new MockFactory()
		{
			protected void configure() {
				expect(value("a")).andExpect(header("header")).andRespond(withValue("b"));		
			};
		};
				
		
		//test code
		
		mockFactory.verify();
	}
}

It’s not as elegant as the direct inheritance, but it works. If we are brave enough, we can even use a closure.

public class MockTest extends MockFactory{
	@Test
	public void testMockClosure()
	{
		MockFactory mockFactory = new MockFactory()
		{{
				expect(value("a")).andExpect(header("header")).andRespond(withValue("b"));		
		}};
		
		
		//test code
		
		mockFactory.verify();
	}
}

(I bet you did not know that Java has closures already).

So I have shown you four variants, which one is the best? I do not know, each of them has it’s pros and cons. I personally like the last one the most. But the super static variant is not bad neither. Or the static? Or some mix between them? Some other? You have to make your own opinion.

References:
http://martinfowler.com/bliki/FluentInterface.html
http://martinfowler.com/dslwip/InternalOverview.html
http://camel.apache.org/routes.html
http://easymock.org/

jOpenSpace – doporučená literatura

Snad se na mě Satai nebude zlobit, ale ocituji jím doporučenou literaturu z letošního jOpenSpace. Pokud mě moje zápisky neklamou byly to:

Petr Hamerník ještě doporučil V pavučině sítí*. Mezi řečí jsem pochytil doporučení na Krach * a The Long Tail.

Zatím jsem četl ty z hvězdičkou a všechny mohu jen doporučit.

Když už jsme u knih, ještě doporučuji knihkupectví The Book Depository, knihy jsou tam sice dražší než na Amazonu, ale mají dopravu zdarma, takže to ve finále vyjde levněji. Navíc člověk nemusí čekat, až se mu toho nakupí víc.