NuDoq === ‘nearly awesome’

on Saturday, 19 April 2014

Documentation matters.
It takes a lot of time writing it and writing decent documentation it is an art in itself. Writing good documentation is a full-time gift.

Doc it like it’s 1999

I decided very early on boarding OSS that I would commit the time to write API documentation, regardless of my 3 tenets:

  • First directive is API design
  • Second directive is API design
  • When directives One and Two fail, documentation prevents total failure

Not only NMoneys comes with full-fledged XML documentation, some builds ago I included a .chm for old times’ sake.

But Mum does not (usually) feed me anymore

I even thought of a plan to not only compile the API documentation into .chm, but take advantage of the html generated and push it somewhere online.

And then, she passed by. Casually. Without giving herself importance. And I laid my eyes on her. Nudoq, from now on you have female gender in my vocabulary

Seriously rocking

I read about it while reviewing the project site of a random OSS library and it totally blew me off my socks. That is exactly what I had been looking for: good-looking, online documentation that takes no effort beyond documenting your code.

It works without you noticing. As long as you include XML comments in your code and push it to Nuget, chances are that she made your documentation available to everyone already.
She did that to NMoneys, check it out if you don’t believe your eyes.

nudoq.currency

All that glitters ain’t code

Unfortunately, it is not perfect.
I found myself some issues: failing to document inner classes, weird rendering and failing to refresh the documentation whenever a new version (or three) are pushed to the Nuget Gallery.

Something that worries me a bit, is that even though there is a Github organization for it, I cannot find a repository to clone and contribute to. There is a post in their feedback forums stating that it may be on its way, but it is from some time ago and it has not received much attention.

It would be a pity that it was not open sourced, since I am more than willing to contribute to such an awesome idea.
Please, let me work for you for free.

Searching Currencies

The main reason that NMoneys.Web was envisioned (apart from the learning experience) was to provide information about how the library displays monetary quantities in order for non-technical users to be able to spot mistakes or improvements.
Such requirement is fulfilled in the Currencies section

Snapshot/Detail

There are quite a few currencies (NMoneys supports, at the time of writing, 183) so I thought a tile-like layout would be suitable to display the most important information (codes, names and symbols).

currencies

For more detailed information it makes sense to have one of those evil modals (out-of-the-box Bootstrapper) and since there is some information, grouping in tabs looked like a good idea, sprinkling it with some tooltips.

detailtooltip

Finding one’s way… Or a currency

A very early “requirement” was the ability to filter/search currencies (it seems that Find in Page of your browser is not good enough Smile with tongue out).
After a couple of Google searches, I found that jquery.quicksearch (now pretty “forgotten”) and (the even older) jquery.highlight fitted the bill pretty nicely. A couple of train rides later, pseudo-free-text filtering plus highlighting was implemented on a shoestring with minimal coding:

$(function () {
    var $searchBox = $('#search-box');
    var snapshotSelector = '.snapshot';
    var $snapshots = $(snapshotSelector);
    var $titles = $('.initial');
    $searchBox.quicksearch(snapshotSelector,
        {
            'delay': 300,
            'onAfter': function () {
                var searchTerms = $searchBox.val();
                if (searchTerms) {
                    $snapshots.unhighlight().highlight(searchTerms);
                    $titles.hide();
                }
                else {
                    $snapshots.unhighlight();
                    $titles.show();
                }
            }
        });    
});

It’s not a SPA. It’s better than good. It’s… good enough.

OSS Catching Up

on Friday, 18 April 2014
It's rare these days to have a mostly free evening to look after some OSS.

NMoneys

I was able to release a healthy and round 3.5.0.0 which can be obtained from Nuget or Bintray.
The only change was to surface an IEqualityComparer instance to be able to compare code instances. The use case? Using it in dictionaries or sets. The reason? Performance.

Perf-what?

