Satsa aldrig pengar på en hålstege…

2012-09-20

Enligt mig så tycker jag att en av de svåraste lägen jag kan hamna i är när floppen kommer upp och det visar sig att jag har en hålstege.. Vad i h-e skall man då ta sig till? Det är så fruktansvärt sällan som jag träffar de där fyra outsen som behövs. Väldigt ofta slänger jag handen kanske trots att oddsen finns för att syna. Jag hatar verkligen hålstege.

Men att slänga en hand som i det långa loppet skulle kunna betala sig är ju bara dumt, så jag måste lära mig att hantera den situationen. Så vad göra?

Min erfarenhet säger mig att en hålstege i en multipott är en riktigt dålig idé även när oddsen finns. Du vinner inte tillräckligt mycket för att motivera alla förluster. Dessutom så blir det väldigt ofta split pott i en multipott. Nä, en hålstege spelas bäst i headsup-läge.

Ett möjligt undantag är om bordet är väldigt passivt. Och då menar jag väldigt passivt. Typ rundcheck på flopp och kanske bara en mini-bet på turn. Men på dessa bord kan man ju spela nästan vad som helst och vinna i längden, så den typen av bord använder jag inte som någon måttstock.

Varför inte spela hålstegar i multivägspott? Detta för flera anledningar:

  • – Det är större risk för att du faktiskt inte har fyra outs. Risken aär större att någon av de andra aktiva spelarna faktiskt sitter med en av dina outs är markant större.
  • – Oftare än annars så drar du mot split pott, vilket gör att oddsen inte blir till din favör. I heads up så är split pot (på fullbordad stege) ovanligare har jag märkt.
  • – Om du inte har hålstege som drar till nötstegen så är det lätt att du faktiskt drar dött. Vad händer om du sitter med 78, bordet är TJx och upp kommer 9an? Väldigt ofta i en flervägspott sitter någon med KQ och du har just förlorat…

Hålstegar i multivägspott är komplicerat och därför undviker jag dem i dessa lägen. Heads-up är en helt annan sak, men då spelar faktiskt korten mindre roll – det är ett mycket mer spel mot din motståndare än vad ni faktiskt har för kort. Mycket mer psykologi än faktiskt spel.

Men hur spelar ni andra hålstegdrag, rent generellt?


Felhantering

2012-09-11

I teorin så är det ganska enkelt att hantera fel, men som vanligt så är det inte alltid det lättaste att översätta teori i praktik. Jag har sett otaliga sätt och tillämpningar på hur felhantering har implementerats i allehanda programspråk, och jag måste säga att jag inte är helt övertygad om att något sätt som något programspråk erbjuder är det mest optimala.

Problemet jag har är tvåfalt: Det är dels en ren syntaxfråga – vilken syntax krävs av språket för att indikera och hantera fel och den andra delen handlar om den mer rena abstrakta observationen vad som skall felhanteras och hur.

Syntax

I Java har vi s.k. Try…Catch…Finally satser som är ett helt ok att hantera fel och som har blivit mer eller mindre en de facto standard. Det fungerar men för mig är det väldigt mycket som stör mitt öga. Det blir väldigt mycket ”klutter”. Tyvärr har ju även .Net implementerat denna syntax.

Ruby använder andra ord men det är samma syntax som Java/.Net Try/Catch; ”Begin…Rescue…End”.

I LotusScript så är vi tvingade att använda det förhatliga ”On Error Goto” som inbjuder till spaghetti-kod.

I C så har vi ingen syntax för felhantering – vi använder svarskoder (”return codes”) från våra metoder för att indikera hur det resulterade där int 0 vanligtvis betyder att metoden lyckades.

Jag inte tycker om try…catch-syntaxen. Den stör mitt öga. Om nu varenda funktion/metod har felhantering så kommer varenda en att innehålla en try-catch sats och då kommer du ha mycket kod för ingenting. Det blir väldigt mycket text som ditt öga måste ignorera för att se vad koden faktiskt gör. Jag gillar inte principen att man skriver något som inte behöver läsas.

Det finns ett sätt att slippa try..catch men det är inget sätt jag rekommenderar. Det är att använda CHECKED EXCPTIONS enbart. Det är bara ett sätt att dölja felhanteringen och flytta problematiken. Dessutom så är checked exceptions ett brott mot Open/Closed principle. Tyvärr så finns det vissa bibliotek som tvingar oss att använda CHECKED EXCEPTIONS, så då är vi tvingade att skriva Wrappers för dessa för att få bort otyget.

