The Dark Arts of Self-Writing Code: A Journey from DOS to .NET Sorcery

The Dark Arts of Self-Writing Code: A Journey from DOS to .NET Sorcery

The Beginning of a Digital Sorcerer

Every master of the dark arts has an origin story, and mine begins in the ancient realm of MS-DOS 6.1. What started as simple experimentation with BAT files would eventually lead me down a path to discovering one of programming’s most powerful arts: metaprogramming.

I still remember the day my older brother Oscar introduced me to the mystical DIR command. He was three years ahead of me in school, already initiated into the computer classes that would begin in “tercer ciclo” (7th through 9th grade) in El Salvador. This simple command, capable of revealing the contents of directories, was my first spell in what would become a lifelong pursuit of programming magic.

My childhood hobbies – playing video games, guitar, and piano (a family tradition, given my father’s musical lineage) – faded into the background as I discovered the enchanting world of DOS commands. The discovery that files ending in .exe were executable spells and .com files were commands that accepted parameters opened up a new realm of possibilities.

Armed with EDIT.COM, a primitive but powerful text editor, I began experimenting with every file I could find. The real breakthrough came when I discovered AUTOEXEC.BAT, a mystical scroll that controlled the DOS startup ritual. This was my first encounter with automated script execution, though I didn’t know it at the time.

The Path of Many Languages

My journey through the programming arts led me through many schools of magic: Turbo Pascal, C++, Fox Pro (more of an application framework than a pure language), Delphi, VB6, VBA, VB.NET, and finally, my true calling: C#.

During my university years, I co-founded my first company with my cousin “Carlitos,” supported by my uncle Carlos Melgar, who had been like a father to me. While we had some coding experience, our ambition to create our own ERP system led us to expand our circle. This is where I met Abel, one of two programmers we recruited who were dating my cousins at the time. Abel, coming from a Delphi background, introduced me to a concept that would change my understanding of programming forever: reflection.

Understanding the Dark Arts of Metaprogramming

What Abel revealed to me that day was just the beginning of my journey into metaprogramming, a form of magic that allows code to examine and modify itself at runtime. In the .NET realm, this sorcery primarily manifests through reflection, a power that would have seemed impossible in my DOS days.

Let me share with you the secrets I’ve learned along this path:

The Power of Reflection: Your First Spell

// A basic spell of introspection
Type stringType = typeof(string);
MethodInfo[] methods = stringType.GetMethods();
foreach (var method in methods)
{
    Console.WriteLine($"Discovered spell: {method.Name}");
}

This simple incantation allows your code to examine itself, revealing the methods hidden within any type. But this is just the beginning.

Conjuring Objects from the Void

As your powers grow, you’ll learn to create objects dynamically:

public class ObjectConjurer
{
    public T SummonAndEnchant<T>(Dictionary<string, object> properties) where T : new()
    {
        T instance = new T();
        Type type = typeof(T);
        
        foreach (var property in properties)
        {
            PropertyInfo prop = type.GetProperty(property.Key);
            if (prop != null && prop.CanWrite)
            {
                prop.SetValue(instance, property.Value);
            }
        }
        return instance;
    }
}

Advanced Rituals: Expression Trees

Expression<Func<int, bool>> ageCheck = age => age >= 18;
var parameter = Expression.Parameter(typeof(int), "age");
var constant = Expression.Constant(18, typeof(int));
var comparison = Expression.GreaterThanOrEqual(parameter, constant);
var lambda = Expression.Lambda<Func<int, bool>>(comparison, parameter);

The Price of Power: Security and Performance

Like any powerful magic, these arts come with risks and costs. Through my journey, I learned the importance of protective wards:

Guarding Against Dark Forces

// A protective ward for your reflective operations
[SecurityPermission(SecurityAction.Demand, ControlEvidence = true)]
public class SecretKeeper
{
    private readonly string _arcaneSecret = "xyz";
    
    public string RevealSecret(string authToken)
    {
        if (ValidateToken(authToken))
            return _arcaneSecret;
        throw new ForbiddenMagicException("Unauthorized attempt to access secrets");
    }
}

The Cost of Power

Ritual Type Energy Cost (ms) Mana Usage
Direct Cast 1 Baseline
Reflection 10-20 2x-3x
Cached Cast 2-3 1.5x
Compiled 1.2-1.5 1.2x

To mitigate these costs, I learned to cache my spells:

public class SpellCache
{
    private static readonly ConcurrentDictionary<string, MethodInfo> SpellBook 
        = new ConcurrentDictionary<string, MethodInfo>();

    public static MethodInfo GetSpell(Type type, string spellName)
    {
        string key = $"{type.FullName}.{spellName}";
        return SpellBook.GetOrAdd(key, _ => type.GetMethod(spellName));
    }
}

Practical Applications in the Modern Age

Today, these dark arts power many of our most powerful frameworks:

  • Entity Framework uses reflection for its magical object-relational mapping
  • Dependency Injection containers use it to automatically wire up our applications
  • Serialization libraries use it to transform objects into different forms
  • Unit testing frameworks use it to create test doubles and verify behavior

Wisdom for the Aspiring Sorcerer

