lørdag den 3. marts 2012

Find vej i naturen

Det siges, at det bedste i hele verden er at blive fundet, når man er blevet væk; er det næstbedste så er finde noget, som man ikke vidste hvor var? Og hvad nu, hvis man endda kan kan gøre derude hvor luften er frisk og himlen er høj?

Hvis ja, så vil jeg gerne anbefale Find vej i Danmark projektet.

Projektet kommer fra Dansk Orienterings-Forbund og omfatter en lang række fine små ruter med faste poster og tilhørende gode kort. Ofte er der holdere med kort ved startstedet og kvalitet af disse er helt i top. Men de er populære, så vær forberedt på at kasserne kan være tomme når man kommer (så hent enten et kort på forhånd, tag en god udskrift med som reserve eller hav flere mulige ruter klar).

Jeg opdagede selv projektet ved et tilfælde i nærheden af Fåborg og har siden også været afsted nogle gange i skovene lige syd for Århus. Turen med start ved campingpladsen i Blommehaven kan anbefales.

Måden vi gør det på, er den børnevenlige variant som vi kalder at "gå et orienteringsløb". Det er helt grundlæggende, at der skal være god tid. Rigtig god tid, faktisk. For når man kommer væk fra stierne, så finder man ofte noget som er værd at stoppe op for at undersøge nærmere.

Og selvom stierne selvfølgelig er hovedparten af turen, så skal man regne med at komme væk fra stierne, og derfor bør man undgå habit og dansesko. Almindelig praktisk påklædning til en gåtur i skoven vil være helt fint.

Jeg vil mene at ruterne er overkommelige selv for utrænede, specielt hvis man gør sig lidt umage undervejs og har sat sig ind i andre signaturer end bare sti-billedet. Der er en fin forklaring på kortene (og hvis man er lige detajleorienteret som mig, så er her en meget grundig signaturforklaring; men man behøver altså langtfra at kunne dem alle på forhånd).



Her på billedet er Thomas i gang med at afprøve nogle af grønne nuancer på kortet; hvidt er alm. skov, medens grønt på orienteringkort brug til at angive til at angive nedsat gennemløbelighed eller gennemtrængelighed. Og det skal man have respekt for, specielt de mørkere grønne områder.

En anden signatur, som man skal have respekt for, er den blå. Jeg formåede på allermest pædagoiske vis at illustrere at de små stiplede blå streger betyder "blød bund": skoven var lige ved spise min ene sko!

Kompas bør ikke være nødvendigt, hvis man da har sin retningssans i behold og husker det gode råd om, at hvis man kommer i tvivl om hvor man er, så gå tilbage til der hvor man sidst var sikker. At prøve at støve rundt indtil man (måske) er heldig, er ikke en god metode, og ofte gør det kun ondt værre.

Ellers er det bare at komme afsted, for alle kan være med. Og husk børn, hvis man har nogle eller kan låne nogle.

søndag den 15. januar 2012

How to get Spring transactions to work with the JUnit Theories testrunner

Yes, I will make an exception and write this in English because I think the subject might have broader interest: A solution to the challenge of combining the JUnit Theories testrunner with Spring transaction support.

I am not going to say a lot about JUnit Theories (or @Rule that matter); you can google plenty of good information about that yourself. I am definitely NOT going to even try to talk about how to get Spring transactions to work with your database of choice. And I am not going to argue that it makes much sense to combine Theories and transactional databases. But, hey, challenges doesn't have to make sense to be interesting, right? :-)

And this is a challenge, because Springs support for unittest almost only works with the Spring testrunner and Theories only works if you use the Theories testrunner - and you can only have one testrunner per test. But luckily there is a way out.

So, lets see some code - and lets start with this fairly simple Spring based test:

@ContextConfiguration(locations = "classpath:testcontext.xml")
@Transactional
@RunWith(SpringJUnit4ClassRunner.class)

public class SimpleTest {
@Autowired DataSource datasource;

private JdbcTemplate jdbcTemplate;

@Before public void setup() throws SQLException {
jdbcTemplate = new JdbcTemplate(datasource);
}

@Test
public void canInsert() throws SQLException {
jdbcTemplate.update("INSERT INTO test( id ) VALUES (?)", 1);
}
}

Note that it uses the Spring testrunner and that it wants to be transactional. Doing so makes Spring to some pretty nifty magic behind the scenes, so that everything you do to the database in a single test is wrapped in a transaction that is rolled back afterwards. Spring has even thought of starting the transaction before the @Before method and will first end it after the @After method, which is pretty clever.

But it all hinges on using the the Spring testrunner. So what if you want to use another testrunner like for instance Theories?

Well, the Spring testrunner delegates to another Spring class called TestContextManager and a fairly common workaround therefore is to do the same delegation in the @Before method as Spring would do in the testrunner. Just like this:

@ContextConfiguration(locations = "classpath:testcontext.xml")
@Transactional
@RunWith(Theories.class)
public class BuggedTheoriesTest {
@Autowired DataSource datasource;

private JdbcTemplate jdbcTemplate;

@Before public void setup() throws Exception {
//here we hook into the Spring test-support framework
final TestContextManager tcm = new TestContextManager(getClass());
tcm.prepareTestInstance(this);

//this will work for everything but spring transactions as transactions expects to be enabled before @Before

jdbcTemplate = new JdbcTemplate(datasource);
}

@Test
public void canInsert() throws SQLException {
jdbcTemplate.update("INSERT INTO test( id ) VALUES (?)", 1);
}
}

The good news is, that it actually manages to get the spring context loaded so the database is accessible. The bad news is, that we're just a tad to late for transactions to work. Remember that they were supposed to start before the @Before method? Well, the downside here is that we're too late when we try to call upon the help of Spring in the @Before method it self.

My googling skills didn't find any solution to this problem, which probably goes to say a lot about my googling skills. So I came up with the solution below (the parts of which I have found by googling :-)). I am not going to say it is particularly clever or even pretty, but hey, it seems to work!

It is based on using the @Rule annotation that was introduced in JUnit 4.7. I am not sure why it is called a "rule", but it is a mechanism that enabled you to define a wrapper that will wrap every invocation of testmethods in the test including the @Before and @After parts.

@ContextConfiguration(locations = "classpath:testcontext.xml")
@Transactional
@RunWith(Theories.class)
public class FixedTheoriesTest {
@Autowired DataSource datasource;

private JdbcTemplate jdbcTemplate;

@Rule public SpringTestContextManagerRule springTestContextManagerRule = new SpringTestContextManagerRule();

@Before public void setup() throws Exception {
jdbcTemplate = new JdbcTemplate(datasource);
}

@DataPoints public static int[] ids() {
return new int[] {1,2,5,10,20,50,100,200,500};
}

@Theory
public void canInsert(int id) throws SQLException {
jdbcTemplate.update("INSERT INTO test( id ) VALUES (?)", id);
}
}

That's all there is too it: Spring with transactions working with JUnit Theories!

Oh, and yes, you'll probably need this as well :-D :

public class SpringTestContextManagerRule implements MethodRule{

@Override
public Statement apply(final Statement statement, final FrameworkMethod frameworkMethod, final Object testInstance) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
final TestContextManager tcm = new TestContextManager(testInstance.getClass());
tcm.prepareTestInstance(testInstance);
tcm.beforeTestMethod(testInstance, frameworkMethod.getMethod());
try {
statement.evaluate();
tcm.afterTestMethod(testInstance, frameworkMethod.getMethod(), null);
} catch (Throwable t ) {
tcm.afterTestMethod(testInstance, frameworkMethod.getMethod(), t);
throw t;
}
}
};

}
}

Notice how this Rule makes a Statement that has an evaluate()-method that wraps around the statement passed to it. In that way rules can make statements that wraps statements of other rules, eventually leading to a statement wrapping an actual testmethod.

There is one caveat, though: The implementation is based on a MethodRule; this has been deprecated in later versions of JUnit, and is supposed to be replaced with a TestRule. The only problem with the new TestRule is that it will only provide you with the name of the test method to be invoked, not a reference to the method itself. It should be possible to work around this, but it is easier to use a MethodRule regardless of the deprecation warning.

I have uploaded a maven-based project to github. It should be fairly self-contained, the only real assumption is, that there is a MySQL database on localhost with a schema called testdb that can be used by the user "test".

mandag den 24. oktober 2011

Logik for teknokrater

I dag var jeg vidne til en sand Århus-historie: På Banegårdspladsen i Århus var jeg ved at stige på rutebilen til Skanderborg, da passageren foran mig beder om et klippekort. Det prøver chaufføren så at lave, men må efter lidt tid give op med ordene: "Nåe ja, jeg kan ikke sælge klippekort sålænge vi er i Århus, og det står også på Midt-trafiks hjemmeside" "Ah, hvad?" tænkte jeg.

Det med hjemmesiden er i øvrigt en sandhed med modifikationer, for man har åbenbart forsøgt at kompensere for kvalitet i beskrivelsen af reglen med kvantitet i antallet af steder, hvor den er nævnt ... med det resultat, at man står forvirret tilbage med et inkonsistent billede af, hvad der er op og ned. Hovedparten af formuleringerne peger dog ganske rigtigt i den generelle retning, at man kan ikke købe klippekort i busserne, så længe at de befinder sig i Århus eller Randers.

Hvorfor står til gengæld hen i det uvisse - jeg vil gætte på, at det er en konsekvens af at man har forsøgt at slå rutebiler og bybusser sammen; det giver nemlig god mening, at man ikke kan købe klippekort i bybusserne i Århus.

