Rash thoughts about .NET, C#, F# and Dynamics NAV.


"Every solution will only lead to new problems."

Sunday, 19. December 2010


Compute Fib(n) in O(log n)

Filed under: F# — Steffen Forkmann at 17:07 Uhr

Today I learned a neat way to compute the n.th Fibonacci number in O(log n) time. The idea is that we can compute the Fibonacci Q-Matrix in O(log n) by using recursive powering:

Fibonacci Q-Matrix

And here is a simple implementation in F#:

let q1 = 1I,1I,1I,0I

let mult (a11,a12,a21,a22) (b11,b12,b21,b22) = 
    a11 * b11 + a12 * b21,
    a11 * b12 + a12 * b22,
    a21 * b11 + a22 * b21,
    a21 * b12 + a22 * b22

let sq x = mult x x

let rec pow x n =
    match n with
    | 1 -> x
    | z when z % 2 = 0 -> pow x (n/2) |> sq
    | _ -> pow x ((n-1)/2) |> sq |> mult x
         
let fib n =
    let _,x,_,_ = pow q1 n
    x

printfn "%A" (fib 49)
Tags: , ,

Monday, 6. December 2010


Sudoku solver in F#

Filed under: F#,Kata — Steffen Forkmann at 15:07 Uhr

On my flight to the US I had a small competition with my dad. He was solving a Sudoku and I tried to write a generic solver in the same time. I admit he was a little bit faster but anyway I put my code on github.

Tags: ,

Wednesday, 24. November 2010


Aufzeichnung meines Vortrages zu Higher-Order-Functions in C# verfügbar

Filed under: Informatik,Veranstaltungen,WebCasts — Steffen Forkmann at 15:12 Uhr

Letzte Woche habe ich im Rahmen der F# Gruppe der .NET Online User Group einen Vortrag zu “Higher-Order-Functions in C#” gehalten. Unter http://vimeo.com/17048170 ist die Aufzeichnung nun zu finden.

Funktionale Programmiersprachen nehmen seit geraumer Zeit einen hohen Stellenwert in der Wissenschaft ein. Mittlerweile ziehen viele der funktionalen Konzepte bereits in den Mainstream ein. Bei diesem Treffen wollen wir einen Einblick in funktionale Konzepte und deren Umsetzung in C# gewinnen. Insbesondere soll auf "Funktionen höherer Ordnung", "Pattern Matching", "Unveränderlichkeit" und parallele Programmierung eingegangen werden.

Vortragsabstract

Tags: ,

Wednesday, 10. November 2010


Dynamics NAV 2009 R2 Developer Day

Filed under: Dynamics NAV 2009,Veranstaltungen — Steffen Forkmann at 10:33 Uhr

Heute fand der “Dynamics NAV 2009 R2 Developer Day” statt. Bei diesem Event hat Microsoft mal wieder eine Konferenz in die Welt gestreamt. Da der Dynamics Bereich aber traditionell eher verschlossen ist, wurde der Stream nicht öffentlich gemacht, sondern nur in den jeweiligen Microsoft-Centern in 18 Ländern für eingeladene Partner gezeigt.

In diesem Blogpost verwalte ich meine eigenen Notizen zum Developer Day. Falls etwas zu knapp formuliert ist, kann gern über die Kommentare nachgefragt werden.

Als Release-Termin für Dynamics NAV 2009 R2 wurde der 15.12. angegeben.

What’s new in C/SIDE

Page Designer

  • Neuer Wizzard
  • Stärkerer Einsatz von Factboxes
  • “Strukturhighlighting” (= Gruppen werden fett dargestellt)

Go to Definition

  • Ctrl+F12 ==> Go to definition
  • Wenn die Definition nicht im selben Objekt ist, wird immer ein neues Designer-Fenster geöffnet, auch falls schon ein Fester des Objekts offen ist .
  • Momentan kein “Find References”

