and has 0 comments

  There is an issue with American science fiction, where the stakes have to be raised all the time. Everything has to become different, bigger, flashier, louder, until it becomes so ridiculous that you just have to start over. My greatest regret is that the Expanse series didn't focus more on the Sol world, so carefully crafted in the first books only to be discarded for (cheap?) alien cosmic horror. Perhaps there was never a market for that, but when the series ended, it is the complex interaction between Inners and Belters and the larger than life characters there I missed the most.

  Leviathan Falls doesn't address all of the open threads, loses focus on the world and stays on the crew of the Rocinante: victims, heroes, rebels, guardians of the Universe. It then unequivocally cuts all of those threads and ends the entire series with terrible finality.

  But the book is great, like most of the series, a page turner that I couldn't let go until I had finished it. Stakes were never higher, heroes never this heroic, villains never more terrifying and yet relatable. To me, at this moment, biggest villain(s) is still James S. A. Corey for killing my world.

and has 0 comments

 So you clicked on this post because you thought that:

  • I was smart enough to know how to be better than anybody else
  • I could summarize all the ways to become so
  • I would generously share them with you
  • You would understand what I am telling you in 3 minutes or whatever your attention span is now

While I appreciate the sentiment, no, I am not that smart, nor am I that stupid. There are no shortcuts. Just start thinking for yourself and explore the world with care and terror and hope, like the rest of us. And most of all, stop clicking on "N ways to..." links.

and has 0 comments

  Stranger in a Strange Land is mainly satire. It tries to shake the reader from stasis and make them ask questions and think for themselves. For Robert A. Heinlein, science, freedom of thought and critical thinking were really important and it shows in how he approaches the story. However, the book is also philosophy, pulp fiction, religious experimentation, erotica, science fiction and pure lunacy. Also, if you are one of the social justice people, don't read this book, especially feminists.

  First published in 1961, it both shows its age and is way ahead of its times. The book immensely influenced culture to the point that it added a new word to the English dictionary: "grok", which is used throughout the book as a synonym to "comprehend", although apparently it means a lot more.

  The book is pretty damn large, split into five parts which each felt like a different story. Probably today it would have been published as a pentalogy. The first part is pure science fiction satire. A young man, raised by Martians, returns to Earth, where he has to confront the reality of our culture. Shots are fired towards everything: politics, law, religion, capitalism, culture. 

  The second part is about him finding some allies which protect him and allow him to have the time to evolve. Here it kind of transforms to the normal kind of pulp published at the time (and since).

  From the third part on, Heinlein gives agency to his character. People interact with him, teach him about the world while he starts "spreading his wings". A lot of discussion about how he naively perceives the world. More focus is put on his superpowers: he can not only make stuff (and people) disappear forever, but he can control his body, move things with his mind, is capable of telepathy.

  In the fourth part, Mike the Martian becomes a cult leader. He establishes a church, starts filtering people through a number of "circles" and at the end he has them speaking and thinking in Martian, which gives them the same powers that he has. His church is all about free love, communal ownership (if it even matters), group telepathy and so on. At this point I was reminded of The Center of the Cyclone, which started as a scientist's journal on LSD experimentation and ended as a complete mental breakdown of a person communing with extraterrestrial beings.

  The fifth part just wraps it all up in a biblical allegory, with Mike the God sacrificing himself for his church and humanity as a whole.

  It took me forever to finish the book. Partly because I was focused on other stuff, but also because the book is filled with random stuff. You might think that as Mike is the primary character, he is also the protagonist, but instead this old man Jubal is the carrier of the reader's point of view. The man is cultured, intelligent, arrogant, likes to hear himself speak, condescends to everybody and is generally grumpy - which is presented as being endearing, but in fact it's pretty annoying. He lives in a grand mansion with four young girls, which are his secretaries. When he permits them, they are quite lively and opinionated :) Apparently, many considered Jubal as a stand in for Heinlein himself.

  I admit that I loved the first part of the book. I thought it was humorous and poignant, laying bare the hypocrisy of the modern world. Also it had a good pace, it was presenting new information and there was no Jubal. Then things started to feel a bit weird, but I kept at it. The ending was almost like having to listen to one of those convinced hippies telling everybody how God is love and therefore you should let him fuck you. There are entire chapters about Jubal explaining someone how things truly are and why that person is wrong in their thoughts or beliefs. And then there is the church of love thing, where everybody groks and drinks deep and calls everybody "dear", while smugly announcing that they have the answer to everything.

  As far as I know Heinlein specifically tried to piss off people with the book, to shake things up. It all started from a idea of his wife's to write a Mowgli book, but where the kid has been raised by Martians. more than a decade later, this is the result. I think the Strugatskys did a better and more concise job in Space Mowgli, yet Heinlein managed to inspire whole generations with this book. To this day there is an actual church that follows the principles in the book and a Heinlein Society dedicated to encouraging critical thinking. Who am I to criticize it? But it was damn hard to finish.

and has 0 comments

  A while ago I had discovered the Brave browser for mobiles, which was a Chromium fork that featured ad blocking and privacy guards out of the box, when Google stubbornly refused to enable extension support for mobile Chrome. The thing is, it was only available for mobiles. And even if it were available for the desktop, would it really have anything over Chrome with extensions like uBlock Origin installed?

  The answer is YES! Brave for PC is available and, from the limited interaction I've had so far, it is superior to Chrome. Why? Let me list the reasons:

  • it cares about your privacy and not about how Google can track you best, which might not be high on your agenda or on your browser extension creator's agenda. That's a plus, because as you didn't care about it before, you don't have to care about it now, but it's taken care of.
  • by removing unnecessary functionality from Chromium, it is actually faster than Chrome! Are you old enough to remember when Chrome appeared as the underdog and Internet Explorer reigned supreme and then everybody was like "IE sucks, Chrome rules because it's so fast and only cares about the user experience"? That's what Brave does now to Chrome!
  • it has a "forced" dark mode flag that can turn EVERY web site dark. It's not perfect, but it's out of the box! All you have to do is go to brave://flags/#enable-force-dark and enable the feature. (admittedly, you can achieve the same effect with chrome://flags/#enable-force-dark or edge://flags/#enable-force-dark, but I only found out about it from Brave)
  • the best feature yet is the Simplified View. Most of the times when you open a web site in the mobile version, you get a "Show simplified view" button. You click on that and you get:
    • just the text of the web site
    • whatever font you want
    • whatever theme you want (dark/bright)
    • no ads
    • no flashing things
    • no sidebars
    • no "accept cookies" and "register/subscribe" popups
      Again, this is probably a Chrome feature, but Brave made it public, visible and natural. Haven't found the way to turn it on the desktop browser, yet.

