Saturday, November 17, 2012

How to run and build an AMD application using r.js

Here is an AMD application that adds two numbers together.  1 and 2. 

It assumes you have git shell, node.js and r.js installed.  I followed the recommended layout for installing r.js:

mkdir requirejs 
cd requirejs 
git clone git://github.com/jrburke/r.js.git 
git clone git://github.com/jrburke/requirejs.git 
git clone git://github.com/requirejs/text.git

I then created three files that make my AMD calculator application:
  1. addop.js
  2. calc.js
  3. app.js

addop.js
define([], function() {
    return function (a, b) { return a + b; }
});


calc.js
define(["addop"], function (addOp) {
    return function (operator, a, b)
    {
        switch (operator) {
            case "add": {
                return addOp(a, b);
                break;
            }
            default: {
                return "?";
            }
        }
    }
});


app.js
require(["calc"], function (calc) {
    console.log(calc("add", 1, 2));
});


From my Node.js command prompt I tested the application:
>node \code\requirejs\r.js\dist\r.js app.js

Then built the application:
>node \code\requirejs\r.js\dist\r.js -o name=app out=go.js baseUrl=.

Then tested the build:
>node \code\requirejs\r.js\dist\r.js go.js

The build file (go.js) was concatenated and compressed as expected.  I ran it though a beautifier:


define("addop", [], function () {
    return function (e, t) {
        return e + t
    }
}), define("calc", ["addop"], function (e) {
    return function (t, n, r) {
        switch (t) {
            case "add":
                return e(n, r);
            default:
                return "?"
        }
    }
}), require(["calc"], function (e) {
    console.log(e("add", 1, 2))
}), define("app", function () {})

Monday, October 3, 2011

Hansen8 Developers Group Meeting IX

LINQ

Swathi discussed LINQ and the many advantages it brings. She provided three examples:

var feeType = from p in db.FEETYPEs
  where p.FEEDESC.Contains("Permit")
  select p;

XDocument xmlSource = XDocument.Load("XMLFile1.xml");

var books = from book in xmlSource.Descendants("Table1")
  select new
  {
     Name = book.Element("bookName").Value,
     Author = book.Element("author").Value
  };

//using Query Expression
string[] names = { "Tom", "Rick", "Harry", "Mary", "Jay" };

IEnumerable query = from n in names
    where n.Contains("a") // Filter elements
    orderby n.Length // Sort elements
    select n; // Translate each element (project)
        
//using Lambda Expression
IEnumerable lambdaQuery = names.Where(n => n.Contains("a")).OrderBy(n => n.Length);
Finally, Swathi showed how we can now use LINQ in H8:

var requests = NewComponent();
requests.Load(x => (x.RequestType.RequestType == "Graffiti" && x.IsAssigned == true) || x.RequestType.RequestType == "Dead Animal")

Hansen8 Developers Group Meeting IIX

Windows Workflow Foundation

Anthony lightly touched on WWF and the concept of dehydration and rehydration to persist workflow to a durable medium. He showed examples of the primary events:
  • Completed
  • Terminated
  • Loaded
  • Unloaded
  • Persisted
  • Idled
I've delayed too long in writing this so I cannot elaborate further! He provided this link.

Hansen8 Developers Group Meeting VII

Extension Methods

Tim presented extension methods and used as an example several date extension methods, One of them was DaysUntil:
        /// 
        /// Gets the number of days until the specified date.
        /// 
        /// 
        /// 
        public static double DaysUntil(this DateTime dt)
        {
            DateTime nextDay;

            if (dt > DateTime.Now)
                nextDay = new DateTime(dt.Year, dt.Month, dt.Day);
            else
                nextDay = new DateTime(dt.Year + 1, dt.Month, dt.Day);

            return nextDay.Subtract (DateTime.Now).TotalDays;
        }