It seems that some folks did notice that the performance of the default comparer for enums is not stelar due to boxing and unboxing of values. The penalty is somewhat lessened in .NET 4, but by exposing a comparer backed up by expressions, one can get easily a 6x performance gain (sometimes more, but not consistently).
So, next time need to compare more than a handlful of CurrencyIsoCode instances, it is as easy as using the Currency.Code.Comparer instance to get a small perf boost.
NMoneys_NuGet

Testing.Commons.NUnit

I have not worked that much on the Testing.Commons family lately. Maybe because it already gives me what I demand from it.
But there has been for some time a new version of a package Testing.Commons.NUnit depends on : the fantastic ExpectedObjects and it annoyed me not updating it with peace of mind (or assembly redirects).
Newer features are not useful for my purposes, but nothing of what I use is broken or maybe I trust my tests too much.
Testing.Commons.NUnit.NuGet

MVC sauce

on Tuesday, 25 March 2014

NMoneys.Web is  website, built with ASP.NET MVC. I might as well share with you a couple of things I learnt.

Views

I like Razor a lot. Once you use it, you do not want to hear about the “old” Webforms view engine anymore. Unfortunately, even if you do not use, it is still there, lingering around and being tried for every view.
You can find the tip to remove unused view engines in many places. Now there is one place more:

ViewEngines.Engines.Clear();
var razor = new RazorViewEngine();
razor.ViewLocationCache = new TwoLevelViewCache(razor.ViewLocationCache);
ViewEngines.Engines.Add(razor);

The TwoLevelCache is a simple IViewLocationCache decorator that uses a per-request dictionary to speed view location lookups.

Controllers

Probably the single biggest performance boost you can give a a website is do as little as possible. One way of achieving this sweet spot is caching. And the simplest way to cache controller methods is the output cache.

In this cache, the whole result of the controller is cached. Simply decorate the controller action with an OutputCacheAttribute and, amongst other properties, point the cache profile that will hold the information.

[OutputCache(CacheProfile = "snapshots")]
public ActionResult Index()
{
    var model = ...
    return View(model);
} 

And remember to configure the profile in Web.config:

<system.web>
    <caching>
        <outputCache enableOutputCache="true" />
        <outputCacheSettings>
            <outputCacheProfiles>
                <add name="snapshots" duration="43200" location="Any" />
                ...

Html Helpers

Sometimes one does not need a full-blown partial view or a Razor helper. Most of the time is enough to encapsulate a small bit of reusable markup inside an Html Helper extension method. In here markup is created from code. Of course there are multiple ways to generate it, I will mention some:

Format your strings

I really, really, really did not want to mention it, but since I saw an example of this “technique” recently (I kid you not)…
One simply creates a string that contains the html to be returned and use format placeholders to inject the values. I did that in 1996 (first programming job). I still look behind me in dark alleys in case the maintainer of that code finally got me.

The MVC way

What we can do with out-of-the-box MVC is use the TagBuilder class to compose our tags, which will return a nice IHtmlString that will be rendered the view:

public static IHtmlString IconNavEntry<TController>(this HtmlHelper helper, Expression<Action<TController>> action, string iconClass, string classIfCurrent = "active") where TController : Controller
{
    RouteValueDictionary values = Microsoft.Web.Mvc.Internal.ExpressionHelper.GetRouteValuesFromExpression(action);
            
    string url = UrlHelper.GenerateUrl(//...
    TagBuilder anchor = HtmlTextWriterTag.A.asTag(tb => tb.MergeAttribute("href", url));

    TagBuilder span = HtmlTextWriterTag.Span.asTag(tb => tb.AddCssClass(iconClass));
    anchor.InnerHtml = span.ToString(TagRenderMode.Normal);

    TagBuilder li = HtmlTextWriterTag.Li.asTag(tb =>
        tb.InnerHtml = anchor.ToString(TagRenderMode.Normal));

    if (isCurrentAction(helper, values))
    {
        li.AddCssClass(classIfCurrent);
    }

    return new HtmlString(li.ToString(TagRenderMode.Normal));
}

private static TagBuilder asTag(this HtmlTextWriterTag tag, Action<TagBuilder> building = null)
{
    var builder = new TagBuilder(tag.ToString().ToLower());
    if (building != null) building(builder);
    return builder;
}

Certainly more robust than string-formatting literals but still verbose. Furthermore, the API forces you to code from the inside out, obfuscating the structure of the generated HTML.

FUBU it

One of the multiple sub-projects of FubuMVC, is the HtmlTags project. Basically is TagBuilder done right. It leverages a simple to use fluent API and yields very, very terse and readable code that indicates hierarchy by nesting calls, so there is little doubt of the structure of the HTML:

public static HtmlTag IconNavEntry<TController>(this HtmlHelper helper, Expression<Action<TController>> action, string iconClass, string classIfCurrent = "active") where TController : Controller
{
    RouteValueDictionary values = Microsoft.Web.Mvc.Internal.ExpressionHelper.GetRouteValuesFromExpression(action);

    string url = UrlHelper.GenerateUrl(//...

    var li = new HtmlTag("li")
        .AddClassIf(isCurrentAction(helper, values), classIfCurrent)
        .Append(
            new LinkTag(string.Empty, url).Append(
                new HtmlTag("span").AddClass(iconClass)
            )
        );
    return li;
}

public static HtmlTag AddClassIf(this HtmlTag tag, bool condition, string className)
{
    if (condition)
    {
        tag.AddClass(className);
    }
    return tag;
}

Furthermore, since what is returned is not some sort of string, but a composable object model, the tags can be further customized in the view, really useful for one/twice time change of the rendered HTML. Wicked.

A Web is a Web is a Web

NMoneys.Web is a web application. End of post. Next.

Foundations

For those of us that have little expertise in writing sensible, structured, not-disgusting HTML or CSS, HTML frameworks are Godsend.

I have used Bootstrap but I preferred NMoneys.Web not to look like 90% if the Internet, so I had one of two:

  1. tweak Bootstrap myself
  2. trust someone to customize it

1) was not an option and after toying with some Metro-looking frameworks (and feeling as lost as a jellyfish in Mojave), option 2) crystalized when I found out Flat UI. Flat UI makes Bootstrap look more Metro Modern but still tastes as Bootstrap.

Flat UI is really nice, but please, do not use it. Or if do, customize the hell out of it. The last thing you want is your site looking like NMoneys.Web, don’t you? Smile with tongue out

Pack it really tight

Caring about page footprint is not reserved anymore to insanely visited sites. Nowadays, libraries, better practices and solutions are easily available for everyone. And so everyone should care about bundling and minification of web assets.

In have used Cassette in the past. I liked it. It works. But I have the feeling that, in the end, it will be predated by Microsoft’s own solution because it is good enough for most purposes. Purposes like NMoneys.Web.

And I have to admit that I liked it a lot. It was easy to fulfill my modest requirements and I think that CDN support is pretty nicely handled (not that is a terribly difficult problem to solve). So now all my third-party assets are served from several CDNs: Google Hosted Libraries for jQuery, Bootstrap CDN for Bootstrap and cdnjs for everything else (Parsley and Prettify).

You can check my bundling configuration here. If you see something terribly (or even mildly) wrong, please let me know so that I can learn.

Curly-bracing

One thing I hated about some modern-non-intrusive Javascript that I have seen in quite a few places is having widely-shared pieces of script (sometimes quite chunky) throughout the site.
“It’s cheap”, they say, “they are very efficient selectors”, an they walked away without looking back at my tears rolling down my face. “Don’t worry, it’s cached”, the tried to comfort weeping me…

Sadly is the same thing I have seen in the server-side. Lack of modularity, Poor code architecture. It may be cached, but it still needs to be parsed. And the selectors are there, being executed. It may not be much, but it feels wrong.