Correction: I have found that in Chrome you can enable reader mode with a flag (chrome://flags/#enable-reader-mode) only it doesn't work that well. In Brave all that moved to what is called Speedreader, which also must be enabled via a flag (chrome://flags/#brave-speedreader).

  Have you ever browsed one of these "modern" web sites and you got half way through scrolling past the huge image that fills the screen only to get a big popup about registering to some bullshit service, with another popup asking you to enable cookies and then some lazy overlay hiding the content and demanding you pay for the content? Imagine you have one button to click and you get to read the actual information on that page! How can people browse on the web without Brave?!

  I know that some extensions cover most of the points above, but Brave plus uBlock Origin are amazing! I get to a web page that is automatically stripped of most ads, but there are still parts of it that are not strictly ads, like a subscribe form in the middle of the content, for example. You use the Block Element feature of the ad block extension and you get the cleanest browsing experience you can get. (BTW, Brave also has its own Block Element option, so you might not need an extension at all!)

  And there are dark clouds on the horizon. With the V3 manifest version that Google is pushing, many of the APIs available to ad blocker extensions are limited or downright broken. It's not in their interest to block ads, considering they are in the advertising business. Their biggest achievement (and mistake) was to open source Chromium, so no one can take something like Brave away from you.

  Bottom line: switch to Brave. It's like Chrome, only a lot better! And I am not really one of those "fuck the system, stick it to the man" people, so don't think I do this because I have some big agenda. I really really enjoy using this browser and I hope you will, too.

and has 0 comments

Intro

  A month ago I was lamenting the state of social media (as well as the normal news media and the state of web blogs) and looking to transition to a system of information that would be best for me. It would have to be effective (giving me interesting information) it would have to be efficient (giving me information that is mostly useful for me and not wasting my time) and it would have to be tailored to my own style (should fit in my normal schedule, not be forced in). And I found it, relatively easy, because it was not a new system, but a very old one: RSS feeds!

History

  For people who don't know what Really Simple Syndication (or RDF Site Summary) means, it is a standardized way of publishing just the information of a web site and any updates, for various use: aggregators, readers, automatic processes, even reuse in the website itself as a data source. It was most popular in the time of blogs (remember Web 2.0?) where people would just get a list of all the blogs they enjoyed and then read all of them in some software that would allow them to see them in one place. That software is called an RSS reader.

  Imagine for a moment the grandiose design of RSS. Someone would spend considerable effort to design an attractive web site that would contain useful or entertaining information, then spend even more effort for creating content regularly, so that people would visit and get them ad revenue or make them well known in a community or hire them. Then they would allow you, the reader, to bypass all the design, the ads and what made that blog unique, for your own benefit, in order to get that information. And only if you are interested in what the post has to say, then you click on it and visit their website. Do you see the design flaw here? Of course someone would pervert it into a wall of images and videos followed by a little text, arranged and controlled by them, not by you, filled with ads and other nasty things. Because that's minimum effort for maximum gain, instead of the original purpose of Web 2.0: community effort for the gain of all.

  Slowly, RSS feeds were pushed away from the people's consciousness, became obsolete. Free blogging platforms became bloated, then more and more irrelevant as no one spent any effort updating them with the times. Sites like Twitter started with having RSS feeds for any page, then just removed it later. People stopped blogging. RSS was dead... or was it?

Solution

  Remember that RSS is a standard, so as long as you have a web site with periodical updates, implementing it is simple and often comes out of the box. For websites that refuse to implement RSS, someone else might come and parse their content and publish it as RSS. RSS feed reader software might also implement custom features for specific sources that are not, strictly speaking, RSS. And then what do you get? Exactly what I was looking for:

  • a single source of information
  • aggregating most of what I am interested in
  • in the order, organization and format I want and control

  And it doesn't even need to be an application you install on your computer, as there are free web sites that function as RSS feed readers. I know, it's the same old trap all over again, where you trust a "free" site and then it starts feeding (pardon the pun) on you, but this time it's quite hard to force people into anything. As quick as it becomes annoying, you just switch to another reader, because the reader does not hoard or control the source of information, it is just a tool.

  So I use Feedly, which I think it's very nice. There are a lot of alternatives, though, with various features, some paid, some free. Feedly comes as a free RSS reader, it allows you to also add web sites as sources directly (so they would parse the web site for you and serve it as RSS) and has other gathering methods that are paid, but as I will show you, can be replaced by free options. You can mark items for reading later or use some other system, like opening them in the browser and then reading and closing tabs.

  Here is what you do:

  1. go to Feedly and create a free account
  2. add sources from the web sites you are interested in
  3. read the things you want, how you want them, when you want them
    • use the browser to read them on the Feedly web site
    • use the Feedly app to read it on your phone or tablet
  4. Usually it is a two step process:
    • you scan the list of items and select only the ones that are interesting to you (not unlike a social media wall)
    • you read the things you selected on their original web sites

Q&A

  Now, there are some things that you might want to consider before you embark on trying this method. I will organize this section as an FAQ. Feel free to propose other questions and I will update the post.

Q: I am trying to read the articles I am interested in, but web sites are filled with ads! What to do?
A: for desktop browsers Chrome and Edge install an extension to block ads. I use uBlock Origin and I am very satisfied with it. When you get to a web site that is not covered or that has some non-advertising related page elements that annoy you, the extension has an option to let you choose the things you want to block.
A: for phone/tablet browsers, download and use Brave, which is a fork of Chrome with ad blocking included.

Q: I am getting stuff that I am interested in, then go to web sites and they have paywalls! What to do?
A: Yes, sites like NewScientist, TheEconomist, NewYorkTimes, even Medium, etc. love to ask you for money to read their stuff. There are methods to bypass those paywalls, but not always and not always reliable. For example Readium, or there is a web site that is called 12ft.io, which works as a proxy to remove paywalls, but it doesn't always work. I am sure there must be alternatives out there, too. Share them with me if you find them and I will update this answer.

Q: I love my RSS reader, but it always annoys me with requests to upgrade to a paid version or buy other things! What to do?
A: see the answer above, you can use uBlock Origin to block individual web page elements, assuming you use a web based RSS reader

Q: I am going through my list of items and then I am interrupted by some RL bullshit, I come back and I forgot where I was! What to do?
A: for Feedly, at least, there is an option to mark items as read as you scroll along, which I think it's very nice. Also, for the mobile app, the default way of reading things is to give you a list of up to 30 items, after which you have the option of marking them all as read and continue to the next batch of items

Q: But I liked to see what people say on Twitter! What to do?
A: Some RSS readers have the option to read items from Twitter directly. Feedly has it, too, but it's a paid option. So instead, use Nitter, which is a web site that give you an RSS feed for any Twitter URL, for free.

Q: But I liked to see what people say on Facebook! What to do?
A: Due to the assholiness of that platform, it is next to impossible to get a feed of items compatible with an RSS feed, but there are some options. Some are little more than hacks, using not the Facebook API, but asking you to give them the browser cookies you have (for a few months) when you connect to your Facebook account. First of all, I don't recommend this at all, since it is a horrible security breach. Second of all, it would only give you the items in the Facebook feed you would normally get when using the web site, probably with ads included, and the normal crappy item order, duplicates and having a different list of items every time you refresh the page. The optimal way of using this would be something that could safely get the list of your friends, read the list of the posts of each of them, then return an actual list of posts in chronological order as an RSS feed. Alas, I couldn't find a free version of a software to do that and I fear the Facebook API would intentionally prevent you from doing this anyway. However, who knows, maybe I will attempt to build such a tool myself in the future. Interested?

Q: But I liked to see what videos appeared on YouTube! What to do?
A: actually, YouTube channels have their own RSS feed you can use. The problem is that YouTube videos are not really... web pages. I usually follow and watch those as a separate process, using the YouTube web site. But that's my own choice.

Q: I got the reader, but where do I get the blogs that hold the information I want?
A: Feedly has a very nice feature to add items. You can add a web site, you can search for keywords, etc. It's not perfect, though, and perhaps you don't want to trust their list of information sources. There is of course Google, but what I found is that most "Top X blogs in field Y" pages are woefully incomplete or outright misleading. I guess this part is always the hardest: find sources of information that can be trusted and provide accurate information in the fields you are interested in.

Q: I want to get suggestions for interesting web sites or share my own choices with others! How?
A: RSS feeds are usually shared or backed up as OPML content, which is a standard XML file containing the list of RSS feeds, organized in the categories you have chosen for them. I recommend you periodically export your OPML file to your computer, so you can always switch from a reader to another or make sure you don't lose the hard sought sources of information you found. Any RSS reader worth the name has an import/export feature for OPML files.

Q: What are your sources?
A: That could be a blog post in itself. I start with the web sites that I am usually following, like BBC News, for example. But I am saving the feeds for the categories I am interested in: Science, Medicine, Entertainment, etc. This way I get around all the stupid politics. Then there are web sites like Phys.org, Hacker News, Space News, Medical Xpress, Ars Technica, etc. Of course, every time I find an interesting person, book author, good programmer and so on, I try to find their blog and add it to the list, or at least their Twitter feed (see above). And then there are some web sites that pride themselves in serving "long content": well thought out articles, researched and crafted over time. Alas, most of them tend to be political, but still very informative occasionally. Mentioning just a few: Longform, Longreads, The Conversation, The American Scholar.

Further steps

This is by no means the end all solution. In fact, as in the title, it is a (permanently?) transitional one. A complete solution would include reading a lot of books, making more personal connections and meeting new people, experimenting with everything I read, since experience only comes through trial, not information absorption. This is not just a need for hobbies and social interaction brought on by the pandemic, but a necessary step towards establishing a network of reliable sources of experience. While I would prefer I do everything passively, online and automated, alas, I have reached the conclusion it's not feasible at the moment.

First of all, the state of the blogosphere, as far as I see, is not good. Influenced by pressure from various (some even well intentioned) directions, people have stopped investing in regularly updated personal content sites. Facebook pushed people towards sharing rather than digesting information, meaning the Internet is flooded with shares, but not with actual original content. Twitter pushed people towards microblogging, which is basically limiting what you have to say about things and then sharing something. Dev.to is a blogging platform for developers, anyone can blog there. Great source for information, one might think, but it quickly turned into a place where people recycle short content in order to be rewarded with "hearts", which most people do not award to articles that are informative, complex and take a long time to read and process. They don't even read those. This of course if they do not blatantly advertise something or push some agenda. So many people have moved their tutorials, experiments and knowledge sharing to video, as this is the way children and young people absorb information nowadays. It is slow and not something that can be browsed easily or split into useful bits that can be reused. All of these are making people write less, in smaller bits and with reduced complexity or publish it as video. Basically the ordinary TV news item that I am trying to avoid.

Second of all, most content that requires effort also often requires financial or political capital. Meaning even long form content on the Internet is corrupted by market forces, with truth and innovation secondary to whatever purpose the author is pursuing. Without personal effort to detect early and filter out this kind of stuff, the method I outlined above will not work. The list of information sources you consume must be constantly curated. Forever.

One big peril of this method is having so many sources that to keep up with the news (RSS feeds are read only from a few days ago, so if you completely miss a week of RSS, you will lose those articles) you need to devote a lot of time to reading them. In the end, you get an even more addictive social media feed, that gives you more interesting things with less annoyance. The solution for this, I believe, is to dedicate a maximum time for news reading. This way, when the number of sources becomes untenable, you are forced to remove the less relevant ones.

I hope you find this guide useful for your own purposes and it helps you expand and enrich your experience. Please do share any questions, ideas or anything relevant to improving the method and this post. Be Web2.0 again!

and has 0 comments

The Nazi officer smirks, as the prisoner begs for his life. Instead of any human feelings, he just revels in the pain he inflicts. He is powerful, merciless, and stupid enough to be foiled by the heroes who, against their better interest, came to liberate the helpless victims of this evil butcher. Change the channel! The heartless businessman pushes for more sales of the opioid drug his company produces, destroying the lives of honest, hard working Americans living in flyover country. Change it again! The evil general commands the destruction of a helpless village, laughing maniacally while the future hero of the story vows revenge in Japanese.

You've heard it before, you've seen it before and you've read it before. The mindless, unreasonably evil character who has two purposes only: to be totally unlikeable, an example of what not to be, and to be defeated by the hero, an example of what you should be. But it's not enough! The hero must be a "normal" person, someone you can relate with: powerless, bound by social contracts, connected with people in their community, wanting nothing more than to live their life in peace. But no! This evil asshole is just determined to stand in the way for absolutely no other reason than gaining ultimate power, more than they, or anyone else, deserve. And the hero needs to overcome impossible odds just to have the opportunity to defeat, in an honorable way, the villain. In the end, they will prevail thanks to a combination of friendly help, evolving to a higher level of power (which was always inside them) and sheer dumb luck.

Now, the Dunning Kruger folk will just lap this story up, imagining themselves the hero, but realistic people will just think "wait a minute! If this guy who is well connected in his community, strong as an ox and looking like The Rock, after focused training that he immediately picks up finding magical and physical powers that are beyond reason, has almost no chance of defeating the villain and only gets there through luck, then what the hell chance does a normal human being have?". And a few broken people would ask themselves if the villain wasn't a bit right, wanting to destroy this pathetic place we called "the world".

Where did these stories come from? Why are we suffocated by them and still consuming them like addicts? What is the result of all that?

The psychopathic villain trope is just a version of the old fashioned fairy tale: the knight and the dragon, the peasant and the lord, the girl and the lecherous wizard, the light and the dark. It is the way we explain to little children, who have no frame of reference, that there are ways we prefer them to be and others than we do not. It's a condescending format, design to teach simple concept to little idiots, because they don't know better. Further on, as the child grows up, they should learn that there are nuances, that no one is truly evil or good, that all of us believe we are the protagonist, but we are just a part of a larger network of people. This we call "real life" and the black and white comic book story we call "fantasy", designed to alleviate our anguish.

Yet we stick to the fantasy, and we avoid reality. And it's easy! In fact, it's much easier than any other strategy: close your mind, split your understanding into just two parts, one where you feel comfortable and the other which must be destroyed in the name of all that is holy. To even consider the point of view of the other side if blasphemy and treason. In fact, there is no other side. There is your side and then there is evil, darkness, void, unknown. Which conveniently makes you the good guy who doesn't need to know anything about the other side.

OK, maybe you can't win every battle. Maybe you will never win any battle. But you are a warrior at heart! You don't actually have to do anything. And as you wait for the inevitable defeat of evil at your righteous hand, you can watch other heroes like yourself defeat evil, stupid, one sided villains. And it feels good. And it has been feeling good for as long as stories existed, then books, then plays, then movies and now video games. Yet never have we been bombarded, from every conceivable angle, with so many versions of the same thing.

If hero escapism was a pill that made life more bearable, now it's most of our lives: films, series, games, news. We were raised on them and we are being tamed by them every single day. They are so ubiquitous that if they are gone, we miss them. It's an addiction as toxic as any other. We can't live without it and we pay as much as necessary to get our hit. And this has been happening for at least two generations.

So when we are complaining that today's dumb entitled teenage fuck generation is incapable of understanding nuance, of moderation, of rational thought, of controlling their emotions, of paying attention for more than five minutes to anything, of dialogue, of empathy... it's not their fault. We raised them like this. We educated them in the belief that they are owed things without any effort, that their feelings are valid and good and that it's OK to consider everybody else evil as long as they are different enough. That we must be inclusive with any culture, as long as it is also inclusive, otherwise exclude the shit out of it.

The trope of the psychopathic villain did not teach these people to be heroes, it taught them to be the foil to the people too different from them. And here we are. Psychopaths on all sides, thinking they are good and righteous and that sooner or later ultimate power will be theirs. The only positive thing in all this: they believe the power is inside them and will reveal itself when most needed, without any effort or training. That's what makes them dumb psychotic evil villains, completely unreasonable and easy to defeat.

If only there were any smart heroes left.

and has 14 comments

  Today I saw a Windows Update message that I can install Windows 11 on my computer. Great! I let it install and all went without a hitch. I don't see any problems with it, my software works fine, the only problem is that the taskbar icons are in the middle of the screen rather than to the left and it has that default setting of huge annoying icons instead of text, grouping all windows of the same type and so on. Simple, just go to settings, right?

  Wrong! Windows 11 now comes with a taskbar with LESS options than before. If you continue using it you will have to live with grouped apps under huge icons, with no recourse whatsoever!

  Luckily, Michael Crider from PcWorld to the rescue. Just download the setup to Explorer Patcher from GitHub and run it. The Windows 10 taskbar will be back. Just right click on it and select Properties and you can customize it even better than the old one! Cheers, Michael!

and has 0 comments

  Can we use the scientific method as a guide for life? Let's find out!

  In these times science is either misunderstood or maligned (more often both), but what do you think science actually is? The "simple" Wikipedia definition is "a systematic enterprise that builds and organizes knowledge in the form of testable explanations and predictions about the universe", which is a criminally roundabout way of saying it's the result of the scientific method, the one that you see in the picture there. No matter how little you know or how stupid you think you are, the scientific method is a way of acquiring knowledge and then building upon that knowledge. It has nothing to do with nomenclatures, hard mathematics, quantum mechanics or complex lab equipment. Those are results of science, not components. One may build upon them, but might as well decide they want to go another direction.

  Why am I writing this? Because I am not a scientist, but I feel inspired by the scientific method. It provides a sure algorithmic way of improving... well, anything! All you have to do is repeatedly follow four simple steps:

  • Observe
  • Predict
  • Test
  • Analyze

 And while discussing this with anyone is something I enjoy, this post is not about the entire process, but just about the first step: Observation. I strongly believe that what is missing most from our collective lives is observing the world around us. I was reading something about a plant today and I realize that I have no idea what the plants I see are called, what they are useful for, and furthermore I rarely pay any attention to them in the rare cases I do go out and find some. My wife is different. Her life is based on observation and, while I don't always agree with her conclusions, I begrudgingly have you admit that I mostly analyze her observations rather than make my own.

Imagine you are in a biology class in school, let's say primary school and they have to learn botany. Are you seeing it, in your mind's eye? Where are the students? How does the teacher enter the class? What does he do? What do the pupils do then? What tools are they using?

Now tell me, where did you imagine this class taking place? Because when I did it, I imagined a room at the first floor inside a concrete building. The teacher enters the room and writes something on the blackboard and the children open some textbook. Perhaps it's a whiteboard and children have tablets, because it's the future and I am fucking old. But where are the plants under study? If we are lucky, there are some in the window behind the teacher's desk, because they have a small, but higher chance of surviving there than anywhere else in the classroom. If the school has a high enough budget one can imagine an occasional field trip with the kids, using a bus to go to a botanic garden and walk around for a bit. An artificial and abstract representation of something that is never observed.

How can one study anything without observing it? In an average class what pupils are observing are the opinions of other people, translated into text and pictures in books. They move from subject to subject, always basing their learning on what someone else saw and abstracted away. They are taught, in a consistent and constant way, to base their thinking on what people in authority have chewed and regurgitated for them. It doesn't matter if those people are right or wrong, that's not the argument I am making, it's about what we are actually learning, in schools and then later in everything we do. It only takes one moment of disconnect, of betrayal of trust, for the foundation of entire lives to be shattered, because if you suddenly learn you may not get the right information from the people you thought of as experts and authority figures, then your entire life experience so far may be a lie.

Most people dislike and distrust science because it is presented in an abstract manner, removed from day to day experience. But that's not science! Science is based on *your* experience. The very word means knowledge. And while you are bombarded with information every minute of every day, that's not knowledge unless it fits in your chain of experiences.

Now tell me another thing: what do you want to improve? Your life, probably. How do you define it, what are its components, how do you measure its quality? In the end (or is it the start), how well are you observing your life? How do you observe yourself, the people around you, the world in which you live?

Let's start there, with defining ourselves and our place in the world, let's observe the immediate reality of our existence. We'll wing it from there. It won't be science until we make testable predictions, actually test them and then adapt to what the analysis tells us, but it's a start. The alternative is to try to fix something without understanding how it works. Or worse, waiting for someone else to do it for us and hoping they understand it better than we. We will end up hitting something repeatedly, expecting it to start working as we want.

I was reading an article a few days suggesting that he have evolved to hold opinions that make us "win" not that are necessarily true, that those opinions are there to define our belonging to a social group and not to inform our actions according to reality. The scientific method appears to do away with emotions and instinct, thus feel unnatural, but in the things we choose observe we find ourselves, in the predictions we make we put our hopes and in the effort to test and improve our understanding we enforce our will.

Do you feel lacking control over things? Are you angry and frustrated? You might not have much power, but *this* you can do no matter who you are, where you are and who stands with or against you. Science: see, think, try, choose.

and has 0 comments

I got this exception at my work today, a System.ArgumentException with the message "Argument passed in is not serializable.", that I could not quite understand. Where does it come from, since the .NET source repository does not contain the string? How can I fix it?

The stack trace ended up at System.Collection.ListDictionaryInternal.set_Item(Object key, Object value) in a method where, indeed, I was setting a value in a dictionary. But this is not how dictionaries behave! The dictionary in question was the Exception.Data property. It makes sense, because Exception objects are supposed to be serializable, and I was adding a value of type HttpMethod which, even if extremely simple and almost always used as an Enum, it is actually a class of its own which is not serializable!

So, there you have it, always make sure you add serializable objects in an exception's Data dictionary.

But why is this happening? The implementation of the Data property looks like this:

public virtual IDictionary Data { 
  [System.Security.SecuritySafeCritical]
  get {
    if (_data == null)
      if (IsImmutableAgileException(this))
        _data = new EmptyReadOnlyDictionaryInternal();
      else
        _data = new ListDictionaryInternal();
    return _data;
  }
}

Now, EmptyReadOnlyDictionaryInternal is just a dictionary you can't add to. The interesting class is ListDictionaryInternal. Besides being an actual linked list implementation (who does that in anything but C++ classrooms?) it contains this code:

#if FEATURE_SERIALIZATION
  if (!key.GetType().IsSerializable)                 
    throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "key");                    
  if( (value != null) && (!value.GetType().IsSerializable ) )
    throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "value");                    
