Archive for the ‘kage/cake’ Category

Strongly typed + primitive obsession = poorly typed

torsdag, februar 21st, 2013

Due to the rather large amount of work required to create an object in Java there is a shortcut which leads to primitive obsession: Use the best existing match – for web services a String seems sufficiently applicable for any type, which makes a Map<String, String> or Properties the default data structure for transferable objects.

Property objects easily extended – you simply add new keys – and in that sense they are much handier than Beans, but they aren’t objects in the sense that an object hides information – which is quite difficult if being a data transfer object – but they don’t have methods which works upon the intrinsic state of the objects. Not having methods on the objects leads to procedural programming, which defeats the purpose of objects entirely.

Claiming Java is a strongly typed language and then defaulting to using Strings is really an oxymoron and detrimental to the quality of anything developed in such a language.

I’m all for rapid development and in a tight spot or early on in exploratory development primitives can be used, but they should be replaced by meaningful types as soon as possible. Ages aren’t measured in Integer, money isn’t Double, and I’m sure names belong to a subset of all the possible String values.

While I’m bashing Java – and in particular Java developers – then this is valid for most C-styled languages and developers in those languages. I’m quite puzzled as to why newish strongly typed languages didn’t look at Pascal’s type declaration – it is extremely simple to define or simply alias an existing type. It seems Scala did pick up on that and added the type keyword, which is an easy way to alias another type. E.g. for prototyping you can define Name as a type, which underneath is a String. You can still make type errors by using a declared String as Name or Name as String, but if you define the methods and functions as taking Name as parameter or returning Name, then you should spot some issues in the prototyping phase, and when you exchange the alias for a real type, you should no longer be able to make the type errors. While this is ugly it is far superior to the String hell of Java. NB: This is not the way type was intended to be used.

You should be able to spot the issues by reading code. Sometimes it helps reading it out aloud.

As an example let’s take Martin Fowler’s EventCollaboration example:

class Trader...
        public void PlaceOrder(string symbol, int volume) {
            StockExchange exchange = ServiceLocator.StockExchangeFor(symbol);
            Order order = new Order(symbol, volume, this);
            exchange.SubmitOrder(order);
        }

Transcribing what I was reading out aloud:

  • We have a Trader class in which we can place an order. Placing and order requires a string called symbol and an integer volume – presumably of the things identified by the symbol string.
  • To process the placing of the order we locate the StockExchange, which we will refer to internally as exchange, through a ServiceLocator service using the symbol as argument.
  • Proceeding we create an Order, which we will refer to as order, using the parameters given and the Trader object itself.
  • Finally we submit the order to the exchange.

While that seems like a reasonable process for placing an order only the last step is actually placing the order.

One part is getting the StockExchange on which to place the order, another is actually building the order. This leads to the fact that Trader will have to know about the internals of Order – this may be relevant, then again as Order must know about Trader we have introduced a dependency cycle between the two objects.

Furthermore, if symbol was ever to be confined to some meaningful subset of the String hell, then we would have to modify at least 3 classes: Order, Trader, and ServiceLocator.

While the example goes on changing the method to cater for EventCollaboration:

class Trader...
        public void PlaceOrder(string stock, int volume) {
            Order order = new Order(stock, volume);
            outstandingOrders.Add(order);
            MessageBus.PublishOrderPlacement(order);
        }

A nicer and more consistent way would be to replace the previous method by:

public void place(Order order, StockExchange exchange) { 
    exchange.SubmitOrder(order);
}

Naturally this leads to the discussion of where the remaining steps should go and whether Order should know about Trader or not. My point is that Order should not be created in the flow of PlaceOrder it should be given as a parameter. And giving it as a strongly typed parameter you can remove the type from the method name. Trader.place(Order) reads much better than Trader.placeOrder(Order) – who knows maybe you’ll find a recurring pattern which could lead to an interface and from there to insights.

Why pick on Fowler?

Well, there are several reasons:

  • The code is available. That is, it exists for another purpose than mine. If I wrote example code it would not prove anything except that I couldn’t program.
  • Martin Fowler is known for his books Refactoring: Improving the Design of Existing Code and Patterns of Enterprise Application Architecture – the latter which is used in academia and from which the code in the examples are from – well, the companion web-site.
  • Wanting to “improve the design of existing code” should not leave you stranded with poor code to start with
  • If teaching material is poor, the experience will suffer
  • My guess is that Martin Fowler is a better than average programmer – presumably quite a lot better than average. Showing that his code is not perfect is simply an indication of the state of software in general
  • If you focus on one thing you may lose sight of other elements. In the EventCollaboration example the focus is on event collaboration and not on cyclic dependencies

Back on track