Multi-Developer Szenarien

  • Locking von Objekten
  • Öffnen von gelockten Objekten ist in Read-Only-Modus möglich
  • “Force unlock” ist für Superuser möglich
  • Meine Frage nach “Lock auch aus C/AL-Code” wurde mit Ja beantwortet.
  • Tools/Options/“Auto-lock on design”
    • Meine Frage nach “Auto-lock on first modification” wurde leider nicht beantwortet
How to use the application testability features
  • Vortrag war Low-Level-Einführung in automatisiertes Testen
  • Keine Verbesserungen zu NAV 2009 SP 1
    • also auch immer noch kein Mocking von Triggern
  • Jeder Test wird in eigener Transaktion durchgeführt
  • Code nach ASSERTERROR wird trotzdem ausgeführt
    • Transaktion wird jedoch zurück gerollt
  • Neues Application Test Toolset auf Partnersource (mit 226 Test Cases)
    • Meine Frage nach einer Erweiterung der Standardtestfunktionen wurde nicht beantwortet.
.NET Interoperability
  • Interop nur mit .NET 3.5 libs möglich
  • Nur auf NAV Server bzw. RTC
  • Anlegen von .NET Typen ist unglaublich umständlich
    • Warum schreibt man alle Typen in eine einzige Liste?
    • Keine einfache Möglichkeit über Namespaces zu browsen
  • Simple Datentypen (Double, Integer, Text) werden automatisch in ihre .NET-Entsprechungen gemappt
    • Options auf enums?
  • Format() mapped auf .ToString()
  • Achtung: Static classes werden über alle Client-Sessions geshared
  • NAV Scoping Regeln werden angewendet
    • Wenn lokale C/AL-Methode endet, wird das .NET Objekt disposed
    • Was ist mit Referenzen in noch lebenden .NET Objekten
  • .NET Variablen habe ein RunOnClient-Property
  • Deployment von Custom .NET Assemblies
    • Auf C/SIDE-Client für Development (Compile)
    • Auf die Tier wo der .NET Typ benutzt wird (siehe RunOnClient)
  • Client Warning bei erster Benutzung einer .NET Assembly
    • Keine Warnung bei SPN-Deployment
  • Kein try/catch/finally Exception handling
    • Exception wird als Textnachricht an den Client gesendet
  • Keine Events
Calling out to other Web Services from NAV

NAV Web Services

  • NAV 2009 SP1 führt Web Services immer in UTC-Zeit aus
  • NAV 2009 R2 führt WebServiceDefaultTimeZone ein (Default UTC)
  • Manuelles Change-Tracking immer noch nötig
  • Meine Frage nach “echtem” WCF noch unbeantwortet (aber Demo sah so aus)

Externe Web Services

  • Benutzt .NET Interop ==> Genauso wie in C#
  • Wenn WSL vorhanden, dann kann ein Proxy über svcutil erzeugt werden. Dieser muss dann als DLL auf den NAV Server deployed werden
  • Meine Frage nach asynchronem Aufruf wurde nicht beantwortet
    • Ich vermute unmöglich, da keine .NET Events unterstützt werden und ich noch keine Möglichkeit sehe Callbacks zurück ins NAV zu registrieren
    • Sicherlich möglich durch Publish eines Callback-Webservice (aber das ist irgend nicht schön)
CRM Integration
  • “Connector for Microsoft Dynamics“ für das Mapping
    • Hat NAV und CRM Adapter
    • Eigene 3-Tier-Applikation mit eigenem SQL-Server für Integrationsdaten
    • Integration ID – GUID hält NAV und CRM Datensatz zusammen
  • Neue Database Trigger in Codeunit 1 die IMMER bei INSERT, MODIFY, DELETE und RENAME feuern
  • Jede zu synchronisierende Tabelle muss auf NAV Seite als Page WebService veröffentlicht werden
  • Viele Synchronisationswege nur One-Way
    • Rechnungen sollten z.B. nur vom ERP-System verwaltet werden
  • Eindruck: Unglaublich kompliziertes System, da Mapping über Wizzard im Connector mit eigener kleiner Programmiersprache
    • Warum keine simple C# Projektvorlage mit ein paar Interfaces die man implementieren muss?
    • Warum extra SQL-Server-Instanz? Warum reicht nicht eine Message-Queue?
  • Backup und Restore muss zwischen allen 3 Datenbanken (NAV, CRM, Connector) synchronisiert werden