Nu kunne man så have valgt at sige, at man slet ikke kunne købe klippekort i busserne længere, men det turde man måske ikke af frygt for at fornærme os, der kommer fra landet (som f.eks. Skanderborg)? Og hvis årsagen vitterlig er, at man ikke kan eller vil have samme service i århusianske bybusser som i resten af Midt-trafiks område, så kunne man f.eks. have formuleret reglen som at busser, der ikke kører ud af Århusområdet, ikke vil sælge klippekort.

Man kunne såmænd også have lavet denne aktuelle regel, og så ladet det være op til chaufføren, om han rent "undtagelsesvist" ville vælge at se bort fra den, trafiksituationen, ruteføringen og omstændighederne i øvrigt taget i betragtning. Hvad ville ulykken være ved, at der en gang imellem skulle smutte et klippekort eller to over pulten i bussen, så længe chaufføren har friheden til at kunne henvise til hovedreglen?

Men nej, ikke alene finder man på en ny finurlig regel, i stedet for at benytte sammenlægningen til at få luget ud i de mere eller mindre tilfældige forskelle der var i de eksisterende regler, men selvfølgelig skulle man bruge penge på at få modificeret billetautomaterne. Og det er da en sand Århus-historie sådan at kaste gode penge efter dårlige.

PS: Passageren fik for resten sit klippekort; chaufføren var af den service-mindede type, som der heldigvis stadig er mange af bag rattet af vore lokale rutebiler, og han formåede derfor at overbevise bussen og/eller billet-maskinen midlertidigt om, at vi ikke længere var i Århus. For uden for Århus-området må man godt være hjælpsom.

lørdag den 10. juli 2010

Lottoøkonomi

Da jeg i sin tid startede på Handelshøjskolen, da grinede vi en del af vittigheden om, at lotteri i virkeligheden er en ekstraskat på de sandsynlighedsregningsmæssigt udfordrede. Senere er det gået op for mig, at intet kunne være mindre sandt: et negligerbart men sikkert tab imod en lille mulighed for en skelsættende stor gevinst, kan faktisk være attraktiv (det kommer i høj grad an på, hvad ens situation i øvrigt er). Og læg så dertil retten til at drømme for en stund. Næh, verden er ikke så nem som de introducerende tekster gerne ville gøre den til.

Første gang at jeg hørte om Helle og Villys "giv os en time om ugen"-plan, så tænkte jeg godt nok, at det var underligt, at det blev opfattet som en mere farbar vej at bede 40 mennesker, som allerede arbejder "fuld" tid, om en time mere, end at få bare en arbejdsdygtig, men i dag offentligt forsøget person, igang med at arbejde.

Men måske har de ret - det er trods alt deres gesjæft at have en god fornemmelse for, hvad retning de politiske vinde blæser. Og ihukommende mine erfaringer med lotterispillets finurligheder, så må jeg erkende, at man ikke bare lige kan regne om imellem fuldtidsbeskæftigede og ubeskæftigede (i videste forstand, for vi har efterhånden fået opbygget et system, hvor man nemt kan blive klassificeret som værende "uden for arbejdsstyrken" og dermed ved et kunstgreb ikke tæller med som arbejdsløs).

Det er i hvert fald rigtigt set, at vi bliver nødt til at tage tyren godt ved hornene og kigge den dybt i øjnene - vi bliver nødt til at øge vores effektivitet, og vil vi ikke løbe hurtigere, så må vi enten løbe i længere tid (eller være flere til at løbe). Så på den led, så er det fin plan - man kan måske nok med rette indvende, at det er både for lidt og for sent til at gøre en forskel, men der er vi jo nok tilbage ved det, som mere prosaisk ofte kaldes for det muliges kunst. Hellere en fugl i hånden end ti på taget!

Trods det lave ambitionsniveau har forslaget nu alligevel sine udfordringer i praksis:

Den første står jeg såmænd selv for - jeg arbejder allerede jævnligt mere end en time ekstra om ugen uden at det medfører nogen særlig opmærksomhed (jeg har fået at vide, at det følger med fin titel, ansvar og gråt hår...). Så jeg tænker, at det må være alle I andre, som altså lige må lægge jer lidt mere i selen, og se at komme ind i spillet!

Og så er der den med at have gjort regning uden vært, for man kan måske nok mene, at Villy og Helle her er ude med at love en gratis omgang på andres regning. Siden det kom frem, har vi da også måtte lægge øre til, at de godt og grundigt er blevet undsagt af "en af deres egne", nemlig Dennis Kristensen. Selvom han tydeligvis har nogle medlemmer i ældreplejen, som sagtens vil kunne finde de berømte 12 minutter om dagen, uden at komme til at svede af den grund, så mener han stadig at buen i hans kreds er spændt til bristepunktet. Så han tænker også, at det må være nogle andre, som må lægge sig godt i selen, og se at komme ind i spillet!