Going back to the introduction I mentioned that ages aren’t measured in Integer, money isn’t Double, and I’m sure names belong to a subset of all the possible String values. Let’s dive into these in greater detail.

Age

The standard 32 bit Integer range is -2,147,483,648 to 2,147,483,647 – if age is measured in years, and we’re talking about humans, then an unsigned 8-bit (0-255) seems quite the fitting range. I’ve never heard of humans being more than 150 years old – and not even that. Most certainly none have been recognized as being -7 years old.

If the age is to be measured in seconds since the start of the epoch (Jan 1st, 1970 00:00:00 UTC), then either it’s not Age but rather a time in space, or we’re into an uncertainty of approximately 43,200 seconds (half a day) – at least I have no idea of when I was born. In either case 32-bit is off. The range of 4 billion seconds is about 136 years. That is, we can only go back to 1901 and forward to 2038, which isn’t suitable for all occasions.

Money

Money consists of an amount of a certain denomination. Most – but not all – currencies have some sort of 1/100 of the denomination, and for percentages, taxation, and currency exchange we often have to work with numbers 1/100 of that, but we shouldn’t go beyond those digits, and we should not accept scientific notation, e.g. $1E2. NaN and Math.PI don’t seem fitting either. Numbers have certain operation, which can be performed upon them, e.g. addition and multiplication. You can’t add $1 and €1 in a meaningful way – at least not without an exchange rate, and you cannot multiply them.

That should leave sufficient arguments not to use floating points without going into details of What Every Computer Scientist Should Know About Floating-Point Arithmetic

Names

I know I’m a bit cynical when saying that nobody is called:

I'm a little teapot,
Short and stout,
Here is my handle, 
Here is my spout,
When I get all steamed up,
Hear me shout,
Tip me over and pour me out!

source

Nor

Robert'); DROP TABLE

XKCD’s Bobby Tables

Why the obsession?

Well it is about minimizing required work. If you have more than one method, which will take an argument of a given type, e.g. age, then you should check the validity of the input for each and every method. Binding the check to where the argument is instantiated, you will know that the argument conforms to the anticipated accepted values everywhere else. In essence you are white listing your input.

If you have a range with start and end, and these two endpoints aren’t connected and the bounds checked, i.e. that start comes before end, but blindly passed on, then you’d have to check over and over again. Possibly introducing an off by one error along the way.

It’s the mathematical laziness, one abstract solution, as opposed to the busy-work mindlessness.

So while primitive obsession is problematic, primitive obsession in a strongly typed language is extremely detrimental. The arguments for a strong type check is defeated by the poor choices made basically removing the foundation for the trust in the types. A dynamically typed programming language would be better, i.e. not as bad in this case – not that you would be better off making mistakes in those languages.

Banankage

lørdag, januar 22nd, 2011

125 gram margarine eller smør

125 gram melis – evt. lidt mindre, hvis der tilsættes brun farin
2 æg
125 gram hvedemel
1 tsk. bagepulver
125 gram bananer uden skræl (de skal helst være godt modne, eller kan et par minutter i ovnen sikkert gøre underværker)
1 spsk. citronsaft
evt. lidt brun farin – hvilket giver en lidt anderledes smag, men sÃ¥ skal der tages noget af sukkeret fra.
evt. en sjat rom. Rom og bananer er som regel en ganske god blanding.
evt. chokolade til glasur.

Rørt dej: Ingredienserne røres sammen i den nævnte rækkefølge (eller kastes i en ond foodprocessor). Sukkeret røres sammen med det bløde fedtstof til massen er hvid og skummende. Rør æggene i, et ad gangen. Hvert æg bør indarbejdes godt i dejen, før det næste tilsættes. Sigt mel og bagepulver i massen, rør rundt indtil en homogen dej forefindes.

Bananen dryppes med citronsaft, moses med en gaffel inden den røres i dejen.

Dejen kan bages i en smørsmurt, melstrøet springform 25 min. ved 200 grader eller i en sandkageform 45 min. ved 185 grader.

Lad kagen hvile 5-10 min. i formen efter den er taget ud af ovnen.

Kagen kan pyntes med bananskiver, der glaseres med citronglasur eller med smeltet chokolade.

Honning Hjerter

lørdag, januar 22nd, 2011

600 gram mel

2 tsk. stødt kanel
2 tsk. stødt nellike
2 tsk. hjortetakssalt
1 tsk. stødt ingefær
30 gram potaske (røres ud i vand)
200 gram smeltet smør eller margarine
500 gram honning
2 æg

OBS: Nybegyndere bør måske nøjes med den halve portion.

Hæld de tørre ingredienser i en skål.

Smelt smør/margarine – kom honningen deri nÃ¥r fedtstoffet er smeltet.