Usage:

  var dt = new DateTime(DateTime.Now.Year, cmbMonth.SelectedIndex + 1, cmbDay.SelectedIndex + 1);
  var du = dt.DaysUntil();
He indicated some disadvantages, chief among them being the inability to reflect upon them. There is no way of knowing via reflection that DaysUntil is an extension method. Interestingly if you write an extension method which shares the same functionality of an existing method the extension method will not get called. This means you could write extension methods for future functionality so that when recompiled for a later framework those methods would run natively without the need to delete them. Of course you could also wrap them in compiler directives or simply delete them so that also got filed under a disadvantage. He hinted at some practical extension methods for Enum such as Has, Add, Remove but did not share the source code. I've always been frustrated by the inability to easily detect if an Enum has a certain value (assuming it is decorated with a FlagAttribute. With this extension you could test via myEnum.Has(MyEnum.SomeValue).

Monday, September 26, 2011

Digital Design

Web Based Digital Design


This is the first of what I hope to be several posts related to building a web-based digital design tool. Today I wrote some basic logic operation in terms of "nor" gates.



var logic = {
    nop: function (a) {
        return a;
    },
    nor: function (a, b) {
        return (a | b) ? 0 : 1;
    },
    not: function (a) {
        return this.nor(a, a);
    },
    or: function (a, b) {
        return this.not(this.nor(a, b));
    },
    nand: function (a, b) {
        return this.or(this.not(a), this.not(b));
    },
    and: function (a, b) {
        return this.nor(this.not(a), this.not(b));
    },
    xnor: function (a, b) {
        return this.or(this.and(a, b), this.and(this.not(a), this.not(b)));
    },
    xor: function (a, b) {
        return this.or(this.and(a, this.not(b)), this.and(this.not(a), b));
    }
};

I then defined a gate constructor



var gate = (function () {

    function tick(op, input) {
        this.value = this.next;
        var params = [];
        for (var i = 0; i < input.length; i++) {
            params[i] = input[i].value;
        }
        this.next = op.apply(logic, params);
    }

    return function (opName, input) {
        var that = this;
        clock.hook(function () { tick.call(that, logic[opName], input); });
    }

}).call();

I then created a small test



(function () {
    var zero = { value: 0 };
    var one = { value: 1 };
    var input = [zero, one];
    var g1 = new gate("xor", input);
    var g2 = new gate("and", [g1, input[1]]);
    clock.tick();
    clock.tick();
    assert(g1.value == 1, "0 xor 1");
    clock.tick();
    assert(g2.value == 1, "1 and 1");
    input[0] = one;
    clock.tick();
    clock.tick();
    assert(g1.value == 0, "1 xor 1");
    clock.tick();
    assert(g2.value == 0, "0 and 1");
}).call();

For the time being my clock looks like this



var clock = {
    tick: function () { },
    hook: function (callback) {
        var tick = this.tick;
        this.tick = function () {
            tick();
            callback();
        };
    }
};

Next step is to construct a more robust test by building a JK flip-flop circuit and then a counter.

Tuesday, August 30, 2011

Hansen8 Developers Group Meeting VI

WCF

Pradeep presented WCF and it's ability to, via configuration alone, communicate using different bindings using endpoints. He demonstrated self-hosted and IIS-hosted services. He also demonstrating calling the same method using multiple bindings from the WCF Test Client.

The meeting got interesting when Russell asked Pradeep to create a method which accepts one int parameter and load it as a Web Service. Here is what we learned.

First, create a new "WCF Service Application" it will generate this code for you:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WcfService1
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
    public class Service1 : IService1
    {
        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }

        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite == null)
            {
                throw new ArgumentNullException("composite");
            }
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }
    }
}