#endif

So both key and value of the Data dictionary property in an Exception instance need to be serializable.

But why didn't I find the string in the source reference? While the Microsoft reference website doesn't seem to support simple string search, it seems Google does NOT index the code GitHub pages either. You have to:

  • manually go to GitHub and search
  • get no results
  • notice that the "Code" section of the results has a question mark instead of a number next to it
  • click on it
  • then it asks you to log in
  • and only then you get results!

So bonus thing: if you are searching for some string in the .NET source code, first of all use the GitHub repo, then make sure you log in when you search.

and has 2 comments

Intro

Four years ago I was writing about being on social media for a year, as a follow up for another post about being on social media for four months. I do promise not to make this into a series. Probably it will be the last post on the subject anyway. Hopefully.

So five years ago I was saying: "I had high hopes that once I connect with all my friends I would share of their interesting experiences and projects, we would communicate and collaborate better, we would organize more parties or gettogethers, meet up more frequently if we are in the same area. Be interesting, passionate; you know... social. Instead I got cute animal videos, big pointless images with texts plastered all over them". That has not changed at all. My hopes waned, but never completely vanished, as I was trying and tweaking various methods of controlling content, but the quality of things has never actually improved. My desire to share in the actual life important events of others is still there, only it's clear I won't get that from social media. Long story short, I intend to stop reading social media, instead trying to find an effective method of getting the connection I need.