Bland den udrørte potaske i skålen sammen med æg efterfulgt af honning/fedtstofblandingen. Det hele skal æltes sammen til en homogen masse, lad det blot forblive i skålen, da dejen er rimelig tynd på dette tidspunkt.

Ingen panik, ikke mere mel i – det ordner sig, nÃ¥r fedtstoffet sætter sig.

Lad dejen stå koldt et par dage så smagen kan gennemtrænge.

Dejen rulles ud i ca. 1 cm tykkelse. Forme kan bruges til at trykke kager ud, men man kan også forsøge sig ud i frihånd.

Kagerne lægges pÃ¥ en smurt bageplade – brug evt. bagepapir i stedet. Kagerne vil hæve lidt under bagningen og vil iøvrigt ogsÃ¥ løbe lidt ud, sÃ¥ hold et par centimeters afstand imellem dem.

Pladen stilles i en 200 graders varm ovn, hvori kagerne bages i ca. 10 minutter.

Kagerne kan pyntes med chokolade eller hvid glasur (1 æggehvide, 150 gram flormelis, 4 dråber eddike piskes sammen) kan sprøjtes på, når hjerterne er afkølet og tørre.

Man behøver naturligvis ikke pynte kagerne, men jeg syntes, at de er mere saftige – i længere tid – med en skal af chokolade… og sÃ¥ smager det jo godt :o)

Når glasuren er tør pakkes kagerne lufttæt.

Klejner

lørdag, januar 22nd, 2011

2 æg

100 gram melis
revet skal af 1 citron (økoligisk citron, de er ubehandlede)
100 gram smeltet smør eller margarine
50 gram kartoffelmel
250 gram hvedemel
1/2 tsk. bagepulver

olie eller palmin til friturestegningen

Pisket dej: Hele æg og sukker piskes, til det ikke knaser mere og “æggesnapsen” er blevet næsten hvid og ganske luftig. Citronskal tilsættes. Smeltet, afkølet smør røres i. Kartoffelmel, hvedemel og bagepulver sigtes sammen og blandes i lidt efter lidt.

Dejen lægges koldt, til den er fast. Den rulles ud sÃ¥ tyndt som muligt (omkring 2 mm finder jeg passende) og skæres med klejnesporen i 5 cm brede strimler. Strimlerne skæres igen i spidse firkanter (parallellogrammer eller “ruder”). Disse ridses i midten, hvorefter klejnerne vrides. Klejnerne lægges koldt.

Olien eller palminen opvarmes i en tykbundet gryde til 180 grader, eller til det syder om en tændstik, når denne stikkes ned i olien. Klejnerne koges hurtigt heri, 3-4 stykker pr. gang. De affedtes på gråt papir eller køkkenrulle og gemmes i kagedåser, når de er kolde. De kan også lægges i fryseren.

Hvis klejnefedtet skummer og bruser, er det ikke tilstrækkelig varmt. Da må det varmes igennem en tid, før man igen lægger klejner i.

Klejnerne synker til bunds idet de lægges i olien, men stiger hurtigt op til overfladen, så snart en skal har formet sig, og bagepulveret har sørget for luftlommer i klejnen. Alt efter dejens tykkelse skal de ligge kortere eller længere tid (vi snakker få sekunder) i overfladen inden de vendes, så også den anden side bliver gyldenbrun. Dette tager få sekunder.

Advarsel: Frist ikke skæbnen til at hælde mere mel på/i, når dejen skal rulles ud. Mere mel gør dejen porøs, det bliver svært at vride klejerne uden at de knækker. Desuden vil de hyppigt falde fra hinanden under kogningen eller kort derefter samt evt. virke en smule tørre.

Kransekage Konfekt (Lagkagehusets)

lørdag, januar 22nd, 2011

500 gram marcipan

150 gram sukker
2 spsk. honning
100 gram æggehvider (3 æggehvider kan også benyttes)

Denne opskrift er fra Lagkagehuset, den blev vist pÃ¥ TV 2 den 29. december 2003 i “Go’morgen Danmark” (opskriften er her). I deres opskrift laves der mandelhorn af 300 gram af den endelige masse, det har jeg ikke gjort sÃ¥ sidst jeg lavede toppe blev det til 71 stk. Heldigvis kan de fryses efter de er bagt, og de smager endda lidt bedre efter frost. Bare tag dem ud af fryseren et stykke tid inden de skal spises.

Ælt marcipan og sukker sammen — det er hÃ¥rdt, men kan sagtens lade sig gøre ved hÃ¥ndkraft.

NÃ¥r marcipan og sukker er æltet grundigt sammen tilsættes 2 spiseskefulde honning – det holder kransekagen fugtig. Bland igen til en ensartet masse.

