Saturday 26 October 2019

book cover I haven't been as frustrated with a book as with Lightless for a long time. Everyone in it is incompetent to the level of cretinism. The only people remotely good at what they do are psychos, all of them.

I understand why books like these need to be written: when you write a character based play-like story you become a better writer, but it doesn't mean what you write is any good. In this case, a character based story has cardboard shapes moving around randomly instead of characters. It failed. The main character is a computer programmer. As one, I felt insulted that C.A. Higgins believes we are that moronic.

As for the plot, that's the most redeeming factor, but it's not great either. In a future where mobile devices don't exist and locks are still based on physical keys and the Solar System is under the iron boot control of ... err... The System, an organization straight out of Blake's 7, with the same cartoonish efficiency, a mysterious ship is boarded by two people who turn out to be criminals the System wants. 90% of the book is people being dumb and talking to each other, all while assuming they are the bread of the universe. The rest is people doing really dumb things.

Conclusion: all the "smart" bits of the book were obvious from the start, making the journey of the buffoons in the story to figure them out really boring. The idea of the Ananke was added only to make this, of course, a trilogy. It reads like a theater play with people being stuck in a room.

FizzBuzz for the next generation

FizzBuzz is a programming task that is often used for job interviews, because it shows the thinking of the candidate in an isolated and concrete case. The requirements may vary slightly, but is goes like this: A loop is going through numbers from 1 to 100. The candidate must write the code in the loop that will display, for each number, a string. This string is: "Fizz" for numbers divisible by 3, "Buzz" divisible by 5 and "FizzBuzz" for numbers that are both divisible by 3 and 5. For all other numbers, just display that number.

There have been many implementations of this, for example my own in JavaScript from a while ago and FizzBuzz Enterprise Edition, which is always a good read about how not to complicate your code. However, since I've last written about it, JavaScript has changed, so I felt compelled to write an updated version. And here it is:
(d=n=>('0369'.includes((f=n=>n>9&&f([...''+n].reduce((s,v)=>+v+s,0))||n)&&f(n))&&'Fizz'||'')+(/[05]$/.test(n)&&'Buzz'||'')||n)*(i=n=>n>100||console.log(n+': '+d(n))+i(n+1))*i(1)

Among the abominations there, some of them inspired by C++ because why not, there are some of the new JavaScript constructs, like arrow functions and the spread operator. I know it seems pointless, but it's not: try to understand what the code does. If you want to see it in action, open Dev Tools in any browser and copy paste it in the console.

Tuesday 22 October 2019

Adding comments to SQL code generated by Entity Framework Core

A funny feature that I've encountered recently. It's not something most people would find useful, but it helps tremendously with tracing and debugging what is going on. It's easy, just add .TagWith(someString) to your LINQ query and it will generate comments in SQL. More details here: Query tags.

Code Coverage in .NET Core

One of the best things you could do in software is unit testing. There are tons of articles, including mine, explaining why people should take the time to write code in a way that makes it easily split into independent parts that then can automatically tested. The part that is painful comes afterwards, when you've written your software, put it in production and you are furiously working for the second iteration. Traditionally, unit tests are great for refactorings, but when you are changing the existing code, you need not only to "fix" the tests, but also cover the new scenarios, allow for changes and expansions of existing ones.

