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.

Tuesday 24 September 2019

About fat shaming

Recently I've started seeing a lot of opinions about what is called "fat shaming", the practice of making fun of someone or being offensive towards them because they are overweight. Some say that being morbidly obese should feel shameful, others that shaming people for their weight is cruel and doesn't help in any way, as stress and low self esteem lead to even more weight gain. There are even scientific reports in mainstream media about this.

I am here to tell you that, as someone who has always been heavier than desired, that probably shame doesn't help, but having a clear idea of your normal weight does. When I has about 115kg I felt fine, I felt normal, I had to have friends tell me that I gained too much weight. So I went to a nutritionist, lost weight, it wasn't even very difficult. I went to 102kg and stabilized around 105. I felt absolutely thin and sexy! I gained weight again after, but my image of myself had changed. I didn't feel normal at 115, so I started taking care of what I was eating. I am still orbiting 105kg now and probably it will be very hard for me to go under that limit, however what I am trying to tell you is that if I feel fat at one level, I will make at least a modicum of effort to not gain more weight. If my image of myself, both conscious and unconscious, is that normal is somewhere, I will go towards that limit.

Picking on someone or intentionally offending them is an asshole move, obviously, but changing the level of "normal" to suite the current average or culturally accepted weight in the name of niceness and political correctness is absolutely wrong. Just my two cents.

Trail of Lightning (The Sixth World #1), by Rebecca Roanhorse

book cover Rebecca Roanhorse is a Native American and she writes of a world after an undefined global catastrophe, with the reservations united as a true separate nation. Magic is back, too, monsters and gods and everything in between with it. Our hero is a girl who was trained to kill monsters by a demigod after her grandmother was brutally murdered in front of her. She must now unravel the mystery of monsters terrorizing the land, her own emotions about the now absent demigod and solve the riddle of her own story.

Trail of Lightning has an interesting story, reminded me a lot of Obsidian and Blood, by Aliette de Bodard, only that was with Aztecs and was more technical and this is more adventurous. The writing is competent, the logic holes in the story are small and forgivable. I liked that is had that Native American background, even though I felt it wasn't explored enough.

But what bothered me was the plot. It's all convoluted, but suddenly pieces fall together to further the plot or clues appear out of thin air, while things that should be immediately obvious or at least evoking curiosity are ignored and left for later when they are planned to be revealed. In the end, everything was connected. Surprise! I feel that the characters were butchered or at least boxed in by this overarching cliché of the mandatory connectivity in all things. Chekhov's Gun is important because we are talking about a violent tool for death. If a napkin is described in a scene it doesn't mean somebody is bound to blow their nose in the third act.

Bottom line: Post apocalyptic Obsidian and Blood, only not as good.

The Hot Zone: The Terrifying True Story of the Origins of the Ebola Virus, by Richard Preston

book cover A few weeks ago I watched the mini series The Hot Zone, the TV adaptation of this book. And while more than 90% of the show is contained in the book, the rest of 10% is pure soap opera garbage and the characters and situations are jumbled about to make the show runners' point, not the book's. The pointless dramatization of inconsequential events makes no sense to me when the first part of the book, the one detailing the gruesome deaths of people from Marburg and Ebola and the last part of the book, examining how a "bullet dodge" did not make people more apprehensive and careful - quite the contrary - are more dramatic and were not really presented in the film. And frankly, the differences in characters between the show and the book should be a bit offensive, to the real people at least. That being said, you can opt for watching the show, but I recommend the book instead.

The book itself is much better structured and carefully crafted. It consists of four parts: the first is about the deaths of people (the discovery of the virus by people - or more accurately, the other way around), the second is the setup for the outbreak in Reston, Washington, the third is how they dealt with it and the fourth is more like an epilogue.

It is obvious that as I am reading this review, Ebola did not invade Washington, then spread over the continental U.S. so I will not spoil anything by saying that the (real life) heroes save the day, but the devil is in the details. So many things could have gone wrong - and did. So many procedures put in place to encourage safety ended up circumvented because they were badly designed. The book praises the general who decided to act swiftly, rather than go through endless "asking for permission" with all the different, segregated and non-cooperative agencies which have carved their own administrative turf. Was that the correct decision?

If there is something I did not like in the book it's the title. The Hot Zone describes the first outbreaks, but it doesn't have anything more to do with exposing the actual origins of Ebola other than "they came from Africa". And the book treats Ebola and Marburg as close cousins and examines them together. Probably "The Terrifying True Story of the Outbreaks of Filovirus and Our Inability to Handle Them or Learn Anything Useful" would have been a less commercial title, but still...

Bottom line: I liked the book, even if I was mostly interested in the clinical symptoms and the technical exploration of the virus than the Reston case, but I do agree they should be examined together. Richard Preston writes well and even if sometimes he got a bit carried away trying to set up the mood of a place and what people thought and felt, I didn't feel annoyed at any time. Also, if you like what you read, he wrote three more books in his "Dark Biology" series.

Read this, it's a fascinating story. If you are squeamish, though... maybe you should try something else.

The Color of Distance, by Amy Thomson

book cover I got this book because I heard it was good and the synopsis reminded me of the Xenogenesis series by Octavia Butler, which I liked, despite its global rape undertones. In fact, The Color of Distance is also about a woman changed by aliens to be more like them, but it is an overly positive story.

Amy Thomson tells the story of Juna, left behind for dead after a shuttle crash on an alien planet inhabited by non technological beings that have deep social connections and the ability to see and change things at a very fine level inside living creatures. Thus set up, the only possible direction for the plot is that the aliens save Juna, remaking her in order to be able to survive in their world.

From then on, things could have gotten really nasty. Think Shogun, or Xenogenesis, or The Sparrow for that matter, since I've mentioned rapey things. But no, the aliens are amazingly benign and there is a "noble savage" beauty in their calm and harmonious world that should teach us something. In fact, I was hearing Thomson's voice ever couple of chapters whispering "Hey! This should really teach us something!". It wasn't as heavy handed as that, but I felt it a bit.

The lack of real conflict and only a few almost technical problems to solve made it a bit boring, but as world building goes, it's pretty interesting. In fact, I thought the best part was then humans come back for Juna, where the book explores how people react after "going native" and coming back to their old environment. But this also was almost devoid of conflict or real issues.

Bottom line, it was a fine book. If you are looking for a nice alien world and society book, this is it. If you are looking for terrifying and exciting adventures navigating an unknown society and the clash of worlds, this is certainly not it. And no one gets raped! Yay!

The Doomfarers of Coramonde (Coramonde #1), by Brian Daley

book cover Imagine something as pompous as Lord of the Rings, with the many names, and the fancy speech, and the heavy lore, but worse. Imagine characters so cardboard and childish as to be the basest of archetypes: the young prince, the evil vizier, the good mage, the wise intellectual, the down-to-earth soldier, the evil step-mother queen, the noble savage, the beautiful red-head that doesn't speak much or voice any opinion of consequence, but all men talk about her and plan what to do with her (when they are not saving her) and so on and so on.

Why would you read it? I don't know. I managed to get past halfway through The Doomfarers of Coramonde until I asked myself the same question and decided to switch books. However it is clear that Brian Daley put his heart and sweat into this. It is not a bad book, it's just not very good, and the work that went into the world building and the naming of each and every character, whether they matter or not, make me want to rate this book higher.

Bottom line: B- for effort, but a D for enjoyment.

Vaccinated: One Man's Quest to Defeat the World's Deadliest Diseases, by Paul A. Offit

book cover Vaccinated is an ode to Maurice Hilleman, a rather modest man with a big heart who worked tirelessly towards making vaccines for serious diseases and taking almost no recognition for it. Clearly biased towards the man - Paul A. Offit positively worships him - but informative and well documented.

And it is not only about Hilleman, although he was a giant in the domain of vaccination and affected most important decisions in it. For example you learn about Andrew Wakeman, the man who, while financed by the Personal Injury Lawyer for several families that were suing pharmaceutical companies, imagined a connection between vaccines and autism, a move that has repercussions even today. You also learn about how hepatitis vaccines were tried on mentally challenged people in asylums. Doctors, including Hilleman, convinced themselves that they were attempting a cure for a disease that would eventually affect their guinea pigs and who, when ill, would have no resources to go to doctors or receive proper medical attention. And you learn about how vaccines are the only medical devices that can virtually eradicate disease, often with just one cheap dose for life, therefore there is little incentive for big pharma to invest in them. As opposed to something more lucrative like alimentary supplements, pills that just alleviate the symptoms, etc.

It is a book worthy of a read, that teaches a lot about what a vaccine is, how to make it and why and how it works. Also why some cause problems that then are misinterpreted by the general public.

Saturday 14 September 2019

Had to move the blog to another URL because of DMCA

As I was saying in a previous post, I came back from vacation to about 5 DMCA notices about posts that had no infringing content that I could see. I've tried changing the URLs of links, the images, then reposted the posts. DO NOT DO THAT ON BLOGGER! Apparently, even if their rule says to not publish the post unchanged, they consider any republication of a post automatically put in Draft because of a DMCA notice to be infringing. And what happens after trying to republish five posts a few times? Your blog gets deleted and any attempt to contact the assholes at Blogger is ignored or, worse, a complete farce.

Example: A DMCA requests comes for a blog post containing only my text, a link to IMDb and a YouTube embed. The post gets sent to Draft. I send a counter notice to Blogger, then republish the blog. This might be considered "infringing" of their policy, but it only happened once, so I don't think this is the reason why they deleted the blog. Then they delete the blog (all the blogs on that user, I had some private ones that I hadn't backed up at all and now they are completely gone) and send me an email containing, I kid you not, this text: "we have removed the blog. Thank you for your understanding."

I've tried contacting them about my user being blocked from Blogger and the blogs deleted, but they have replied only with an automated message saying it usually takes two days to get back to me. Two weeks later, no reply from them... except the ones for the DMCA counter-notices. Guess what they said? I kid you not: "Thanks for reaching out to us. We have no record of the following URLs having been removed by Google due to a legal complaint". I replied with a quote of their previous email. No reply.

So the only solution, until I find my own hosting and I set up my own blog, is to rename the blog and move it on another user.

This is a cautionary tale, too. Always backup your blog and any content you post on another platform, no matter how "no evil" it is. Also, make sure you backup everything, even the little details, checking the result, because backup and restore tools don't bring money to the platforms, so they usually suck big time. For example for Blogger there is no way to import a post with a JavaScript script in it that contains comments, because the newlines have been stripped and the comment affects the next line of code. And most of all, when your post gets DMCA'd, leave it in draft, file a counter-notice and pray that they actually mean something.

On the administrative side, because of the domain change and the backup SNAFU, the blog might not work completely as expected. Please let me know if anything goes wrong so I can fix it. For example, the links to the blog are automatically converted by JavaScript, because I can't export, replace and import the posts again without losing the JavaScript in some pages and posts. Plus, I have no idea if this blog is going to last.

Wish me luck, folks!

Saturday 31 August 2019

Censorship, Wikipedia and manga online links

I have a few posts that link to various sites that provide free online viewing of manga. Recently, I've been getting DMCA notifications about "copyright infringement", therefore I am replacing them with Wikipedia links. I am aware that whoever sent those notifications is wrong, since they can't possible have copy rights for links of sites they do not control, but I am not going down that rabbit hole. Google still works, after all.

And speaking of Wikipedia, I've recently been to Turkey where I was shocked to see that the entire Wikipedia site is blocked. According to Wikipedia, the site is or was censored in one way or another in China, France, Germany, Iran, Pakistan, Russia, Saudi Arabia, Syria, Tunisia, Turkey, United Kingdom, Uzbekistan and Venezuela. Hmm, France, Germany and the UK, huh? I wish you'd have said something, visitors from those countries... assuming my blog is not censored as well, [intense stare into the future, horizon and the wall in front] as the shining beacon of freedom it is for the entire world [snapping out of it].

Anyway, seems that only China and Turkey are seriously banning the Wikipedia articles, so I've added a way to "Fix" the links by replacing them with Google queries *if* you are in Turkey, China or Taiwan, thanks to ipapi for the user location detection service.

Friday 30 August 2019

Istanbul, not Constantinopole

Intro


Istanbul is a beautiful lie. You are being served, begged of, you can haggle any price and no one will get upset, you are a king among serfs, everything is ancient, colorful and traditional. But as you walk around in the high but pleasant sea-side heat you can't help but wonder: how high was that initial price if you can lower it again and again and again? How are you a king while walking in the most populous city of one of the most powerful countries in the region? Why are there armored cars here and there, watching you while you unsuccessfully try to reach Wikipedia on your cell phone in Democracy Park? How can all these traditional shops sell the exact same thing all over the city? Why are there so many types of tea in the bazaar, but when you go to a cafe they only serve one?

Now, I enjoyed my visit to Istanbul. My hotel was sub par, but I didn't care about it too much because the staff was doing their best to be accommodating. Yet there are some things I would have liked to know before going there. Here are my thoughts.

Prerequisites


The first thing to consider when going to Istanbul is if you want to rent a car. The answer to this is "I do not want to rent a car, because I want to survive this vacation". The driving is chaotic and the roads are steep and crowded. Most of the time you don't even want to take cabs. People cross the street randomly and there are scooters that speed onto any temporarily free surface. Yet, except a motorcycle guy that probably died on the freeway, I have not seen even a car bump in this mess. To be a driver in Istanbul is both a badge of honor and skill and a psychiatric condition. You've been warned!

The second thing you need is select the part of Istanbul you want to be based in, because the city is vast and split by the sea into three parts: two in Europe and one in Asia. If you are a touristy kind of person, go to the Sultanahmet, Eminonu side. If you want more authenticity, real people living their lives, go to the Asian side, while the other European side is more for the city lifestyle and shopping, like in Taksim square. I haven't been to the modern part of the city, but from afar the buildings there look tall and beautiful and I am told it's great, too.

You've got to be careful choosing your hotel. Istanbul is so chocked with them that when you look at the map you feel that you have not zoomed in enough. In fact every building in some areas is a hotel and all that separates them are small windy one car streets: no side walk, no parking spaces, no green space. You have to pay attention to the pictures of the hotel, to how may rows of windows they have, for example. It will tell you how tall they really are and how many windows your room will have. A lot of these places have large lobbies and terraces, but it's where you enter the hotel and where you get breakfast in the morning, while your room might have just a window overlooking a fence. I've seen rooms that had no windows. So it is vital you speak directly to the hotel and discuss the conditions of your rooms (do not trust they will get the information from Booking or act on it). It's not that they want to cheat you, but everything in Istanbul is negotiable. You need to speak to an actual person. The city abhors algorithms.

One more important thing is your infrastructure. You need information and transportation. In Istanbul a lot of transportation works with an IstanbulKart, an electronic card you can put money on and then pay for trams, buses, ferries, etc. Cabs, of course, are different. Careful with the cabs: you might get a perfectly good one from the airport, with a meter and a credit card reader, then get another that only accepts cash and you must negotiate the price. Now, it might feel like a waste, but I recommend you get one kart for each person. While you can very well use only one for an entire group, I got into the situation where my wife passed and I didn't, so she had to wait until I found a recharging station and had to negotiate with the Turkish only interface.

That gets me to the information portion: Turkey is not in the EU. That means that calls and SMS messages are very expensive and probably mobile Internet as well. While most shops have WiFi, when you are on the road you need Internet. If you have a dual SIM phone (and even if you don't) I recommend you buy a prepaid Turkish card for your Internet and local calls. I didn't do that, so I got stuck a lot of times. As so many translation systems work online, too, I think it's a good idea. Everything in Istanbul is in Turkish, with occasional afterthoughts about other languages. People there know very little English and when they do, you are not sure if they understood what you told them or they simply don't want to appear stupid.

The fun


The fun is all on you! I won't tell you what is good and what is not, because not one of the people that prepared me for my trip had an experience even close to mine. It's not that I am special, but people really are different and Istanbul provides differently depending on your style. What I can tell you is that it is a city worth visiting, but perhaps not for the usual reasons. It feels different. It's not a clone of all the other cities I've been to. It really has its own culture, it's not overwhelmed with the same multinational corporations, it doesn't have banks and pharmacies everywhere, and the lack of rules (or the difference in them) opens the mind to possibilities.

For me the mosques were all the same, the palaces were just buildings with old furniture in them, the museums collections of objects with little life to them. For example I went to the Royal Kitchens in Topkapi; there was nothing to reflect the life that went on there. Just random kitchen implements nicely ordered inside transparent cages. I didn't find the haggling with shop owners pleasant or the ice cream seller antics entertaining. The food was nice, but not extraordinary. The bazaars were full of shops that sold the exact same things. I couldn't get close to a shop without someone harassing me about buying or entering. These are not the reasons why I enjoyed Istanbul.

Instead, it was the weird combination of new and old, of people living their lives differently, the all present sea breeze which made the heat bearable. It was the way people did all of these annoying things and yet I felt no malice from or toward them. It all felt viscerally eternal, like this city had the power to survive the world encroaching on it.

I don't know, maybe you just need to have played Quest for Glory II to feel this way. Or maybe it's just me. I don't think I would want to return soon, but it's an experience I recommend. And now, try to get this out of your head:

Thursday 29 August 2019

Vita Nostra (Метаморфозы #1), by Marina Dyachenko, Sergey Dyachenko

book cover Imagine Harry Potter were a Russian girl named Sasha Samokhina. Instead of an Oliver Twist childhood followed by the happy admission to a place of high learning, she starts off within a happy family and then is forcefully inducted into a village institution apparently bent on making people crazy upon punishment of hurting said family. Instead of a loyal gaggle of friends to help the hero through random quests, it's a bunch of normal kids that either hate her, ignore her or get infatuated with her for their own random reasons. Instead of a nasty revenant with superpowers, she has only her own weakness and her insane teachers to fight against. And most of all, everything she achieves she does through effort, not by being lucky, getting powerful items from mysterious friends or being helped by previously unknown actors.

This is Vita Nostra - and not a book about Italian mobsters as the title made me believe, a book written by two married writers, Marina and Sergey Dyachenko, who wrote 26 other books before this you probably have never heard of because they are in Russian and no one bothered to translate them to English. I wonder if I would have ever heard of them if there weren't currently living in California. There are, of course, similarities to Harry Potter: the same idea that teachers perceive pupils as incompetent infants that cannot be trusted with information and power, for example. The same underestimation of children leads to both the successes of Potter and Samokhina (if hers can be called successes, it's a Russian book after all). There is also the isolation of children, away from family, friends and the rest of the world, a typical indoctrination move. Will our hero keep her morals or succumb to the ideas forced upon her by cruel educators? Will the teachers be proven right and their methods validated, or are they just assholes? Is this really a Hogwarts thing or more the Stanford Experiments meet 120 Days of Sodom? Well, that is for the reader to find out, as they go through the three books (yes, Russians are affected by trilogiopathy as well).

Warning, though, the book starts very slowly and with a style reminiscent of a lot of stories I disliked profusely: the dream sequence, where you cannot be certain that what the character perceives is real or not. Also, the ending is abrupt and says almost nothing. Oh, yes, I can speculate, but would be the point of that? In order to understand what is going on, you just have to read at least the second book as well.

Bottom line is that I liked the book after I got through the slow beginning, I was captivated by the lead character and I found it hard to put the book down, but it's not always easy to empathize with Sasha and the rest of the characters are not deeply explored.

Quakeland: On the Road to America's Next Devastating Earthquake, by Kathryn Miles

book cover We trust the ground beneath our feet as something solid that can take our weight, keep our structures straight, holds fast. Yes, we read things, we know about tectonics, but other than that, everything is stable. In the very beginning of Quakeland, Kathryn Miles thoroughly debunks that idea: Earth is an ocean of lava upon which very thin amalgamations of sand and rubble float precariously. What we call faults are just the largest of cracks, stable and classifiable; there are many more that we have no idea exist, fragile enough to be affected or even created by human activity. At this point, I was expecting an exciting journey through the center of the Earth. If the book would have continued as it started, it would have been a solid five stars, an educational tool to teach what most of the people have no idea about: the fragility of the thin crust we call solid ground. Alas, it was not to be.

The rest of Quakeland, let's say the last 80%, was a very US-centric analysis of how neglected earthquakes are when constructing and maintaining American infrastructure and a fear inducing series of "what-ifs" and possible disasters affecting that one country. I shouldn't have expected anything else, I mean the subtitle is pretty clear, but how can someone switch registers from talking about the very structure of the planet to the measly issues of one country and its weird measuring units? And maybe she did not use the almost ubiquitous bus size, but Miles did use the swimming pool together with the M-scale (do not let any "serious" seismologist hear you talk about Richter), the miles, the feet, the pounds, etc. The writing is competent and almost formulaic in structure, but I can't say I had any issues with it.

The bottom line is that the beginning was brilliant, the information that fracking (and mining in general) - regardless if it is toxic, damages the ground water or anything else activists throw at it - causes long series of earthquakes that affect whole areas while and even after operations cease, as powerful political and economic forces deny and actively fight the science that demonstrates this was new and important. Yet other than that it was just a normal reporter speculating about the possibilities of quakes - man made or not - causing serious harm. A lot of terribilism and fear mongering. That is why I can't really recommend this book and I will rate it as average only.

Wednesday 21 August 2019

Installing emacs on Windows 10 linux subsystem and Android

Here are the steps for installing Emacs on Windows 10:
  • First enable the Linux subsystem:
    • Start Powershell as administrator
    • Type 'Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux' and confirm
    • Restart computer
    • Go to Windows Store and search for 'Linux'
    • Install Ubuntu, SUSE or anything you like from there and run it
  • Second, install Emacs:
    • Type 'sudo add-apt-repository ppa:kelleyk/emacs'
    • Type 'sudo apt update'
    • Type 'sudo apt install emacs25'

At this time you should have Emacs running in the Linux subsystem on Windows 10.

You can also install it on Android:
  • Install the Termux app
  • Type 'apt update'
  • Type 'apt install emacs'

But why would you need to install Emacs at all? Because now you can run 'emacs -batch -l dunnet'. Don't forget to 'save'! :D

Monday 19 August 2019

Timers that capture the execution context, evil AsyncLocal and the quick and ugly solution used by Microsoft devs

It all started with the source code for NonCapturingTimer, a static factory class that was creating a System.Threading.Timer without capturing the execution context and was described as "A convenience API for interacting with System.Threading.Timer in a way that doesn't capture the ExecutionContext. We should be using this (or equivalent) everywhere we use timers to avoid rooting any values stored in asynclocals.". What did that even mean?

An issue opened by David Fowler sheds some light on this: "Any lazy activation of timers will capture the ExecutionContext. Combining this with a lazy initialization of the HttpClient and the handler graph may end up holding onto AsyncLocals for longer than expected. This could end up looking like a memory leak". This follows a Twitter thread from Fowler declaring AsyncLocal as evil.

There are also multiple issues that have crystallized into a proposal for a future version of .NET: "Timer static Create methods that make rooting behavior explicit".

And if you look at the ASP.Net sources on GitHub, they do use the class mostly for one time timer calls and periodic cleanup calls. I should mention that Ben Adams from Microsoft calls this way of creating timers ugly.

I don't have the time to go down further on this rabbit hole, but maybe people will find answers here when looking into this and comment on their findings.

The Ten Thousand (The Macht #1), by Paul Kearney

book cover The Macht series is not related to anything Germanic, as the name might imply, but is instead inspired by the Greek Hoplites. Even if The Ten Thousand happens on another planet that has different continents and two moons and three intelligent races, Paul Kearney could have written it just as well as a historical novel set in ancient Greece, with Greek mercenaries getting hired by Persians as weapons in a civil war that went awry. In fact, the story really is inspired by an actual historical group called the Ten Thousand and the main character, with the unfortunate name of Rictus, seems to be inspired by that of real life Xenophon. The book seems to be a retelling of Anabasis.

Now, the story is well written and short. I read the whole thing in a day. It's like a 300 novel, with the courageous and lethal Macht force finding itself on a foreign continent, surrounded by overwhelming hostile forces and having to march through rough and deadly terrain in order to get home. There is a lot of fighting, technical and military, some romance, bro-mance and feudal politics, but it's essentially the story of a huge march seen through the eyes of an experienced soldier, but young and new to the mercenary troupe.

Bottom line: I don't know if I am going to read any other Macht book. This one felt self contained and I am not that much into ancient fights in the Bronze Age. I liked The Ten Thousand, though, and I recommend it as a short and captivating read.