Hur borde det se ut då? Hmm. Det är en svår nöt att knäcka. Personligen så skulle jag vilja kunna göra något i stil med att deklarera i början av en funktion vilka fel som har felhantering och hur dessa skall hanteras, men att koden för att hantera dessa fel INTE LIGGER I SAMMA METOD som resten av koden:


public void myTestFunction() {
 Declare Error IllegalFunctionCallException informUser(IllegalFunctionCallException);
 ...
 Throw new IllegalFunctionCallException("Test");
 ...
}
public void informUser(Exception e) {
 //Handle the error caused...
}

Problemet med detta är att det är bara minimal skillnad från klassiska ”On Error Goto” syntaxen och kan potentiellt göra spaghetti av din kod. Dock har det här tillvägagångssättet den fördelen att båda metoderna blir mer lättlästa. Du skulle också kunna återanvända metoder för felhantering så att du slipper repetera felhanteringen. Samma sak kan iofs uppnås med try-catch men med någon slags ”declare” sats så kan du skriva allt på en rad och det upptar inte nämnvärd utrymme i din metod.

Men hur skall koden se ut då??!! Ja du… om jag hade svar på den frågan så vore jag glad och kanske skulle kunna tjäna en slant. Så tills vidare får jag leva med den näst bästa lösningen och det är att använda try-catch-satser.

Så problemet kvarstår. Detta får mig att fundera vidare på vad vi egentligen använder Exceptions till.

Hur använder vi Exceptions?

Det finns ju i princip två typer av undantag/exceptions: Rena run-time fel såsom I/O error osv. dvs sådana fel som vi som programmerare inte har kontroll över. I normala fall skall detta inte inträffa, men möjligheten finns. Alltså måste detta hanteras på något sätt.

Den andra typen av undantag/exception som finns är när vi använder Exceptions istället för den gamla C-varianten som RETURKOD! Vi låter anropande metod veta att vi misslyckades genom att sända tillbaka ett Exception. Detta anser jag vara förkastligt! Skillnaden mellan returkod och exception är i dessa fall endast semantisk och bidrar inte till att koden blir bättre. Semantisk? Ja, koden blir i princip densamma: Anropande kod måste fortfarande analysera om metoden lyckades eller ej: Med returkod så sker analysen omedelbart:
If returnValue==0 Then...
Med felhantering så sker den indirekt:

try {
 callThisMethod();
catch (Exception e) {
 //Didn't succeeded with call to callThisMethod();
}

Det andra problemet med denna typ av felhantering är att det blir mycket mer komplicerat om vi i try-satsen skulle anropa 3-4 olika funktioner. Hur vet vi då i catch-sektionen exakt vilken metod som fallerade? Detta sätt att felhantera känns fel. Rakt upp och ner fel på alla sätt och vis.

Det borde gå att konstruera din kod så att du inte anropar en metod innan du vet att den kommer att lyckas. Undantag blir då endast Runtime-errors såsom I/O problem mm som inte kan förutses och som ligger utanför din applikations kontroll.

Ta t.ex. ett exempel om vi har en metod som gör resize på en JPG-bild, men som av någon anledning inte hanterar något annat bildformat. Då är det vanligt att man i metoden skriver en if-sats som evaluerar vad det är för bildformat på bilden och sedan genererar en Exception om det inte är en JPG. Exempelvis:


public void resizeJPG(String filePath) {
 if (getFilepathExtension(filePath).equalsIgnoreCase(".jpg")) {
  //Process image
 } else {
  Throw new IllegalFiletypeException("Unsupported filetype!");
 }
}

Borde man inte göra tvärtom? Se till att man inte anropar funktionen om bilden inte är en JPG? Då blir resizeJPG() metoden renare och mer lättläst. Visst; du flyttar if-satsen uppåt i kedjan, men med rätt design bör inte det bli problem. En sådan sak borde kanske till och med avhjälpas med att tillämpa Factory Design Pattern och lägga hela evalueringen i Factory-klassen. Tydligare än så kan det inte bli.

Kvar att hantera i resizeJPG() metoden blir att hantera I/O-fel och fel som genereras från grafik-biblioteken. Dessa typer av fel kommer man ”tvingas” att hantera på samma sätt som tidigare, dvs i resizeJPG() metoden och skicka uppåt med en ny Throw för att meddela anropande funktion att det blev ett fel som inte gick att hantera. Fördelen är att try-catch satsen i anropande metoden blir lite mindre komplex:


public void resizeAll(...) {
 try {
  resizeJPG(...);
 } catch(ImageCreationException e) {
  //Process error; possibly show error to user... and/or create a log entry
 }
}
public void resizeJPG(...) {
 try {
  //Process image
 } catch(IOException e) {
  Throw new ImageCreationException("Unable to create image...",e);
 } catch(Exception e) {
  Throw new ImageCreationException("Unable to create image...",e);
 }
}

Eftersom vi använder Factory Design Pattern så kommer funktionen ”resizeJPG()” bara att utföras när Factory har skapat en klass som innehåller den här metoden när käll-filen är av typen JPG. Om filen inte är en JPG så kommer en annan klass att skapas som rapporterar ett fel till användaren att han bara får använda JPG-filer… resizeJPG() kommer då aldrig att anropas/användas.

Varför kodar inte folk på det här sättet? Kanske för att de inte ser skillnad på Exception och Exception. De betraktar alla exceptions som runtime och man använder svångrem och hängslen: ”Måste säkerställa att det inte blir fel i den här metoden, så vad kan gå fel… bäst att koda in alla tänkbara scenarior…” istället för att jobba sig uppåt i abstraktionen.

En tanke slog mig…

En liten tanke dök upp: Vad skulle hända om man kunde definiera flera fel på samma catch-rad:

...
} catch(IOException, NullPointerException, Exception e) {
...
}

