Code-first Metadata

This is “code first” in the general sense, not the specific sense of Entity Framework. This has nothing to do with Entity Framework at all, except that team showed us how valuable simple access to code-like metadata is.


Code first is a powerful mechanism for expressing your metadata because code is the most concise way to express many things. There’s 60 years of evolution to todays’ computer languages being efficient in expressing explicit concepts based on a natural contextualization. You can’t get this in JSON, XML or other richer and less-opinionated formats.


Code first is just one approach to getting strong-typed metadata. The keys to the kingdom, the keys to your code, lie in expressing the underlying problems of your code in a strong-typed manner, which you can read about here.


The problem is that the description of the problem is wrapped up with an enormous amount of ceremony about how to do what we’re trying to do. Let’s look at this in relation to metaprogramming where the goal is generally to reduce ceremony and


Only write the code that only you can write



In other words, don’t write any code that isn’t part of the minimum definition of the problem, divorced of all technology artifacts.


For example, you can create a SemanticLog definition that you can later output as an EventSource class, or any other kind of log output – even in a different language or on a different platform.


To do this, describe the SemanticLog in the simplest way possible, devoid of technology artifacts.


namespace ConsoleRunT4Example
{
[SemanticLog()]
public class Normal
{
public void Message(string Message) { }
[Event(2)]
public void AccessByPrimaryKey(int PrimaryKey) { }
}

}

Instead of the EventSource version:


using System;
using System.Diagnostics.Tracing;

namespace ConsoleRunT4Example
{
[EventSource(Name = "ConsoleRunT4Example-Normal")]
public sealed partial class Normal : EventSource
{
#region Standard class stuff
// Private constructor blocks direct instantiation of class
private Normal() { }

// Readonly access to cached, lazily created singleton instance
private static readonly Lazy<Normal> _lazyLog =
new Lazy<Normal>(() => new Normal());
public static Normal Log
{
get { return _lazyLog.Value; }
}
// Readonly access to private cached, lazily created singleton inner class instance
private static readonly Lazy<Normal> _lazyInnerlog =
new Lazy<Normal>(() => new Normal());
private static Normal innerLog
{
get { return _lazyInnerlog.Value; }
}
#endregion


#region Your trace event methods

[Event(1)]
public void Message(System.String Message)
{
if (IsEnabled()) WriteEvent(1, Message);
}
[Event(2)]
public void AccessByPrimaryKey(System.Int32 PrimaryKey)
{
if (IsEnabled()) WriteEvent(2, PrimaryKey);
}
#endregion
}
}

Writing less code (10 lines instead of 47) because we are lazy is a noble goal. But the broader benefit here is that the first requires very little effort to understand and very little trust about whether the pattern is followed. The second requires much more effort to read the code and ensure that everything in the class is doing what’s expected. The meaning of the code requires that you know what an EventSource is.


Code-first allows you to just write the code that only you can write, and leave it to the system to create the rest of the code based on your minimal definition.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>