From my journey from DOS batch files to the heights of .NET metaprogramming, I’ve gathered these pieces of wisdom:

  1. Cache your incantations whenever possible
  2. Guard your secrets with proper wards
  3. Measure the cost of your rituals
  4. Use direct casting when available
  5. Document your dark arts thoroughly

Conclusion

Looking back at my journey from those first DOS commands to mastering the dark arts of metaprogramming, I’m reminded that every programmer’s path is unique. That young boy who first typed DIR in MS-DOS could never have imagined where that path would lead. Today, as I work with advanced concepts like reflection and metaprogramming in .NET, I’m reminded that our field is one of continuous learning and evolution.

The dark arts of metaprogramming may be powerful, but like any tool, their true value lies in knowing when and how to use them effectively. Remember, while the ability to make code write itself might seem like sorcery, the real magic lies in understanding the fundamentals and growing from them. Whether you’re starting with basic commands like I did or diving straight into advanced concepts, every step of the journey contributes to your growth as a developer.

And who knows? Maybe one day you’ll find yourself teaching these dark arts to the next generation of digital sorcerers.

To be, or not to be: Writing Reusable Tests for SyncFramework Interfaces in C#

To be, or not to be: Writing Reusable Tests for SyncFramework Interfaces in C#

Writing Reusable Tests for SyncFramework Interfaces in C#

When creating a robust database synchronization framework like SyncFramework, ensuring that each component adheres to its defined interface is crucial. Reusable tests for interfaces are an essential aspect of this verification process. Here’s how you can approach writing reusable tests for your interfaces in C#:

1. Understand the Importance of Interface Testing

Interfaces define contracts that all implementing classes must follow. By testing these interfaces, you ensure that every implementation behaves as expected. This is especially important in frameworks like SyncFramework, where different components (e.g., IDeltaStore) need to be interchangeable.

2. Create Base Test Classes

Create abstract test classes for each interface. These test classes should contain all the tests that verify the behavior defined by the interface.


using Microsoft.VisualStudio.TestTools.UnitTesting;

public abstract class BaseDeltaStoreTest
{
    protected abstract IDeltaStore GetDeltaStore();

    [TestMethod]
    public void TestAddDelta()
    {
        var deltaStore = GetDeltaStore();
        deltaStore.AddDelta("delta1");
        Assert.IsTrue(deltaStore.ContainsDelta("delta1"));
    }

    [TestMethod]
    public void TestRemoveDelta()
    {
        var deltaStore = GetDeltaStore();
        deltaStore.AddDelta("delta2");
        deltaStore.RemoveDelta("delta2");
        Assert.IsFalse(deltaStore.ContainsDelta("delta2"));
    }

    // Add more tests to cover all methods in IDeltaStore
}
    

3. Implement Concrete Test Classes

For each implementation of the interface, create a concrete test class that inherits from the base test class and provides an implementation for the abstract method to instantiate the concrete class.


using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public class ConcreteDeltaStoreTest : BaseDeltaStoreTest
{
    protected override IDeltaStore GetDeltaStore()
    {
        return new ConcreteDeltaStore();
    }
}
    

4. Use a Testing Framework

Utilize a robust testing framework such as MSTest, NUnit, or xUnit to ensure all tests are run across all implementations.

5. Automate Testing

Integrate your tests into your CI/CD pipeline to ensure that every change is automatically tested across all implementations. This ensures that any new implementation or modification adheres to the interface contracts.

6. Document Your Tests

Clearly document your tests and the rationale behind reusable tests for interfaces. This will help other developers understand the importance of these tests and encourage them to add tests for new implementations.

Example of Full Implementation


// IDeltaStore Interface
public interface IDeltaStore
{
    void AddDelta(string delta);
    void RemoveDelta(string delta);
    bool ContainsDelta(string delta);
}

// Base Test Class
using Microsoft.VisualStudio.TestTools.UnitTesting;

public abstract class BaseDeltaStoreTest
{
    protected abstract IDeltaStore GetDeltaStore();

    [TestMethod]
    public void TestAddDelta()
    {
        var deltaStore = GetDeltaStore();
        deltaStore.AddDelta("delta1");
        Assert.IsTrue(deltaStore.ContainsDelta("delta1"));
    }

    [TestMethod]
    public void TestRemoveDelta()
    {
        var deltaStore = GetDeltaStore();
        deltaStore.AddDelta("delta2");
        deltaStore.RemoveDelta("delta2");
        Assert.IsFalse(deltaStore.ContainsDelta("delta2"));
    }

    // Add more tests to cover all methods in IDeltaStore
}

// Concrete Implementation
public class ConcreteDeltaStore : IDeltaStore
{
    private readonly HashSet _deltas = new HashSet();

    public void AddDelta(string delta)
    {
        _deltas.Add(delta);
    }

    public void RemoveDelta(string delta)
    {
        _deltas.Remove(delta);
    }

    public bool ContainsDelta(string delta)
    {
        return _deltas.Contains(delta);
    }
}

// Concrete Implementation Test Class
using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public class ConcreteDeltaStoreTest : BaseDeltaStoreTest
{
    protected override IDeltaStore GetDeltaStore()
    {
        return new ConcreteDeltaStore();
    }
}

// Running the tests
// Ensure to use a test runner compatible with MSTest to execute the tests