2009-12-08

Läsbara metodanrop

Ibland kan koden bli lite mer läsbar som man skippar återupprepningar. Det vill säga i stället för att skriva


repository.GetProductByNumber(number)

kan man skriva

repository.GetProductBy(number)

eller

grid.LoadResourceForUser(user)

blir

grid.LoadResourceFor(user)

Eller vad säger ni?

2009-11-29

Valmöjligheter är inte komplexitet

På senare tid har det varit mycket diskussion om ”Is software development too complex?”. Vissa menar att mjukvaruutveckling är för komplext i och med att det finns så många olika tekniker, ramverk, leverantörer med mera att välja mellan.

Min syn är dock att valmöjligheter inte relaterar till komplexitet. Att ha många olika val ger oss bättre chans till att få mjukvaruutveckling till att bli mindre komplex snarare än tvärtom. Att ha flera val ger oss möjligheten till att skapa en bättre process där vi hittar val som är nischade till att lösa just våra problem. Genom att vi kan plocka ihop en verktygslåda med enbart de verktyg som passar oss kan vi skapa mindre komplexa lösningar samtidig som att vår process kan bli mindre komplex. Hade vi inte haft många val så hade vi varit tvungna att välja verktyg som egentligen inte passar oss och därmed behövt skapa en mer komplex process. Till exempel om man måste välja ett ramverk som egentligen inte passar kommer man behöva skriva en massa onödig kod för att få det att fungera som man vill och därigenom introduceras onödig komplexitet.

Att vi börjar få många val i .Net-världen är något som vi skall njuta av – inte arbeta emot eller gnälla över. Om man tycker det är jobbigt att behöva tänka själv över vilka val man skall göra – ja, då är nog inte utvecklingsbranschen något för en.

2009-11-23

Podcast

För några dagar sedan fick jag frågan om jag hade några tips på bra podcast, antigen bra serier eller bara enstaka avsnitt.

Nedan är några podcast-serier som jag följer samt några avsnitt som jag tycker har varit extra intressanta. Det är ganska ojämn kvalité på avsnitten, vissa är bra medan andra inte är så bra.

ALT.NET (ej aktiv), http://feeds.feedburner.com/altnetpodcast
"18: Talking with Jeremy Miller about Alt.Net"
"15: Domain Driven Design"

Elegant Code, http://feeds.feedburner.com/elegantcodecast
"Code Cast 30 – Story Teller with Jeremy Miller"

Software Engineering Radio, http://se-radio.net/rss
"Episode 139: Fearless Change with Linda Rising"
"Episode 138: Learning as a Part of Development with Allan Kelly"

Hansel Minutes, http://feeds.feedburner.com/HanselminutesCompleteMP3
"The History and Future of Web Standards with Molly Holzschlag"
"SOLID Principles with Uncle Bob"

Hearding Code, http://herdingcode.com/?feed=rss2
"Herding Code 58: Presentation Patterns with Jeremy Miller, Ward Bell, Rob Eisenberg and Glenn Block (Part 1) "
"Herding Code 58: Presentation Patterns with Jeremy Miller, Ward Bell, Rob Eisenberg and Glenn Block (Part 2)"

.NET Rocks!, http://feeds.feedburner.com/dotnetrocks_AAC

Polymorphiv Podcast, http://polymorphicpodcast.com/podcast/feed/

Ruby on Rails Podcast, http://feeds.feedburner.com/rubyonrailspodcast

Har du tips på någon bra?

2009-11-09

Testa genom arv

Om man befinner sig i situationen att man behöver skriva test för protected metoder så är det oftast något annat som är det egentliga problemet. Kanske behöver man bryta ut något koncept till en ny klass eller bara tänka om i hur man har designat/kodat. Det finns dock scenarion där det finns en nytta med att kunna testa genom arv, därav är det viktigt att kunna detta som ett verktyg i sin TDD-låda.

Att testa kod via arv är enkelt, det enda man behöver göra är att ärva från den klassen man vill testa och sedan göra en publik metod i sin ärvda klass som publicerar den dolda metoden. Exempel:

I koden nedan jagar vi en bugg som vi tror finns i metoden IsValidH2O och vi skulle således behöva se i vårt specifikation (test) om den returnerar sant eller falskt. Vi ärver från klassen och skriver en metod (IsValidH2O_ForSpec) som publicerar IsValidH2O. Det är denna metod vi testar emot.