Facebook

I have to admit I've had some success in "taming" the platform to provide some interesting content. I've unfollowed every source that didn't give me relevant information, I've followed science, technology and medicine accounts, I've actively used the "Hide posts like this" option until my "wall" became less annoying. I even tried "Liking" stuff that I wanted more of, although that actually seemed to be the least consequential action I was making (maybe because of the algorithm's superficial understanding of what I am actually looking for). However, it was always a tiring activity, having to aggressively fight the system instead of being served by it. Like riding a raging bull to work every day. Inevitably, some click bait or ad post would arouse my curiosity and, after clicking on it, I would be presented with more of that crap, even if I didn't like it. Meanwhile, my "friends" were posting photos of themselves, political rants and useful announcements like when they had their latest baby. I mean, even programmers that I know are active were never posting anything remotely technical or at least news worthy. That, frankly, I don't understand.

At the same time I tried as best I could to post science and software links and relevant content about interesting books and whatever caught my fancy that was NOT funny animals or sarcastic humor (although some of that might have slipped in) in the hope of improving the walls of all my friends. Some seemed to like it. I guess some of you are my *real* Facebook friends and most of you are not! 

But the app itself figured out I was less engaged (or just spammed everybody because why not) and started showing me alerts for absolutely everything. People are live streaming, people are going to events, people are having a shit. And with the new normal for everything to be fighting for your attention, it got annoying. I had to navigate the large (and increasing) number of possible alerts and choose what I wanted because the default is that you want everything all the time to snap you from whatever you are doing. Like that makes sense.

Twitter

There are some things that I want to document, but I don't want to blog about anymore. They are not appropriate on Facebook either, as I believe the audience is wrong. One such example is TV (if one can still call them that) series, where I can throw a small rant, complete with hashtags, for everyone who would be interested in opinions about the show, not my own personal stuff. I guess it might work on Facebook, but I haven't tried. The hashtaggy thing should remain on Twitter, it feels only right. Also, it has this system where you are not friends with anybody, you just follow what they are saying. That's good.

Like with Facebook, I've curated the sources of my tweets and the content is mostly... really really informative. I want to say that I will devote no more time reading Twitter, but it's a lot harder to do than with Facebook. Twitter has a very simple, but somewhat effective filtering system based on keywords. Once I removed political keywords, US president names, everything -ist, -phobe, woke and the like, the bullshit I normally have on Facebook largely disappeared. Actually, I haven't done that on Facebook because on Twitter I mostly follow international accounts (in English) and filtering posts on exact words in Romanian, with all of its conjugations and possible forms and lettering would be a nightmare.

BTW, I've set up Twitter to give me tweets in English, Romanian, Dutch, Bulgarian, Italian, German and some other languages. I think the only tweet I got in another language than English was this year, and only because I has followed the guy myself.

There are issues on Twitter as well. One of things that I had to struggle with constantly is telling the app to show me tweets in chronological order. Instead, it wanted to decide FOR ME what I should be looking at. And, when it finally got it straight that I want all my Tweets as they come, they added a feature to restrict the number of tweets that are loaded. The button to "Show more Tweets" looks exactly like any other link and I may just miss it entirely. I can't mark tweets as read, specify a lower time bound for tweets or disable that stupid button. And even if I use the button, I can only do it a few times until it won't load more things because software developers on mobiles never used WPF and then made fun of it for being slow and working only on Windows. (look up Virtualization in WPF, guys!)

And the same issue I had on Facebook I had here: most developers or movie people or science people share all kind of personal opinions and rarely what they are working on, links on the things that inspire them or anything actually connecting anyone with anything. Meanwhile the platform is going further towards blinky images and large texts and video previews and longer text. Having Dorsey step down from Twitter doesn't help either, as corporate assholes will make the decisions now.

Anything else

I have not been active and I don't intend to become on any of the Instagram, YouTube, TikTok, Twitch, etc. platforms, because they are visual in nature. I am more textual.

But I did start to watch more stuff on YouTube and I've got the feeling that many people have started to express themselves more there, as it feels more digestible for younger people. The new "streamer" fad has become very influential. I've found development, science, movie, chess, nature, medicine, humor channels that entertain me an inordinate amount of time while also being very informative. To me watching somebody speak at normal speed about something until they get to the part that actually interests me is torture. Luckily, YouTube has the option to choose a speed of play. It's not exactly a complete solution, but it does help. However watching, let's say, software development videos at 2.5 speed is tiring and you get no inkling on where to skip to get to the good part without missing out.

Of course, having an ad blocker makes this a lot more fun that it would have been without it. I doubt I could stand YouTube otherwise.

But even YouTube has this system in which it tries to control what you are watching, even if it's your Subscription list. If there are too many videos, I feel like it applies a little filtering or ordering. And the list of items in your subscription is generated occasionally, not whenever you open the page.

The video watching stuff will probably continue to take a lot of my time. It's a passive activity, though, so I will have to limit it in some way. More in the conclusion of the post. 

My blog

As you may know, I've moved the blog to my own domain because Google Blogger just decided to automatically, unilaterally and permanently block my blog account. No appeal request was ever answered. I've only had my blog on their platform for 12 years, so who cares? That liberated me, though, to control the full content and functionality of the blog, but it probably lost me a lot of ranking. The result is that very rarely someone comes on the blog for help or interaction. Sites like Stack Overflow solve the issue of finding answers to small problems and people seem to care less about long form content.

Having lately worked in highly paid yet technically dead jobs and a general feeling of "been there, done that" also made me post less and less on the blog. If you look in the last few years, most of the stuff I write about are the books that I read, and lately I haven't been reading that much (except Twitter and Facebook) either. Surely that didn't help people wanting to connect with me. Yet at the same time, I don't want to pretend I have something to teach when myself have not been learning anything new in ages.

If (I am giving myself an out here) I stop wasting so much time parsing walls of stuff trying to occasionally get to something good (BTW, that sounds like gambling, Belgium lawyers! People are performing the same actions but get content they want randomly), watching videos I don't need to watch (because some of them are quite pointless, even if occasionally entertaining) and not watch news anymore (everybody has some agenda behind their news items, but lately it's been so damn obvious that you can't even call it "hidden agenda" and feel smug about yourself), then I should have at least enough time to read more books. I don't know if I will have the material, inspiration and time to research new software technologies in my spare time to start writing meaningful technical content, though. One can only hope. And I mean me.

Conclusion

Lately I've spent my last hour or more before I go to sleep skimming through Twitter and Facebook items, looking for a good reason to continue doing so. I couldn't find it. If I find something interesting (usually on Twitter, but sometimes on Facebook) I share it with my friends on Facebook. It is a rather significant account of my state of mind, since my personal life is hardly something to publish, and these are the things I am interested in.

Before that, I go through my YouTube videos. Some of the things there are what could be considered high level content: documentaries, expert opinions, etc., but most of the ones I find time to consistently watch are short funny animations, short angry rants and short... you get the pattern already.

Therefore my New Year's Resolution (I know they are considered toxic now, but it comes from a good place I think) is to stop reading social media and instead find a more focused solution on getting only exactly the content I need. That requires defining what precisely is the content I need, but at least vaguely I know:

  • I want to find again (if it exists anymore) the software development community that was so active fifteen years ago: blogs, people that share their work and are proud of their accomplishments rather than their opinions on everybody else's, aggregators of actual work, not sharing obvious derivative content or tutorial achievements.
  • I need to restrict myself to the channels where people choose to share educational content. So even if I know someone is a hot shot in software development, I won't just add him as a friend or follow him and hope some day he will stop talking about systemic racism and instead focus on computer systems.
  • Some things will catch my interest for a limited time, like standup comedy for the last year, but I will feel when it starts to get repetitive or slide into something else and cut them off
  • The method of finding relevant content has to be less manual. Instead of trying to find the gem in the mud, just avoid mud in a sea of gems.

Failing at that, I will have to get my content from the original long form content: books. It will be an activity that sounds passive, but it won't be. Books require effort reading them, a focus of attention and so on. More than skimming two page long Internet content, that's for sure. That, if I don't listen to the books instead of reading them, falling asleep and then pretending to have read the thing. No, I won't do that.

I will also continue to share what I find interesting on Facebook. Sharing is caring after all. I just won't read what everybody else is sharing. I know that sounds more self absorbed than useful, but that's the best I can do. The alternative would be to post everything to my blog and repost the links to social media automatically. I just don't feel sharing a link is actually blog post material, which is traditional long form (like this shitty thing no one will read). I mean, how ridiculous it would be to get a link to my blog in Twitter, than you then follow to get to the link I liked while looking at Twitter?

However, it is clear that, as a principle, what I need to remove from my life is as much passivity as possible. I need to involve myself more, pay more attention, focus, make personal connections. That's also something I will attempt to do, though I will likely not share that on social media, except as occasional blog posts on how great my life is and how yours sucks balls.

At this point I only hope you had the attention span to read this to the end, the emotional involvement required for you to care and that you will understand why I don't Like anything you post. I didn't do that even when I was active on social media, I will certainly not do it now.

One possibility is that I will fail at this resolution completely. I gauge this as very remote a possibility, but it exists nonetheless. I really hope someone will smack over the head if I get to that point. I would certainly deserve it. Not you, wife! (she likes smacking me)

I know it's premature, but I wish you a Happy New Year, as I do indeed intend to have one myself.

and has 0 comments

Intro

When learning to code we get to these exercises and tests and katas and interview questions using some array and expecting some magical string or number and you hear they are called algorithms. And they are intellectual, complex, mathematical, abstract, annoying and feel completely random. But when you are actually doing something real, code doesn't look like that at all. It took me years to understand what the problem is and I am going to share that with you today.

The short version is this: If your program logic doesn't look like an algorithm you are probably doing something wrong. Programming katas are simple because they need to be able to check your answers and give an unequivocal result. It's good to know them, but you shouldn't need to know them, because they are not meant for the real world, but for controlled short term experiments. Unless you are going to work for a sorting company, that's a thing.

Now for the long version.

What you expected versus what you get

You get your first job as a developer and your tasks sound like "fix the color of the submit button" and "the report page shows title in the right, move it to the left". And you think "why the hell did I go through those manual Bubble sort algorithms and learned Quicksort partitions if this is what programming looks like?!". The answer is that you will get to a point where your skills will make people feel confident enough to let you design and architect the things you write. Only then the algorithmic thinking will help because you will have decided yourself what the button does and why its color or position are what they are.

When you start designing flows and entire systems and how they click together it helps a lot to see a component as an algorithm: inputs, rules and outputs. "But, Siderite, a button is not either of those!" you will say. And that is true, but also completely irrelevant. Your program logic should not care about a button, but about an input. And now you also see why the summing of distinct array items is a poor substitute for real life problems, because a click on a button is not a value in a properly contained list, but an event. And most programming exercises and even entire computer classes don't treat events as abstract inputs at all.

Lately this has started to change, both in how programming languages look at actions and events as first-class citizens, but also in theoretical and programmatic concepts like observables, streams, functional programming, reactivity, event buses and messaging, microservices, etc. It makes sense to not quite get it when you have not begun to touch these concepts and when everybody and their grandmother focus on the latest frontend framework, rapid application dev tools or extensions to VS Code, but at their very core all of these things are solutions to the same problem, following the same principles.

Breaking reality apart

As you start to climb toward seniority (and that does NOT mean going to Mexico so they call you "señor developer") you learn about Separation of Concerns, as a good strategy to isolate changes, improve readability and testing and ease maintainability and deployment. You learn about writing applications in layers: the UI, the business logic, the database access, etc, which is also about separating concerns. And as you go further and further on that path you realize...

Wait! This business logic thing looks like an algorithm! It abstracts all of its dependencies until all that remains is: inputs, rules, outputs.

But there are things to confound you: events, user input, parallel tasks, race conditions, heavy load use, the cloud. You can use the same tools, though! Abstract everything, separate concerns. What is an event but a signal coming from a source? Your input is the observable source object and the events themselves just values coming in. Or just a method that receives an event object and you handle sending the event someplace else. Everything coming from the user can be handled the same way. Concurrency is solved by maintaining as little internal state as possible and, when absolutely necessary, guarding it against concurrent access via clear established methods, like semaphores and transaction contexts.

Once your logic is clear, your data structured and every external dependency abstracted away, you can run and test every subsystem in isolation. You don't care something is supposed to be a click, or an error, or a network message or on Windows or Linux or how it's deployed or if the database is available and what kind it is, what UI is being used and what it does, where in the world you are and what time it is and so on. Your code is now an algorithm: a set of rules applied on predictable input which can then be tested for an expected output.

A new requirement comes: you change just the part responsible for the requirement. You can write unit tests before or after or test it manually without caring about anything outside that piece of code. A bug is reported: you write a test that reproduces the bug, you change the code, see the test pass and you never had to open a browser or an app or go to some external environment or ask some other team for user access or if you can use the database. How does it sound to be able to code without ever having to manually go through application scenarios?

Of course there will be an ugly user facing piece of code that you will have to write, but it should be minimal. Your logic is sound, almost mathematically provable to be correct, and how you plug it in is irrelevant. Yes, you will have to work with the graphical designer in your team and make it so the nicely colored card slides across the screen, but that is a meaningless process that you play with in complete isolation from your logic. End to end testing is sometimes necessary, but it's a human thing to do, as well. Just check the "feel" of things, how they look, how they move, if it works for you. The only reason why you are going through it is because you have not been able to completely abstract the end user, with their stupid requests and complicated needs and ideas of what beautiful means.

Yet that is beginning to change as well. Artificial Intelligence, of all things, has advanced so far that you can create minimal interfaces using human language requests. "Build me a web page with a list of items that can be scrolled and selected to be displayed in a details pane on the right". I can imagine this can be used in real life only when the logic of the application has already been written and one is able to just plug and play such a monstrosity without much effort, while also being prepared to change the requirements, recreate the entire things in a different way, but plug it in the same.

And there will be some sort of deployment framework, with people deploying stuff and checking stuff, with data in databases or other persistence mediums. Your code logic? Doesn't care.

Imposter syndrome

Does this sound like a pipe dream that a snake oil peddler is trying to sell you? Let me tell you that the only reason you are not working like that now is because someone though it was too complicated and decided to cut corners. And they have been paying for it ever since, as well as you.

The only proven way of solving complex problems is Divide and Rule. Life is complex and real problems, too. Separation of Concerns, Inversion of Control, Domain Boundaries are the tools you use to break any problem into smaller manageable pieces. And that brings us back to interview questions and pointless algorithms.

When you go to a code test, you are the algorithm. They give you some input and an expected output and check to see if your internal rules are up to the task. Of course you could google for an easy solution. More than that, what kind of employee would you be if whenever the boss asked for something you would build it from scratch without seeing what others did? What hubris to believe that you could know the answer better than anyone else without even checking!

Test succeeded

The conclusion of this stream (heh!) of consciousness is that once you realize the algorithmic nature of any problem (once you abstract every interface with reality), you can see the actual value of being proficient in writing one. You might start with sorting and fizzbuzz and other bullcrap like that, but they are just steps on a larger ladder that will eventually make sense, just like learning the letters of the alphabet prepared you to read to the end of this post. Also, if you are trying to get a job as a book editor and the HR person is asking you if you know all the letters of the alphabet, maybe you don't want to work there.

P.S.

The links in this article are important, especially if you are a just beginning your journey as a developer. Check out the concepts there and learn to use them in your life, it will get a whole lot easier!

and has 0 comments

The point of regular expression character classes is to simplify your expressions, but they can introduce subtle bugs or efficiency issues.

Let's check out this StackOverflow answer to question \d less efficient than [0-9]

\d checks all Unicode digits, while [0-9] is limited to these 10 characters. For example, Persian digits, ۱۲۳۴۵۶۷۸۹, are an example of Unicode digits which are matched with \d, but not [0-9].

This makes sense, only it has never occurred to me until this very moment. I would never use a [0-9] notation and I would replace it with a \d if found in code.

What does that mean?

One simple consequence of such a class would be performance: searching for a large list of characters is less efficient. Another would be introducing the possibility for bugs or even malicious attacks. Let's see the code for a calculator that adds two numbers. It's a silly piece of code, but imagine that a more complex one would take the user content and save it into a database, try to process it or display it.

static void Main(string[] args)
{
    Console.InputEncoding = Encoding.Unicode;
    var firstNumber = GetNumberString();
    var secondNumber = GetNumberString();
    Console.WriteLine("Sum = "+(int.Parse(firstNumber) + int.Parse(secondNumber)));
}

private static string GetNumberString()
{
    string result=null;
    var isNumber = false;
    while (!isNumber)
    {
        Console.Write("Enter a number: ");
        result = Console.ReadLine();
        isNumber = Regex.IsMatch(result, @"^\d+$");
        if (!isNumber)
        {
            Console.WriteLine($"{result} is not a number! Try again.");
        }
    }
    return result;
}

This will try to get numbers as a string and test it using the regular expression ^\d+$, which means the string has to consist of one or more digits. Note that I had to set the console input encoding to Unicode in order to be able to paste Persian numbers. This code works fine until I use Arabic or Persian digits, where it breaks in the int.Parse method. Using ^[0-9]$ as the regular expression pattern would solve this issue.

Same issue will occur with \w (warning: \w is letters AND digits) and [a-zA-Z] (or just [a-z] and using RegexOptions.IgnoreCase).

If one uses code to determine the number of matches for each regular expression pattern

var regexPattern = @"\d";
var nr = 0;
for (int i = 0; i < ushort.MaxValue; i++)
{
    string str = Convert.ToChar(i).ToString();
    if (Regex.IsMatch(str, regexPattern))
        nr++;
}
Console.WriteLine(nr);

we get this:

  • for \d : 370
    • ALL digits
  • for \w : 50320
    • ALL word characters (including digits) 
  • for [^\W\d] : 49950
    • ALL word characters, but not the digits 
  • for \p{L} : 48909
    • ALL letters
  • for [A-Za-z] : 52
    • letters from a to z
  • for [0-9] : 10
    • digits from 0 to 9

I hope this helps.

and has 0 comments

Let's start with a simple requirement and the obvious first draft of the code. The requirement is "build a method that receives a string and writes to the console a URL using that string as a parameter".

The obvious first attempt and working in every version of C# would be:

private static void ShowUrl(string something)
{
    var url = "https://siderite.dev/blog/search/formattablestring?param1="+something;
    Console.WriteLine(url);
}

But then you get some problems. You want to use a parameter that has strange characters in it, like an email, another URL, arithmetic symbols, etc. So you realize that you need to use an URL encode class. Next version is:

private static void ShowUrl(string something)
{
    var url = "https://siderite.dev/blog/search/formattablestring?param1="+Uri.EscapeDataString(something);
    Console.WriteLine(url);
}

Now that works for a second. One might argue about the difference between System.Web.HttpUtility.UrlEncode, System.Net.WebUtility.UrlEncode and System.Net.Uri.EscapeDataString. Yet, his is not the post to do that. Follow the above links for more information.

Then someone decides to use a null for the parameter and you get a ArgumentNullException and you rage in frustration "This is complicated and ugly! The first version looked much better and handled nulls, too. And now I have to add this long Uri.EscapeDataString to every URL parameter in every URL building code I write and also check for null!".

But... what if you could write the method just like the first version and get rid of every problem?

First of all, let's get rid of that plus sign and use interpolated strings. They've been around for awhile:

private static void ShowUrl(string something)
{
    var url = $"https://siderite.dev/blog/search/formattablestring?param1={something}";
    Console.WriteLine(url);
}

Now, this has the same problem of the first version: no URL encoding. And you don't want to add an escape function to every parameter (imagine there would be 10 parameters in this URL). How about we use the fact that the URL is an interpolated string?

Check out this code:

private static void ShowUrl(string something)
{
    var url = UrlHelper.Url($"https://siderite.dev/blog/search/formattablestring?param1={something}");
    Console.WriteLine(url);
}

It uses an UrlHelper class to fix the problems with the URL in the string we generate. Or is it a string? I was writing a long time ago a post about FormattableString and how I didn't see a real use scenario for it. Well, this is it! Let's see what UrlHelper looks like:

public static class UrlHelper
{
    public static string Url(FormattableString url)
    {
        return string.Format(
            url.Format, 
            url.GetArguments()
                .Select(a => Uri.EscapeDataString(a?.ToString()??""))
                .ToArray());
    }
}

The Url method receives not a string, but a FormattableString. When an interpolated string is used as a FormattableString, it gives the developer access to a Format string and a list of arguments in GetArguments. In order to convert it to a string, one must only do String.Format(s.Format,url.GetArguments()).  In our case, the Format property will have the value "https://siderite.dev/blog/search/formattablestring?param1={0}" and the arguments list will contain one value: the value of the something parameter.

Therefore, the Url method will be able to format the string, but first URL encode every single parameter in it.

I admit, this might not be the most readable code in the world, which is my pet peeve with FormattableString. Reading the ShowUrl method you have no clue that UrlHelper.Url receives a FormattableString as parameter. One might even look at that string and say "Hey, wait a minute! That's a bug waiting to happen!" and then proceed to fix it. Perhaps the name of the method could be made more intuitive like EncodeUrlParameters.

But wait! We can do better. I don't know how it might help in the future, but perhaps someone might want to process the parameters of the URL further. By returning a string we eliminate some of the information of the incoming parameter and we don't want to do that.

Also, careful people will notice that using String.Format introduces a subtle bug (or feature): we format the string without specifying a culture. This might be fine, using the current one by default, but it might also cause some issues. The FormattableString class does provide the static CurrentCulture and Invariant methods and, of course, the ToString method would work just fine as well, but then we lose the ability to process the parameters.

So here is the final version of the UrlHelper class:

public static class UrlHelper
{
    public static FormattableString EncodeUrlParameters(FormattableString url)
    {
        return FormattableStringFactory.Create(
            url.Format,
            url.GetArguments()
                .Select(a => Uri.EscapeDataString(a?.ToString() ?? ""))
                .ToArray());
    }
}

By using FormattableStringFactory from System.Runtime.CompilerServices we get a FormattableString as an argument and we return one, with parameters URL encoded. Now, if the result of the method is used as a string, it will be automatically handled by ToString and if it will be used as a FormattableString it will contain all the information provided by the original parameters.

Hope that helps!

Bonus time! There's more!

What if you could make this behavior built in by introducing a new type? Methods from, let's say, a REST client class could use FormattableStrings as URL parameters. But what if we could specify the type of the parameters and get the implicit (hint, hint!) result already URL encoded?

public class UrlString
{
    private FormattableString _formattableString;

    public UrlString(FormattableString formattableString)
    {
        _formattableString = formattableString;
    }

    public static implicit operator FormattableString(UrlString urlString)
    {
        if (urlString == null) return null;
        return UrlHelper.EncodeUrlParameters(urlString.ToFormattableString());
    }

    public static implicit operator string(UrlString urlString)
    {
        if (urlString == null) return null;
        return ((FormattableString)urlString).ToString();
    }

    public static implicit operator UrlString(FormattableString formattableString)
    {
        return new UrlString(formattableString);
    }

    private FormattableString ToFormattableString()
    {
        return _formattableString;
    }
}

This UrlString class will implicitly be converted into a FormattableString or a string and a FormattableString will be converted into a UrlString. So now your code might look like this:

// used like this
RestClient.Get($"https://test.com?x={something}");

// this method does not URL encode anything
public RestResponse Get(string url) {
  ...
}

// this method does URL encode everything, just by changing the type
public RestResponse Get(UrlString url) {
  ...
}

Intro

Dependency injection is baked in the ASP.Net Core projects (yes, I still call it Core), but it's missing from console app templates. And while it is easy to add, it's not that clear cut on how to do it. I present here three ways to do it:

  1. The fast one: use the Worker Service template and tweak it to act like a console application
  2. The simple one: use the Console Application template and add dependency injection to it
  3. The hybrid: use the Console Application template and use the same system as in the Worker Service template

Tweak the Worker Service template

It makes sense that if you want a console application you would select the Console Application template when creating a new project, but as mentioned above, it's just the default template, as old as console apps are. Yet there is another default template, called Worker Service, which almost does the same thing, only it has all the dependency injection goodness baked in, just like an ASP.Net Core Web App template.

So start your Visual Studio, add a new project and choose Worker Service:

It will create a project containing a Program.cs, a Worker.cs and an appsettings.json file. Program.cs holds the setup and Worker.cs holds the code to be executed.

Worker.cs has an ExecuteAsync method that logs some stuff every second, but even if we remove the while loop and add our own code, the application doesn't stop. This might be a good thing, as sometimes we just want stuff to work until we press Ctrl-C, but it's not a console app per se.

In order to transform it into something that works just like a console application you need to follow these steps:

  1. inject an IHost instance into your worker
  2. specifically instruct the host to stop whenever your code has finished

So, you go from:

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;

    public Worker(ILogger<Worker> logger)
    {
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
            await Task.Delay(1000, stoppingToken);
        }
    }
}

to:

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;
    private readonly IHost _host;

    public Worker(ILogger<Worker> logger, IHost host)
    {
        _logger = logger;
        _host = host;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        Console.WriteLine("Hello world!");
        _host.StopAsync();
    }
}

Note that I did not "await" the StopAsync method because I don't actually need to. You are telling the host to stop and it will do it whenever it will see fit.

If we look into the Program.cs code we will see this:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService<Worker>();
            });
}

I don't know why they bothered with creating a new method and then writing it as an expression body, but that's the template. You see that there is a lambda adding dependencies (by default just the Worker class), but everything starts with Host.CreateDefaultBuilder. In .NET source code, this leads to HostingHostBuilderExtensions.ConfigureDefaults, which adds a lot of stuff:

  • environment variables to config
  • command line arguments to config (via CommandLineConfigurationSource)
  • support for appsettings.json configuration
  • logging based on operating system

That is why, if you want these things by default, your best bet is to tweak the Worker Service template

Add Dependency Injection to an existing console application

Some people want to have total control over what their code is doing. Or maybe you already have a console application doing stuff and you just want to add Dependency Injection. In that case, these are the steps you want to follow:

  1. create a ServiceCollection instance (needs a dependency to Microsoft.Extensions.DependencyInjection)
  2. register all dependencies you want to use to it
  3. create a starting class that will execute stuff (just like Worker above)
  4. register starting class in the service collection
  5. build a service provider from the collection
  6. get an instance of the starting class and execute its one method

Here is an example:

class Program
{
    static void Main(string[] args)
    {
        var services = new ServiceCollection();
        ConfigureServices(services);
        services
            .AddSingleton<Executor,Executor>()
            .BuildServiceProvider()
            .GetService<Executor>()
            .Execute();
    }

    private static void ConfigureServices(IServiceCollection services)
    {
        services
            .AddSingleton<ITest, Test>();
    }
}

public class Executor
{
    private readonly ITest _test;

    public Executor(ITest test)
    {
        _test = test;
    }

    public void Execute()
    {
        _test.DoSomething();
    }
}

The only reason we register the Executor class is in order to get an instance of it later, complete with constructor injection support. You can even make Execute an async method, so you can get full async/await support. Of course, for this example appsettings.json configuration or logging won't work until you add them.

Mix them up

Of course, one could try to get the best of both worlds. This would work kind of like this:

  1. use Host.CreateDefaultBuilder() anyway (needs a dependency to Microsoft.Extensions.Hosting), but in a normal console app
  2. use the resulting service provider to instantiate a starting class
  3. start it

Here is an example:

class Program
{
    static void Main(string[] args)
    {
        Host.CreateDefaultBuilder()
            .ConfigureServices(ConfigureServices)
            .ConfigureServices(services => services.AddSingleton<Executor>())
            .Build()
            .Services
            .GetService<Executor>()
            .Execute();
    }

    private static void ConfigureServices(HostBuilderContext hostContext, IServiceCollection services)
    {
        services.AddSingleton<ITest,Test>();
    }
}

The Executor class would be just like in the section above, but now you get all the default logging and configuration options from the Worker Service section.

Conclusion

What the quickest and best solution is depends on your situation. One could just as well start with a Worker Service template, then tweak it to never Run the builder and instead configure it as above. One can create a Startup class, complete with Configure and ConfigureServices as in an ASP.Net Core Web App template or even start with such a template, then tweak it to work as a console app/web hybrid. In .NET Core everything is a console app anyway, it's just depends on which packages you load and how you configure them.

and has 0 comments

  Mirage is inspired by the "Years of Lead" in Morocco's 1960s history and its underlying message about the terrors of colonialism is quite important. At first I thought it was inspired by the plight of Arabs in Palestine, so it's also very timely. That is why it pains me to say that I couldn't go more than several chapters in. The writing is amateurish, the lead teen character inconsistent and annoying and this is clearly a YA book written by a woman for other women.

  That may sound misogynistic, but everyone who has ever hunted for a good book to read knows what I mean: you get to something that has rave recommendations, raised to the level of masterpiece by a few articles, but then when you start reading and you look closer at those reviews you see that they are mostly from women writing those five star animated GIF capital letter emoji filled things. And all the men give two stars and wonder how did they get to read the book in the first place, just like you.

  I don't want to be unfair to Somaiya Daud - this is her debut novel and I am sure her writing will get better with time - but for me reading through the rest of the book and knowing that it's yet another trilogy in the making, so having to wait even more to even get to the end of the story, was too much. It also addresses issues of personal helplessness, which is probably my Achilles' heel. If I ever want to get to those good books that I want to find, I have to fail fast and cut my losses early.

  Bottom line: I couldn't even begin to start reading the book. A combination of subject, debut writing style and aggressive and misleading advertising made me abandon it immediately.