Long story short, you will not be able to be confident your test suite covers the code as it changes until you can compute something called Code Coverage, or the amount of your code that is traversed during unit tests. Mind you, this is not a measure of how much of your functionality is covered, only the lines of code. In Visual Studio, they did a dirty deed and restricted the functionality to the Enterprise edition. But I am here to tell you that in .NET Core (and possibly for Framework, too, but I haven't tested it) it's very easy to have all the functionality and more even for the free version of Visual Studio.

These are the steps you have to take:
  • Add coverlet.msbuild NuGet to your unit tests project
  • Add ReportGenerator NuGet to your unit tests project
  • Write a batch file that looks like
    @ECHO OFF
    dotnet test "YourProject.csproj" /p:CollectCoverage=true /p:CoverletOutputFormat=\"opencover\" /p:CoverletOutput=bin/coverage --collect:"code coverage"
    "..\packages\reportgenerator\4.3.0\tools\netcoreapp3.0\ReportGenerator.exe" "-reports:bin\coverage.opencover.xml" "-targetdir:bin/CoverageReport" "-assemblyfilters:-*.DAL*" "-filefilters:-*ServiceCollectionExtensions.cs"
    start "Code Coverage Report" "bin/CoverageReport/index.htm"
    
    and save it in your unit test project folder
  • Optional: follow this answer on StackOverflow to be able to see the coverage directly in Visual Studio

Notes about the batch file:
  • 4.3.0 is the current version of ReportGenerator, change it with whatever version you have
  • the DAL filter tells the report to ignore projects with DAL in their name. You shouldn't have to unit test your data access layer.
  • the ServiceCollectionExtensions.cs filter is for files that should be ignored, like extension methods rarely need to be unit tested

Running the batch should start dotnet test and save the result in both coverage.opencover.xml and also some files in the TestResults folder. Then ReportGenerator will generate an html file with the coverage report that will get open at the end. However, if you followed the optional answer, now you are able to open the files in TestResults and see what parts of your code are covered when opened in the Visual Studio editor! I found this less useful than the HTML report, but some of my colleagues liked the option.

I hope this helps you.

Ascension (Tangled Axon #1), by Jacqueline Koyanagi

book cover If you want a book about women feeling stuff and constantly interrupting each other whenever they are about to communicate anything relevant while acting like space pirates in a desolate corporate universe, but doing nothing particularly consequential, Ascension is the book for you.

It is the distant future: space is called The Big Quiet, the universe has turned into a cosmic version of bankrupt Detroit because of the infusion of magic tech coming from a different universe (well, it's baryonic matter infused with human will, but yeah... magic) and all major characters are women and most of them are lesbian. About what you would expect from Jacqueline "(J)" Koyanagi, who describes herself via marketing as "writes science fiction and fantasy featuring women of color who love other women, disabled characters, neuroatypical characters, and diverse relationship styles.".

The main character is a female engineer (ugh, space surgeon) that falls in love with a peg leg female captain of a starship (that she also falls in love with) while being pursued by the authorities for something they didn't do. The physical attraction between the two girls is so strong that events like death of her family or genocide are just pushed in the background.

I guess we need books like these to realize how someone might act annoyed with books that only contain straight male characters, but other than that this is just low quality space pulp. And this trend is taken to a point so extreme that in the whole book there are only three males: a man who is part wolf, full of muscle, brooding silence and the occasional snarl, a security guard who is incapacitated before acting and the husband in a random family who's first act is to isolate and attack the protagonist before also being quickly disabled. I pity women who see males like this.

Bottom line: I read it all just to see if behind all the agenda bullshit there was anything interesting related to story or characterization or world building. But no.

Beer Money: A Memoir of Privilege and Loss, by Frances Stroh

book cover The autobiography of an artistic daughter of a beer tycoon, Beer Money has almost nothing to do with beer, but everything to do with how we can't really choose your family and how toxic interacting with them can be. I liked the writing and sad as it is, the book was not meant to be dramatic, only truthful.

It was a difficult book to finish, even as it was very personal, as I like biographies to be. Mostly because it is just biographical, with nothing in the lives of the characters that has any meaning. The only lesson one can learn from the book is that once you realize your family is crap, you should stay away, no matter how difficult it would be. A very valuable lesson, I agree, but singular.

Frances Stroh is part of the old German family that introduced fire brewed beer to the US on a large scale. Their Detroit empire imploded from bad management by family members, the collapse of the car industry and so on. And while that was going on, she had to contend with a passive mother, a father with an inflated ego who couldn't care less about the people around him unless in rare moments that seemed like a heavenly gift to respect and love deprived children, siblings who went into drugs and alcohol to avoid the pain and last but not least the lukewarm reaction of the world to her own artistic ambitions.

The author seems to have accepted her fate and the strained love/disappointment relationship with the most important people in her life. I liked it and I thought Frances Stroh has a gift for melancholic writing, but I can't really recommend it to most people.

Wednesday 16 October 2019

Epiphany! Why political correctness is wrong.

Just has a revelation. There are studies that show the moment you introduce currency in a social transaction, the dynamics change dramatically, leading to conflict, selfishness and the dissolution of societal and even emotional bonds. For a random reference check this article: Why Good Deeds and Money Don’t Mix.

I've been struggling with this new political correctness movement because 1) I didn't get it 2) almost every one of the people actively acting offended in this context appears to be... not nice and 3) it doesn't seem to be helping any. So, am I the bad guy? I started to ask myself. Am I a racist homophobic sexist misogynistic normie white male working in the tech field or is there something else going on? Judging by how far from normie people who actually know me think I am, I started to think about it more.

And it came to me! Political correctness is a form of currency forcefully introduced into our social transactions. Not only is it causing trouble for people who are assholes, but also for normal people who suddenly feel they have to pay something. And, as currency does, it breaks society, not strengthens it.

That is why so many people caught in this are so violent and partisan about it. That is why when you are nice towards a - I don't even know how to call them these days - not white person it feels good, as it would being nice towards anybody else, but when you are forced to do it, it well... feels forced. It feels like duty, like work, like paying a tax. The concept of balance slowly creeps in and makes one push back. Maybe with a joke, maybe with an angry tweet, maybe with something worse like actually picking on someone for their skin color, sex, age, religion or anything else. And they do it because picking on someone for being... I don't know... Romanian, doesn't feel like restoring anything. And now Romanians are pretty angry, because offending Jewish people or of recent African descent is somehow "wronger", so they get offended and feel left out. It's wrong to pick on anyone either way, deal with it!

In the end, introducing currency just pushes people into two diametrical opposed groups: the payers and the people who are owed. And of course, the people who ride the wave and get their little percentage to convert it to any other currency: money, hate, power, etc. We become slaves to the middlemen even when we interact with other people! Hell, they want to introduce ethics for computers now. Where does it end?!

So, as I am an egalitarian in my misanthropy, I submit that you should get offended by people just like any other person would. Leave currency to bankers. Or pick on them! No one ever got into a twist for calling bankers names.

Sunday 13 October 2019

The Troop, by Nick Cutter

Book cover I started reading The Troop after reading some amazing reviews on how creepy and scary it is, how well it is written and so on. I agree this is a good book, but not without its faults. It felt like a rollercoaster, because at first I thought it's going to be a monster body horror, which I like, then it turned out it could be a contagion story, which I love, maybe even a world wide epidemic, which I always hope for, but yet it wasn't. I thought it resembled a cross between King's Dreamcatcher and Golding's Lord of the Flies.

The best part is Nick Cutter's writing. He is careful with his characters, goes deep into defining their motivations, their inner thoughts. I loved that he would have filtered their previous experiences through a horror lens, so even their histories are aligned to the mood of the book. I know it's a common writer tool and he's a bit obvious about it, but I personally enjoyed it. Then there is the story, which happens on an isolated island and involves children being horribly killed by a relentless organism. I'm a sucker for those. Overall, the book was great. It felt like a Stephen King novel and the author paid homage to the writer in the acknowledgements section.

However, there were some elements that annoyed the hell out of me. One of them was the use of interviews and official reports and news stories about what was going to happen. It spoiled so much of the plot! Then there was the character dynamic. Such wonderfully crafted people seemed to not do anything of what they were supposed to do and the idea is that in terrible circumstances, our mettle is truly tested and the real person surfaces, but in many cases what the characters did made no sense. Even if well written, the basic archetypes were kind of obvious, too. And finally the technical aspects of the plot looked good on paper, but do not stand up to scrutiny.

Some notes: the horror of Lord of the Flies comes from showing how horrible ordinary people, children, can be. They are not psychos, they are people. Cutter overused psychopaths in The Troop. The tension in King's novels is growing and growing and is almost never released until the very end. Cutter spoiled what was going to happen and even if he described horrible things, he kind of did it in a constant way that got tiresome after a while. Worst of all, these flaws in the book made it predictable.

Bottom line: the book proves great writing talent and knowledge of people's character, however the author feels too nice to push the boundaries to do something truly brilliant. Well, he is Canadian...

Friday 11 October 2019

An incremental way of improving exception throwing in C#

There is one basic functionality of all main programming languages: throwing exceptions. Determining in code that something is wrong, one throws an exception of a certain type with extra messages and values. The problem this solves is breaking an execution flow that has entered an invalid state and being aware of what happened. Traditionally, errors are then caught in higher levels of the application and decisions are made: ignore the error, log it, encapsulate it into another exception with extra information, throw it as it is after some cleanup, etc.

But as the joke goes, now you have two problems. When developing .NET code you have to ask yourself what type of exception you are going to throw, what data to add to it and think of what will catch it above and how will it interpret what you sent. Some people create a different exception type for each little issue, in view of the multiple catch(SpecificExceptionType) functionality, so they can choose later what to do at a higher level. Others try to use the out of the box Microsoft exception types, a clear case of stuffing square pegs in round holes. Inevitably someone will just give up in frustration and throw a new Exception("Something went wrong!"); and be done with it. And recently, in order to solve the problems with the above approaches, I envisioned (with full documentation and implementation) a dependency injected IExceptionFactory which I thought was the greatest invention since fire only to discover it was so unwieldy to use that I despaired and deleted the entire thing.

Discussion


Discussing with friends about this deceptively complicated problem, I think I found a solution that covers all major scenarios. But before doing that, I can just feel that some of you thought "Hey! I am doing that and there is nothing wrong with it!", so let's discuss what's wrong with the approaches above. If you want to skip this, go to The Solution section.

Multiple Exception implementations


Extending Exception is not simple. There are four constructors and I dare you to say out the top of your head what Exception(SerializationInfo, StreamingContext) is and where it is used. There are numerous code analyzers that spew a lot of warnings about how Exceptions should be implemented correctly. That's another story: here is a nice article about it. More importantly, doing all this work for every possible exception takes time and effort and duplicated code. In the end, you will get to the next scenario, but with a larger set of hole shapes.

Also, the try/catch block in C# 6.0 has been updated with the catch when syntax, so you can have multiple catch blocks with the same Exception type and different conditions.

Using existing exception types


If you get an empty string from a method and you expected something there, you should throw an exception, but which one? The value is not null, so ArgumentNullException is kind of not applicable. Is ArgumentOutOfRangeException better? I mean, empty string is not in the range of accepted values for the parameter, maybe it could be it. Or is it just ArgumentException? You decide on ArgumentException and you smugly add the name of the variable with nameof(yourLocalVariable), because you are knowledgeable in the ways of code... and you get a warning that yourLocalVariable is not the name of any parameter of the method you are in. That's right, the value was invalid, but ArgumentExceptions are used specifically for the current method arguments.

You don't want to use multiple custom exception types, because you've read this post and abandoned it half way, but you agreed with the first point. Or maybe you are just lazy. You ignore the warning, you use ArgumentException anyway. Later on you are reading the logs and are trying to remember where in the code you used yourLocalVariable and why does it matter it's empty.

Admit it, the Microsoft exception types were not really meant to help you throw exceptions, they are there for Microsoft's internal code and use. Most of the few cases when the exception type is spot on are probably not what the makers of that exception type envisioned when they made it.

Using Exception and a meaningful message


You are done with pointless standards. You just use throw new Exception($"This really specific thing happened with variable {yourVariable}"); and let God sort them out! You can use catch when to look into the string and parse it for information and make decisions on it. It actually works, you're rightly satisfied with yourself. You've showed them all how it's done. Boom! And then a junior developer comes along and decides your wording it not quite right for a native English speaker and changes the string. Suddenly everything literally goes boom, as exceptions get where they shouldn't and flows change unexpectedly.

After warning the entire team to never change the exception strings as they are used in the functionality of the application and you even consider creating a resource system for Exception strings so that it can be used for decision making regardless of content (and inevitably hate the way you need to store format strings and remember what value goes where), a member of the UI team comes and says "Hey, I need to get the reason the flow failed to the user. And I need to translate it to their language". And you despair.

Using a single type of Exception that has everything you need


A slight variation on all of the points above, this involves creating only one type of custom exception, add to it whatever is needed to determine flow, string resource ids, etc. This is actually a pretty decent idea, as it puts the control back into the developer's hands. Why depend on Microsoft types or parsing strings. Context is for kings and you are a king amongst kings.

However, whenever you want to change something, like add a value to an enum that defines the type of the exception, change the way in which a certain exception is handled, you have to change all the code that uses that exception. It's a single point of use, but not a single point of change.

Moreover, other devs in the team think it is cumbersome to work with it. The exception type is stored in the basest of libraries and they all want to add something to it. It becomes bloated and soon enough it creeps into a huge mess that is handled differently in different code and is not easy to maintain, understand or use.

Another layer of indirection


So why not use an exception factory? Everything else in your code works on the premise that "if you want something, you inject an ISomething in the constructor and worry about the implementation never". Why not inject IExceptionFactory everywhere where you need exceptions, then do something magic with it? The result of the operation is determined by the implementation, too. If you want another implementation, you just inject something else. It's genius!

Only then you have to use it. How do you inject the factory in static methods, extension methods, stuff so basic that it used as utilities classes all over the code and now you have to add an extra dependency to everything that uses those classes? Everybody hates you, hates having to add an extra constructor parameter, an extra field, then throw exceptions with something like throw _exceptionFactory.New("Something went wrong!",new ParameterEmptyExceptionData(nameof(localVariable), localVariable)); while adding a dependency to the logging library that the factory uses to log generated exceptions.

Oh, it's just crap!

The Solution


Let's start from an existing piece of code: throw new ArgumentException("{localVariable} is null or empty");. Optimally, we would just want to change this code slightly to solve several issues:
  • formalize that it is an argument empty exception
  • make it clear it's localVariable that was empty
  • maybe add the actual value of localVariable
  • declare the context in which the exception was thrown
  • declare the message that should be used in the exception
  • throw a meaningful exception type
  • decide if this exception should be ignored or thrown
  • log the exception
  • minimize developer effort
  • minimize dependencies
  • use a solution that is closed for modification, but open for extension

A tall order, especially since we've already decided that we don't want to use the factory idea. Some of the issues above are also non-issues in most cases. What if I don't care about the language of the message or if it is a resource or not, it's something used internally in our code. localVariable is empty, I don't need its value. The context is clear from the Stack trace. The exception is meaningful enough as an ArgumentException. In other words, we need to solve one more issue: all of the issues above are optional.

The software pattern that covers this scenario and has been used extensively by library makers is the build pattern. For the sake of exploration, let's see how this would work:
var exception = new ArgumentException("{localVariable} is null or empty");
var builder = new ExceptionBuilder(ex, logger)
                       .SetError(Error.EmptyValue)
                       .SetName(nameof(localVariable))
                       .AddValue(localVariable)
                       .SetOrigin("Getting the localVariable in order to save the world")
                       .SetMessageId(Messages.EmptyWorldNameWhenTryingToSaveIt)
                       .ShouldBeIgnored();
  throw builder.Build(); // this also logs and returns an exception of a type the builder decides relevant

This looks promising, considering that every method above is optional, except the builder instantiation and the build at the end, but it's still too close to the factory idea above. Why use new in a project that is based on dependency injection? Why use .Build() everywhere where you need to throw an exception. Where does the logger come from?

So here is the solution I am proposing, using several resources we have at our disposal in C#:
  • the Exception type has a Data Dictionary property for additional data
  • extension methods can be defined in multiple places for the same type
  • there is no need for an instance of a builder when throwing an exception or Build

The code will look like this:
throw new ArgumentException("{localVariable} is null or empty")
             .SetError(Error.EmptyValue)
             .SetName(nameof(localVariable))
             .AddValue(localVariable)
             .SetOrigin("Getting the localVariable in order to save the world")                       
             .SetMessageId(Messages.EmptyWorldNameWhenTryingToSaveIt)
             .ShouldBeIgnored()
             .Build();

Each method above is an extension method on the Exception type. Any of them can decide to return the original object or a different one, but they all return an instance that extends Exception. The information attaching methods use the Data property to hold the information. The Build method is designed to take every information attached to an Exception and perform more complex actions, like logging or constructing a completely different object to be returned, however that step is also optional.

And here is the source for an ExceptionBuilder static class that acts as both container for the more common extension methods as well as the point where dependencies are being registered:
/// <summary>
    /// Add data to exceptions, then build a Custom exception
    /// using registered <see cref="IExceptionBuildHandler"/> and optional logging
    /// </summary>
    public static class ExceptionBuilder
    {
        private const string CustomPrefix = "Custom.";
 
        private static readonly List<IExceptionBuildHandler> _handlers = new List<IExceptionBuildHandler>();
        private static ICustomLogger _logger;
 
        #region Extended Data
 
        /// <summary>
        /// Attaches a custom <see cref="Error"/> to the exception
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="error"></param>
        /// <returns></returns>
        public static Exception SetError(this Exception ex, Error error)
        {
            _logger?.LogTrace($"Setting error {error} in exception {ex}");
            return ex.SetData(nameof(Error), error);
        }
 
        /// <summary>
        /// Attaches an object as the exception origin to the exception
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="origin"></param>
        /// <returns></returns>
        public static Exception SetOrigin(this Exception ex, object origin)
        {
            _logger?.LogTrace($"Setting exception origin {origin} in exception {ex}");
            return ex.SetData("origin", origin);
        }
 
        /// <summary>
        /// Attaches a name parameter to the exception
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static Exception SetName(this Exception ex, string name)
        {
            _logger?.LogTrace($"Setting exception name {name} in exception {ex}");
            return ex.SetData("name", name);
        }
 
        /// <summary>
        /// Declare an exception as not breaking the execution flow.
        /// Implement catch blocks for exceptions like this to support this scenario.
        /// </summary>
        /// <param name="ex"></param>
        /// <returns></returns>
        public static Exception TryToIgnore(this Exception ex)
        {
            _logger?.LogTrace($"Declaring exception {ex} as not breaking execution flow");
            return ex.SetData("tryToIgnore", true);
        }
 
        /// <summary>
        /// True if this exception is declared as not breaking execution flow
        /// </summary>
        /// <param name="ex"></param>
        /// <returns></returns>
        public static bool ShouldBeIgnored(this Exception ex)
        {
            return object.Equals(ex.GetData("tryToIgnore"), true);
        }
 
        /// <summary>
        /// Attaches a type to the exception
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static Exception AddType(this Exception ex, Type type)
        {
            _logger?.LogTrace($"Attaching type {type} in exception {ex}");
            return ex.AddData("types", type);
        }
 
 
        /// <summary>
        /// Attaches a value to the exception
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Exception AddValue(this Exception ex, object value)
        {
            _logger?.LogTrace($"Attaching type {value} in exception {ex}");
            return ex.AddData("values", value);
        }
 
        /// <summary>
        /// Gets data from exception based on key.
        /// Returns null if not found.
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static object GetData(this Exception ex, string key)
        {
            key = $"{CustomPrefix}{key}";
            if (ex.Data?.Contains(key)!=true)
            {
                return null;
            }
            return ex.Data[key];
        }
 
        /// <summary>
        /// Attaches an object to exception data replacing any previous one with the same key
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ex"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Exception SetData<T>(this Exception ex, string key, T value)
        {
            key = $"{CustomPrefix}{key}";
            var result = ex.AsCustomException();
            ex.Data[key] = value;
            return result;
        }
 
        /// <summary>
        /// Adds an object to a list that resides in the exception data at the given key
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ex"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Exception AddData<T>(this Exception ex, string key, T value)
        {
            key = $"{CustomPrefix}{key}";
            var result = ex.AsCustomException();
            var alreadyExists = ex.Data.Contains(key);
            if (!alreadyExists || !(ex.Data[key] is List<T> list))
            {
                if (alreadyExists)
                {
                    _logger?.LogWarning($"Overwriting data {ex.Data[key]} with key {key} with an empty list of {typeof(T).Name} in exception {ex}.");
                    _logger?.LogWarning($"Are you using Add* and Set* builder methods at the same time or adding objects of different types?");
                }
                list = new List<T>();
                ex.Data[key] = list;
            }
            lock (list)
            {
                list.Add(value);
            }
            return result;
        }
 
        #endregion Extended Data
 
        /// <summary>
        /// Builds the exception from the Data and the provided base exception
        /// </summary>
        /// <param name="ex"></param>
        /// <returns></returns>
        public static CustomException Build(this Exception ex)
        {
            var CustomException = ex.AsCustomException();
            lock (_handlers)
            {
                for (var index = _handlers.Count - 1; index >= 0; index--)
                {
                    var handler = _handlers[index];
                    var result = handler.Build(CustomException, _logger);
                    if (result != null)
                    {
                        CustomException = result.AsCustomException();
                        break;
                    }
                }
            }
            _logger?.LogTrace($"Built exception {CustomException}");
            return CustomException;
        }
 
 
        #region Registration
 
        /// <summary>
        /// Register an <see cref="IExceptionBuildHandler"/>. The last handler to be added will take precedence.
        /// </summary>
        /// <param name="handler"></param>
        public static void RegisterBuildHandler(IExceptionBuildHandler handler)
        {
            lock (_handlers)
            {
                _logger?.LogTrace($"Registering exception build handler {handler}");
                _handlers.Add(handler);
            }
        }
 
        /// <summary>
        /// Register a logger
        /// </summary>
        /// <param name="logger"></param>
        public static void RegisterLogger(ICustomLogger logger)
        {
            _logger = logger;
            _logger?.LogTrace($"Registered logger in the exception builder");
        }
 
        #endregion Registration
 
        private static CustomException AsCustomException(this Exception ex)
        {
            return ex is CustomException CustomException
                ? CustomException
                : new CustomException(ex);
        }
    }


Note a few things:
  • All of the extension methods are returning the same object, with the exception of Build, which returns a CustomException that maybe writes the extra Data values in ToString
  • The external dependencies are being registered via methods. In the class I use, I even replaced those methods with a RegisterServiceProvider method that sets up everything it needs, including the list of handlers, from dependency injection
  • One doesn't need to call Build and every extension method just naturally continues a normal existing code like throw new WhateverException();
  • When using Build, though, you can change the exception object that is being thrown just by injecting another instance of IExceptionBuildHandler
  • In my project, I've devised a method of injecting code via a text configuration file. That means that you can change what happens when an exception if being thrown without recompiling your existing code.

Finally, there is one design decision that I am not sure about: to use throw exception, or to use exception.Throw()? The former is natural to all devs, but it needs special catch blocks to be able to resume execution; whatever the builder returns, it will always throw something. The latter needs a change in all code that throws exceptions, but it could handle the decision to whether to throw anything at all without recompile.

I lean on the first, just because changes in an existing code base can be done incrementally and the code can be understood by all devs, regardless of seniority.

I find this to be a wonderful idea, clear, useful and flexible. I hope you do, too!

Death, sex and psychopaths... solutions to the same problem

There are few big questions as big as "Why death?" and "Why getting old?" and "Why sex?. And it's surprising that the answer is probably parasites.

After a lifetime of fighting disease and random damage, it becomes more efficient to give up and just start anew. Death comes just as a natural consequence of a body that has (or should have) achieved replication already and is out of warranty, so to speak.

Sex is similar. Once a parasite finds a way in, it makes a whole lot of other parasites that know that way, too. If an entire population is the same, clones of the same splitting creature, they are all just as vulnerable. Sexual reproduction mixes things up and leads to more variety, jump starts evolution and maximizes the chances that a portion of a population is immune to any one attack.

And I've been thinking today, as a tangent, that another big question might have the same answer: "Why are there sociopaths?". If societal development and cooperation is the solution for gaining supremacy over individualistic populations, why aren't we all social and empathetic and nice? And I am thinking: empathetic people want to help others, especially sick and hurting people. Instead, they get sick themselves and help spread the disease. It helps to have a small, but significant minority, of assholes who only care about themselves. In case of a major outbreak, they stay clear and survive.

Friday 4 October 2019

Grateful American: A Journey from Self to Service, by Gary Sinise

book cover We know Gary Sinise from Forrest Gump, CSI: New York, The Stand and so many other movies and TV shows. I've always liked him, not in a "Wow, he's great!" kind of way, but he always gave me this impression of a serious and decent guy. And there are two things I found most relevant in Grateful American. One, Sinise is a serious and decent guy. Second, Americans are weird.

The book is made out of chapters that do not necessarily follow each other chronologically and instead are each focused on a specific theme. Some of them I loved, the ones related to how acting changed him from a lost and wild kid to someone belonging to a family he made efforts to build and support, for example. Some I didn't really get, like those focusing on why American troops are defending America and the world from evil and how brave they are and the people trying to kill them are cowardly terrorists.

I feel Gary Sinise likes to belong. He got saved by acting, put all of his passion into his theater company. Then he found supporting the military and giving concerts and raising funds for the "fallen heroes" and "our wounded" and first responders. At some point he even found religion, after being an atheist for his entire life, just because it gave structure to his family. Yet for all the talk, he focused mainly on what he did and what other people did with and for him than on other people or on what he felt. He barely mentioned his family up until they got sick or died.

I like reading autobiographies, especially from actors, because they present things from a very personal perspective, making me feel I am living a part of that. I partially liked this book, but it didn't give me the feeling I wanted. What a difference between this book mentioning Sally Field because she was in Forrest Gump, the film that made Sinise famous and won awards, and Sally Field's autobiography, which barely mentioned the movie and instead focused on what was emotionally important to her. On the other hand, it was impossible for me to empathize with the courageous American troops who bomb a country in the middle ages, then arrive there to liberate cities and give toy animals to orphan girls. And that part was important to Gary Sinise.

Bottom line: it felt to me like the book looks upon Gary as an outside person would. It felt impersonal and a bit self centered at the same time. Actions, events, curated feelings. I was expecting something more raw and personal.