Implementing all day

This is my personal coding blog

Sjov med Emoji

Mit team blev netop gjort opmærksom på en fejl på en af vore portaler. Brugerne postede kommentarer, men nogle af beskederne var fyldte med spørgsmålstegn (?). Vi kunne ret hurtigt slå fast, at det selvfølgelig var brugere, der postede beskeder med emoji’s fra deres mobiltelefoner.

Hvorfor 0x3F?

Vi kunne se i databasen, at beskederne var gemt med ?? (0x3F 0x3F) i stedet for emoji-symbolet (som jo er en unicode karakter). Hvorfor? Det skulle jo virke ud af boxen! Jeg ressearchede lidt i unicode (se link til Jon Skeets fine artikel), og fandt ud af at unicode symbolerne både kan være 2 og 4-byte lange. Der er tale om et surrogat-par. Man afgør om der er tale om et surrogat-par, ved at teste om første 2 byte ligger i intervallet 0xD800 – 0xDBFF (HighSurrogate) og at næste 2 byte samtidig ligger i intervallet 0xDC00 – 0xDFFF (LowSurrogate). Det lader altså til at databasen bare har gemt disse surrogat-par som ‘??’, og ellers bare har ladt som ingenting. Hvilket kan påvises med følgende SQL:


For at vores system kan understøtte emoticons, er vi altså nød til at ændre felttypen i vores database-kolonne til nvarchar. Ellers bliver vores emoji’s bare afkortet, og der er ingen vej til at genfinde symbolerne i databasen, da de blot er erstattet med ‘??’. Vær i øvrigt også opmærksom på variabeltyper i stored procedures - de skal selvfølgelig også være n-type, for ikke at ødelægge encodingen. Det faktum kostede en kollega en hel eftermiddag med bug hunt.

Men hvordan får vi smukke emojier?

Man kan selvfølgelig sætte sig ned, og begynde fra en ende af, og tegne gif’er, og lave replace i data, så beskederne renderes med sirlige symboler, men der stopper min tålmodighed. Heldigvis er der opensource alternativer. Der er mange, men vi valgte EmojiOne. Gratis at bruge (også kommercielt), og med grafikfiler på CDN hos jsDelivr.net – nice. EmojiOne stiller et javascript objekt til rådighed, så man kan parse sin unicode klientside, og lave flot html. Vi kunne bare godt tænke os at ha lidt styr på parsningen, og gøre det serverside i c#. Det skulle jo være en ret enkel opgave, der kan listes sådan:

  1. Loop igennem karakterer
  2. Undersøg om karakter surrogatpar, og om det er emoji
  3. Udskift karakter med Html

Vores loop er nødt til at være for-next løkke, da vi skal teste for par, og dermed skal have mulighed for at indexserer til næste karakter. Så vores check, går så ud på at teste for høj-surrogatværdi, og efterfølgende verificerer om næste karakter er lav-surrogat, og i bekræftende fald om paret er emoji. Char-typen, har to statiske metoder, der kan hjælpe os med disse tjek: Char.IsHighSurrogate(char) og Char.IsLowSurrogate(char).

Ved at analyserer EmojiOne’s javascript, har jeg fundet ud af at emoji’er har en høj-værdi på 0xD83D eller 0xD83C. Vores tjek for emoji, kan altså klares med en simpel værdisammenligning. Dette tjek, kan muligvis gøres mere smart, men ind til videre, antager vi at det er fint nok. Det er selvfølgelig vigtigt at ikkw-emoji unicode symboler udskrives som de er. Vi skulle jo helst undersøtte f.eks. kinesisk. Udformningen af Html-tag’en er nærmest triviel, og det eneste der er at bemærke, er hvordan vi serialicerer symbolværdien (codepoint). Vi udregner codepoint ved at sammenlægge høj og lav (0x0000 - 0x10FFFF), og formatterer det med X5, for at ramme EmojiOnes filnavn.