Tilsæt nu æggehvide i 3 tempi, der skal æltes/røres godt imellem hver. NÃ¥r det sidste hvide er kommet i er massen forholdsvis lind – lidt i stil med kartoffel- eller æblemos.

Tag en bageplade med bagepapir. Fyld kransekagemassen i en sprøjtepose og sprøjt smÃ¥ toppe ud pÃ¥ bagepapiret. Hvis man ikke lige har en sprøjtepose, sÃ¥ kan en frostpose godt benyttes – denne skal blot fyldes med massen, sørg for, at der ikke er for meget luft i posen, da massen sÃ¥ vil sprutte ud. Klip et hjørne af posen, sÃ¥ der kommer et hul pÃ¥ ca. 1 – 1 1/2 cm i diameter.
Naturligvis får man ikke de fine riller i kransekagetoppene, man ville have fået, hvis man havde brugt en sprøjtepose med en stjernetud.

Pynt nu konfekten med nødder, mandler eller cocktailbær

Bages i ca. 7 minutter ved 210 grader til toppene og evt. kanter er gyldenbrune. For at bunden af konfekten ikke skal tage for meget farve kan man bage den på en dobbeltplade.

Straks de er kommet ud af ovnen sættes de på en bagerist, så de hurtigt kan køle af. Når der er afkølet kan de pyntes mere, med glasur eller chockolade.

TIP: en tynd skive nougat pÃ¥ bunden af kransekagekonfekten kan sagtens spises – det er naturligvis nemmest, hvis nougaten stÃ¥r fremme, sÃ¥ folk selv kan bestemme, hvor meget de vil have pÃ¥ – og sÃ¥ hænger de ikke fast. Ellers kan man bage toppe uden pynt og derefter sætte en lille blok nougat i toppen.

Wienerbrød

lørdag, januar 22nd, 2011

50 g gær

11/4 dl kold mælk
50 g sukker
1 æg
ca. 250 g mel

indrulning:
150-200g smør
50 g mel

Bagetid: 5-7 min. ved 250 grader Celcius
Hak fedtstof og mel sammen til indrulning. Sæt blandingen koldt.

Gæren smuldres og rørres ud i lidt af væsken. Hæld resten af væsken ved (den skal ikke lunes) og tilsæt sukker, æg og halvdelen af melet. Resten af melet tilsættes ad flere gange.

Ælt dejen sej, smidig og blank. Rul dejen ud pÃ¥ et meldrysset bord til en firkant, ca. 35×35 cm.

Rul fedtstof- og melblandingen ud til en knap halvt så stor firkant, og læg den på den ene halvdel af dejen. Bøj den anden halvdel over. Tryk let med kagerullen og rul den dobbelte dej ud til en aflang plade på den anden led.

Bøj dejen sammen i tre lag, så den åbne kant vender mod én selv. Fold sammen og rul ud på samme måde yderligere to gange. Dejen skal foldes og rulles ud tre gange.

Drys mel på bordet mellem hver udrulning, og børst alt overflødig mel af dejen.

Hvis dejen begynder at klistre, bør den lægges koldt ca. 15 min. inden man fortsætter udrulningen.

Den færdigudrullede dej pakkes ind i et viskestykke ca. 15 min. på et køligt sted.

Kagerne sættes på usmurte plader til hævning ca. 1½ time på et køligt sted.

kilde: Gyldendals Kogebog


Man kan godt snyde og undlade at lave indrulningsmassen først, arbejd i sÃ¥ fald frem til der, hvor blandingen skal smøres ud, og tag i stedet en ostehøvl og skær fine stykker af smør, som placeres tæt – dog ikke overlappende pÃ¥ halvdelen af dejen. Fortsæt nu, hvor du slap opskriften tidligere. Har du masser af smør tilovers kan du folde/rulle flere gange, og pÃ¥ den mÃ¥de inkorporere alt fedtstoffet. Bliv ved med at folde/rulle indtil der ikke er flere store smørklatter, men pas ogsÃ¥ pÃ¥ ikke at overarbejde dejen. Jeg vil sige de 3 gange er et minimum du fÃ¥r en pænere struktur ved f.eks. 5-7 gange.


remonce

(fedtet snask, der kan bruges som fyld til wienerbrød

F.eks.
100 g smør eller margarine
100 g flormelis

Rør fedstof og sukker blødt og hvidt.
Eller..

125 g mandler eller nøddekerner
150 g flormelis
2 æggehvider eller 1 sammenpisket æg

Mal mandler eller nødder. Tilsæt flormelis, og tilsæt så meget æggehvide eller sammenpisket æg, at dejen bliver smidig, men fast.