SSRS (RDLC) Reports in Microsoft Dynamics NAV 2009
  • Dataset kann refreshed werden ohne das Visual Studio geschlossen wird
  • Printer Selection funktioniert jetzt mit RTC über die Request Page
  • Transfooter und Transheader offenbar möglich (siehe http://blogs.msdn.com/nav)
  • Kein Druck auf dem NAV Server
    • Wie Archivierung von PDFs?
Developing Pages
  • Keine wirklichen Neuerungen in R2
Business Data Visualization Add-Ins for the RTC
  • Interessante neue Visualisierungsmöglichkeiten
    • Samples werden auf Beispiel-DVD mitgeliefert
    • Beispiel: Interaktive Zeitreihe
Ausblick auf Dynamics NAV 7
  • Forms Designer ist bereits ausgebaut – “There is no way back”
  • C/SIDE bleibt die Entwicklungsplattform – Keine Visual Studio Variante
    • Aussage in Hamburg: Entwicklung im RTC – Gezeigte Screenshots sagen etwas anderes
  • Offenbar integrierte Versionskontrolle geplant 😉
  • UI-Testing “könnte” kommen
  • .NET Interop mit Events
  • Rewrite vieler interner Funktionen um das .NET-Framework besser zu nutzen
    • Da es in NAV 7 keinen Classic-Client geben wird, ist dies auch problemlos möglich.
  • Keine Hybrid-Reports mehr. Entweder Classic Reports oder RDLC
    • 100% automatische Konvertierung in neuen Report Designer
Tags: , ,

Tuesday, 9. November 2010


Erstes Treffen der .NET Online User Group war schon ein Erfolg

Filed under: Online User group — Steffen Forkmann at 8:57 Uhr

Björn Rochel live Gestern hat Björn Rochel mit seinem Vortrag zum Thema Rhino.ServiceBus den aktiven Start der .NET Online User Group vollzogen. Mit 28 Teilnehmern war dies (trotz einiger technischer Probleme bei mir als geplantem Co-Moderator) schon ein voller Erfolg. Wenn die nächsten Treffen auch so in der Art stattfinden, dann kann die NOUG (Twitter-Hashtag #NOUG) echt etwas Großes werden. Danke an alle die mitmachen und der NOUG in so kurzer Zeit schon ein Gesicht und Struktur geben.

Björn hat aus seinem Vortrag auch schon eine geniale weiterführende Idee für die NOUG entwickelt. In einer "Build your own CQRS"-Gruppe will er gemeinsam mit anderen Interessierten eine vollständige Implementierung einer CQRS – Beispielanwendung vorantreiben.

Nächsten Montag hat dann die F#-Gruppe ihr Kick-Off-Meeting. Ich würde mich über viele interessierte Teilnehmer freuen. Bei diesem Treffen wollen wir einen ersten Einblick in funktionale Konzepte gewinnen. Insbesondere soll auf "Funktionen höherer Ordnung", "Pattern Matching", "Unveränderlichkeit" und parallele Programmierung eingegangen werden. Damit wir uns nicht zu sehr in Diskussionen zur F#-Syntax verfangen wollen wir dies beim ersten Treffen in C# probieren. Damit wir auch ein möglichst interaktives Treffen hinbekommen wäre ein Mikrofon und im Idealfall auch eine Webcam nicht schlecht. 😉

Wichtige Links:

[Das Bild habe ich schamlos von DerAlbert geklaut.]

Tags: , , ,

Thursday, 4. November 2010


.NET Online User Group gegründet

Filed under: Coding Dojo,F#,Online User group — Steffen Forkmann at 19:24 Uhr

Nach einigen Diskussionen und Anregungen auf Twitter und einer konstitutionellen Skype-Session (zwischen DerAlbert, Björn Rochel und mir) wurde heute die “.NET Online User Group” gegründet.

Ziele und Einordnung der Gruppe

Unter dem Deckmantel dieser Gruppe wollen wir versuchen möglichst oft und regelmäßig Online-Treffen für .NET-Entwickler aus dem deutschsprachigen Raum zu organisieren.
Die Online User Group sieht sich damit keinesfalls als Konkurrenz zu den bereits bestehenden lokalen User Groups. Wir stellen uns dabei eher vor durch ein breites Angebot an Formaten und das große Einzugsgebiet auch in speziellere Themen tief reinschauen zu können, die bei den lokalen Gruppen aufgrund der heterogenen Interessen eher vermieden werden.

Gruppen

So ist es z.B. geplant Gruppen zu bilden, die sich zu bestimmten “Randgruppen”-Themen ganz intensiv austauschen können. Den Anfang machen wir mit einer F# Gruppe, deren Ziel es ist die Sprache F# im Speziellen und Funktionale Programmierung im Allgemeinen detailliert zu beleuchten. Beim ersten Treffen am 15.11. wollen wir uns mit “Funktionen höherer Ordnung” beschäftigen.

Jede der Gruppen wird min. einen Paten haben. Die Aufgabe des Paten ist es als Ansprechpartner zu fungieren und Termine zu koordinieren. Das soll aber nicht heißen, dass der Pate bei jedem Treffen selbst einen Vortrag halten soll.

Kurzfristige Treffen

In letzter Zeit ist es des Öfteren vorgekommen, dass einige Themen auf Twitter oder in Newsgroups plötzlich sehr intensiv diskutiert wurden. Wir wollen mit der User Group nun auch eine Kommunikationsplattform bieten, die in der Lage ist kurzfristig in einem direkteren Rahmen über solche Themen zu diskutieren. Wir können uns dabei gut vorstellen, dass spontan verabredet wird (z.B. über Twitter) sich am Abend zu einem bestimmten Thema über die Kanäle der User Group (insbesondere LiveMeeting) zu unterhalten.

Coding Dojo

Auch das bereits etablierte Online Coding Dojo mit Albert Weinert und Ilker Cetinkaya wird ab jetzt unter der Flagge der .NET Online User Group durchgeführt werden. Der erste Termin hierfür ist der 18. November.

Klassische Vorträge

Aber auch Vorträge wird es bei der .NET Online User Group geben. Zum jetzigen Zeitpunkt stehen bereits 4 Termine fest:

Weitere Schritte

Um die .NET Online User Group ordentlich anlaufen lassen zu können benötigen wir natürlich jede Menge Hilfe:

  • Bitte helft uns die User Group bekannt zu machen. Twitter, Email, Blogs, Briefe, Faxe, TV-Spots, persönliche Kommunikation usw.
  • Bitte registriert euch auf der Webseite der User Grouo
  • Bitte schlagt Vorträge vor
  • Bitte nennt uns Themenwünsche und Ideen
  • Bitte meldet euch freiwillig als Paten für bestimmte Untergruppen bzw. Themenbereiche
  • Bitte schlagt uns vor wie ihr sonst noch helfen könnt 😉
Tags: , ,

Wednesday, 3. November 2010


Running specific targets in "FAKE – F# Make"

Filed under: F# — Steffen Forkmann at 8:44 Uhr

This article has been moved to http://fsharp.github.io/FAKE/specifictargets.html

Tags: , ,

Wednesday, 14. July 2010


"Fake – F# Make" 1.40.5.0 released – Bugfixes for CruiseControl.NET

Filed under: F#,FAKE - F# Make — Steffen Forkmann at 9:15 Uhr

Today I released “FAKE – F# Make” version 1.40.5.0. This release fixes some issues with CruiseControl.NET compatibility and improves the MSBuild task.

Important links:

Changes for CruiseControl.NET

Daniel Nauck created a FAKE task for CC.Net. This task allows a much easier configuration of FAKE. Please download the latest CC.NET build if you want to use it.

Daniel also created a FAKE build project on his server which showed us some compatibility issues:

@Daniel: Thank you very much for helping me on this CruiseControl.NET stuff. I really appreciate this.

MSBuild task changes

The MSBuild task in FAKE gets a sequence of project files and compiles them in the given order. This might be slow if you have lots of dependent projects. Then MSBuild might analyze the dependencies over and over again. To fix this issue I currently see two possible solutions:

  1. Generate a temporary solution file and use this for compilation.
  2. Analyze the given projects and remove all dependent projects from the list.

FAKE 1.40.5.0 implements the second idea. If you have a better idea please contact me.

Tags: , , ,

Sunday, 11. July 2010


“Fake – F# Make” 1.33.0 released

Filed under: F#,FAKE - F# Make — Steffen Forkmann at 15:11 Uhr

Yesterday I released “FAKE – F# Make” version 1.33.0. This release has lots of small bug fixes and a couple of new features.

Important links:

Git helpers -Fake.Git.dll

Git is a distributed revision control system with an emphasis on speed. Git was initially designed and developed by Linus Torvalds for Linux kernel development. Every Git working directory is a full-fledged repository with complete history and full revision tracking capabilities, not dependent on network access or a central server.

[Wikipedia]

In the last couple of months I worked on small helper library for controlling Git. This library is now released as part of “FAKE – F# Make”. You can find the source code at http://github.com/forki/FAKE/tree/master/src/app/Fake.Git/.

Features:

  • Repository handling
    • init, clone
  • Submodules
    • init, clone, information about submodules
  • Branches
    • checkout, create, delete, merge, rebase, tag, pull, push, reset, commit, …
  • SHA1 calculation
Documentation generation with James Gregory’s docu tool

What’s a docu? A documentation generator for .Net that isn’t complicated, awkward, or difficult to use. Given an assembly and the XML that’s generated by Visual Studio, docu can produce an entire website of documentation with a single command.

[docu website]

Fake comes bundled with James Gregory’s documentations generator “docu”, which converts XML-Documentation comments into HTML files. All you need to do is downloading a template and calling the docu task inside your build script:

!+ (buildDir + "*.dll")
     |> Scan
     |> Docu (fun p ->
         {p with
             ToolPath = docuPath + "docu.exe"
             TemplatesPath = templatesSrcDir
             OutputPath = docsDir })

Since FAKE builds its own documentation with docu I started to add more (and hopefully better) XML doc comments. My plan is to describe more and more of the internal FAKE functions in the next releases. An updated HTML-document (generated via a docu task) can be found at http://www.navision-blog.de/fake/.

Side by side specification

For Test-driven development (TDD) it’s sometimes nice to have the specifications next to the implementation files since the specs are considered as documentation.

By using a tool like VSCommands it is possible to group the implementation with the specs (see also http://gist.github.com/457248).

This “side by side specification” makes TDD a lot easier but of course we don’t want to deploy the specification classes and the test data.

Side by side specification ==> After "RemoveTestFromProject"

FAKE has a new feature which automatically removes all specification files and test framework references according to a given convention:

Target "BuildApp" (fun _ –>
      !+ @"src\app\**\*.csproj"
         |> Scan
         |> Seq.map (
             RemoveTestsFromProject
                 AllNUnitReferences      // a default references convention
                 AllSpecAndTestDataFiles // a default file convention
                 )
         |> MSBuildRelease buildDir "Build"
         |> Log "AppBuild-Output: "
)

The conventions are simple functions and can be customized e.g.:

/// All Spec.cs or Spec.fs files and all files containing TestData
let AllSpecAndTestDataFiles elementName (s:string) =
     s.EndsWith "Specs.cs" ||
       s.EndsWith "Specs.fs" ||
       (elementName = "Content" && s.Contains "TestData")
Miscellaneous
  • SQL Server helpers are moved to Fake.SQL.dll
    • Additional functions for attaching and detaching databases.
  • FileHelper.CopyCached function was added
    • Copies the files from a cache folder. If the files are not cached or the original files have a different write time the cache will be refreshed.
  • EnvironmentHelper.environVarOrDefault added
    • Retrieves the environment variable or a given default.
  • Fixed Issue 3: toRelativePath calculates paths with ..\..\ if needed
  • Added a build time report to the build output.
  • XPathReplace and XMLPoke tasks added.
    • Replaces text in an XML file at the location specified by an XPath expression.
  • ILMerge task added
  • Windows Installer XML (WiX) task added
Tags: , , , , , , , ,

Wednesday, 7. July 2010


Strange bug in Dynamics NAV client

Filed under: Dynamics NAV 2009,Navision — Steffen Forkmann at 7:34 Uhr

My colleague Mathias Meissner found a strange bug in the Dynamics NAV Client (occurs at least in the native clients for NAV 403, 501 and 601). It seems the following code creates a strange memory allocation issue. (Download sample)

OBJECT Codeunit 99500 NAV Bug
{
  OBJECT-PROPERTIES
  {
    Date=17.06.10;
    Time=14:30:30;
    Modified=Yes;
    Version List=;
  }
  PROPERTIES
  {
    OnRun=BEGIN
            TestMiddleCase;  // comment this line out and ReverseString works!
            TestReverseString;
          END;

  }
  CODE
  {

    PROCEDURE TestMiddleCase@5128500();
    BEGIN
      MiddleCase('fooo AnD bar');
    END;

    PROCEDURE TestReverseString@5128502();
    VAR
      l_String@5128500 : Text[1024];
      l_Result@5128503 : Integer;
    BEGIN
      l_String :=
        '1101101111011011110110111101101111011011110110111101101111011011' +
        '1101101111011011110110111101101111011011110110111101101111011011' +
        '1101101111011011110110111101101111011011110110111101101111011011' +
        '1101101111011011110110111101101111011011110110111101101111011011' +
        '1101101111011011110110111101101111011011110110111101101111011011' +
        '1101101111011011110110111101101111011011110110111101101111011011' +
        '1101101111011011110110111101101111011011110110111101101111011011' +
        '1101101111011011110110111101101111011011110110111101101111011011';

      IF STRLEN(l_String) <> 512 THEN
        ERROR('Wrong strlen');

      l_Result := TestReverseStringSub(l_String);

      IF l_Result <> 512 THEN
        ERROR('Error: Actual: ' + FORMAT(l_Result) + ' ' + ' Expected: 512');
    END;

    PROCEDURE TestReverseStringSub@5128521(p_String@5128500 : Text[1024]) r_Int : Integer;
    VAR
      l_StringMgt@5128501 : Codeunit 5128519;
    BEGIN
      p_String := ReverseString(p_String);
      EXIT(STRLEN(p_String));
    END;

    PROCEDURE ReverseString@5128509(p_In@5128502 : Text[1024]) Result : Text[1024];
    VAR
      i@5128500 : Integer;
      l_Length@5128501 : Integer;
    BEGIN
      l_Length := STRLEN(p_In) + 1;

      FOR i := 1 TO l_Length - 1 DO
        Result[i] := p_In[l_Length-i];
    END;

    PROCEDURE MiddleCase@1000000000(p_StringToConvert@1000000000 : Text[250]) ConvertedString : Text[250];
    BEGIN
      ConvertedString :=
        UPPERCASE(COPYSTR(p_StringToConvert, 1, 1)) +
        LOWERCASE(COPYSTR(p_StringToConvert, 2));
    END;

    BEGIN
    END.
  }
}

Since we don’t do anything evil here my only advice is to initialize every return parameter with a default value. This seems to fix the bug.


    PROCEDURE ReverseString@5128509(p_In@5128502 : Text[1024]) Result : Text[1024];
    VAR
      i@5128500 : Integer;
      l_Length@5128501 : Integer;
    BEGIN
      Result := ''; // Init return value – this fixes the issue!
      l_Length := STRLEN(p_In) + 1;

      FOR i := 1 TO l_Length - 1 DO
        Result[i] := p_In[l_Length-i];
    END;

Interestingly I didn’t find a smaller sample which reproduces this memory issue.

Tags: ,