søndag den 21. august 2016

Bézierkurver

For nyligt kom snakken i festligt lag forbi Bézier-kurver - det kan der siges meget klogt om (som f.eks. hos wikipedia). Der kan også siges meget vrøvl, og vi var vist langt nok ude på aftenen til, at jeg gjorde det sidste. Men det var for mig anledning til at genbesøge de fascinerede kurver, og selvom det hurtigt kan udarte sig i megen matematik, så er de faktisk overraskende nemme at konstruere på papir.

Hvis man er vant til at arbejde med Bézier kurver i grafiske værktøjer, så arbejder man med 3. grads eller kubiske kurver (som har to kontrolpunkter, en til hver ende af kurven). Men lad os starte med 2. grad eller kvadratiske kurver (som kun har et kontrolpunkt):


Ideen er simpel: I den ene ende starter man med fuldt ud at være på den ene linje (fra endepunkt til kontrolpunkt), og blander man trinvist med den anden linje (fra kontrolpunkt og til det andet endepunkt) indtil man fuldtud er på den anden linje i det andet endepunkt.

Tegner man det i frihånd, så kan fint nøjes med at lade kurven tangere hjælpelinjerne, som ovenfor. Men der er tale om en parametriceret kurve, hvilket illustreres af dette andet eksempel:


Her har jeg fremhævet tangentpunktet 3/8-del inde på kurven.

En af de fine ting ved en Bézier-kurve er, at den tangerer linjen til kontrolpunktet når man kommer til endepunktet. Det er mao. nemt at få en kurve, som kan forsættes i en lodret linje, som ovenfor. Men hvad hvis man gerne vil kontrollere begge endepunkters hældning? En mulighed er selvfølgelig at sammenstykke to 2. grads kurver, så de deler et endepunkt på linjen imellem de to kontrolpunkter, som hver især giver den rette hældning for den anden ende af kurverne:


Her sidder den midt imellem de to punkter, men man kan selvfølgelig også flytte den tættere på de to reelle kontrolpunkter.

Men vi kunne også sammenblande to 2. gradskurver - hvis vi kalder endepunkterne for E1 hhv. E2 og kontrolpunkterne for K1 hhv. K2, så vil den ene kurve gå fra E1 til K2 med K1 som kontrolpunkt, og den anden gå fra K1 til E2 med K2 som kontrolpunkt.


Her er det sammenblandingen en 1/4-del inde på begge kurver, som er markeret. Den sammenblandede kurve tangerer linjen imellem de to kurvers 1/4-dels tangentpunkter, en 1/4 inde.

Dette giver en 3.grads, eller kubisk, Bézier-kurve:


Det kræver en del mere arbejde at tegne sådan en kurve (og hvis man kigger efter, kan man også se, at jeg har tegnet skævt nogle gange). Men det er bestemt muligt med en lineal og noget forholdstalsregning (eller en passer, hvis man er mere ihærdig), og den virker mindre "bulet" end ovenfor, hvor det var to 2. grads kurver, som blev stykket sammen.

Hvis man er meget ambitiøs, så kan man sammenstykke to 3. grads kurver på samme måde, som de to 2. grads kurver blev, og det får man så en 4. grads kurve ud af. Jeg overlader det som øvelse til læseren (der er eksempel på en 4. og på en 5. grads kurve på wikipedia - jeg ville bare vise, at det faktisk kan "tegnes i hånden").

lørdag den 30. juli 2016

NCAP for software

Det her er interessant:
A famed hacker is grading thousands of programs — and may revolutionize software in the process (theintercept.com)

Som jeg læser ideen, så svarer det lidt til Euro NCAP og deres stjerner for bilers sikkerhed, bare for software.