public class TheHolyGrailSpecs_When_the_h2o_is_holy
{
private TheHolyGrail_ForSpec theHolyGrail;

[SetUp]
public void Context()
{
IH20 h2oStub = new H20Stub();
theHolyGrail = new TheHolyGrail_ForSpec(h2oStub);
}

[Test]
public void It_should_be_classified_as_valid_h2o()
{
Assert.That(theHolyGrail.IsValidH2O_ForSpec(), Is.True);
}
}

public class TheHolyGrail : IGrail
{
private readonly IH20 h2o;

public TheHolyGrail(IH20 h2o)
{
this.h2o = h2o;
}

protected bool IsValidH2O()
{
// Code
return true;
}
}

public class TheHolyGrail_ForSpec : TheHolyGrail
{
public TheHolyGrail_ForSpec(IH20 h2o) : base(h2o)
{
}

public bool IsValidH2O_ForSpec()
{
return base.IsValidH2O();
}
}


Enkelt men kraftfullt. Dock är detta inget sätt man skall använda ofta eftersom testen blir sköra och fula. Men ibland finns det tillfällen då de kan hjälpa en.

2009-10-29

JavaZone 2009

Av en slump snubblade jag över en radda med inspelningar från JavaZone 2009 (sept 9-10). Jag blev förvånad över hur många sessioner som verkade intressanta. Eller vad sägs om följande:

  • The Productive Programmer: Mechanics - Neal Ford
  • The Uncertainty Principle - Kevlin Henney
  • Code Smells and Refactoring Revisited: Advances from the software engineering research community - Aiko Fallas Yamashita
  • Lizard Brain Web Design - Scott Davis
  • One web, CSS3, and HTML5 - Håkon Wium Lie
  • DDD panel - Kevlin Henney, Eric Evans, Einar Landre, Scott Davis, Phil Wills, Greg Young, Randy Stafford
  • Strategic Design & Responsibility Traps - Eric Evans
  • Patterns for persisting large and rich domain models - Randy Stafford
Se dem och andra inspelningar på http://tcs.java.no/tcs/

2009-10-25

AssertWasCalled och Assert.Throws

Ett tips när man skriver specifikationer (test) med Rhino Mock och NUnit är att använda AssertWasCalled och Assert.Throws istället för andra mindre tydliga sätt.

AssertWasCalled
För att specificera att en viss metod skall anropas kan man använda AssertWasCalled med tillhörande MethodOptions:


ITheDependency theDependency = MockRepository.GenerateMock<ITheDependency>();
ITheClass theClass = new TheClass(theDependency);

theClass.MethodX();

theDependency.AssertWasCalled(x => x.MethodZ(null),
callOptions => {
callOptions.Repeat.Once();
callOptions.IgnoreArguments();
});


Assert.Throws
För att specificera att ett visst beteende skall kasta ett fel, kan man använda Assert.Throws istället för ExpectedException / try.../catch:

ITheDependency theDependency = MockRepository.GenerateMock<ITheDependency>();
ITheClass theClass = new TheClass(theDependency);

Assert.Throws<ArgumentNullException>(() => theClass.MethodY(null));


Testklasser:

public interface ITheDependency
{
void MethodZ(string value);
}

public interface ITheClass
{
void MethodX();
void MethodY(string value);
}

public class TheClass : ITheClass
{
private readonly ITheDependency _theDependency;

public TheClass(ITheDependency theDependency)
{
_theDependency = theDependency;
}

public void MethodX()
{
// Do Stuff
_theDependency.MethodZ("value");
}

public void MethodY(string value)
{
if (value == null)
{
throw new ArgumentNullException();
}
// Do Stuff
}
}
Läs mer på: http://nunit.com/index.php?p=assertThrows&r=2.5 och http://www.ayende.com/wiki/Rhino+Mocks+3.5.ashx

2009-10-18

Minimera storleken på dina JavaScript med Microsoft Ajax Minifier och MSBuild

I samband med att Microsoft Ajax Library (Preview 6) annonserades i början av veckan så annonserades även ett nytt verktyg för webbutvecklare, Microsoft Ajax Minifier. Med Microsoft Ajax Minifier kan man minska storleken på de JavaScript-filer som läggs i produktion. Genom att ta bort mellanslag, kommentarer, radbryt, döpa om lokala variabler så kan storleken minska drastiskt.

Enligt en jämförelse som Scott Guthrie har gjort så minimeras filerna rejält med Minifier:


(Referens)

Verktyget för detta finns i tre olika utföranden:

ajaxmin.exe - för kommandoprompten
ajaxmintask.dll – en task för MSBuild skript
ajaxmin.dll – en dll som kan användas från kod

I exemplet nedan kommer jag att använda MSBuild för att minimera de skript som finns på en webbplats.

1. Börja med att installera Microsoft Ajax Minifier
2. Skapa ett MSBuild skript (ex "jsMinifier.msbuild") med följande xml:


<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Run">

<UsingTask TaskName="AjaxMin" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\MicrosoftAjax\AjaxMinTask.dll" />

<PropertyGroup>
<SearchPath>$(MSBuildStartupDirectory)\**\*</SearchPath>
<SearchInclude>.js</SearchInclude>
<SearchExclude>.min.js</SearchExclude>
</PropertyGroup>

<Target Name="Run">

<CreateItem Include="$(SearchPath)$(SearchInclude)" Exclude="$(SearchPath)$(SearchExclude)">
<Output TaskParameter="Include" ItemName="JavaScriptFiles"/>
</CreateItem>

<AjaxMin
SourceFiles="@(JavaScriptFiles)"
SourceExtensionPattern="\$(SearchInclude)$"
TargetExtension="$(SearchExclude)"/>

<AjaxMin SourceFiles="@(JavaScriptFiles)"
SourceExtensionPattern="\$(SearchInclude)$"
TargetExtension=".hard$(SearchExclude)"
CollapseToLiteral="True"
LocalRenaming="CrunchAll"
OutputMode="SingleLine"
RemoveUnneededCode="True"
StripDebugStatements="True"
EvalsAreSafe="True"
InlineSafeSettings="True"
CombineDuplicateLiterals="True"
CatchAsLocal="True"/>
</Target>

</Project>


Den plats som skriptet körs ifrån kommer agera som root för sökningen efter *.js-filer. Det vill säga om skriptet ligger i ...\WebSite\ så kommer alla undermappar till "WebSite" att sökas igenom.

Skriptet kör AjaxMin på två olika sätt, ett normalläge (nedan märkt med "min") och ett så kallat "Hypercrunching"-läge (nedan märkt med "hard"). När alla attribut är påslagna kommer skripten att minimeras mycket.

Exempel:


MSBuild-skriptet kan initieras från olika håll; Visual Studio, byggserver, bat-fil med mera. För att köra den från en bat-fil är det bara att skriva "%WinDir%\Microsoft.NET\Framework\v3.5\MSBuild.exe jsMinifier.msbuild".

Mer om vad de olika egenskaperna gör och hur man kan använda detta från Visual Studio går att läsa i dokumentationen som följer med i installationen.

Läs mer på: http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=34488

2009-10-05

Namnge dina koncept

Ett bra sätt för att göra din kod enklare att läsa är att namnge de koncept du har. Det kan till exempel vara att namnge de villkor du har i if-statser. Villkoret som är skrivet i if-satsen beskriver något större än bara ett bool-värde, det är någon form av logisk förklaring på vad som skall hända.

Exempel:


if(ProductRows != null && ProductRows.Count != 0)
{
// Do Stuff
}

Koden ovan kan enkelt skrivas om så att det blir lättare att förstå vad man är ute efter. Om man bryter ut villkoret till en metod kan man istället skriva:

if (HasProductRows())
{
// Do Stuff
}

Ett annat exempel är:

if (IsValid && StatusCode = 771 && ... )
{
// Do Stuff
}


Kan bli:

if (IsValidForDispatch())
{
// Do Stuff
}

Koden kan på detta sätt bli lättare att ta till sig.

2009-10-01

Dela din kod enkelt

Med pastie kan du enkelt dela kodsnuttar med andra:



Istället för att klistra in koden i msn/mail/etc så kan man enklet klistra in på sidan och sedan dela med sig av url:en.

2009-09-23

En resa med value objects

Value Objects är objekt som bär ett värde men har inget koncept för identitet (läs mer om dem här och här). Detta betyder att vi skapar en specifik klass för ett specifikt värde och således får värdet vara det som är viktigt för objektet, inte någon specifik identifierare . Eftersom vi kapslar in värden i objekt så blir de immutable, det vill säga att när de väl är skapade så går de inte att ändra på. En stor fördel genom att skapa dessa är att vi isolerar funktionalitet till det ställe där den hör hemma istället för att sprida det över andra klasser.