And that I tried to avoid in NMoneys.Web and what I could do was:

  1. create a Razor sections for assets that go at the end of the body (@scripts) and another for those that go in the head (@head)
    <head>
        @Styles.Render(...)
        @RenderSection("head", required: false)
    </head>
    <body>
        ...
        @Scripts.Render(...)
        @RenderSection("scripts", required: false)
    </body>
  2. create a script bundle for each “page” of the site. For example, one bundle for the script to be run in the /samples area
    var prettify = new ScriptBundle("~/bundles/prettify", "//cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.js")
        .Include("~/Scripts/prettify.js");
    prettify.CdnFallbackExpression = "window.prettyPrint";
    bundles.Add(prettify);
    
    bundles.Add(new ScriptBundle("~/bundles/app_samples").Include(
        "~/Scripts/app.Samples.js"));
    
    bundles.Add(new StyleBundle("~/Content/prettify", "//cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.css")
        .Include("~/Content/prettify.css"));
  3. render the bundle or bundles required for that single page in the right section
    @section head
    {
        @Styles.Render("~/Content/prettify")
    }
    
    @section scripts
    {
        @Scripts.Render("~/bundles/prettify")
        @Scripts.Render("~/bundles/app_samples")
    }

That way, only needed bundles are rendered in the page that uses them. They will be optimized and won’t hurt performance of other page. I totally understand that this simplistic approach is not 1:1 applicable when there are many resources to be shared; but like most things, it is a question of managing dependencies step by step.

NMoneys.Web.

on Saturday, 15 March 2014

I am a developer. It happens that most of the applications I have developed are web applications. That should make me a web developer. But for the last developments in the area, I don’t consider myself one.

I still get the chills with Javascript, I don’t like coffee, I do not hate CSS too much, I do not have NodeJs installed in every  machine and scaffold web frameworks are alright. There is definitely lots of web stuff that I do not get to do on a day by day, otherwise I would love js, crave coffee, despise CSS, kneel to NPM greatness and do my own grids.

But I like exploring and learning by doing. That is why I chose to develop a web site in my scarce spare time.
And since I also like things with a meaning (small as it may be) I created a web site for NMoneys.

Before the storm…

There has been a slow stream of changes lately for NMoneys. That is not to say little has happened.

To start with, I got to use the library in two real-world projects. And no single developer complained. That should be a measure of success, I guess Smile

It is not true that NMoneys is lacking a website. It has one. It is its project site. It is decently populated with examples and documentation. But there was something missing: visuals. One can stretch it, and consider part of this blog as part of that website. Or its recent home for binaries.

I started this pet project long time ago, but I kept procrastinating due to the lack of deadlines (classic).
As it goes, this release is the third incarnation of the project. It started with my happy idea of learning XAML and show off NMoneys using a Zune-looking Metro application. Unfortunately for me, that was a bigger bite than I thought. So I gave it up for a while.
Later on, I set myself to stick to the Web and write some more Javascript. That second incarnation went way farther but it never saw “the light”. But it laid the foundations for this third incarnation.

…one forgets the umbrella

In this de-structured series of posts I will be writing about things that I found out interesting: MVC, Javascript, REST APIs, documentation, The Cloud,…

If this list of topics don’t get the reader a little aroused I’ll eat my proverbial hat (or stop blogging altogether), because, if that is the case, I am targeting the wrong audience pretty badly.
Here comes NMoneys.Web. Flood it with visits.

NMoneys 3.4.1.0

on Friday, 14 March 2014

A maintenance version of NMoneys has just been released.

What is maintained?

The amendment 157 from ISO has been applied. More significant decimals for CLF.

Pretty cool that ISO changes are available in NMoneys the same day they are effective in the standard if I must say so.

Besides, and taking advantage of my updated workstation (running Windows 8.1 and .NET 4.5.1), I have been able to complete information about a bunch of other currencies. Check out the Changelog for more information about the contents of the release.

Bits, please

Because one cannot reference this post from Visual Studio, you can get the Nuget package on the usual place:

NMoneys_NuGet

New Home for binaries

As I mentioned before, Google fulfilled its promise of effectively killing the Download Area.
From now on, binaries cannot be posted in the page of the project.

Instead, I am going to give Bintray a try (phonetic pun not intended).
It looks very promising (a bit Java-centric) but remember it is still in Beta. Let me know how that goes.
As for myself, I might be able to automate the release process even more, due to their REST API.

Oh, and here is the nice download badge: