Sunday, May 31, 2009

motivation for Andand.NET

Some of my followers on twitter encouraged me to post about my andand implementation, so here is the first in a series.

In brief: I wanted to replace

if (a != null && a.b != null && a.b.c != null) {
return a.b.c.d;
}
else {
return null;
}

by

return andand(a.b.c.d);

and I manged to learn a little bit about monads, generalized algebraic data types, and .NET on the way to achieving

return andand(() => a.b.c.d)


About a month ago I was working with an instance of a generic type:

var page = Potpourri.Page.getPage(s, count.Value);
ViewData["reverse-memento"] = page.reverseMemento.itemNumber;

This code obtains a range of rows from a database given a starting position and a window size. Simple integer offsets don't work for the general case of concurrent access by lay users to a mutable table. My approach requires getPage to know an equivalence relation on elements, but it doesn't require that getPage know about itemNumber specifically or even that there be just one field/property that's sufficient to determine equality.

So, AFAICT, there's no good way to avoid violating Demeter here.

Certainly there remains a practical problem that the next and previous page references could be undefined for any given page. In this case, reverseMemento could be null.

The awkward conditional needed to avoid NullReferenceException here brought to mind Object#andand. Informally, andand provides short-circuit behavior for chained accesses. The Ruby andand relies on Ruby metaprogramming features. The closest thing we have to a macro facility in c# is Linq expression trees, and I hadn't had an excuse to use System.Linq.Expressions yet, so this seemed like a good opportunity.

My first implementation directly transformed expression trees, replacing member accesses by conditional member accesses that return null whenever a is null in a.b.

My second implementation was inspired by a question about the relation between andand and the Maybe monad. I thought it would be a good idea to (re)read some papers about monads and test my understanding by implementing a few, including Maybe Monad. I also thought it would be instructive to implement Maybe monad in terms of andand, and andand in terms of Maybe monad.

I'll discuss the code in detail in my next post. For now, you can download a snapshot. I guess I'll migrate my existing hg repo to googlecode in time for the next post to make browsing easier.

Monday, May 18, 2009

.emacs

; Some people I know have asked about my .emacs. Voila:

(custom-set-faces
;; custom-set-faces was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
)