Now add a new Console Project to this solution and add this service as a Web Reference and look at the implementation of the GetData proxy:
       [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/IService1/GetData", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
        [return: System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
        public string GetData(int value, [System.Xml.Serialization.XmlIgnoreAttribute()] bool valueSpecified) {
            object[] results = this.Invoke("GetData", new object[] {
                        value,
                        valueSpecified});
            return ((string)(results[0]));
        }

And it only gets worse. Notice the return is decorated with IsNullable=true so let's modify the return type to be a non-nullable type:

        public int GetData(int value)
        {
            return value + 1;
        }

And regenerate the proxy. Now the implementation of GetData has moved the return value into two out parameters:

        [System.Web.Services.Protocols.SoapDocumentMethodAttribute(
          "http://tempuri.org/IService1/GetData", 
          RequestNamespace="http://tempuri.org/", 
          ResponseNamespace="http://tempuri.org/", 
          Use=Description.SoapBindingUse.Literal,
          ParameterStyle=Protocols.SoapParameterStyle.Wrapped)]
        public void GetData(
          int value, 
          [XmlIgnoreAttribute()] bool valueSpecified, 
          out int GetDataResult, 
          [XmlIgnoreAttribute()] out bool GetDataResultSpecified) {
            object[] results = this.Invoke("GetData", new object[] {
                        value,
                        valueSpecified});
            GetDataResult = ((int)(results[0]));
            GetDataResultSpecified = ((bool)(results[1]));
        }

So now you are force to write code like this:

            int result;
            bool hasResult;
            test.GetData(
                value: 1,
                valueSpecified: false,
                GetDataResult: out result,
                GetDataResultSpecified: out hasResult
                );

I would have assumed that in the above code, where the value:1 is not actually provided (because valueSpecified:false) that this would throw an exception on the server. But instead of a fault it assumes a value of 0! So how do we make it default to a 10?

Obviously what is missing here is the ability to mark method parameters as *optional* to complement the feature of marking a field or property as required. And of course the C# language has syntax for that already:

        public int GetData(int value = 10) // does not work
        {
            return value;
        }

But don't count on this optional parameter defaulting to 10 because if valueSpecified is false it will get 0.

I went out in search of an explanation to this lunacy but only found this forum post dating back to August 24, 2006 with no solution in sight.

Best practices dictate the use of a composite type so all service methods accept one parameter and return one result. It's possible to decorate fields of a composite type as required using [DataMember(IsRequired=true)] but the same is not true for method parameters.

WCF and Microsoft are not perfect...I just wish I understood what they were thinking.

Back to Pradeep's presentation, here is is configuration which contains endpoints for the following bindings:
  • wsHttpBinding
  • mexHttpBinding
  • basicHttpBinding
  • netTcpBinding
  • netNamedPipeBinding

He did not discuss nor am I familiar with the purpose of certificateReference .

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 <system.web>
  <compilation debug="true" />
 </system.web>
 <!-- When deploying the service library project, the content of the config file must be added to the host's
 app.config file. System.Configuration does not support config files for libraries. -->
 <system.serviceModel>
  <services>
   <service behaviorConfiguration="EvalServiceLibrary.Service1Behavior"
    name="EvalServiceLibrary.EvalService">
    <clear />
    <endpoint address="ws" binding="wsHttpBinding" name="wsHttp"
     contract="EvalServiceLibrary.IEvalService" listenUriMode="Explicit">
     <identity>
      <dns value="localhost" />
      <certificateReference storeName="My" storeLocation="LocalMachine"
       x509FindType="FindBySubjectDistinguishedName" />
     </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" name="Mex" contract="IMetadataExchange"
     listenUriMode="Explicit">
     <identity>
      <dns value="localhost" />
      <certificateReference storeName="My" storeLocation="LocalMachine"
       x509FindType="FindBySubjectDistinguishedName" />
     </identity>
    </endpoint>
    <endpoint address="basic" binding="basicHttpBinding" name="basicHttp"
     contract="EvalServiceLibrary.IEvalService" listenUriMode="Explicit">
     <identity>
      <dns value="localhost" />
      <certificateReference storeName="My" storeLocation="LocalMachine"
       x509FindType="FindBySubjectDistinguishedName" />
     </identity>
    </endpoint>
    <endpoint address="net.tcp://localhost:8888/EvalService" binding="netTcpBinding"
     name="netTCP" contract="EvalServiceLibrary.IEvalService" listenUriMode="Explicit">
     <identity>
      <dns value="localhost" />
      <certificateReference storeName="My" storeLocation="LocalMachine"
       x509FindType="FindBySubjectDistinguishedName" />
     </identity>
    </endpoint>
    <endpoint address="net.pipe://localhost/EvalService" binding="netNamedPipeBinding"
     bindingConfiguration="" name="pipe" contract="EvalServiceLibrary.IEvalService" />
    <host>
     <baseAddresses>
      <add baseAddress="http://localhost:8080/EvalService" />
     </baseAddresses>
    </host>
   </service>
  </services>
  <behaviors>
   <serviceBehaviors>
    <behavior name="EvalServiceLibrary.Service1Behavior">
     <!-- To avoid disclosing metadata information,
     set the value below to false and remove the metadata endpoint above before deployment -->
     <serviceMetadata httpGetEnabled="True"/>
     <!-- To receive exception details in faults for debugging purposes,
     set the value below to true. Set to false before deployment
     to avoid disclosing exception information -->
     <serviceDebug includeExceptionDetailInFaults="False" />
    </behavior>
   </serviceBehaviors>
  </behaviors>
 </system.serviceModel>
</configuration>

Friday, August 26, 2011

Browser Based Windows Manager

Managing Parent-Child relationships among Browser Windows


The following code demonstrates how to manage the parent-child relationship among browser windows in a way that does not result in accessing properties on closed windows by managing a global list of windows. Features include:

  • Close child windows
  • Alerts in child, parent, root windows
  • Close all windows




window.privateLab = {
    alert: function (msg) {
        window.alert(msg);
    },
    alertParent: function (msg) {
        if (window.opener) window.opener.alert(msg);
    },
    alertRoot: function (msg) {
        globalLab.alert(msg);
    },
    injectText: function (container, text) {
        window.globalLab.injectText(window.document, container, text);
    },
    closeAll: function () {
        window.globalLab.closeAll(null);
    },
    closeChildren: function () {
        window.globalLab.closeAll(window);
    },
    createTopWindow: function (url) {
        return window.globalLab.createWindow(null, url);
    },
    createChildWindow: function (url) {
        return window.globalLab.createWindow(window, url);
    }
};

window.onunload = function () {
    window.globalLab.removeWindow(window);
    window.globalLab.closeAll(window);
};

if (window.opener) {
    window.globalLab = window.opener.globalLab;
} else {
    window.onbeforeunload = function () {
        var children = window.globalLab.getWindows();
        if (children.length) {
            window.globalLab.closeAll(window);
            return "You will lose globalLab!";
        }
    };
    window.globalLab = {
        count: 0,
        windows: {},
        createWindow: function (parent, url) {
            var count, w, windows;
            parent = parent || window;
            url = url || "WindowLab.htm";
            windows = this.windows;
            var id = "WindowLabChildWindow" + ++this.count;
            w = parent.open(url, id, true);
            windows[id] = w;
            return w;
        },
        removeWindow: function (child) {
            if (!child) return;
            delete this.windows[child.name];
        },
        alert: function (msg) {
            window.alert(msg);
        },
        getWindows: function (parent) {
            var result, windows;
            parent = parent || window;
            windows = this.windows;
            result = [];
            for (var name in windows) {
                if (windows.hasOwnProperty(name)) {
                    w = windows[name];
                    if (!w.closed && w.opener == parent) {
                        result.push(w);
                    }
                }
            }
            return result;
        },
        closeAll: function (parent) {
            var w, i, windows;
            parent = parent || window;
            w = this.getWindows(parent);
            for (i = 0; i < w.length; i++) {
                w[i].close();
            }
        }
    };
}