and has 0 comments

  Chess is a game. In order for something to be called a game, it must be fun, it must be tailored to the level of the players and sometimes, especially nowadays, it needs to be exciting to an audience.

  Now, chess engines are fantastic in respecting the rules of chess and mating the king in the quickest possible way, but it's not a game anymore, it's a process. Occasionally people watch what computer engines are doing and notice the beauty in some of the ideas, but that beauty is coincidental, it has no value to the machine and "sparks no joy".

  I've been advocating for a while training chess engines on other values, like beauty or excitement, but those are hard to quantify. So here is a list of values that I thought would be great to train chess engines on:

  1. player rating
    • which is great because it's constrained in time, so if someone is a GM, but completely drunk and haven't been sleeping for a week, the engine would adapt for their play at that time
    • I know that engines have a manual level configuration, but I doubt it was ever correctly modelled as an input. Most of the time, a random move is chosen from the list of best moves, which is not what I am suggesting here at all
  2. value and risk of a move
    • I know this sounds like what engines are doing now, but they are actually minimizing risk, not maximizing value
    • We also have the player rating to take into account now, so the calculation changes with the player! A move that would be negative because another perfect computer chess engine would take advantage of a minute flaw means nothing now, because there is no way an 1800 rated human will see it. And if they do, what a boost in confidence when they win and what pleasure in witnessing the moment!
  3. balance risk with the probability of winning
    • this is the best part. Riskier moves are more fun, but can cause one to lose. Allow a probability of the other player missing a move, based on what we have calculated above. We are actually adding a value of disrespect from the engine. It attempts to win despite the moves it makes, not because of them.

  What I am modelling here is not a computer that plays perfect chess, but a chess streamer. They gambit, they try weird stuff, they do moves that look good because they can think of what the other player is or the audience are going to feel. They are min-maxing entertainment!

  A chess streamer is usually a guy around 2500 showing mercy and teaching when playing against lower rated players and trying entertaining strategies against equal or even better rated ones. They rate the level of a move, which is an essential metric on what strategies they are going to employ and what moves they are going to play. In other words, they are never considering a move without taking context into account.

  Imagine a normal chess engine, using min-max or neural networks to determine how to win the game. Against another computer, the valuation function is extremely important, since it limits the number of possible moves to one or two. Against a human noob, there are a lot of moves that will lead to a win. It is obvious that another metric is necessary to filter them out. That's how humans play!

  Short story shorter: use opponent rating to broaden the list of winning candidate moves, then filter them with a second metric that maximizes entertainment value.

and has 0 comments

  You've seen this before, either as a book or as a TV series or something similar: the hidden world of magic, the gatekeepers tasked to keep the veil on the eyes of the common folk, the particular technique that they use (in spite of many others in existence), the ethnic flavor of the inspiration, even the formulaic definitions of good and evil. As it stands, Ink & Sigil is a rather bland book, with very little original content and the little that is being inspired by other cultures than the one of the author.

  You see, it all happens in Scotland, where everybody speaks with a strong Scottish accent, even the goth lesbian battle seer girl who is Indian. And there is a magical world of the fae, separated from ours by ... legal bindings, enforced by only five people in the whole world who work for no particular reason, with little resources and themselves bound by inexplicable moral qualms. Every fae described is a horrid caricature, an average of the most common clichés. Every fight is fought exclusively with the particular magical trinkets specific to the gatekeepers and nothing else.

  So forgive me when I am not impressed by Ink & Sigil, another uninspired fantasy millionology which translates to a classic detective story with a little bit of magic and locale sprinkled for taste. It's as authentic as a Margarita in a Ruby Tuesday or a single malt whisky made in Texas.

  As for Kevin Hearne, I didn't know who he was, but I could feel he was not Scottish in any way or form. Not because I am an expert in the culture of Scotland, mind you, but because it was obvious. It was funny how American the world view was, even when bad mouthing Americans, people who leer when they see an attractive girl or, God forbid, are racist. The author tried to be subtle and not stink up his writing with politics, but he couldn't help being a raging progressive from time to time.

  Bottom line: it was partly fun, but it was a chore finishing the book while knowing exactly what was going to happen and trudging through the flood of clichés that made up this story. I would not recommend it.

and has 0 comments

  Sorcery of Thorns starts with an interesting idea that made me curious and involved: a library like a prison of Necronomicon-like books, bound in flesh, partly alive, trying to manipulate people in various ways, fighting amongst each other, destroying minds and bodies of unguarded people and able to transform into murderous demonic beasts when damaged.

  Then, almost immediately, Margaret Rogerson turns away from that premise and proceeds to write a very young adult fantasy romance where a Mary Sue orphan girl who has lived all her life in one of these libraries leaves it and falls in love with a young very eligible sorcerer while battling an old sorcerer in authority and patriarchy in general. Gad!

  The writing is not bad, but nothing spectacular either. It's the way the author fails to put her character in even the slightest challenge that makes this book average at most. Whenever something bad happens, or rather about to happen, she immediately finds a new ability or a new friend to save her. Her "best friend" is there just to be used in various occasions and then forgot for the rest of the book. Men dismiss her opinions, not because she is a shut-in orphan and poor and uneducated and doesn't know anything, but because she is a woman. Only then to do 360s and completely believe and support her when the actual need arises.

  And that ending! There is one thing that feels like a consequence, like it all wasn't some sort of bed game to spice up Elisabeth's romance, then it goes poof!

  In conclusion I can't recommend this book. It's not bad, but certainly not good. Somehow I got duped again by the legions of horny girls using fantasy to scratch their itch and then rating books in droves. The only good thing I can say about the book is that it's standalone and not part of some misbegotten series.

and has 0 comments

  Using my system of randomizing the choice of books, I started reading Dread Nation. The very first page there is a dedication to all people of color. So I immediately deflated, as there are some people who think writing with a political agenda doesn't require any actual knowledge of bookcraft. Then there was the author's name, Justina Ireland, suggesting anything else than the Black female writer she is. And then it was a period piece, set right after the American Civil War. And then... it was also about zombies! So I prepared for a bad woke book written by a woman who looks to the past to justify her antiracist outrage. Yeah, I know, I'm a monster. But then I kind of liked the book!

  That doesn't mean I wasn't partly right. The story is told from the first person perspective of a character who is a Mary Sue. She is a Black girl, birthed by a White woman, but also partly raised as a slave, but also knowing how to read and being well read, but also speaking in Black English, but only randomly or when it suits her, she is smart, perfectly trained to fight zombies and also trained in etiquette, but also a rebel and a tomboy, but also cute enough to attract the attention of a beautiful and fiery Black boy, oppressed her entire life, but also capable of taking control of any situation, small of build and being hurt repeatedly, but then shrugging off damage like an action hero, which she also is, and so on. Then there are the male White characters, which are all bad, except maybe some which I am pretty sure will turn out to be bad too in the end. White women are vile, but some of them, if they are not rich, are OK. Black boys are naive and needing guidance, even if they have their hearts in the right place.

  In short, the book is very inconsistent in its characterization and this girl can do *everything*, except maybe feel when people are sneaking up to her to cock guns when the story requires her to get caught and brutalized. But the world building is good. The author researched books about the forced Native American "educational" centers, another bright spot in the U.S. history - land of the free if you survive, are not enslaved and are White - and created this world where the dead had risen right in the middle of the Civil War, abruptly terminating it, yet not solving any of the social issues that had been in dispute during it.

  And yes, it does feel a little "inspired" from the likes of Lovecraft Country, only instead of cosmic horror you get the run of the mill zombie outbreak as the background for a story about racism. The writing is typical Young Adult, focused on what the character feels, intends and believes, with action and interaction with other people just there to further the story in a blatantly obvious way. But it was also fun. Unfortunately, it is yet another "first book in a trilogy" and you would have to read the two other books to get any closure. I liked the book, but not that much to continue reading the rest.

  Interesting SQL table hint I found today: READPAST. It instructs SQL queries to ignore locked rows. This comes with advantages and disadvantages. For one it avoids deadlocks when trying to read or write an already locked row, but it also provides the wrong results. Just as NOLOCK, it works around the transaction mechanism, and while NOLOCK will allow dirty reads of information partially changed in transactions that have not been committed, READPAST ignores its existence completely.

  There is one scenario where I think this works best: batched DELETE operations. You want to delete a lot of rows from a table, but without locking it. If you just do a delete for the entire table with some condition you will get these issues:

  • the operation will be slow, especially if you are deleting on a clustered index which moves data around in the table
  • if the number of deleted rows is too large (usually 5000 or more) then the operation will lock the entire table, not just the deleted rows
  • if there are many rows to be deleted, the operation will take a long while, increasing the possibility of deadlocks

  While there are several solutions for this, like partitioning the table and then truncating the partitions or soft deletes or designing your database to separate read and write operations, one type of implementation change that is small in scope and large is result is batched deletes. Basically, you run a flow like this:

  1. SELECT a small number of rows to be deleted (again, mind the 5000 limit that causes table locks, perhaps even use ROWLOCK hint)
  2. DELETE rows selected and their dependencies (DELETE TOP x should work as well for steps 1 and 2, but I understand in some cases this syntax automatically causes a table lock and maybe also use ROWLOCK hint)
  3. if the number of selected rows is larger than 0, go back to step 1

  This allows SQL to lock individual rows and, if your business logic is sound, no rows should be deleted while something is trying to read or write them. However, this is not always the case, especially in high stress cases with many concurrent reads and writes. But here, if you use READPAST, then locked rows will be ignored and the next loops will have the chance to delete them.

  But there is a catch. Let's take an example:

  1. Table has 2 rows: A and B
  2. Transaction 1 locks row A
  3. In a batched delete scenario, Transaction 2 gets the rows with READPAST and so only gets B
  4. Transaction 2 deletes row B and commits, and continues the loop
  5. Transaction 3 gets the rows with READPAST and gets no rows (A is still locked)
  6. Transaction 3 deletes nothing and exists the loop
  7. Transaction 1 unlocks row A
  8. Table now has 1 row: A, which should have been deleted, but it's not

  There is a way to solve this: SELECT with NOLOCK and DELETE with READPAST

  • this will allow to always select even locked and uncommitted rows
  • this will only delete rows that are not locked
  • this will never deadlock, but will loop forever as long as some rows remain locked

  One more gotcha is that READPAST allows for a NOWAIT syntax, which says to immediately ignore locked rows, without waiting for a number of seconds (specified by LOCK_TIMEOUT) to see if it unlocks. Since you are doing a loop, it would be wise to wait, so that it doesn't go into a rapid loop while some rows are locked. Barring that, you might want to use READPAST NOWAIT and then add a WAITFOR DELAY '00:00:00.010' at the end of the loop to add 10 millisecond delay, but if you have a lot of rows to delete, it might make this too slow.

  Enough of this, lets see some code example:

DECLARE @batchSize INT = 1000
DECLARE @nrRows INT = 1

CREATE TABLE #temp (Id INT PRIMARY KEY)

WHILE (@nrRows>0)
BEGIN

  BEGIN TRAN

	INSERT INTO #temp
    SELECT TOP (@batchSize) Id
    FROM MyTable WITH (NOLOCK)
    WHERE Condition=1

    SET @nrRows = @@ROWCOUNT

    DELETE FROM mt 
    FROM MyTable mt WITH (READPAST NOWAIT)
    INNER JOIN #temp t
    ON mt.Id=t.Id

	WAITFOR DELAY '00:00:00.010'

  COMMIT TRAN

END

DROP TABLE #temp

Now the scenario goes like this:

  1. Table has 2 rows: A and B
  2. Transaction 1 locks row A
  3. Transaction 2 gets the rows with NOLOCK and so only gets A and B
  4. Transaction 2 deletes rows A and B with READPAST, but only B is deleted
  5. loop continues (2 rows selected)
  6. Transaction 3 gets the rows with NOLOCK and gets one row 
  7. Transaction 3 deletes with READPAST with no effect (A is still locked)
  8. loop continues (1 rows selected)
  9. Transaction 1 unlocks row A
  10. Transaction 4 gets the rows with NOLOCK and gets row A (not locked)
  11. Transaction 4 deleted with READPAST and deletes row A
  12. loop continues (1 rows selected), but next transaction selects nothing, so loop ends (0 rows selected)
  13. Table now has no rows and no deadlock occurred

Hope this helps.

  So yeah, I've decided to try out stock trading. I wanted to see how it works, how it feels and if it's a valid avenue for investment versus something like placing money in a bank. Long story short: it is! I fact, I would say placing money in banks feels stupid now. Will this make me a billionaire in Euros? No. But let me detail.

  Usually, when people get some extra money they think: should I leave them in my expenses account or should I move a sum to a savings account? The difference being the amount of interest and some rules against retrieving money from the savings account. One account is for fast operations, the other is for the rainy days, one you think of in days, the other in months. Well, imagine you have to save money in order to someday retire. That's one you would think of in decades. Well, in that case, stocks are what you need. 

Here is a chart of QQQ, a aggregate stock on the top performing stock, for the last 22 years. Its value rose consistently and grew 536%. That's 8.7% a year on average. In comparison, the average inflation rate in the same period is something like a third. Tell me, which bank will give you this interest?

But take a closer look. You see that big spike at the end? That's November 2021, when the U.S. market reached its apex, due to various reasons. Since then it plummeted, so the value now is the same as in June 2021. If you would have read a blog post like this and invested all your money in QQQ stock in November, you would have found a special set of skills, found me and killed me now. Or look on the left of the chart, to the spike there. In March 2000 the value increased to 118, only to then go down for a period of 16 years, only to grow 250% in the next 6 years!

So in the end, it goes to your trust in the world as a whole. Will it grow, stagnate or disintegrate? If you are optimistic in the long run or at least think that the next 20 years will go the same, then this is for you.

Of course, it was an interesting moment to start learning and experiment with stock trading in 2022. The boom that the trillions of US dollars injected by Biden in the economy because of Covid (so yeah, you read that right, the economy went up during the pandemic) ended, also the distraction caused by Covid which turned from an excitingly unexpected threat to life to an endemic virus that coexists with all the others we got used to. Now we have to look back at how to get those trillions paid, how much good Brexit does to the economy, how the European Union economy recovers and, to add insult to injury, another psychopathic world leader threatening World War III. Can you even think of making money on the stock market now?

The answer is again, yes! Did I make more money? No. But I didn't lose that much either and I believe that loss will disappear. I won't go into the details, but enough to say that while the stocks that took the market to that November high dropped, but other stocks that are considered safe, like the dividend stocks of huge companies, went up. And there is another hook: if the market goes down and you trust it to increase (on average) every year, that means the lower the stocks the higher they will rise in the future!

But, you will ask yourself, what am I missing? I everybody could do that, why don't they? Where is the high risk that everybody warns me about when talking about the stock market?

Well, first there are the short to medium term risks like the 2008 economic crisis or a measly World War. However, can you show me without looking at the years where is that crisis on the chart above? As I said, this is a "sure thing" only on large periods of time and while the global order remains largely unchanged. Also, money itself is a form of national stock. That's why you get inflation, where the buying power of the same sum of the same currency is vastly different from year to year. It's not a matter of money vs stock, but of stock vs stock, of managing risk.

Again with the risk! Where is it? Personally I think there is a huge psychological risk. Because you have a lot more options, you get more opportunities to fuck it all up. For example a guy sold his house and bought Tesla stock for all the money. He even tweeted to Elon Musk to encourage him to increase the value of the stock from $900 to $1000. The highest value for Tesla was 1222, but now it's 838. The guy could have increased his personal wealth 20% in just 20 days if he bought in October 2021. He didn't.

There is a huge pressure to perform when you gamble (and that's the correct word) with your money. You may take a few hundred Euros like me and play around, then the pressure is not that high, but if you put most of your savings into this, you always get to second guess yourself. Did I buy the correct thing? Oh, it's growing! Oh, it's going down! Oh, no, I am losing money, should I sell early or wait until it gets back up?

Sometimes you trust a company so much that it makes no sense to invest in something else. So you just buy the one stock. And then it goes bankrupt! Or the stock falls so much and forever that you have lost all of your savings. Having a diverse portfolio decreases your risk, but also your revenue.

There is a saying among traders that goes something like this: 95% of people trading are losing money and the rest of 5% bought some stock and then forgot about it for a few years. This says something about the safest way to proceed, but also tells you something about where the money from trading is coming from: those 95%.

So I am not an expert in any conceivable way, but I am going to try things out. There is a lot to learn, but when you push everything aside, there are two basic strategies: timing the market and investing long term.

Timing the market is to "buy the dip" when the stocks are low and sell them when they spike. The good news is that it makes you filthy rich, the bad news is that you can't time the market. And I am not joking. This is basically playing Roulette. If you consistently place your bets on the right number, you become filthy rich (or are thrown out of the casino), but that's theoretically impossible. And while a casino game is probabilistic, the market is actually fighting against you, adapting to strategies and making them obsolete in days (if not in minutes, considering you are competing with AI algorithms run by companies betting billions).

Investing long is what I described above. You take your savings (which come after you've bought your house, saved some in the bank and you have a comfortable sum left to live on) and you buy either diverse stocks from the top 500 or ETF (Exchange traded fund) which does this for you, for a small percentage. Invesco QQQ from above is an ETF, for example. And you do it with your monthly savings, every month. And you leave it alone. And you count your money (or lack thereof) when you retire.

That being said, there is a lot to learn about trading. The statistical indicators, what they mean, the math, the taxes, the way to investigate companies, how to structure your portfolio, the information sources, the gotchas, the various people and tricks that want to manipulate you and/or the market so that they make the money.

and has 0 comments

  Decency makes us abstain from doing something that we could do, we might be inclined to do, but we shouldn't do. It's living according to some general principles that are intimately connected to our own identity. And when someone else is indecent, we try to steer them towards the "right path", for our own sake as well as theirs. This is what I was raised to think. Today, though, decency is more and more proclaimed for actively opposing things that are declared indecent and nothing else. It's the glee that gives it away, that twisted joy of destroying somebody else after having being given permission to do so. You see it in old photos, where decent town folk were happily and communally lynching some poor soul. After half a century the world is finally becoming a global village, but not because of the free sharing of information, as the creators of the Internet naively believed, but because of social media and 24 hour news cycles. And we are behaving like villagers in tiny isolated bigoted villages.

  South Park is a comedy animated show that has a similar premise: a small U.S. town as a mirror for the world at large. And while 25 years ago that was a funny idea, now it feels weirdly prescient. The latest episode of the show depicts the vilifying of some local residents of Russian descent because of the Ukraine conflict as a symptom of nostalgia towards the Cold War era. Then too, people were feeling mighty good about themselves as they were fighting the Ruskies, the Commies, the Hippies, or anything that was threatening democracy and the American way of life.

  This is not an American affliction as it is human nature. Witch hunts, lynching, playing games with the heads of your enemies, sacrificing virgins, they all have the same thing in common: that feeling that you have social permission to hurt others and that if they are bad, that makes you good. But acting good is what makes you good, not merely destroying evil. When Stalin was fighting Hitler no one said what a nice decent guy Stalin was. Yet now this mob mentality has been exported, globalized, strengthened by the sheer number of people that now participate. It's not easy to mention decency when thousands of people may turn on you for defending their sworn enemy. This "either with us or against us" feeling is also old and symmetrically evil, because usually all sides harbor it towards the others.

  I have started this post two times before deleting everything and starting again. At first I was continuing the story of the playground war, South Park style, where the town people refuse service to the family of the bully, start giving the victim crotch protectors and helmets at first, then baseball bats and pocket knives, slowly delimiting themselves from that family and ostracizing it as "other", even while the two kids continue to go to school and the bullying continues. But it was the glee that gave it away. I was feeling smart pointing out the mistakes of others. Then I tried again, explaining how Putin is wrong, but that's not the fault of the entire Russian people, most of them already living in poverty and now suffering even more while the rich are merely inconvenienced. I also shed doubt on the principledness of vilifying Russia when we seem to do no such thing to Israel, for example. And then I felt fear! What if this is construed to be antisemitic or pro Putin? What if I want to get hired one day and corporate will use the post as proof that I am a terrible human being? Because some nations can be vilified, some must be, but other should never ever be. And I may be a terrible human being, as well.

  Isn't stifling free expression for the sake of democracy just as silly as invading a country for the sake of peace?

  Regardless of how I feel about it, I am inside the game already. I am not innocent, but corrupted by these ways of positioning and feeling and doing things. I am tempted to gleefully attack or to fearfully stay quiet even when I disagree. So take it with a grain of salt as I am making this plea for decency. The old kind, where acting badly against bad people is still bad and acting good and principled is necessary for the good of all.

  Only you can give yourself permission to do something, by the way.

and has 0 comments

  Senlin Ascends reminded me of many things: the intellectual protagonist, lost in a world that feels part dream like in Zamyatin's We, a metaphorical world that reflects our own social order like in Snowpiercer, the cruel tourist traps hiding horror like in Song of Kali. But the book is anything but derivative. Josiah Bancroft writes this in his own voice, slowly building both the world and the characters.

  Have to admit that I've found it difficult to keep reading the book. The naïve character that never seems to catch a break and keeps getting abused by an uncaring world makes it hard to enjoy. The book is very well written, but starts by destroying your faith in humanity. This also does make the last quarter of the book a little jarring, as the winds suddenly blow in a slightly different direction. It is possible that Bancroft found it as hard to torture his protagonist as I found it to bear reading about it. Yet, he seems to have kept at it, as this is just the first book of a series of four books (and a series of shorts).

  The book is a steampunkish novel set in a fictional tower of Babel where a teacher and his new bride go on a honeymoon, only to be swept into the tumultuous world contained by the tower. Each level of the tower is separate in culture and resources: the higher the level, the harder to get to and the richer the society. But that doesn't mean better, in any way.

  That's the plot in a nutshell, but the beauty is in the details. I can't say the book is perfect, but I am going to give it my highest rating because it is certainly a good book and refreshingly original.

 So I got assigned this bug where date 1900-01-01 was displayed on the screen so, as I am lazy, I started to look into the code without reproducing the issue. The SQL stored procedure looked fine, it was returning:

SELECT
  CASE SpecialCase=1 THEN ''
  ELSE SomeDate
  END as DateFilteredBySpecialCase

Then the value was being passed around through various application layers, but it wasn't transformed into anything, then it was displayed. So where did this magical value come from? I was expecting some kind of ISNULL(SomeDate,'1900-01-01') or some change in the mapping code or maybe SomeDate was 1900-01-01 in some records, but I couldn't find anything like that.

Well, at second glance, the selected column has to have a returning type, so what is it? The Microsoft documentation explains:

Returns the highest precedence type from the set of types in result_expressions and the optional else_result_expression. For more information, see Data Type Precedence.

If you follow that link you will see that strings are at the very bottom, while dates are close to the top. In other words, a CASE statement that returns strings and dates will always have the return type a date!

SELECT CAST('' as DATETIME) -- selects 1900-01-01

Just a quickie. Hope it helps.

and has 0 comments

  Tracing and logging always seem simple, an afterthought, something to do when you've finished your code. Only then you realize that you would want to have it while you are testing your code or when an unexpected issue occurs in production. And all you have to work with is an exception, something that tells you something went wrong, but without any context. Here is a post that attempts to create a simple method to enhance exceptions without actually needing to switch logging level to Trace or anything like that and without great performance losses.

  Note that this is a proof of concept, not production ready code.

  First of all, here is an example of usage:

public string Execute4(DateTime now, string str, double dbl)
{
    using var _ = TraceContext.TraceMethod(new { now, str, dbl });
    throw new InvalidOperationException("Invalid operation");
}

  Obviously, the exception is something that would occur in a different way in real life. The magic, though, happens in the first line. I am using (heh!) the new C# 8.0 syntax for top level using statements so that there is no extra indentation and, I might say, one of the few situations where I would want to use this syntax. In fact, this post started from me thinking of a good place to use it without confusing any reader of the code.

  Also, TraceContext is a static class. That might be OK, since it is a very special class and not part of the business logic. With the new Roslyn source generators, one could insert lines like this automatically, without having to write them by hand. That's another topic altogether, though.

  So, what is going on there? Since there is no metadata information about the names of the currently executing method (without huge performance issues), I am creating an anonymous object that has properties with the same names and values as the arguments of the method. This is the only thing that might differ from one place to another. Then, in TraceMethod I return an IDisposable which will be disposed at the end of the method. Thus, I am generating a context for the entire method run which will be cleared automatically at the end.

  Now for the TraceContext class:

/// <summary>
/// Enhances exceptions with information about their calling context
/// </summary>
public static class TraceContext
{
    static ConcurrentStack<MetaData> _stack = new();

    /// <summary>
    /// Bind to FirstChanceException, which occurs when an exception is thrown in managed code,
    /// before the runtime searches the call stack for an exception handler in the application domain.
    /// </summary>
    static TraceContext()
    {
        AppDomain.CurrentDomain.FirstChanceException += EnhanceException;
    }

    /// <summary>
    /// Add to the exception dictionary information about caller, arguments, source file and line number raising the exception
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private static void EnhanceException(object? sender, FirstChanceExceptionEventArgs e)
    {
        if (!_stack.TryPeek(out var metadata)) return;
        var dict = e.Exception.Data;
        if (dict.IsReadOnly) return;
        dict[nameof(metadata.Arguments)] = Serialize(metadata.Arguments);
        dict[nameof(metadata.MemberName)] = metadata.MemberName;
        dict[nameof(metadata.SourceFilePath)] = metadata.SourceFilePath;
        dict[nameof(metadata.SourceLineNumber)] = metadata.SourceLineNumber;
    }

    /// <summary>
    /// Serialize the name and value of arguments received.
    /// </summary>
    /// <param name="arguments">It is assumed this is an anonymous object</param>
    /// <returns></returns>
    private static string? Serialize(object arguments)
    {
        if (arguments == null) return null;
        var fields = arguments.GetType().GetProperties();
        var result = new Dictionary<string, object>();
        foreach (var field in fields)
        {
            var name = field.Name;
            var value = field.GetValue(arguments);
            result[name] = SafeSerialize(value);
        }
        return JsonSerializer.Serialize(result);
    }

    /// <summary>
    /// This would require most effort, as one would like to serialize different types differently and skip some.
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    private static string SafeSerialize(object? value)
    {
        // naive implementation
        try
        {
            return JsonSerializer.Serialize(value).Trim('\"');
        }
        catch (Exception ex1)
        {
            try
            {
                return value?.ToString() ?? "";
            }
            catch (Exception ex2)
            {
                return "Serialization error: " + ex1.Message + "/" + ex2.Message;
            }
        }
    }

    /// <summary>
    /// Prepare to enhance any thrown exception with the calling context information
    /// </summary>
    /// <param name="args"></param>
    /// <param name="memberName"></param>
    /// <param name="sourceFilePath"></param>
    /// <param name="sourceLineNumber"></param>
    /// <returns></returns>
    public static IDisposable TraceMethod(object args,
                                            [CallerMemberName] string memberName = "",
                                            [CallerFilePath] string sourceFilePath = "",
                                            [CallerLineNumber] int sourceLineNumber = 0)
    {
        _stack.Push(new MetaData(args, memberName, sourceFilePath, sourceLineNumber));
        return new DisposableWrapper(() =>
        {
            _stack.TryPop(out var _);
        });
    }

    /// <summary>
    /// Just a wrapper over a method which will be called on Dipose
    /// </summary>
    public class DisposableWrapper : IDisposable
    {
        private readonly Action _action;

        public DisposableWrapper(Action action)
        {
            _action = action;
        }

        public void Dispose()
        {
            _action();
        }
    }

    /// <summary>
    /// Holds information about the calling context
    /// </summary>
    public class MetaData
    {
        public object Arguments { get; }
        public string MemberName { get; }
        public string SourceFilePath { get; }
        public int SourceLineNumber { get; }

        public MetaData(object args, string memberName, string sourceFilePath, int sourceLineNumber)
        {
            Arguments = args;
            MemberName = memberName;
            SourceFilePath = sourceFilePath;
            SourceLineNumber = sourceLineNumber;
        }
    }
}

Every call to TraceMethod adds a new MetaData object to a stack and every time the method ends, the stack will pop an item. The static constructor of TraceMethod will have subscribed to the FirstChangeException event of the current application domain and, whenever an exception is thrown (caught or otherwise), its Data dictionary is getting enhanced with:

  • name of the method called
  • source file name
  • source file line number where the exception was thrown.
  • serialized arguments (remember Exceptions need to be serializable, including whatever you put in the Data dictionary, so that is why we serialize it all)

(I have written another post about how .NET uses code attributes to get the first three items of information during build time) 

This way, you get information which would normally be "traced" (detailed logging which is usually detrimental to performance) in any thrown exception, but without filling some trace log or having to change production configuration and reproduce the problem again. Assuming your application does not throw exceptions all over the place, this adds very little complexity to the executed code.

Moreover, this will enhance exception with the source code file name and line number even in Release mode!

I am sure there are some issues with code that might fail and it is not caught in a try/catch and of course the serialization code is where people should put a lot of effort, since different types get to be serialized for inspection differently (think async methods and the like). And more methods should be added so that people trace whatever they like in thrown exceptions. Yet, as I said, this is a POC, so I hope it gets you inspired.

 T-SQL Querying is a very good overview of SQL Server queries, indexing, best practices, optimization and troubleshooting. I can't imagine someone can just read it and be done with it, as it is full of useful references, so it's good to keep it on the table. Also, it's relatively short, so one can peruse it in a day and then keep using it while doing SQL work.

What I didn't like so much was the inconsistent level of knowledge needed for the various chapters. It starts with a tedious explanations of types of queries and what JOINs are and what ORDER BY is and so on, then moves on to the actual interesting stuff. Also, what the hell is that title and cover? :) You'd think it's a gardening book.

Another great thing about it is that it is available free online, from its publishers: Packt.

and has 0 comments

  It all reminded me of a playground brawl between kids. Here is the big brawny kid, beating the smaller one. Other small kids shout in support of the victim, but neither does anything. Teachers preach sternly about principles that kids should obey, how bullying is just wrong and one shouldn't do it, parents at home advise kids to stand up for their rights and take a stand. The school psychologists preach that violence at home leads to violence in children and we are all victims. And the result? Small kids keep getting bullied.

  The small kid has options. He can fight - hopelessly, he can run - not for long, he can take a big stick from a friend and bloody the bully's nose - and be mauled for it. But more often they cower in fear, stunned, frozen, hoping things are not happening. And if they are, they won't be so bad. And if they are bad, they would eventually stop. His eyes dart from one person to another in the group of onlookers. "Please! Please, help me!" they silently beg. But some people are frozen, too, some are indifferent, some are expressing disapproval, but then moving on. Most of them pretend it doesn't happen.

  And the kid is thinking, stuck in his inadequate body: This will stop, because it doesn't make sense. And he thinks of all the ways of why his abuse does make sense. Perhaps they miscalculated somehow. Things have to make sense!

  Worse of all, some people would just assume that the bullied child deserves it. He must have done something! There must be a reason for why a kid would attack another. They might even consider various options. Does the bully have an abusive father or other family problems? Is it poverty? Is it education? Perhaps the smaller kid disrespected the larger one on account of religion, race or sexual orientation. Surely, a small kid in school would ONLY behave rationally! And the kid, too, gets to think that perhaps he does deserve it.

  That's us, surrounding ourselves in rationalizations, morals, laws and principles. Trying to contain reality in nice neat boxes and then deny there is anything outside those boxes.

  That's me, too. I watch and I am thinking. Maybe it is military exercises. How funny it would be for Russians to just stop and go home. OK, the mad discourse on TV is troubling, but maybe it's just a bargaining chip in a discussion I am not privy to. They invaded Ukraine, but maybe they stop at the border of the rebel regions. They attack the whole Ukraine, but surely they're gonna stop at its borders. They claim Transnistria is Russia, too, but maybe they won't attack Moldova. Maybe they will stop at the border of Moldova. Maybe they won't enter Romania! Maybe the economic sanctions and stern wording of the Western teachers is going to calm the kid down. Maybe no one will use nukes!! Perhaps they will not shoot each other's satellites from orbit, stranding everybody on this shit planet! Maybe China will stay out of it?

  Maybe Russia has a reason to do all of this, because of the US slowly suffocating that country, economically, militarily and culturally, using their EU henchmen!!! Yes! It all makes sense! It is domestic violence, if only Russia would go to therapy, everything would be all right. I mean, they HAVE TO act rationally, right? They're a country! A whole country big as a continent. And surely the West will understand they are people, too, and show them compassion and help them get past it. Aren't we all human? Can't Biden call Putin as tell him "Dude, chill! I apologize. Let me give you a hug. You are appreciated and I love you!". Isn't this just a joke? 

  I blame us. Whenever a new personality cult pops up we secretly (or less so) hope this is the one. That person who is really strong and not just posturing, intelligent not just conniving, competent not just overconfident, caring and not just obsessing, principled and not just frustrated. We crave for a god to follow and obey and who would make us feel safe. And we tried different things, too. Let's replace a person with multiple ones: senates, parliaments, committees, counsels, parties, syndicates, omertas, majority rule, Twitter likes. It never works. Every time, the power people wield gets to them and somehow... makes them less.

  As I stood there, watching Vladimir Putin explain like a stern grandfather who is also a complete psycho how their brothers across their border are not really a country, nor a people and he has absolute rights over them, I despaired. "Not again!", I thought. I am not much into history, but it felt familiar somehow. Are we getting one of these every century? The strongman going nuts with an entire country following him because... what else is there? For decades people have asked what has made people follow Hitler. The answer seems to be that they thought about it and then went "Meh!".

  And then I watched the valiant exponents of democracy: the EU, the UK, the US. All posturing, talking about principles and international law, begging Putin to stop, making stern discourses on how Putin doesn't have the right to do what he does. What are these people doing? I've worked for them, I know how ineffectual they are, I know that every word in their mouth is unrelated to the truth. They are not lies, per se, just complete fabrications and fantasies. Now, of all times, one should snap out of it, right? Nope. Not happening. They convince themselves that people can't think any other way than them. Surely Putin will stop when his country will slide into economic crisis, because we are all bureaucratic machines that care about profit only. Surely Putin will stop because Biden tells him to. Surely the EU's committees will find a way to word a stern letter that would convince Putin to think about humanity!

  We're screwed.

and has 0 comments

  I have a problem with LGBT books, because they are read by mostly LGBT people who then feel obliged to praise the story and how they identified with the characters. Have the writer be a woman and you will be hard pressed to find the few reviews written by people who just randomly stumbled upon the book or maybe lazily read some very positive reviews and decided to read it, like I did. And when you get burned like that, the more you stop trying to read these books, amplifying the effect.

  Unfortunately, Karen Memory is one of those books. Funny enough, I've previously read a short story collection by Elizabeth Bear and I've forgotten all about it, but then I reread my review and... it's kind of the same. She writes well, but I can't relate to the stories or the characters and mostly because she uses fantasy settings to sell basic bland ideas that are not related to fantasy or sci-fi. A bit of a bait and switch.

  Karen Memery (with an e) is a teenage middle-end lesbian prostitute who knows horses, fighting, shooting and is also a seamstress. In a Western-like steampunk universe which sounds suspiciously similar to episodes from Warrior (great TV show BTW), she is the protagonist, but there is very little steampunk and no sex. Instead it's all about diverse people caring about each other's feelings while the bad men are coming for them.

  20% of the book in, I've decided to abandon it, but I did make the effort to hunt down the reviews that were focusing on the story and not on the diversity or how cool steampunk westerns are. People finishing the book didn't think much of it either, especially since she seems to go all Mr. Nobody towards the end. She's a teenage girl!

  Anyway, no.

and has 0 comments

  I started reading this book at random, and by random I mean I used a tool to choose it for me. And what a coincidence that, published in 2011, it talks about the geopolitical and economical drivers that would shape the next decade while I read it in 2022, as a conflict between Russian and the U.S. in Ukraine is looming. Was Friedman a sort of Hari Seldon and he predicted it all or was it all just bull? Well, a bit of both.

  The Next Decade wants to be a U.S. centric but objective dissection of the world, all pretenses aside, with the goal of predicting what will happen and what Americans should be doing about it. George Friedman starts by explaining why the United States have become an empire, almost by accident, and that while the reality of the fact cannot be denied, the anti-imperial principles upon which the nation was founded as still relevant and even essential to the wellbeing of America (and hence the world). He decides that the most important actor in this story is the American president, the modern embodiment of both the principles of the nation and of a Machiavellian prince. The rest of the book is a continent by continent analysis of what countries are driven by and will do and what this prince has to do to ensure and promote American supremacy over the world. In the author's view, the highest virtue of a good leader is to act in the best interests of his nation, while attempting to follow a moral code as well as possible in the circumstances.

  Does it sound arrogant, pompous and presumptuous? Yes, quite. But does it also sound close to how heads of state think and make decisions? A resounding yes. In fact, his talk of the Georgian conflict, where Russians invaded and Americans wrote some stern condemnations in response is terrifyingly close to what happens now in Ukraine, only the U.S. cannot afford to repeat that performance now.

  Here's a quote:

  In order to understand this office I look at three presidents who defined American greatness. The first is Abraham Lincoln, who saved the republic. The second is Franklin Roosevelt, who gave the United States the world’s oceans. The third is Ronald Reagan, who undermined the Soviet Union and set the stage for empire. Each of them was a profoundly moral man … who was prepared to lie, violate the law, and betray principle in order to achieve those ends. They embodied the paradox of what I call the Machiavellian presidency, an institution that, at its best, reconciles duplicity and righteousness in order to redeem the promise of America.

  Friedman thinks, for example, that bin Laden forced the hand of the American president to overextend in the Middle East, a pointless military gesture, but a politically necessary one, which lead to a rise of Iranian influence and distracted from Russia. As in The Next 100 Years, the author is still obsessed with the importance of Mexico, Poland and Turkey, but he adds more stuff related, for example, to Romania, which must be built up militarily so that it defends the Carpathians for the Americans for free. The European Union is a joke, fractured by history, culture, economy, financial systems, laws and held together by a fairy tale ideal of a bureaucratic world where war (inevitable to Friedman) doesn't exist. But even so, Germany must be stopped from joining up with Russia and as best as possible removed from its alliance with France. Africa is a place that the U.S. should just ignore. And so on and so on. Basically, America should make sure that in no place will any power even begin to rise in a region because it would impede its natural right to rule the world.

  The scary thing is that every one of these predictions or analyses are propped by well explained and documented arguments. It's not that Americans are assholes for doing that, it would be costly and stupid for them to not do that. As Friedman puts it, the U.S. has become empire without intention and is now forced to act as such for better or worse.

  I must warn you that this is not your school history book, where valiant heroes defend their homeland against evil, but a very cynical overview of how foreign policy is done. It describes a world in which every country is at war with every other country and any sense of morals is slave to necessity and only serves to bring a modicum of validation to the inevitable evil nations do.

  Bottom line: a very well written book, extremely apropos these days, something that I urge to be taken with a grain of salt, but highly recommended as a read.

and has 0 comments

  I am a fan of the original quadrilogy, but The Cold Forge is the first book from the Alien franchise I am reading, mostly because of the Alien Theory YouTube channel which recommended this (and Into Caribdis, also by Alex White) as two of the great books in that universe. And I did like it, it is well written and using a lot of the Alien trademark items: the bleak predatory corporate world, the psychopath in love with the aliens, the isolated setting, the company stooge, the female protagonist who has to do everything and then some just in order to survive, the double crossing, the androids, the power loader robot and so on. But at the same time, it felt too familiar, like the writer was too afraid to set foot outside the established borders of the franchise, lest he stumbles and gets impregnated and eaten.

  Also, while reading the book I've got to realize that Alex White nailed it in regards to the main character. Yes, she is a woman, but physically weak. Her strengths lie in determination, smarts and high morals. It was never about the gender of the protagonist as it was about raising the stakes by following a weak character who has to overcome even more than an average person. I think Ripley is also the same, even if towards the end she was physically intimidating and powerful as well: not a strong female lead for the sake of it, but because it makes sense and brings value to the story.

  Anyway, back to the book, I felt that we got way too much of the villain and too little of the aliens, maybe even of the protagonist herself. As such, The Cold Forge is more a very detailed exploration of the mindset of a psychopath than a new perspective on the xenomorphs. We get a space station in which dozens of aliens roam around and the focus is almost always on what the antagonist thought and felt while conveniently only secondary characters had to deal with the aliens.

  Be warned that this book will make you hate humanity a little bit and get you more and more frustrated, to a point close to Stockholm Syndrome, with how paralyzed by social norms the characters are and how freely the predatory psycho navigates through those and kills anyone he wants. The parallel is clear: the worst humanity can bring is very similar to the alien drones: hidden, unexpected and brutal, uncaring of anything but their goal.

  Bottom line: I liked the book and I think it was a good introduction to the literary Alien universe, but I expect many new ideas and more focus on the aliens in following works. I don't want to read again and again about people being people while some random killer bug brings a slight element of chaos to the story.