Då skulle det bli mindre kod då vi på flera typer av fel skulle utföra samma kod. Lättare att läsa, mindre kod och framförallt mindre duplicerad kod. Duplicering är en av alla de saker som orsakar buggar i programkod. Frågan är bara om detta skulle få några andra konsekvenser än vad jag kan förutse just nu.

Oj… det blev ett långt inlägg men jag tycker hela konceptet med felhantering är stort och komplext. Dock är det av stor vikt att man gör det rätt. Vad är rätt? Jag vet inte, jag provar mig fram fortfarande.

Är det någon som har någon bra bok/artikel/tips på det här med felhantering så mottar jag det med tacksamhet!


Kommande ändring i Diablo 3; Trail of Cinders

2012-09-09

Jag blir så less… varför är 9 av 10 ändringar som Blizzard gör med Diablo 3 en försämring för mig som spelare? När det äntligen blev en förbättring så skall det omedelbart bli en försämring för att ”det var alldeles för bra”. Hmpf.

Vad består ändringen av?

Jo, efter patch 1.0.4 så gör Diablo Wiki IconTrail of Cinders 1500% weapon damage över 3 sekunder. Äntligen fick vi som spelar Demon Hunters en spell som känns riktigt bra. Innan patch 1.0.4 så gjorde den 300%(?) över 3 sekunder. Det innebar i praktiken ingen skada för fiender på Inferno då de rör sig så snabbt och dödar dig på ett skott. Därför var det ett riktigt lyft att den blev 5 gånger så stor. Man motiverade också ändringen med att just Trail of Cinders var en runa som var väldigt lite använd, så man ville buffa den lite så att den blev mer attraktiv.

Nu skall man i nästa patch (1.0.5?) ta ner den tillbaka till 300%. Eh? Vad hände? Skall man nu göra den värdelös igen? Varför?

Varför?

Jo, det visade sig att det var ”en miss” från Blizzards sida. Det var inte meningen att den skulle bli så bra.(!) Man vill inte heller att dicipline baserade skills skall kunna används för attack, utan de skall endast vara försvars-baserade.

BS!

Dessa förklaringar HALTAR, minst sagt.

Att ett företag som håller på med programutveckling och har funnits så länge MISSAR en sådan stor detalj finner jag totalt otänkbart. Det finns SÅ många personer i hela utvecklingskedjan så att en sådan stor detalj skulle gått igenom hela kvalitetsprocessen går inte. Punkt.

Med tanke på att det då var medveten höjning till 1500% – varför sänker de den igen? Jag kan bara tolka det som att de har tittat på användnings-statistiken och sett att plötsligt har ALLA den. Och det går inte för sig.(?) Därför måste de sänka värdet igen.

Detta föranleder att resonemanget med att de inte vill att disciplin-baserade skills skall användas som attack är ett svepskäl. Du har aldrig kunnat använda Trail of Cinders som attack. Gör du det på inferno så är du död, och med reparationskostnaderna så vill man inte det.

Det var en person på D3s officiella forum som då nämnde att, ”ja, men då hamnar ju Trail of Cinders i samma kategori som Teleport, Spirit walk och Leap. Det är ju bra!”

Till det har jag att säga: Nej, jämförelsen haltar även där. Demon Hunters är den enda klassen som har sin ”mana” uppdelad på två olika typer av ”mana”: Hatred och Discipline. Wizard har bara en: Arcane. Which Doctor har bara en: ”Mana”. Barbarian har bara en: ”Fury”. Munken har bara ”Spirit”. Så när en Wizard använder en spell – oavsett om den är attack-baserad eller försvarsbaserad – så används ”Arcane”. Demon Hunter har sin uppdelad. Eftersom Hatred återgeneras snabbt och kan återgeneras snabbare genom att använda Hatred genererande attack-spells så anser jag det naturligt att spells som kostar hatred inte gör så stor skada, men kan kastas utan cooldown (vilket faktiskt inte är fallet – vissa spells har ÄNDÅ cooldowns!). Eftersom Discipline generas långsamt och inte kan påskyndas på något sätt så blir hushållningen med denna mycket viktigare, men i gengäld så skall dessa spells vara mycket kraftfulla. Därför har jag inga problem med att du har attack-spells som går på Discipline. Dessa spells kommer du ändå inte att slösa med då du inte har hur mycket Discipline som helst och den återgenereras väldigt långsamt.

För övrigt är detta också en anledning till att jag har svårt att begripa begreppet med att använda ”Cooldowns” på spells. Men det är ett annat kapitel…

Tittar vi sedan på Diablo Wiki IconSpirit Walk och Teleport som används som jämförelse så blir det ännu mer oförklarligt varför man sätter 300% på Trail of Cinders.

Spirit Walk med Diablo Wiki IconSeverance gör 225% weapon damage för 2 sekunder. Total skada 450%.
Teleport med Diablo Wiki IconCalamity gör 265% wepon damage 1 gång.
Om Trail of Cinder skall ligga i samma storleksordning som dessa så skall man sätta Trail of Cinders till 675% över 3 sekunder; 675% delat med 3 = 225%. Därför kan jag acceptera att man sänker från 1500% till runt 700%. Men 300%??? Det är bara löjligt.

Sedan kommer det där med att Leap, Spirit Walk och Teleport ignorerar en Waller’s vägg. Det gör inte Vault. Det gör att man också behöver någonting extra på ToC som kompensation, om man nu inte också ändrar Vault att även den ignorera walls.

Men Leap, Spirit Walk och Teleport har ju ”cooldowns”, medans du kan göra vault 5-6 gånger i snabb följd! Det är väl orättvist?

Eh, nej. Eftersom Vault är en Discipline spell och vi har redan etablerat faktum att Discipline är LÅNGSAM att regenerera så vill man inte slösa med den resursen, för om en Demon Hunter får slut på Discipline så är det game over. Då dör man på inferno. Så är det bara. Därför kan man kosta på sig att göra vault en eller två gånger. Absolut inte mer. Du behöver sedan discipline till andra spells, som t.ex. Shadow Power eller Smoke Screen, eller Caltrops.

En Wizard kan göra Teleport, kasta alla möjliga spells under de 16 sekunder som är hans cooldown, och ändå inte få slut på sin resurs (”Arcane”). Därefter teleportera igen. Eller så kan han använda en annan spell som även den ignorerar väggar: Diablo Wiki IconArchon. Hur orättvist är inte det! Wizard har TVÅ spells som ignorerar väggar, medan Demon Hunter inte har någon!

Även misstag kan vara av godo

Ok. Låt säga att det var ett misstag och det blev för högt värde. Vad gör det? 1500% över 3 sekunder är ingen faktor som förstör spelet genom att göra den oövervinnerlig. Tvärtom gör detta misstag att spelet blev roligare. Kör vidare med det! Tänk på alla andra misstag i historien som har blivit lyckade; pencillinet t.ex. Tänk om de hade kastat sitt misstag i papperskorgen… Nä, låt spelet bli roligt och allting måste inte vara balanserat och kategoriserat korrekt. Det kan faktiskt vara roligt om det inte är det.


Svenska Pokerförbundets extra stämma

2012-09-07

På söndag så håller Svenska Pokerförbundet en extra stämma (i enlighet med vad som beslutades på årsmötet). Du som är medlem är välkommen dit att delta. Är du inte medlem så kan du gå in på Svenska Pokerförundets hemsida och anmäla dig där.

Tid och plats: 9 september klockan 13:00 på Hotell Anglais i Stockholm

Alla som vill att pokersverige skall växa och frodas och jobba för ett bättre pokersverige uppmanas att gå med i förbundet och påverka!

Logo SvePof


Vad är en klass?

2012-09-07

