Hello World

The evolution of software development, as illustrated by Hello World.

Hello World (beginner)

namespace HelloWorldApp
{
    using System;

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

Hello World (student)

namespace HelloWorldApp
{
    using System;

    class Program
    {
        const string HelloFormat = "Hello {0}!";

        static void Main(string[] args)
        {
            PrintHello("World");
        }

        static void PrintHello(string name)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ArgumentException(nameof(name));
            }

            Console.WriteLine(string.Format(HelloFormat, name));
        }
    }
}

Hello World (junior developer)

namespace HelloWorldApp
{
    using System;

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                PrintHello("World");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }

        static void PrintHello(string name)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ArgumentException(nameof(name));
            }

            var helloProvider = new HelloProvider();

            Console.WriteLine(helloProvider.ProvideHello(name));
        }
    }
}

namespace HelloWorldApp
{
    using System;

    public class HelloProvider
    {
        const string HelloFormat = "Hello {0}!";

        public string ProvideHello(string name)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ArgumentException(nameof(name));
            }

            return string.Format(HelloFormat, name);
        }
    }
}

Hello World (medior developer)

namespace HelloWorldApp
{
    using System;

    using Microsoft.Extensions.DependencyInjection;

    class Program
    {
        static void Main(string[] args)
        {
            var serviceProvider = BuildServiceProvider();
            var mainApp = serviceProvider.GetService<MainApp>();

            mainApp.Run(args);
        }

        static IServiceProvider BuildServiceProvider()
        {
            var services = new ServiceCollection();

            // register services
            services.AddScoped<IHelloProvider, HelloProvider>();

            // register main application
            services.AddSingleton<MainApp>();

            return services.BuildServiceProvider();
        }
    }
}

namespace HelloWorldApp
{
    using System;

    public class MainApp
    {
        private const string World = "World";
        private readonly IHelloProvider _helloProvider;

        public MainApp(IHelloProvider helloProvider)
        {
            _helloProvider = helloProvider ?? throw new ArgumentNullException(nameof(helloProvider));
        }

        public void Run(string[] args)
        {
            try
            {
                Console.WriteLine(_helloProvider.ProvideHello(World));
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
    }
}

namespace HelloWorldApp
{
    public interface IHelloProvider
    {
        /// <summary>
        /// Provides a "hello" greeting for the given subject.
        /// </summary>
        /// <param name="name">The subject to greet.</param>
        /// <returns>A "hello" greeting.</returns>
        string ProvideHello(string name);
    }
}

namespace HelloWorldApp
{
    using System;

    public class HelloProvider : IHelloProvider
    {
        private const string HelloFormat = "Hello {0}!";

        public string ProvideHello(string name)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ArgumentException(nameof(name));
            }

            return string.Format(HelloFormat, name);
        }
    }
}

Hello World (senior developer)

namespace HelloWorldApp
{
    using System;
    using System.IO;
    using System.Threading.Tasks;

    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;

    using Serilog;

    class Program
    {
        static async Task Main(string[] args)
            => await BuildApplication().Run(args);

        static MainApp BuildApplication()
            => BuildServiceProvider().GetService<MainApp>();

        static IServiceProvider BuildServiceProvider()
        {
            var services = new ServiceCollection();
            var config = BuildConfigurationHierarchy();

            // register logging
            services.AddLogging(x =>
            {
                var seriLogger = new LoggerConfiguration()
                    .ReadFrom.Configuration(config)
                    .CreateLogger();

                x.AddSerilog(seriLogger, true);
            });

            // register services
            services.AddScoped<IHelloConfigurationProvider, HelloConfigurationProvider>();
            services.AddScoped<IHelloProvider, HelloProvider>();

            // register configuraion elements
            services.Configure<HelloWorldConfig>(config.GetSection("HelloWorld"));

            // register main application
            services.AddSingleton<MainApp>();

            return services.BuildServiceProvider();
        }

        static IConfigurationRoot BuildConfigurationHierarchy()
            => new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json", false)
                .AddJsonFile("appsettings.development.json", true)
                .Build();
    }
}

namespace HelloWorldApp
{
    using System;
    using System.Threading.Tasks;

    using Microsoft.Extensions.Logging;

    public class MainApp
    {
        private readonly ILogger<MainApp> _logger;
        private readonly IHelloConfigurationProvider _configurationProvider;
        private readonly IHelloProvider _helloProvider;

        public MainApp(
            ILogger<MainApp> logger,
            IHelloConfigurationProvider configurationProvider,
            IHelloProvider helloProvider)
        {
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _configurationProvider = configurationProvider ?? throw new ArgumentNullException(nameof(configurationProvider));
            _helloProvider = helloProvider ?? throw new ArgumentNullException(nameof(helloProvider));
        }

        public async Task Run(string[] args)
        {
            _logger.LogDebug("application startup");

            var config = _configurationProvider.ProvideCurrentCultureConfig();
            if (config == null)
            {
                _logger.LogError("configuration was not found");
                throw new InvalidOperationException("configuration was not found");
            }

            try
            {
                var greeting = _helloProvider.ProvideHello(config.WorldName);
                _logger.LogInformation("priting greeting: {0}", greeting);
                Console.WriteLine(greeting);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "fatal application error!");
                Console.WriteLine(ex);
            }

            _logger.LogDebug("application shutdown");
        }
    }
}

namespace HelloWorldApp
{
    public interface IHelloProvider
    {
        /// <summary>
        /// Provides a "hello" greeting for the given subject.
        /// </summary>
        /// <param name="name">The subject to greet.</param>
        /// <returns>A "hello" greeting.</returns>
        string ProvideHello(string name);
    }
}

namespace HelloWorldApp
{
    using System;

    using Microsoft.Extensions.Logging;

    public class HelloProvider : IHelloProvider
    {
        private readonly ILogger<HelloProvider> _logger;
        private readonly IHelloConfigurationProvider _configurationProvider;

        public HelloProvider(
            ILogger<HelloProvider> logger,
            IHelloConfigurationProvider configurationProvider)
        {
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _configurationProvider = configurationProvider ?? throw new ArgumentNullException(nameof(configurationProvider));
        }

        public string ProvideHello(string name)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                _logger.LogError("name was null or whitespace");
                throw new ArgumentException(nameof(name));
            }

            var config = _configurationProvider.ProvideCurrentCultureConfig();
            if (config == null)
            {
                _logger.LogError("configuration was not found");
                throw new InvalidOperationException("configuration was not found");
            }

            _logger.LogInformation("proving greeting for name: {0}", name);

            return string.Format(config.GreetingFormat, name);
        }
    }
}

namespace HelloWorldApp
{
    public interface IHelloConfigurationProvider
    {
        /// <summary>
        /// Provides "hello world" configuration for the current culture.
        /// Uses <code>Thread.CurrentThread.CurrentUICulture</code> for culture info.
        /// If no config exists for the thread culture, the default config is returned.
        /// </summary>
        /// <returns>A "hello world" configuration element.</returns>
        HelloWorldCultureConfig ProvideCurrentCultureConfig();
    }
}

namespace HelloWorldApp
{
    using System;
    using System.Threading;

    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Options;

    public class HelloConfigurationProvider : IHelloConfigurationProvider
    {
        private readonly ILogger<HelloConfigurationProvider> _logger;
        private readonly IOptionsMonitor<HelloWorldConfig> _configMonitor;

        public HelloConfigurationProvider(
            ILogger<HelloConfigurationProvider> logger,
            IOptionsMonitor<HelloWorldConfig> configMonitor)
        {
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _configMonitor = configMonitor ?? throw new ArgumentNullException(nameof(configMonitor));
        }

        public HelloWorldCultureConfig ProvideCurrentCultureConfig()
        {
            var languageCode = Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName;
            _logger.LogInformation("detected language code: {0}", languageCode);

            if (_configMonitor.CurrentValue.CultureSettings.TryGetValue(
                    languageCode,
                    out var cultureSpecificConfig))
            {
                _logger.LogInformation("using culture-specific config");
                return cultureSpecificConfig;
            }
            else
            {
                _logger.LogInformation("using default config");
                return _configMonitor.CurrentValue.DefaultSettings;
            }
        }
    }
}

namespace HelloWorldApp
{
    using System.Collections.Generic;

    public class HelloWorldConfig
    {
        public HelloWorldCultureConfig DefaultSettings { get; set; }

        public Dictionary<string, HelloWorldCultureConfig> CultureSettings { get; set; }
    }
}

namespace HelloWorldApp
{
    public class HelloWorldCultureConfig
    {
        public string GreetingFormat { get; set; }

        public string WorldName { get; set; }
    }
}

{
    "Logging": {
        "LogLevel": {
            "Default": "Warning"
        }
    },
    "Serilog": {
        "Using": [ "Serilog.Sinks.RollingFile" ],
        "MinimumLevel": "Warning",
        "WriteTo": [
            {
                "Name": "RollingFile",
                "Args": {
                    "pathFormat": "HelloWorld-{Date}.txt",
                    "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}) {Message}{NewLine}{Exception}"
                }
            }
        ]
    },
    "HelloWorld": {
        "DefaultSettings": {
            "GreetingFormat": "Hello {0}!",
            "WorldName": "World"
        },
        "CultureSettings": {
            "en": {
                "GreetingFormat": "Hello {0}!",
                "WorldName": "World"
            },
            "nl": {
                "GreetingFormat": "Hallo {0}!",
                "WorldName": "Wereld"
            }
        }
    }
}

{
    "Logging": {
        "LogLevel": {
            "Default": "Debug"
        }
    },
    "Serilog": {
        "MinimumLevel": "Debug"
    }
}

Hello World (principal developer)

namespace HelloWorldApp
{
    using System;

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}