Euro NCAP initiativet har formået at gøre sikkerhedsmæssigt dårligt konstruerede biler usælgelige, og har fået gjort sikkerhed til et konkurrence parameter. Dets - efter min mening - største fortjeneste har været, at det har formået at hæve bundniveauet markant. Og det håber jeg også vil kunne ske for software, for det har vi brug for - og ovenstående ligner efter min mening et godt bud på, hvordan det kunne gøres.

"Stjernerne" uddeles efter statisk analyse af programmer, og kan derfor ikke sige noget om, hvorvidt det er sikkert eller gør det, som det påstår at gøre; det kan derimod påpege, om programmet er bygget på en måde, som enten ikke lever op til gængs og tidssvarende praksis, eller som øger dets sårbarhed.

Den første ting, som man kigger på, er et absolut mål, nemlig om der er brugt en nyere compiler og om dens muligheder for at øge sikkerheden er udnyttet. F.eks. om der bruges address space layout randomization (ASLR) og heap- og stack-beskyttelse. Det svarer lidt til, at man tæller airbags i biler; det er ikke noget, som man som almindelig bruger kommer til at mærke noget til (forhåbentlig!), og antallet i sig selv siger ikke noget om sikkerhedsniveauet; på den anden side, så er der vist ingen tvivl om, at airbags er nyttige og at de næppe ville have været i ret mange modeller, hvis ikke man havde talt dem.

Den anden ting, er hvor mange andre software biblioteker man bygger på. Her tænker jeg, at (i hvertfald) tre dimensioner er interessante:

  1. Antal: siger noget om kompleksiteten - man bør ikke genopfinde hjulet, men hvis der er taget mange eksterne biblioteker ind, så øger det naturligt sårbarheden; det kan være en indikation for en ringe styret udviklingsprocess, hvis der er brugt unødigt mange biblioteker.
  2. Alder: bruges der tidsvarende og opdaterede biblioteker, eller er det noget, som man enten er ligeglad med, eller lader forfalde?
  3. Hvilke: Visse biblioteker er erkendt mere sårbare end andre, og det kan i sig selv være interessant, hvis der bygges med dårlige materialer.

Den tredje ting er nødvendigvis relativ, nemlig et mål for programmets kompleksitet: det kan f.eks. være metrikker for, om der bruges mange betingelser. Det er oplagt, at der er en vis iboende kompleksitet i alle problemstillinger og at den varierer fra problemstilling til problemstilling, men det er også lige så oplagt, at unødigt komplekse løsninger indeholder et langt større potentiale for uhensigtsmæssigt og uønsket opførsel; der er simpelthen mere, som kan gå i stykker.

Hvis det skal lykkedes at få givet 'stjerner' til software, så kræver det to ting: For det første skal det sandsynliggøres, at en dårlig score tyder på et usikker software (men ikke nødvendigvis omvendt), og det er man tilsyneladende igang med. Her håber jeg bare, at man starter forsigtigt ud, for der vil helt sikkert komme kritik - og det er nemmere at affærdige eller miskreditere noget, som er kompliceret end noget, som åbenlyst er rimeligt.

For det andet, så skal der være alternativer. Hvis ikke vi brugere kan og vil 'stemme med fødderne', så vil det bare løbe ud i ende- og nyttesløse debatter på oversete fagmedier som f.eks. Version2. Det hjælper ikke noget at teste og diskutere kollisionssikkerhed, hvis det eneste man kan købe er en Trabant, og det hjælper heller ikke, at man kan vælge hvilken-som-helst farve, hvis det i praksis skal være sort (NemID, Rejsekort m.fl., jeg kigger på jer!). Artiklen peger selv på forskelle imellem browsere, og der har vi - for det meste - stadig et reelt valg; de dage, hvor stort set alt interessant var 'optimeret til IE' er heldigvis ved at være overstået.

Til sidst et forbehold: jeg kender kun initiativet fra ovenstående kilde, og kan derfor kun udtale mig om selve ideen, som jeg forstår den - ikke om hvorvidt denne eller hin person eller firma er troværdige.

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?