(setq default-buffer-file-coding-system 'unix)

(setenv "PATH" (concat "c:/cygwin-1.7/bin;" (getenv "PATH")))
(setq exec-path (cons "c:/cygwin-1.7/bin/" exec-path))

(require 'cygwin-mount)
(cygwin-mount-activate)

(add-to-list 'load-path "/cygdrive/c/program-files/emacs-22.3/site-lisp")

(add-to-list 'auto-mode-alist '("\\.cs$" . java-mode))
(add-hook 'java-mode-hook
(lambda ()
(setq indent-tabs-mode nil)))

(autoload 'js2-mode "js2" nil t)
(add-to-list 'auto-mode-alist '("\\.js$" . js2-mode))
(add-hook 'js2-mode-hook
(lambda ()
(setq indent-tabs-mode nil)))

(autoload 'python-mode "python-mode" "Python Mode." t)
(add-to-list 'auto-mode-alist '("\\.py\\'" . python-mode))
(add-to-list 'interpreter-mode-alist '("python" . python-mode))
(add-hook 'python-mode-hook
(lambda ()
(set (make-variable-buffer-local 'beginning-of-defun-function)
'py-beginning-of-def-or-class)
(setq outline-regexp "def\\|class ")
(setq indent-tabs-mode nil)))

(load (concat "/cygdrive/c/program-files/emacs-22.3/site-lisp/" "nxml-mode-20041004/rng-auto.el"))
(add-to-list 'auto-mode-alist '("\\.\\(xml\\|xsl\\|rng\\|xhtml\\)\\'" . nxml-mode))
(add-hook 'nxml-mode-hook
(lambda ()
(setq indent-tabs-mode nil)))
(setq magic-mode-alist
(cons '("<\\?xml" . nxml-mode)
magic-mode-alist))

(setq binary-process-input t)
(setq w32-quote-process-args ?\")
(setq shell-file-name "bash") ;; or sh if you rename your bash executable to sh.
(setenv "SHELL" shell-file-name)
;; For subprocesses invoked via the shell
;; (e.g., "shell -c command")
(setq explicit-shell-file-name shell-file-name)
(setq explicit-sh-args '("-login" "-i"))

(put 'erase-buffer 'disabled nil)

Thursday, April 23, 2009

API refs no longer fashionable

Recently it seems that API references have gone out of fashion. I'm guessing VS.NET IntelliSense might explain the lack of interest? Well, IntelliSense is no good for lengthy explanations. And so far nobody has cared enough about IntelliSense to implement it for C# and Emacs.

So I'm going to keep on publishing API ref pages for the free software I write.

BTW, I eventually found an NHibernate API ref.

Sunday, April 5, 2009

Oops.NET

I think the world needs another error-handling module for .NET applications.

My experience working in the IT departments of big companies suggests that most .NET applications do not behave well under exceptional circumstances. Sometimes programmers ignore exceptions and allow their programs to corrupt data. More often, our apps lose valuable diagnostic information during crashes. Occasionally, while attempting to preserve diagnostic details, our programs cause cascading failures that overshadow the original!

So, contrary to my first impression, even very simple error-handling code in thoroughly mundane programs is not too trivial share.

Before writing yet-another error handling module, I searched for something to reuse.

Microsoft's Enterprise Library has an exception handling module. In the old days, one reason to avoid it was because of its restrictive license; these days it is offered under the permissive MS-PL. But, it's still not right for most of the (small) apps I encounter, because its purpose is to provide high-level abstractions for conditions throughout an application.

ELMAH is aimed at ASP.NET specifically, but it wants to do data access and logging on its own. I do recognize the irony in launching competition for ELMAH due to ELMAH's tendency to reinvent the wheel, but I strongly value small sharp tools.

So I'm making something new.

It's conceptually based on the "oops page" I wrote for Tyco Healthcare iDeal many years ago. iDeal was an ASP.NET app that helped salespersons develop contracts; the Oops page gave our users an easy way to file bugs so that we wouldn't have to decipher vague phone messages and partial screenshots of ASP.NET default backtraces any more.

At Anheuser-Busch, our Enterprise Architecture group used to hand out sample code to illustrate our policies about how .NET apps (ASP.NET apps in particular) should crash. The sample could only be obtained by asking for it, which effectively encouraged teams to guess about its contents. The sample tried to show a few variations on its theme, but its presentation confused many teams, who either copied redundant code or omitted crucial details. We needed production-quality reusable code rather than sketches that wound up being reused by copy-and-paste. Because iDeal Oops was proprietary, and because it didn't address console apps, WinForms, Web Services, etc., I had to rewrite it for A-B.

Now I find myself back at the company formerly known as Tyco Healthcare, and I see apps that would benefit from Oops. I could extract Oops from iDeal, package it as nicely as the code I wrote for A-B... But I'm afraid I might wind up working on .NET at some other company, and I never want to have to rewrite this code again. And, it's clearly worth sharing.

So, I'm finally publishing Oops.NET. Coming soon: log4net integration demo, bugzilla integration demo, and support for WinForms, System.Web.Services, System.ServiceModel, and WPF.

Friday, February 13, 2009

underrated: Class Library Projects

This is the preface for vsweb.

My first job after college was programming and sysadmin at BigCo, mostly working on the ASP.NET framework. Early on, I was basically working alone as an programmer although I had a mentor/partner for the sysadmin role. Later, I joined a team that was just beginning to function in fact, although in the tradition of BigCo it had been called a "team" for years before that. There was little development infrastructure in place, and what we had was disfunctional -- think Visual SourceSafe, with MS Office documents and SharePoint lists for defect tracking and planning. I suggested we switch to SVN, my teammate Mike pushed for draco.net (CI), I setup a Bugzilla instance, we held an NUnit tutorial, and a couple of years later we had some some experience with organizing a team software development effort and supporting it with various tools. Things eventually stabilized and the main challenge at work shifted from learning to explaining.

My second job was coaching and mentoring for another BigCo. My new employer had not a dozen but hundreds of programmers, hence the ability specialize full-time on reflective work. In this role, I was exposed to a much larger and broader set of projects than I would have been as an ordinary programmer. I had the opportunity to revisit the lessons I'd learned before, see how they fit with new evidence, and articulate them for the benefit of others.

So, that's how I came to write vsweb: why web application developers should use Class Library Projects rather than project templates whose names include the word "web." Enjoy.