Vad är egentligen en klass när vi pratar om programmering – vare sig det är Java, .Net, eller php…? Jag har under 20 års tid använt klasser till höger och vänster, men egentligen aldrig funderat på vad en klass EGENTLIGEN är. Googlar man frågan så finner man tusentals artiklar som handlar om HUR man använder klasser och vilka delar som utgör en klass, men ingenstans har jag funnit svaret på den mer övergripande (något abstrakta) frågeställningen: vad är egentligen en klass?

Därför tog jag ett steg tillbaka och funderade själv; när använder man klasser och varför? Programmerar du Java så kan du inte undvika att använda klasser – du kan inte ens starta ett Java-projekt utan ha en klass med en main() funktion i den. Jo, jag använder klasser för att samla ihop funktioner som hjälper mig att hantera en enskild uppgift. Visst kan en klass i princip utföra flera uppgifter, men läser man ”Clean Code – A Handbook of Agile Software Craftsmanship” av Robert C. Martin så skall ju varje klass endast utföra en endaste sak och göra det transparent (dvs det skall inte råda några tveksamheter om vad klassen gör).

Räcker det med att säga att en klass är samlad kod som innehåller en eller flera metoder som skickar data mellan sig med hjälp av lokala fält? Nej, jag tycker inte det. En klass är ju inte bara en samling funktioner – hela den här samlingen av fält och metoder representerar ju någonting annat. De representerar ju ett objekt, eller? Egentligen inte! Går vi vidare i abstraktionen av fält, metoder, klasser och objekt så landar jag i den här formuleringen:

En klass är en abstraktion av ett objekts strukturella uppbyggnad samt definition av hur den skall konstrueras.

Vad betyder då det här? Jo, att en klass är den abstrakta representationen av ett objekt. Det är först när du har instansierat en klass som det faktiskt blir ett objekt som du processar. Den abstrakta representationen definierar också hur du skall konstruera objektet och vilka externa beroenden som klassen har.

Det här betyder att klassen och objektet är två separata entiteter. Klassen är en mall, en slags ritning över hur objektet faktiskt skall se ut och fungera. Objektet lever sedan sitt liv inne i klassen och styrs av dess regelverk. Klassen definierar hur objektet får användas och vad objektet får göra. Klassen definierar vilka beroenden objektet har att rätta sig efter.

Än sen då?

Hur hjälper det här mig när jag programmerar? Behöver man verkligen förstå att klassen är abstraktion av ett objekt? Det kan det göra – det beror på hur du programmerar och angriper en uppgift. Det är väldigt lätt hänt att man börjar programmera och skriver en klass som gör det, och så bygger man ut den när man upptäcker att det behövs göras mer saker med objektet. Då blir koden väldigt snabbt dålig och svårhanterlig.

Om du då istället tänker på att klassen är en abstraktion så ”tvingar” denna insikt dig att först göra en abstraktion av objektet innan du faktiskt kodar din första rad. Detta kan spara dig mycket problem längre fram…

Vad är Din syn på saken?

Hur långt ifrån sanningen är jag, enligt dig? Skriv en kommentar och ge mig Din syn på saken.


Välkommen!

2012-09-06

Man skulle kunna säga ”Hello World!” här men jag låter bli…

Jag har tidigare startat bloggar men har efter en tid tappat lusten och låtit det hela rinna ut i sanden. Nå, hursomhelst tänkte jag nu göra ett lite annorlunda försök. Den här gången skall jag bara publicera texter när jag känner för det och bara när jag faktiskt har något att tillägga.

Vad kommer jag skriva om? Ja, det blir främst inom 3 intresseområden;

  • Systemutveckling/Programmering
  • Poker
  • Diablo 3

Varför dessa områden? Jo, jag älskar att programmera och jobbar som systemutvecklare. Jag har extremt bred kompetens då jag har kunskap inom flertalet olika programmeringsspråk och verktyg, t.ex. Visual Basic (4 / 5 och 6), C++, LotusScript, Java, HTML, CSS, JavaScript, PHP – bara för att nämna några. Jag kommer därför att använda den här bloggen för att fördjupa mig inom framförallt Java som jag känner är det som erbjuder mig det jag eftersöker just nu.

Poker: Jag är extremt intresserad hobbyspelare. Kanske inte så speciellt duktig. Min bankrulle står still – jag spelar ihop nästan exakt lika mycket som jag förlorar, vilket känns stundom lite frustrerande, men å andra sidan så är min hobby ”gratis”!

Diablo 3 är mitt PC-spel jag spelar mest just nu när jag inte spelar poker. Underbar känsla att spela ett hack-n-slash-spel där man slipper att tänka, och kan bara spela för att se blodet stänka och samla ihop guld o andra värdesaker… Spelet är inte svårt – bara underhållande! Precis som jag vill ha det.

Väl mött!