public static class EmojiHelper { static string IMAGE_TYPE = "svg"; static string IMAGE_PATH = string.Format("//cdn.jsdelivr.net/emojione/assets/{0}/", IMAGE_TYPE); public static string FromUnicode(string unicodestring) { var sb = new StringBuilder(); if (!string.IsNullOrWhiteSpace(unicodestring)) { for (var i = 0; i < unicodestring.Length; ) { int length = 1; if (char.IsHighSurrogate(unicodestring, i) && i + 1 < unicodestring.Length && Char.IsLowSurrogate(unicodestring, i + 1)) { // Vi har et 4-byte symbol length = 2; int high = unicodestring[i]; int low = unicodestring[i + 1]; int codepoint = 0x10000 + (high - 0xd800) * 0x400 + (low - 0xdc00); if (high == 0xd83d || high == 0xd83c) { // Vi har en emojii ;-) sb.AppendFormat(@"<img class=""emoji"" alt=""{2}{3}"" src=""{0}{4:X5}.{1}?v=1.2.4"" />", IMAGE_PATH, IMAGE_TYPE, (char)high, (char)low, codepoint); } else { // Vi har en mærkelig unicode-symbol som: 大家好 (Hello world :-) sb.Append(unicodestring[i]); // Høj sb.Append(unicodestring[i + 1]); // Lav } } else { // Kun 2-byte symbol sb.Append(unicodestring[i]); } i += length; } } return sb.ToString(); } }

Det var hvad der skulle til – nu har vi flotte emoji’er i vores kommentarer :-)

Code on…

Links

http://www.emojione.com/developers

http://csharpindepth.com/Articles/General/Unicode.aspx

Hent ikke jQuery 2 gange

“There can be only one..”

Jeg har vænnet mig til at bruge requireJS, som min afhængigheds- , og buildframework, når jeg fremstiller MarionetteJS applikationer. Jeg har vænnet mig til at definerer moduler, så de både kan indlæses med requireJS, og opfylde MarionetteJS modul-definitioner. Det virker perfekt, og jeg har egentlig ikke tænkt videre over,hvilke komplikationer dette setup, kan medfører i blandede scenarier. For nyligt skulle jeg implementerer en lille applikation, på en side i en større portal. Jeg fremstillede min main.js fil, og loadede applikationen og afhængigheder som jeg plejer. Jeg placerede script-elementet som det sidste i Html’en. Alt virkede som det skulle. Lige ind til en eksterne konsulent besluttede at forskønne Html’en med en jQuery-udviddelsesmodul (selectBoxIt http://www.selectboxit.com). Nu fik jeg pludselig problemer med at select-elementer, ikke kunne sættes til værdier via script, og ligeledes virkede det som om at disse, heller ikke længere rejste hændelser i DOM’en. I følge udvidelsesmodul-dokumentatinen, skulle SelectBoxIt godt nok skjule det oprindelige Html-element, men alle metoder og hændelser, skulle forsætte med at virke. Det så bare ikke ud til at være tilfældet på denne portalside. Efter længere tids efterforskning, og utallige stoppunkts undersøgelser, fand jeg frem til problemet. Det viste sig at requireJS indlæste jQuery, som allerede fandtes i det globale objekt (window). Det giver i sig selv ingen problemer, ud over at det er en kende ineffektivt at hente jQuery 2 gange. Problemet var at SelectBoxIt udviddelsesmodulet, blev fjernet fra det jQuery modul, som endte i globalen. Derfor blev UI afkoblet fra select-elementets hændelser og metoder. Jeg brugte ikke selv SelectBoxIt, så jeg ville ikke introducerer denne afhængighed til applikationen, og requireJS shim funktion virkede jo ej heller. Så slog det mig, og løsningen var yderst simpel og ligetil. Jeg fjernede jQuery i mit path-element i require.config kaldet, og så indføjede jeg et kald til define, for at deffinerer jQuery for requireJS, og dermed for min applikation.

define('jquery', [], function(){
	return window.jQuery;
});

 

Andet skal der ikke til. På denne måde har jeg sikret at jQuery kun hentes een gang, og min applikation, behøver ikke at være afhængig af SelectBoxIt, eller havd nu designere og andre kreative sjæle, nu finder på at introducerer til siden. Eneste problem, er at min app nu vil fejle, hvis jQuery skulle forsvinde fra siden. Sansynligt? Nej vel…
Code on…

Så hvad er der i C# 6? Egenskabsinitialicering og primærkonstruktør

1. oktober, blev det annonceret på https://roslyn.codeplex.com/discussions/568820 af MadsTorgesen, at primærkonstruktør og egenskabsinitialicering IKKE kommer med i næste release. Ærgeligt. Nedenstående er derfor ikke længere aktuelt.

Jeg har set lidt på, hvad der venter os i den kommende opdatering af c# - version 6.

Ind til nu, har egenskabsinitialicering foregået nogenlunde således:

public class Person
{
	public Person(string navn)
	{
		this.Navn = navn;
		this._id = Guid.NewGuid();
	}

	public string Navn { get; set; } 
	
	private Guid id;
	public Guid ID { get{ return id; } }
}

Man er nød til at have et backing-felt, for at kunne tildele readonly egenskaben id med en værdi.

I C# 6 kan man nu initialicerer egenskaben direkte hvor egenskaben erklæres i koden.

public class Person
{
	public string Navn { get; set; } = "Jesper"; 
	public Guid ID { get; } = Guid.NewGuid();
}

Læg mærke til at vi med denne syntaks, ligeledes kan udelade setteren, og reelt gøre egenskaben uforanderlig. For at opnå dette tidligere, måtte man, som sagt, ty til at implementerer backing-felt. Det vil gøre klasse-koden kortere, mere kompakt og samle definition og initialisering i koden.

Denne syntaks leder os så hurtigt videre, til det lidt større koncept – primær konstruktøren. En primær konstruktør, gør det muligt for os at definerer en konstruktør for en klasse, og tilgå parametrene i resten af klassekroppen:

public class Person(string navn, int alder)
{    
	public string Navn { get; } = navn;    
	public int Alder { get; } = alder;
} 

Det nye består i at man angiver parametre i parentes efter klasse-navnet. Alle andre konstruktører skal så kalde ind til primærkonstruktøren, via this() syntaksen. Kompileren vil rejse fejl, hvis man forsøger sig uden kald til primærkonstruktøren. Det sker for at garanterer at primærkonstruktør-parametrene er til rådighed i hele klassekroppen.

public class Person(string navn, int alder)
{
    public Person(string navn) 
		: this(navn, 0){}    
	
	public string Navn { get; } = navn;    
	public int Alder { get; } = alder;
} 

Igen må man sige vi får en yderst kompakt og funktions orienteret kode, men hvad så med validering af input til primær konstruktøren. Det gøres nemt ved at tilføje en separat kodeblok i klasse kroppen:

public class Person(string navn, int alder)
{    
	{
         if(navn == null) throw new Exception("Navn skal angives");    
	}    
	
	public string Navn { get; } = navn; 
}

Man kan med sidstnævnte primærkonstruktør blok, nok argumenterer for hvor meget mere simpel syntaksen bliver.
Alt I alt et sæt features, der gør arbejdet med til at skrive kode kortere. Om man synes om syntaksen, og mener at det bliver mere overskueligt, er vel op til den enkelte udviklers temperament. Jeg selv elsker jo korte, eksplicitte sætninger, så mon ikke jeg tager den til mig ret hurtigt.

Code on…