Phillip Trelford's Array

POKE 36879,255

Metadata: data about data

Compilers for statically typed languages like C# and F# maintain data about types from programs. This type data is used at design time to provide IntelliSense and during compilation to generate new types and bind to existing types. We can think about this type data in the abstract as data about data, or Metadata. In statically typed languages the typed Metadata is typically imported and generated from typed programs.


Question:

What if a compiler could be augmented with metadata from other sources, say a database or an XML DTD or a DSL?

Answer:

Then we could map to data easily inside our programs without resorting to either late binding or a code generation step!!!


Examples of accessing attributes of an XML element

1: Late-binding with string literals (F#)

let person = XElement.Parse("<Person Name=\"Bob\"/>")
let name = person.Attribute(XName.Get "Name").Value

 

2: Late-binding with dynamic lookup (F#)

// Define dynamic lookup operator
let (?) (el:XElement) (name:string) = el.Attribute(XName.Get name).Value
// Lookup Name attribute
let name = person?Name

 

3: Code generation using XSD.exe (C#)

string xml = "<Person Name=\"Bob\"/>";
var s = new XmlSerializer(typeof(Person));
var person = s.Deserialize(new StringReader(xml)) as Person;
var name = person.Name;

 

4: Hypothetical code binding (F#)

let person = XmlProvider.LoadXml("<Person Name=\"Bob\"/>")
let name = person.Name

 

The first 1st and 2nd methods using late-binding in effect use string-literals so lack type safety. The 3rd method required a code generation step that generated a whopping 62 lines of C# code to map 1 XML element with a single attribute.

The 4th (hypothetical) method provides all the immediacy benefits of a dynamic language like Python with the compile time safety and ease of use of a statically typed language.

PDC 2010: The Future of F#: Data & Services at Your Finger Tips – Don Syme:

Programming today exhibits a voracious appetite for information, and one of the most important trends in languages today is to make access to data and services fluent and seamless. Come and see the latest from the F# team, and learn how we are extending F# to embed the analytical programmer instantly in a world of typed data and services, whether they be web, enterprise, client or local.

From the slides that are now up on the PDC site, it looks like F# 3.0 is about to deliver!

Declarative Naming

Like sentence construction, declarative programming requires careful selection of words. Nouns for class and property names, verbs for method and event names.

Ignoring the arbitrary ‘I’ at the start of interface names, nouns or adjectives can describe their capabilities, e.g. comparable, equatable and observable.

Declarative names should describe the “what” without the “how”. Short names typically indicate good abstraction. Long or schizophrenic names are a code smell suggesting poor separation of concerns and that refactoring may be required.

Luke“ Luke. Let the force words guide you.”

A Brief History of Naming

In the beginning, Microsoft operating systems such as MS-DOS or Windows 3.x did not support long file names like other operating systems such as Unix, OS/2, and the Apple Macintosh MAC OS. The earlier versions of Microsoft's operating systems had a limitation of an eight character file name or directory, and a three character extension. [Information about long file names]

Going back a bit further to the 8-bit era of computing, I remember my first Z80 assembler for the Amstrad CPC, HiSoft’s DevPac which only treated the first 6 characters of a label as significant. Meaning coding schemes for labels were required for larger programs, a bit like postal codes for addresses, .

Later with newer assemblers, CPUs and C, restrictions relaxed, but naming conventions like Hungarian notation remained to indicate things like the types of variables. Thankfully with the advent of modern compilers and IDEs, bringing type checking and type information on tooltips, the need for these notations has been removed. Nowadays we should be free to focus on good declarative naming.

Declarative Naming Resources

When following a variant of Domain-driven design (DDD), a ubiquitous language helps define names for core business concepts. This just leaves naming for technical abstractions, and there are plenty of resources out there to help.

Online:

Books:

And now for some examples…

Managers

Like a manager typically has no specific role, so a manager class is probably a poor abstraction. More often than not you’d be better starting with a collection.

INotifyPropertyChanged

In an MSDN article by Josh Smith on MVVM, a ViewModelBase class is suggested that implements the INotifyPropertyChanged interface. To me this seems a poor abstraction as a class need not be a View Model in order to implement this interface, and the name gives no obvious indication to its behaviour, instead suggesting a set of base behaviours. A better abstraction would be ObservableObject, like the framework’s ObservableCollection class which implements the not too dissimilar INotifyCollectionChanged interface.

IDictionary

An improvement on the naming of the pre-generics un-typed equivalent Hashtable class, the Dictionary class better specifies the “what” over the “how”. However the new underlying generic IDictionary interface could be improved by separating the concerns of reading and writing items across 2 interfaces.

GetOrAdd

The new ConcurrentDictionary class in .Net 4.0 contains a method GetOrAdd. Again in terms of naming, this seems to be a poor abstraction, and again by emphasizing the “how” rather than the “what”. A better name would be Obtain, a suggestion in a Martin Fowler tweet.

ToString

A good example of declarative naming, also promoting the idea of functional transformation and idempotence.

Pluralisation

I like pluralisation for collections, e.g. Items, its both short and descriptive. The new IObservable<T> interface as used by the Reactive Extensions (Rx) also seems to lend itself well to pluralisation, e.g. Notifications.

Last word?

For variable names the last word of the object may suffice, e.g.

let connection = new SqlConnection()

Finally

KentBeck: if you can’t find a really good name for something, pick a really terrible name (i like "fred"). then you are motivated to fix it.

Disclaimer:

For legacy code consistency may be as important as declarative naming, so abandoning coding schemes like Hungarian notation on a large codebase may be counter-productive.

Silverlight 4 Calculator Sample in F#

If you have Silverlight 4 installed you should see a calculator sample below coded in F#. The sample originally targeted WPF, only a few modifications were required to run in Silverlight:

  • the view is hosted in a UserControl instead of a Window
  • a C# project is used to launch the UserControl and generate the Silverlight XAP file

The sample demonstrates creating a View in WPF or Silverlight without XAML. The idea is to make things a little easier from F# by implementing a (+) operator overload to attach dependency properties.

The following snippet shows the keypad being constructed by transforming tuples describing the key character and action to buttons:

let keys =
    let grid = new Grid()
    for i = 1 to 4 do
        ColumnDefinition() |> grid.ColumnDefinitions.Add 
        RowDefinition() |> grid.RowDefinitions.Add
    [ 
    ['7',Digit(7);'8',Digit(8);'9',Digit(9);'/',Operator(Divide)]
    ['4',Digit(4);'5',Digit(5);'6',Digit(6);'*',Operator(Multiply)]
    ['1',Digit(1);'2',Digit(2);'3',Digit(3);'-',Operator(Minus)]
    ['0',Digit(0);'.',Dot;'=',Evaluate;'+',Operator(Plus)]
    ]    
    |> List.mapi (fun y ys ->
        ys |> List.mapi (fun x (c,key) ->
            let color =
                match key with
                | Operator(_) | Evaluate -> Colors.Yellow
                | Digit(_) | Dot -> Colors.LightGray                        
            let effect =
                Binding("Operator",
                        Converter=operationEffectConverter,
                        ConverterParameter=key)    
            Button(Content=c,CommandParameter=key,
                Width=40.0,Height=40.0,Margin=Thickness(4.0),
                Background=SolidColorBrush(color)) +                
                Button.CommandBinding(Binding("KeyCommand")) +
                Button.EffectBinding(effect) +
                Grid.Column(x) + Grid.Row(y)                         
        )
    )
    |> List.concat
    |> List.iter (grid.Children.Add >> ignore)
    grid

 

Note: This article is more a thought experiment in trying F# code instead of XAML to describe a View. In many cases XAML with a C#/F# View Model may be the pragmatic choice.

PS There is a very concise WebSharper F# Calculator sample, that generates JavaScript.

SilverlightCalculator.zip (10.09 kb)