Exemplet nedan är en Person-klass med Mail som sträng. Eftersom att mail är en sträng måste vi lägga in valideringen för denna i Person-klassen (vi skall inte använda extension methods). Detta gör att vi belastar Person-klassen med ansvar den inte vill ha.

public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Mail { get; set; }
public int Age { get; set; }

public bool IsMailValid()
{
Regex regex = new Regex(@"[a-zA-Z0-9_\-\.]+@[a-zA-Z0-9_\-\.]+\.[a-zA-Z]{2,5}");
return regex.IsMatch(Mail);
}
}
Specifikationen för koden ovan

[TestFixture]
public class PersonSpecs_When_a_person_has_a_correct_mail_address
{
private Person _person;

[TestFixtureSetUp]
public void Context()
{
_person = new Person()
{
FirstName = "John",
LastName = "Doe",
Age = 20,
Mail = "john.doe@mail.net"
};
}

[Test]
public void It_should_pass_the_mail_address_validation()
{
Assert.That(_person.IsMailValid(), Is.True);
}
}
Detta är inte så bra. Om vi istället låter Mail vara ett objekt (såsom FirstName, LastName och Age) så kan vi flytta ut valideringsansvaret till Mail-klassen:

public class Person
{
public FirstName FirstName { get; set; }
public LastName LastName { get; set; }
public Mail Mail { get; set; }
public Age Age { get; set; }
}

I mail-klassen lägger vi även till kod för operationerna == och != samt GetHashCode, ToString och Equals.

public class Mail : ICanBeValidated
{
private readonly string _mail;

public Mail(string mail)
{
_mail = mail;
}

public bool IsValid()
{
Regex regex = new Regex(@"[a-zA-Z0-9_\-\.]+@[a-zA-Z0-9_\-\.]+\.[a-zA-Z]{2,5}");
return regex.IsMatch(_mail);
}

public override string ToString()
{
return _mail;
}

public static bool operator ==(Mail left, Mail right)
{
if (Object.ReferenceEquals(left, right)) return true;

if ((object)left == null || (object)right == null) return false;

return left.GetHashCode() == right.GetHashCode();
}

public static bool operator !=(Mail left, Mail right)
{
return !(left == right);
}

public override int GetHashCode()
{
return _mail.GetHashCode();
}

public override bool Equals(object obj)
{
if (obj == null) return false;

if (obj.GetType() == this.GetType()) return obj.GetHashCode() == this.GetHashCode();

return false;
}
}

Den gamla specifikationen blir då:

[TestFixture]
public class PersonSpecs_When_a_person_has_a_correct_mail_address
{
private Person _person;

[TestFixtureSetUp]
public void Context()
{
_person = new Person()
{
FirstName = new FirstName("John"),
LastName = new LastName("Doe"),
Age = new Age(20),
Mail = new Mail("john.doe@mail.net")
};
}

[Test]
public void It_should_pass_the_mail_address_validation()
{
Assert.That(_person.Mail.IsValid(), Is.True);
}
}

Men vänta nu, vi kan ju göra specifikationen mycket enklare. Eftersom att vi har brutit ut mail så kan vi specificera valideringsmetoden utan att behöva ett person-objekt (vi kan använda vårt fina interface):

[TestFixture]
public class MailSpecs_When_having_a_correct_mail_address
{
private ICanBeValidated _mail;

[TestFixtureSetUp]
public void Context()
{
_mail = new Mail("john.doe@mail.net");
}

[Test]
public void It_should_pass_the_mail_address_validation()
{
Assert.That(_mail.IsValid(), Is.True);
}
}

Vi kan jämföra två olika Mail-objekt för att se om de är samma:

[TestFixture]
public class MailSpecs_When_having_two_mail_with_same_address
{
private Mail _mail1;
private Mail _mail2;

[TestFixtureSetUp]
public void Context()
{
_mail1 = new Mail("john.doe@mail.net");
_mail2 = new Mail("john.doe@mail.net");
}

[Test]
public void They_should_be_marked_as_equal_when_comparing_them()
{
Assert.That(_mail1 == _mail2);
}
}
Läs mer om value objects här eller här.