Men det for mig største skud for boven, som planen fik, kom faktisk fra en helt anden kant: en kyndig person henledte i al stilhed opmærksomheden på, at store dele af overenskomstforhandlingerne er lokale - og der er central indflydelse ikke gangbar valuta. Så de mere lavmælte af Helle og Villys venner kan næppe heller levere varen - de regner nemlig også med at sende regningen for festen videre til nogle andre.

Så måske er det alligevel ikke så nemt at få 40 fuldtidsbeskæftigede til at arbejde lidt mere. Synd, for vi bliver altså nød til at gøre noget ved den samlede samfundsproduktion, hvis vi alle skal have et godt liv, også fremover.

PS: Læg i øvrigt mærke til retorikken - det var ikke "en time om ugen", men "12 minutter om dagen". Det svarer lidt til, at alting koster noget med ...99 til sidst. Og mon ikke det virker bedre end "giv os halvdelen af din frokostpause", for det vil vække de sovende uhyrer omkring betalt frokost i nogle dele af samfundet...

lørdag den 29. maj 2010

Den ægte vare

Det er et stykke tid siden, at jeg sidst har ladet høre fra mig her, og - hånden på hjertet - så skyldes det hovedsageligt, at jeg har haft travlt med alt muligt andet. Men det skyldes også, at der - efter min mening - virkelig sker ting og sager i dansk politik for tiden.

Væk er den Fogh'ske æras småmaniske regler, som grundlæggende havde til formål at undgå at få trykket alt for hårdt på speederen. Lidt ligesom når man efter overgangen fra SU til lønindkomst må lave regler for sig selv om at prøve at undgå fastfood mere end en dag om ugen, eller at kun spise chips om fredagen.

Næh, nu går det for de mange forskellige interessegrupperinger vist mere ud på at sikre, at man ikke mister noget af det forspring, som man vandt, da alt gik hurtigt.

Generelt set, så ser det ud til at den foretrukne løsning er at malke de køer, som man nu engang har, endnu hårdere - og at klemme deres foder. Ikke særligt ambitiøst, for der er da også rigeligt med tyre rundt omkring, som trænger til at blive taget grundigt ved hornene, men det er vel at forvente, når nu Folketinget er fyldt op med 179 socialdemokrater i varierende nuancer.

Jeg troede aldrig, at denne dag ville komme, men jeg overvejer faktisk lige nu at stemme på Socialdemokraterne (dem med stort "S") - ikke fordi, at jeg synes at "Helle og Villy's store plan" er noget særligt - det er helt grundlæggende for alt lidt og for alt sent - næh, det måske mere fordi, at det er tydeligt, hvem der har omkring hundrede års erfaring i at være socialdemokrater, og hvem der hjælpeløst prøver at fumle sig frem i lånte gevandter, der ærligt talt ikke klæder dem særligt godt.

Og når valget nu står imellem forskellige slags socialdemokrater, hvorfor så ikke vælge den ægte vare?

tirsdag den 6. april 2010

Den ene synd...

Der er en god, gammel vending, som siger, at den ene synd ikke undskylder den anden. Men kan en god gerning så undskylde en synd? Altså en slags aflad for forkant?

Når jeg spørger sådan, så er det fordi, at jeg lige har modtaget et CO2 kompenseret brev. Jep, den er god nok, se bare her hos Post Danmark. Man må med andre ord godt opføre sig grimt, bare man får nogle andre til at opføre sig tilsvarende pænt!

Det er da et koncept med perspektiv i: næste gang jeg bliver taget i en fartkontrol, så henviser jeg bare til, at min kone altid kører meget langsommere end tilladt - og hvis jeg en gang skulle formå at forhindre en snothvalp i at få et par velfortjente flade, så er jeg allerede tilgivet, når junior engang kommer til at skramme bilen.

Tak, Post Danmark, for sand innovativ tænkning af den slags, som gør verden til et meget bedre sted.

søndag den 21. marts 2010

Kontekstfri II

Som opfølgning på min post om Context Free kan vi vist godt klare et par billeder mere, begge fuldt deterministiske:



Det er virkelig simple programmer, som ligger bag billederne - ovenstående billede er f.eks. lavet med flg. kode:

startshape START

background { b -1 }

rule START {
CIRCA{ h 0 sat 1 b 0.5 a -.2}
}

rule CIRCA{
3 * {r 120 x 4} CIRCO { s 0.5 b 0.1 h 5 }
}

rule CIRCO{
CIRCLE{ s 8}
CIRCA{}
}

...og så lover jeg ikke at skrive mere om det (medmindre der er mere at sige end bare det, at jeg har lavet flere billeder).