Intro

  Labels. Why do we need them? At first it seems like a natural outcome of people trying to understand their surroundings: good/bad, light/dark, wet/dry, etc. It makes sense to start with a simplified model of reality when it is all brand new. However, as we grow, we soon realize that God/Devil is in the details, that taste is more a matter of subtlety than brute strength and that labels, as useful as they have been, sometimes need throwing away. As the old adage says: a beginner needs to learn the rules, an expert knows all the rules, a master knows when to break the rules.

  So how come, with such a general and all encompassing principle, proven many times over millennia, we still cling to labels? And not only to understand the world around, but to understand ourselves and, ultimately, define ourselves? Not only internally, but externally, as a society? Codifying them in laws and unspoken yet strongly enforced rules?

An innocent example

  Let me give you an example. When we enter adolescence we start getting sexually attracted by other people. So this imaginary adolescent (A) likes one girl, then another, then another. After three girls he decides, with the tacit and active approval of his relatives and friends, he is straight. Another imaginary adolescent (B) likes guys, so he's gay. And now, so that we can identify the usefulness of these concepts, we add a third adolescent (C). A sexy young stud that likes... girls, let's say, and has managed to not only like them, but successfully have sexual encounters with them. He has had sex with 20 girls. So tell me, who is more like who in this triangle of adolescents? How do you split this hyperplane of three people into two parts? How do you cluster these people into two groups? Because to me it seems that A and B are far more alike than any of them is similar to C. Moreover, is the sexual attraction pattern that has been established in early adolescence even stable? What happens if the next person A likes is another guy? Is he bisexual now? By how much? Is he 75% hetero?

  Leaving my personal thoughts aside, can anyone tell me what these labels are for? Because if you find yourself sexually attracted by someone, then for sure you don't need a statistical model to analyze that. Is it for the benefit of the other person? "Sorry, but I am straight", which would translate to something like "Oh, I have to tell you that, based on the statistical evidence for sexual attraction I have gathered, I seem to be exclusively attracted to girls. So don't take it personally. I have nothing against gay people, I just have a biological reason to reject any of your advances". Does that sound in any way useful? Especially since we are being taught that one does not refute another's reasons for sexual or romantic rejection, that they have the given right to unilaterally refuse, regardless of any rational reason.

  One might argue that these labels are like armor to define and strengthen the identity of people. You don't just observe you are straight or gay, you define yourself as such, thus avoiding confusion, minimizing internal conflict and adhering to a community. Then, collectively, one can fight the inevitable "You are weird and must die" situation in which all people find themselves in, at one time or the other, when facing people different from themselves. But then, isn't clearly defining a group of people painting a target on their back? Look at the LGBTQ... whatever community. They are actively combatting the discrimination and disrespect that is thrown at them by finely defining the specific sexual group they belong to, then bundling them all together into a community of completely different people. Because they have a common enemy, you see, the cis people (a term they had to invent to define the majority of people, so they don't have to define themselves as not normal). So if I am gay, for example, I am the G person, not the B person, which also accepts sexual encounters with people of the other sex. Why is that important?

  Why can't I fuck whoever I want to fuck, assuming they agree? Why do I need a label which will restrict my choices in the future?

  People managed to somehow debate gender now. And not in terms of "why does it matter?" but in "you didn't define it correctly. It's spelled Phemail, as per the new gender atlas of 2022!"

A less divisive topic

  And what I am saying is not related just to sexuality. Say race, to take something less divisive. Am I White? How do you know? Because the color of my skin? What if you found out that my parents are both Black and I have a skin condition? Is it ancestry, then? The proportion of genetic code from various (very vaguely defined) groups of people in my own? Then we get to the same thing: if my grandfather is Black, am I 25% Black? What if he was Japanese? What the hell does that matter anyway? Why do we need labels like "Caucasian", "non-White", "person of color", "African American"? Am I a European Romanian as opposed to a South Asian Romanian because his Indian-like race was enslaved in Europe a bunch of centuries ago? Who needs this crap? Is it to define values for eventual retribution for perceived historical slights? Is race an accounting concept?

  I identify as a software developer. I am more alike people writing software that with the majority of men, Romanians, sun deprived people with terribly white skin, guys who like girls or humans in general. And there are a lot of software people that are nothing like me. Is it a useful identity, then, other than for HR people? I would say no. No one cares anyway, except when meeting new people and they ask what I do, I tell them, then there is that awkward "Oh..." and they go ask someone else.

The hell with it

  And the holy trinity would not be complete without religion. Religion is a concept you choose! It's the only thing you are protected by law to believe despite any evidence and to act accordingly. It is the same as the identity shield portion of race or sexuality, but that's where the buck stops. No one can prove you are a Christian or a Buddhist. It's a completely arbitrary belief system that is codified only when interacting with other people. You do to Church and if they start singing, or doing strange hand gestures, you better know the lyrics and the gestures or they won't look positively on you. It's like the secret handshake of the gang in your neighborhood. But when you are all alone and you think about God, it's sure that you are thinking of it slightly different than any other person in the world. So why do you need the label? Why can't you believe in two gods, hedge your bets so to speak? You go to the mosque and then to the synagogue. Surely double dipping would be a worse sin than not believing in the true God, wouldn't it? And then, what God do you believe in more?

  Even nationality is stupid. Does the place where I was born define me, or maybe the one I lived the most in? It certainly influences my culture, my values and one can statistically infer many things about me from them, but they are just influences on the path of my life. Some may be important, some not, I may have rejected some or grew out of them. Other than administrative and bureaucratic reasons, nationality is again a mere choice!

  I agree with people who choose to define themselves in certain ways. I respect every personal choice as long as it doesn't hurt others. I am not against self-defining. What I am against, though, is about giving social and legal power to these labels. And then to redefine them again and again as times change. Think of the tortuous etymology of the word "antisemite" for example. You want to define yourself, fine! Don't impose it on me, though. "I identify as a serial killer. Please don't disrupt me in observing the rituals of my people and let me stab you!"

So what's your point?

  We live in a time where everybody and their grandmother decry divisiveness, extremism, polarization. It seems to me that if we want to minimize that, we should at least renounce placing people in disjunct boxes. One shouldn't care what my race, religion or sexuality is until it's relevant to some sort of interaction. And if they find out, it shouldn't be any more important than any other trivia about my person. I say fight the entire idea of labeling people, as a general principle, whether you do it to hurt them or to declaratively protect them. And if you want to build an atlas to categorize the weird and beautiful human species, do it from a place of observation, not coercion.

Forget canon

  Which brings me to the last point. Some people religiously defend their belief in ... imaginary characters and stories. You hear stuff like "In reality, Star Trek canon says that...". No. I have watched everything Star Trek. There is no canon. Canon is used in the concept of religious writings, where people arbitrarily decide what part of a religion is correct and for which part one should burn other people for supporting. It has no place in fiction. Good writing needs to be consistent. If it spreads over multiple decades, multiple writers, multiple IP owners and different times, it needs to adapt. You can say that something is stupidly inconsistent or that adapting old ideas to new times sometimes is detrimental to those ideas and you'd better start anew with fresh stuff. You might even call people idiots for the way they chose to do any of these things. What you cannot expect is canon for imagination! If you do, you are only helping lawyers carve out the landscape of human fantasy and parcel out terrain and capital for the people who care the least about your entertainment.

Conclusion

  Exploring a new domain always requires defining labels, as a simplistic model for charting the unknown. People are not a new domain, nor are they unknown. They may be unknowable, but they certainly don't belong in nicely shelved boxes in the warehouse of politicians, accountants or lawyers, people lacking all imagination or passion. If you believe the current model of interacting with the world is wrong, maybe the surest way to fix it is to renounce and denounce the labels that define the model.

  A while ago I started looking for books about microbial biology, for whatever reason, and so I also added From Bacteria to Bach and Back, without bothering to look at the description or any of the reviews. And it was a hard to find book, too! So here I am, happy to have gotten it and looking forward to its wisdom. I really try to finish books that I have started, so I did with this one as well, but just couldn't. I had to decide if I want to abandon this and read some other book or just find new reasons to scroll Facebook forever!

  And the reason is not that the book is not saying something interesting and important or that it is not researched. The reason for me being unable to finish reading it is solely based on the style of the writing. Imagine David Attenborough at his most pompous, writing something that has the scope of something Yuval Noah Harari would write and with the condescendence of Richard Dawkins because he wanted to outdo Douglas Hofstadter and you get Daniel C. Dennett writing this book, but without the charisma, conciseness or cleverness of either of the others.

  The book relates exclusively on how evolution leads to intelligence, how our conscious minds can be explained by evolution and mechanistic principles alone and that concepts like free will are not consistent with anything scientific. The problem is that after saying that, it continues to repeat it, more and more smugly, trying to dot every i and cross every t, until reading becomes unbearable. And yes, one could have expected something like this from someone actually named Daniel Clement Dennett the Third, age 75 and having dedicated his life to defining and researching consciousness, but it doesn't make getting through the book any easier. It has nothing to do with bacteria or Bach, other than empty correlations, either.

  Apparently, this should have been the distillation of Dennett's thinking. At almost 500 pages, this is not distilling anything! You don't go into a pub to get a distillate and ask for a pint. And while the subject is interesting and the conclusions iron clad, I do believe that a smart editor could have created a wonderful little book by deleting two thirds of everything written in this.

  Bottom line: sorry, but I couldn't finish it. I couldn't even reach the half point.

 

  BTW, if you are a player of the game, leave a comment. I would like to meet the people I play with.

Intro

  For me it is strange that Kogama Battle isn't a more famous game. I am searching for it on the Internet and no one talks about it. And it's too bad, because it has all the hallmarks of a great game: flexibility, action, strategy, team play, accessibility.

  KB is a browser 3D shooter game. The 3D models are very simple and require little resources, but the network code is pretty good. There are two teams, Red and Blue, each starting from their own "castle". The two castles are three floors high and separated from each other by a water moat in which there are some islands to hop on. The purpose of the game is to reach the flag that is found in the other basecamp. Sounds easy, and it is. But there are so many different ways to win the game, that it becomes extremely amusing to play, if you have people who know how to play it on both sides.

  In this post I will:

  1. enumerate the different strategies for winning
  2. talk about what is good about the game
  3. talk about what is bad about the game
  4. list the items one can use in the game
  5. conclusion

How to win

1. Open the gate

  The obvious way to finish the game seems to be getting the key to the enemy castle (which lies on your side of the water) and carry it to the gate. You have to do this 10 times, then the door opens, allowing access to the enemy flag.

  Counter measures:

  • shoot the enemy as they get the key (either directly or shooting at the target stuck on the platform where the key is, which makes the entire platform explode and kill anyone there)
    • you can use the firewall, too, but it's pretty useless
  • after they open the gate, go to the enemy side, get the key and take it to your gate (applying the key to an open gate closes it and sets the counter back to 10)
    • this of course means your team must defend the flag from the people who entered the base
  • use the builder gun to cover the inside of the gate so that the enemy cannot immediately enter the base
    • the enemy might counter this by shooting a bazooka at the gate before they open it

  The greatest fun here is to get to the enemy side and steal a key when your gate counter is very low, then enter the castle and wait on the top floor. When the enemy has succeeded to open the gate you jump from above and immediately close it. Combined with the builder gun barricade, it makes for great satisfaction to foil your enemy.

2. Use the back door

  On the left side of the stairs to the gate there is a block out of place. It is a hint that you can do something with it. Shoot at it (and the next four blocks) and you open a tunnel to the enemy base. You can only go through it by using the shrinking pill, which means you can penetrate the enemy base, but unarmed and having to wait until you grow back again.

  Counter measures:

  • use the block gun to ... err ... block the tunnel from the inside of the base. Since the enemy is shrunken, they cannot shoot through it
    • there is a way for the enemy to destroy the blocks inside, as well as any defenses, and that is to temporarily switch team. Obviously, this is a form of cheating and only assholes use it, but it adds an element of "sabotage" to the game.
  • kill the tiny enemies, preferably with the flamethrower, when they emerge helpless from the tunnel :)
    • this wastes the resource of a person, but it is fun

3. Come through the window

  One can use the block gun in a variety of ways to gain access, but this is almost like it was designed like that. You need to make a stair like structure with the block gun that leads from the shrinking pill outside to the defense window above. Then, shrink yourself and enter the enemy base through the window, just like with the tunnel.

  Counter measures:

  • use the block gun to block the defense window on the pill side
    • the enemy can destroy that block easily, though, so it must be periodically checked, from outside and inside
  • kill the tiny enemies when they enter the window
  • destroy the blocks as they build the stair

4. Any other way of using the block gun to get to the enemy side:

  • jump and shoot a block under you, creating a column that pushes you up and allows you to get in the enemy base from the top floor
  • attach blocks on the walls of the map and create a bridge to get from one side to another
    • warning, when you create a bridge, the enemy can use it as well
  • shoot from your base to the other base so that there is a bridge created from the enemy base to the central suspended platform, then use the underwater teleporter to get onto the bridge
  • any type of ladder on the enemy base that allows you to get to the top floor

  Counter measures:

  • be vigilant and destroy the block structures constructed by the enemy (a bazooka is most effective)
  • kill enemies that manage to get in the base

5. Ugh! Rocket jumps

  Someone played Quake when they were young and they implemented the same thing here. In my opinion the bazooka is the worst item in the game, killing people after three shots, but destroying a lot of blocks and allowing rocket jumps. It holds 12 shots! I personally believe that people should be ashamed of themselves for using rocket jumps in Kogama Battle, because they are completely screwing the flow of the game.

  That being said, using a bazooka one can reach the other side's flag in less than 30 seconds.

  Another type of jump is pistol jump. I only saw it done once and it looks like a rocket jump, but without getting damaged, which is really dumb to have been allowed. I think you might need to have a jump bonus for this to work. Ugh, bonuses!

  Counter measures:

  • the only real solution is basing someone inside the flag room, armed with a flamethrower or a machine gun, ready to kill the attacker, who should be wounded from the rocket jumps
    • having health around in the base doesn't really help, though
  • some block structures can be erected to deter some sorts of rocket jumps, but it is a trivial matter to destroy them with the same weapon used for the jumps
  • use a sniper to hit them before they rocket jump to your base, which is pretty enjoyable, especially if they have a health bonus and thus die not from your sniper, but from their own jump

6. Team work

  Playing within a common strategy with other people is the fastest way to win in a satisfying manner. Even unlocking a gate takes just a few minutes with people defending the key bearers and having at least two of those. Once a gate is open, there is almost no way to defend the flag from incoming enemies and a strong team can stop anyone from grabbing the 11th key to close the door.

7. Use blocks to guard your flag

  This is more a way to prevent loss, rather than promote a win, but it's necessary. The strategy here involves blocking the way to the flag with blocks. If placed well, they will stop the enemy while the lava wall burns them or force them to fall into a lava pit. Just blocking the entry to the flag room is not enough, usually it takes at least 5 levels of walls. The walls don't need to cover everything from top to bottom, just to stop the movement of the enemy. Sometimes leaving holes in the walls lures enemies thinking there is a way through without having to shoot the blocks out.

  Usually this strategy is essential to delay enemies that opened the gate while you run to close it. Then, press K, which commits suicide, and chances are you will be respawned in the base on the top floor, ready to kill whoever is there.

8. Cheating

  I already said that rocket jumps are shameful, but even worse is switching teams to sabotage because you can't play the game properly. One can do that, and forever lose any self esteem, to use it to destroy block defenses or gain information

The good

  As you can see from above, there are multiple ways to play this. If you play beginners you can even harass them in their own base or write insults with the block gun in their own base, rather than end the round by reaching the flag. There are strategies, counters and counter counters, and they all change based on the composition of the teams. It is the thing that makes it so fun for me. Even for people who only care about shooting, one can be a sniper, a machine gunner, an akimbo shooter, using a flamethrower or a bazooka or a shotgun. People can play offense, defense, or both. There are a myriad ways to use the block gun to do all kinds of things.

  It's a browser game! Just open the page and play! The game moves smoothly, even if sometimes you see people skipping if they have a network issue. It is a shooter, but you don't need special skills to play it. I personally play it with the little laptop dongle on the keyboard (which also makes me unable to shoot while moving, a strange side effect of using the dongle in web games that I can't explain)

  The game is also as short as you want it. I have played 30 minutes rounds protecting the base alone against ten enemies and finished some in 2 minutes.

  There is no chat! Actually there is, but no one uses it because it is an option you have to sign in for. You can do this only on the Kogama web site, but most people play Kogama Battle on other servers. This means no one can shout abuse at you or explain to everybody how things are done or collaborate with the team (unless they use some other channel like a Discord chat) and log in together.

The bad

  The rocket gun! It is so unlike any other item in the game. It destroys everything in its path, except actual players. Carefully crafted block structures are blown away in a second. It holds 12 rounds of ammo! And it allows for rocket jumps. People who rocket jump should be dead when they land!

  The flamethrower. It is a very nice weapon, but has low damage and no lasting flame damage. When you stop shooting it, the damage stops. That's not how flamethrowers work.

  There is no chat! I know this is a good thing, but it is also a bad one. Many a times people who have no idea how to play the game (or trolls) grab a bazooka and start to destroy the defenses trying to get to their own flag! A special kind of person (that is amazingly common) comes and uses the block gun to cover the lava pits so that the enemy can get to the flag better. And they don't even intend harm, they just want to reach the flag and are scared of jumping, I suppose?

  Bonuses. There is a way to get some small perks for the game, like extra life, extra jump, extra speed. I don't know, I never used them. It spices things up, but it also breaks the rhythm of the game. With an extra hit points bonus you don't get instakilled by snipers and you can rocket jump with impunity. I think they are shameful.

  The firewall. Each base has a platform that triggers a wall of fire in front of the gate when a person sits on it. The fire doesn't stick, the damage is low and one needs just the smallest amount of time to use the key to unlock the gate. The firewall, as it stands, is useless.

  The two sides are not created equal. Differences in how blocks stick to the gate, the size of the lava wall and some random blocks on the lower level makes the red side better than the blue one.

  Team inequality is also a problem. One can switch team at any time, join the bigger team, switch again.

Items in the game

Weapons:

  • shotgun
    • fires slowly and in a limited range, but is very powerful. 
    • kills someone in two or three shots, depending on distance
  • flamethrower
    • continuous fire and limited range, medium damage, fires through walls
    • as discussed above, it looks cool and it can be found in a more accessible area of the base, but it's usually less effective than a shotgun
  • akimbo revolvers
    • strange weapons that push you back (no other weapon does that) making aiming difficult, medium damage
    • they are placed outside, good for quickly picking up and destroying blocks or shooting at platform triggers
  • machine gun
    • fires fast, low damage bullets, lots of ammo, pushes people back
    • perfect for pushing someone of a ledge or for defending the base, as it disrupts enemy movement a little
    • good for destroying blocks
  • sniper
    • very high damage, usually kills in one shot (see bonuses)
    • only 5 shots and it needs a long charging time before shooting
    • doesn't affect blocks
  • bazooka
    • destroys blocks easily on a large area, the explosion pushes the shooter (but not the target), needs three shots to kill a player
    • blast also hurts user, but not your own team
    • explosion has area damage that goes through walls as well
    • nasty and stupid weapon :D
  • life gun
    • a weird and kind of useless contraption
    • when fired at an enemy, it sucks away their life, but once stopped, life jumps back to the initial level
    • when used at an ally, it gives life to them, maybe also temporarily. I've never used it.
    • maybe it has a different hidden use as well?
  • block gun
    • fires blocks of destructible stone that can attach themselves to walls or other blocks
    • can be used to defend against bazookas, as placing a block in front of the shooter will make them hurt themselves (even if they are your own team, like for trolls)
    • pressing long will destroy blocks and return them to you

Map features:

  • teleporter
    • there is one in each base lower level that leads in and out and can only be used by the base team
    • there is a neutral one under water which leads to a suspended ledge above it
  • trigger
    • it is a platform that triggers something when someone stands on it
    • there is one in each base to trigger the firewall
    • there is one outside each base, invisible, left of the staircase, sounding an alarm every time someone steps there (announcing a possible tunnel breach)
    • there are triggers on the key platforms, ringing when someone is on them
  • key
    • on each side of the water there is a key that opens the gate on the other side
    • the key is located upon a platform that has a target trigger attached to it
    • takes some time to respawn
    • if you are killed when carrying one, the key is dropped for a few seconds, permitting a team mate to continue carrying it
  • target trigger
    • attached to the platforms on which keys are located
    • if shot, they make the platform explode, killing everything on it
    • takes some time to recharge
  • destroyable blocks
    • not only you can place blocks, there are some placed for you
    • they can be destroyed to gain faster exit access or to get to the flag or secret tunnel
  • lava pits
    • found only in the flag room, they can be jumped over easily
    • if touched by lava you burn fast until you die, even if you get out of it
  • lava wall
    • also in the flag room, it moves from one side of the room to the other and back
    • touching it makes you burn until death
  • lava edges
    • there is one on the top edge of a wall of the top floor as well as around the walls of the map itself
    • pretty useless and only accidentally can someone get burnt by them
  • gates
    • one for each base, they start locked 10 times
    • you need a key with the same color for each of the times to open it
    • a key will reset a gate to closed if used on an open gate
  • middle platform
    • only accessible by using the underwater teleporter (or lucky rocket jumps)
    • it allows for some ways to get to the enemy base as well as an overview of the entire map
    • people sitting on the platform are easily killed from the top of the base
  • shrink pill
    • found outside the base as well as inside the tunnel and inside the base
    • they shrink you to a size that allows for going through small holes or windows
    • you lose any weapon you have when you shrink
  • defense ports
    • each base has two small ones on the lower level, where one can use snipers and bazookas against enemies going for the key
    • each base has two medium ones on the middle level, large enough for a shrunken person to go through
    • each base has large holes in the thin wall on the top floor through which one can look and shoot at the enemies
  • water
    • water makes it almost impossible to see outside it, but you are visible to anyone looking in the water
    • stay long enough under water and you will take very little damage

Game features:

  • the long jump
    • jumps depend on how long one presses space
    • you need to master the long jump before you can play this game well
  • access from the base
    • you can exit the base by using the teleporter or jumping from the top floor
    • in order to exit faster (and safer) use the machine gun to cut through the destructible blocks next to them (or a bazooka, or a block gun)
  • the machine gun push
    • machine gun bullets push the target a bit, which means you can disrupt their movement, push them into lava or into shrink pills (always fun, that)
  • flame through wall
    • much stronger than the firewall is using the flamethrower to shoot through the gate or through walls
    • warning! Do this in front of the gate and you might promote someone shooting a bazooka at you and destroying any block defense there
    • one can sit around a corner or even shoot through floors and give damage while protected from most guns
  • initial block setup
    • it is important when the round starts to cover these bases:
      • block tunnel under the Warning! sign
      • block defense window on the right on the middle floor (where the teleporter and small pill lie outside)
      • block flag by starting from the flag out: block access to the flag, block access out of the lava pit, block escape from lava wall, only then block the entry to the room. Here you need to not block the lava pits or give your enemy footholds above them, instead you block after the pits so that the enemy falls into them if they jump.

Conclusion

  This game is a lot of fun with the right people. If someone would make some small fixes, it could be the seed to a wonderful little game.

  My proposals:

  1. nerf the bazooka
    • less area damage against blocks, two at most and preferable dealing a lot less damage to a block behind a block
    • more damage against people
    • less blast pushback (no rocket jumps)
    • less ammo
  2. upgrade fire damage
    • increase fire damage from fire wall and flamethrower
    • and/or make fire stick to the target for a while
  3. nerf block gun
    • the block gun needs to be fast, so you can't nerf the speed of fire
    • so make it so you can't fire it while moving
      • this will allow for strategic long range structures, but disallow columns and jump-and-fire escapades from one side to the other
  4. force teams equal
    • make it so you can only join the smaller team
    • make the team switch (and initial game join) take a lot longer 
  5. no bonuses
    • remove bonuses, all players should be equal
  6. make it a real capture the flag game. The flag should be captured and taken to your own base before winning
    • this promotes teamwork, as the guy with the flag would not carry any weapons

  That's it. In my mind, this game would be perfect with just a few adjustments.

  You can play this game by googling for it and finding the biggest server at that time. Now, the servers I use are:

  • Crazy Games
  • Y8
  • any other server where Kogama Battle can be found via Google

 Have fun!

  Was I in a mood that I didn't enjoy Revenant Gun or has something changed in Yoon Ha Lee's writing? I can blame it partially on the fact that I didn't remember anything from the previous books, but I do remember I enjoyed them!

  Reading my review of the previous book I see some similarities in feeling: I don't remember much of the story or characters from before and it feels a bit sluggish at the beginning and rushed at the end. But the difference is that I had trouble finishing Revenant Gun and, instead of fondly remembering the situation where the other two books left off and getting closure, I felt like I had difficulty empathizing with any of the characters or caring about the story.

  And it's not like it's a straightforward book. It has two different threads, in one there is a resurrected Jedao reluctantly serving Kujen, the other is another Jedao, inhabiting the body of Cheris. Then there are a zillion officers, hexarhs, servitors, moths, lots of gay love that is unrelated to the story, but may have a place in the culture of this military universe and so on. The writing was decent, but it didn't blow me away.

  Bottom line: Perhaps the lucky ones are those who will read the entire trilogy at once and get both the freshness of the concepts and the closure of the story in one go. As such, I got almost nothing from this.

  Money is the root of all evil is a saying that has proven itself time and time again. Trying to make money from something that was not meant to do that will always soil and corrupt it. It is the case of so called "superchats", chat entries that have money attached to them.

  Here is how it works. Some content creator is doing a live stream and people are discussing the subject in the chat. There have been donation systems that allow people to give money to the creator for a long time and even there you see there is a bit of an issue. The streamer is almost forced by politeness (and because it encourages viewers) to acknowledge every donation. So they punctuate their content with "X has given me Y. Thanks a lot, X". This diminishes, albeit in a small way, the quality of the streamed content. Superchats are this, times 100.

  You see, when a chat message comes with money attached, the streamers are again motivated to acknowledge it. However, this time they read aloud the content of the message as well and respond to it, even if it is just with a sentence. This leads to significantly more disruption, but also has secondary effects that are at the core of the system. People have now been tiered into the ones that write a message and are ignored and the ones that pay to not be ignored, regardless of how useless, stupid or aggressive their chat message is.

  The content creator has only a few options at their disposal:

  • treat the superchats just like normal chat messages, in which case people won't be motivated to superchat, leading to less money for the stream
  • acknowledge and reply to just some of the superchats, which is a form of gambling for the message sender, if you think about it
  • acknowledge and reply to all superchats, which leads to a "super" tier of discussion that can only be accessed if you pay for it

Now, I understand how this system brings more money to the stream, but at what cost? People who crave attention are not the ones that you want to bring to the forefront of any discussion, but even so, many of them are immature teens. In order to have the system working, you need to stream, which motivates the creator to make interactive content and as long as possible to the detriment of short, concise, researched content.

The result is an explosion of low quality live streams, playing (preying!) on people's biases and social instincts, funded by the money of children and highlighting fragments of discussions based on how much they paid and not the quality of their content. Superchats are a disease of the Internet, akin to infomercials, television ads or paid news items. And unlike these, there are no tools to remove the streamer acknowledgements of superchats from the stream.

I am not an activist, but the only way to get rid of this toxic system is to actively fight it. I wonder if it could be seen as gambling, in a legal context. That should shut it down.

  Every month or so I see another article posted by some dev, usually with a catchy title using words like "demystifying" or "understanding" or "N array methods you should be using" or "simplify your Javascript" or something similar. It has become so mundane and boring that it makes me mad someone is still trying to cache on these tired ideas to try to appear smart. So stop doing it! There is no need to explain methods that were introduced in 2009!

  But it gets worse. These articles are partially misleading because Javascript has evolved past the need to receive or return data as arrays. Let me demystify the hell out of you.

  First of all, the methods we are discussing here are .filter and .map. There is of course .reduce, but that one doesn't necessarily return an array. Ironically, one can write both .filter and .map as a reduce function, so fix that one and you can get far. There is also .sort, which for performance reasons works a bit differently and returns nothing, so it cannot be chained as the others can. All of these methods from the Array object have something in common: they receive functions as parameters that are then applied to all of the items in the array. Read that again: all of the items.

  Having functions as first class citizens of the language has always been the case for Javascript, so that's not a great new thing to teach developers. And now, with arrow functions, these methods are even easier to use because there are no scope issues that caused so many hidden errors in the past.

  Let's take a common use example for these methods for data display. You have many data records that need to be displayed. You have to first filter them using some search parameters, then you have to order them so you can take just a maximum of n records to display on a page. Because what you display is not necessarily what you have as a data source, you also apply a transformation function before returning something. The code would look like this:

var colors = [
  {    name: 'red',    R: 255,    G: 0,    B: 0  },
  {    name: 'blue',   R: 0,      G: 0,    B: 255  },
  {    name: 'green',  R: 0,      G: 255,  B: 0  },
  {    name: 'pink',   R: 255,    G: 128,  B: 128  }
];

// it would be more efficient to get the reddish colors in an array
// and sort only those, but we want to discuss chaining array methods
colors.sort((c1, c2) => c1.name > c2.name ? 1 : (c1.name < c2.name ? -1 : 0));

const result = colors
  .filter(c => c.R > c.G && c.R > c.B)
  .slice(page * pageSize, (page + 1) * pageSize)
  .map(c => ({
      name: c.name,
      color: `#${hex(c.R)}${hex(c.G)}${hex(c.B)}`
  }));

This code takes a bunch of colors that have RGB values and a name and returns a page (defined by page and pageSize) of the colors that are "reddish" (more red than blue and green) order by name. The resulting objects have a name and an HTML color string.

This works for an array of four elements, it works fine for arrays of thousands of elements, too, but let's look at what it is doing:

  • we pushed the sort up, thus sorting all colors in order to get the nice syntax at the end, rather than sorting just the reddish colors
  • we filtered all colors, even if we needed just pageSize elements
  • we created an array at every step (three times), even if we only needed one with a max size of pageSize

Let's write this in a classical way, with loops, to see how it works:

const result = [];
let i=0;
for (const c of colors) {
	if (c.R<c.G || c.R<c.B) continue;
	i++;
	if (i<page*pageSize) continue;
	result.push({
      name: c.name,
      color: `#${hex(c.R)}${hex(c.G)}${hex(c.B)}`
    });
	if (result.length>=pageSize) break;
}

And it does this:

  • it iterates through the colors array, but it has an exit condition
  • it ignores not reddish colors
  • it ignores the colors of previous pages, but without storing them anywhere
  • it stores the reddish colors in the result as their transformed version directly
  • it exits the loop if the result is the size of a page, thus only going through (page+1)*pageSize loops

No extra arrays, no extra iterations, only some ugly ass code. But what if we could write this as nicely as in the first example and make it work as efficiently as the second? Because of ECMAScript 6 we actually can!

Take a look at this:

const result = Enumerable.from(colors)
  .where(c => c.R > c.G && c.R > c.B)
  //.orderBy(c => c.name)
  .skip(page * pageSize)
  .take(pageSize)
  .select(c => ({
      name: c.name,
      color: `#${hex(c.R)}${hex(c.G)}${hex(c.B)}`
  }))
  .toArray();

What is this Enumerable thing? It's a class I made to encapsulate the methods .where, .skip, .take and .select and will examine it later. Why these names? Because they mirror similar method names in LINQ (Language Integrated Queries from .NET) and because I wanted to clearly separate them from the array methods.

How does it all work? If you look at the "classical" version of the code you see the new for..of loop introduced in ES6. It uses the concept of "iterable" to go through all of the elements it contains. An array is an iterable, but so is a generator function, also an ES6 construct. A generator function is a function that generates values as it is iterated, the advantage being that it doesn't need to hold all of the items in memory (like an array) and any operation that needs doing on the values is done only on the ones requested by code.

Here is what the code above does:

  • it creates an Enumerable wrapper over array (performs no operation, just assignments)
  • it filters by defining a generator function that only returns reddish colors (but performs no operation) and returns an Enumerable wrapper over the function
  • it ignores the items from previous pages by defining a generator function that counts items and only returns items after the specified number (again, no operation) and returns an Enumerable wrapper over the function
  • it then takes a page full of items, stopping immediately after, by defining a generator function that does that (no operation) and returns an Enumerable wrapper over the function
  • it transforms the colors in output items by defining a generator function that iterates existing items and returns the transformed values (no operation) and returns an Enumerable wrapper over the function
  • it iterates the generator function in the current Enumerable and fills an array with the values (all the operations are performed here)

And here is the flow for each item:

  1. .toArray enumerates the generator function of .select
  2. .select enumerates the generator function of .take
  3. .take enumerates the generator function of .skip
  4. .skip enumerates the generator function of .where
  5. .where enumerates the generator function that iterates over the colors array
  6. the first color is red, which is reddish, so .where "yields" it, it passes as the next item in the iteration
  7. the page is 0, let's say, so .skip has nothing to skip, it yields the color
  8. .take still has pageSize items to take, let's assume 20, so it yields the color
  9. .select yields the color transformed for output
  10. .toArray pushes the color in the result
  11. go to 1.

If for some reason you would only need the first item, not the entire page (imagine using a .first method instead of .toArray) only the steps from 1. to 10. would be executed. No extra arrays, no extra filtering, mapping or assigning.

Am I trying too hard to seem smart? Well, imagine that there are three million colors, a third of them are reddish. The first code would create an array of a million items, by iterating and checking all three million colors, then take a page slice from that (another array, however small), then create another array of mapped objects. This code? It is the equivalent of the classical one, but with extreme readability and ease of use.

OK, what is that .orderBy thing that I commented out? It's a possible method that orders items online, as they come, at the moment of execution (so when .toArray is executed). It is too complex for this blog post, but there is a full implementation of Enumerable that I wrote containing everything you will ever need. In that case .orderBy would only order the minimal number of items required to extract the page ((page+1) * pageSize). The implementation can use custom sorting algorithms that take into account .take and .skip operators, just like in LiNQer.

The purpose of this post was to raise awareness on how Javascript evolved and on how we can write code that is both readable AND efficient.

One actually doesn't need an Enumerable wrapper, and can add the methods to the prototype of all generator functions, as well (see LINQ-like functions in JavaScript with deferred execution). As you can see, this was written 5 years ago, and still people "teach" others that .filter and .map are the Javascript equivalents of .Where and .Select from .NET. NO, they are NOT!

The immense advantage for using a dedicated object is that you can store information for each operator and use it in other operators to optimize things even further (like for orderBy). All code is in one place, it can be unit tested and refined to perfection, while the code using it remains the same.

Here is the code for the simplified Enumerable object used for this post:

class Enumerable {
  constructor(generator) {
	this.generator = generator || function* () { };
  }

  static from(arr) {
	return new Enumerable(arr[Symbol.iterator].bind(arr));
  }

  where(condition) {
    const generator = this.generator();
    const gen = function* () {
      let index = 0;
      for (const item of generator) {
        if (condition(item, index)) {
          yield item;
        }
        index++;
      }
    };
    return new Enumerable(gen);
  }

  take(nr) {
    const generator = this.generator();
    const gen = function* () {
      let nrLeft = nr;
      for (const item of generator) {
        if (nrLeft > 0) {
          yield item;
          nrLeft--;
        }
        if (nrLeft <= 0) {
          break;
        }
      }
    };
    return new Enumerable(gen);
  }

  skip(nr) {
    const generator = this.generator();
    const gen = function* () {
      let nrLeft = nr;
      for (const item of generator) {
        if (nrLeft > 0) {
          nrLeft--;
        } else {
          yield item;
        }
      }
    };
    return new Enumerable(gen);
  }

  select(transform) {
    const generator = this.generator();
    const gen = function* () {
      for (const item of generator) {
		yield transform(item);
      }
    };
    return new Enumerable(gen);
  }

  toArray() {
	return Array.from(this.generator());
  }
}

The post is filled with links and for whatever you don't understand from the post, I urge you to search and learn.

I like Dave Farley's video channel about the software industry quality, Continuous Deployment, so I will share this video about how tech interviews should be like. Not a step by step tutorial as much as asking what is the actual purpose of a tech interview and how to get to achieve it:

[youtube:osnOY5zgdMI]

Top Software Engineering Interview Tips - Dave Farley

  It was very difficult to finish Bad Connections, as it is just a one sided view of the world from a very unsympathetic character. I understand the story was supposed to be a fuller portrait of women as a whole, but damn it makes them look dumb.

  So there is this woman who has to navigate through being the wife, the sexually unsatisfied, the adulteress, the divorcee, the single mother, the mistress, the woman on the side, the compulsive clinger and so on. I guess it was supposed to make the reader understand what it means to be female, yet Molly is emotional, compulsive, egotistic and ultimately weak. The scene at the end it written to provide some sort of feeling of emancipation, but in fact made me think she was even more of a coward than before.

  Bottom line: Joyce Johnson may be a big shot beatnik writer who hung out with Kerouac, but I did not like this book. It was short, yet unentertaining. It was full of meaning, of which I felt none was interesting or educational.

  About a year and a half ago I installed DuoLingo and started going through some of the languages there. The app was advertising itself as "The world's best way to learn a language" and "Learn languages by playing a game. It's 100% free, fun, and scientifically proven to work." And in the beginning it was. You could go through simple but increasingly complex lessons and advance in level, exactly as promised.

  And then whatever happened to mobile apps everywhere happened to DuoLingo as well: incessant ads, with garish colors and loud sounds, overtly lying about what they are advertising for. They changed the internal currency of DuoLingo, started to ask for more things just to get the normal stuff needed to learn a language, like the short stories that are the only part of the app that teaches the language in context. Lately they added speed games that no one can finish without spending the currency they've amassed, but increase the points one gets, so puts pressure on everyone to either play the games or spend a lot of effort to not fall behind.

  And for what? After getting to the third level in a language, I started to take every section and finish it (take it to level 5). There is basically no difference between the lessons as the level increases. You never get to complex sentences, learn new words or gain any new knowledge. You just go through the motions in order to get a golden badge or whatever, while filling in sentences about newspapers. Yes! I don't know if you remember them, they're very important in the universe of DuoLingo.

  Also, there is a huge difference between the way lessons work for different languages. You want Spanish of French, you get different games, a lot of stories and so on. You want something more obscure like Dutch, you don't even get stories!

  So continuing to bear with obnoxious commercials just in order to use the app "100% free" is too exhausting, while the benefits are now minimal to none.

  I also doubt this is any way to learn a language. I am not able to understand speech in the language that I've spent months working on, there are very few sentence composition lessons that cover reasonable scenarios likely to meet in real life and the vocabulary is extremely limited. And limited in a stupid way: instead of learning words that one would use in everyday sentences you learn things like newspaper and apple and rabbit.

  Let's be honest here: I only went with Duolingo because it was easy. It gave me the illusion that I am doing something with my time while playing with my smartphone. If I really wanted to learn a language I would have listened and read in that language, I would have found people speaking the language and chatted with them, whether directly or in writing, I would have taken the list of the top 100 words used in that language and I would have created and written down sentences using those words until I could do it in my sleep. That requires effort and commitment and it is obvious that I wasn't going to spend it. That's on me. However, the state of DuoLingo, particularly compared to how it started, is the fault of the company.

  Conclusion: not only has DuoLingo become a cautionary tale about applications that advertise how free they are and will ever be, but it wasn't a good app to begin with and they never invested much into improving it. All development efforts in the last year have been on how to get you to pay for the app, what clothes Duo the owl wears and stupid time consuming animations to "motivate" you. Gamification has become the goal, not the means to achieve something worthwhile. So, with a heavy heart because of losing all the gems I've gathered and my 550 daily streak, I will be stopping using DuoLingo.

  As any software developer with any self respect, I periodically search the Internet for interesting things that would help me become better as a professional and as a human being. I then place those things in a TODO list and play some silly game. Here is a list of things that I want to pursue sooner or later, possibly later, probably never:

  • Astro: Ship Less JavaScript - static site builder that delivers lightning-fast performance with a modern developer experience.
    In the design of Astro:
    • Bring Your Own Framework (BYOF): Build your site using React, Svelte, Vue, Preact, web components, or just plain ol’ HTML + JavaScript.
    • 100% Static HTML, No JS: Astro renders your entire page to static HTML, removing all JavaScript from your final build by default.
    • On-Demand Components: Need some JS? Astro can automatically hydrate interactive components when they become visible on the page. If the user never sees it, they never load it.
    • Fully-Featured: Astro supports TypeScript, Scoped CSS, CSS Modules, Sass, Tailwind, Markdown, MDX, and any of your favorite npm packages.
    • SEO Enabled: Automatic sitemaps, RSS feeds, pagination and collections take the pain out of SEO and syndication.
  • https://brython.info/ - Brython is a Python 3 implementation adapted to the HTML5 environment
    • Designed to replace Javascript as the scripting language for the Web
    • You can take it for a test drive through a web console
    • Speed of execution is similar to CPython for most operations
  • https://github.com/yggdrasil-network/yggdrasil-go - an early-stage implementation of a fully end-to-end encrypted IPv6 network
    • It is lightweight, self-arranging, supported on multiple platforms and allows pretty much any IPv6-capable application to communicate securely with other Yggdrasil nodes.
    • Yggdrasil does not require you to have IPv6 Internet connectivity - it also works over IPv4.
  • React-Table - Build and design powerful datagrid experiences while retaining 100% control over markup and styles.
    • Designed to have zero design
    • Built to materialize, filter, sort, group, aggregate, paginate and display massive data sets using a very small API surface.
    • Has its very own plugin system allowing you to override or extend any logical step, stage or process happening under the hood.
  • Implement a DisposeAsync method - this implementation allows for asynchronous cleanup operations. The DisposeAsync() returns a ValueTask that represents the asynchronous dispose operation.
  • https://dev.to/neethap/how-to-publish-a-static-react-node-js-app-using-cpanel-the-easy-way-199o - Forget the Setup Node.js App feature on your cPanel. Instead, you want to focus your attention on the build folder
  • https://blog.m3o.com/2021/06/24/micro-apis-for-everyday-use.html - Micro has evolved from an open source framework to a full blown API platform, one that continues to focus on the developer experience first and foremost. The majority of users are building APIs for end public consumption but having to rebuild many of the building blocks they need wherever they go.
  • itsi Meet - Secure, Simple and Scalable Video Conferences
    • The Jitsi Meet client runs in your browser, without installing anything on your computer. You can try it out at https://meet.jit.si.
    • Jitsi Meet allows for very efficient collaboration. Users can stream their desktop or only some windows. It also supports shared document editing with Etherpad.
  • Mumble - Open Source voice-chat software
    • The client works on Windows, Linux, FreeBSD and macOS, while the server should work on anything Qt can be installed on.
  • Swagger UI with login form and role-based api visibility - This post show how to customize Swagger UI in a Blazor WASM project using Swashbuckle library, implement a custom authentication UI and manage api visibility based on user roles.
  • Complete Introduction to React-Redux - third part of a series by Kumar Harsh
  • Wav2vec: Semi and Unsupervised Speech Recognition

Tell me, what will this Visual Basic .NET code display?

For x as Integer = 1 to 2
  Dim b as Boolean
  Console.WriteLine("b is " & b)
  b = true
Next

 Even if you never coded in Visual Basic it's a relatively easy code to translate to something like C#:

for (var x = 1; x <= 2; x++)
{
	bool b;
	Console.WriteLine("b is " + b);
	b = true;
}

Now what will the code display? Let's start with this one. This code will not compile and instead you will get: Use of unassigned local variable 'b'.

But what about the VB one? Even with Option Strict ON it will not even warn you. And the output will be: False, True. What?!

In conclusion, VB.Net will let you declare variables without assigning any value to them, but their value will be inconsistent. Always set the variables you declare. 

  In this trilogy, the first two books were filler promising much for the last one, The Saints of Salvation. And I had to force myself to read it, just to get it over with. Most of the book is about these people pointlessly living their lives and daring you to remember all of their names. I couldn't feel a connection with any of them, so all that was left was to bask in the space technology and the battles and the cathartic ending. Which was something brief and unfulfilling.

  I don't want to spoil this, just in case you like it and want to read it, but Peter F. Hamilton's knack for ruining endings is present here as well. Obsessively trying to close all the loose ends (that no one cared about) and make them connect to each other (for no reason whatsoever) after the unsatisfying ending makes things worse.

  If I were to guess, Hamilton searches for a new universe, one that is kind of inspired by the Commonwealth universe, but it is not as technologically advanced so that it can provide new interesting opportunities for story telling. Salvation was an attempt at a new universe, inspired by British history during the Blitz yet set in the future, but it got really fast into portals and exotic wormholes and gravitonic weapons and quantum effects and ineffectual aliens. Meanwhile the storytelling was lacking! I really hope he moves on to something else.

Learning from React series:

  • Part 1 - why examining React is useful even if you won't end up using it
  • Part 2 - what Facebook wanted to do with React and how to get a grasp on it
  • Part 3 - what is Reactive Programming all about?
  • Part 4 - is React functional programming?
  • Part 5 - Typescript, for better and for worse
  • Part 6 (this one) - Single Page Applications are not where they wanted to be

We cannot discuss React without talking about Single Page Applications, even if one can make a React based web site that isn't a SPA and SPAs that don't use a framework or library. What are SPAs? Let's start with what they are not.

SPAs are not parallax background, infinite scroll pages where random flashy things jump at you from the top and bottom and the sides like in a bloody ghost train ride! If you ever considered doing that, this is my personal plea for you to stop. For the love of all that is decent, don't do it!

SPAs are desktop applications for the web. They attempt to push the responsive, high precision actions, high CPU usage and fancy graphics to the client while maintaining the core essentials on the server, like security and sensitive data, while trying to assert full control over the interface and execution flow. In case connectivity fails, the cached data allows the app to work just fine offline until you reconnect or you need uncached data. And with React (or Angular and others), SPAs encapsulate UI in components, just like Windows Forms.

You know who tried (and continues to try) to make Windows Forms on the web? Microsoft. They started with ASP.Net Web Forms, which turned into ASP.Net MVC, which turned into ASP.Net Web API for a while, then turned to Blazor. At their heart, all of these are attempts to develop web applications like one would desktop applications.

And when they tried to push server side development models to the web they failed. They might succeed in the future and I wish them all the luck, but I doubt Microsoft will make it without acknowledging the need to put web technologies first and give developers full and direct access to the browser resources.

Ironically, SPAs (and modern web development in general) put web technologies first to a degree that makes them take over functionality already existing in the browser, like location management, URL handling and rendering components, but ignore server technologies.

It is relevant to make the comparison between SPAs and desktop applications because no matter how much they change browsers to accommodate this programming style, there are fundamental differences between the web and local systems.

For one, the way people have traditionally been trained to work on the web is radically different from how modern web development is taught.

Remember Progressive Enhancement? It was all about serving as much of the client facing, relevant content to the browser first, then enhancing the page with Javascript and CSS. It started from the idea that Javascript is slow and might not be enabled. Imagine that in 2021! When first visiting a page you don't want to keep the users waiting for all the fancy stuff to load before they can do anything. And SEO, even if nowadays the search engine(s?) know how to execute Javascript to get the content as a user would, still cares a lot about the first load experience.

Purely client tools like React, Angular, Vue, etc cannot help with that. All they can do is optimize the Javascript render performance and hope for the best. There are solutions cropping up: check out SSR and ReactDomServer and React Server Components. Or Astro. Or even Blazor. The takeaway here is that a little bit of server might go a long way without compromising the purity of the browser based solution.

Remember jQuery and before? The whole idea back then was to access the DOM as a singular UI store and select or make changes to any element on the entire page. Styling works the same way. Remember CSS Zen Garden? You change one global CSS file and your website looks and feels completely different. Of course, that comes with horrid things like CSS rule precedence or !important [Shudder], yet treating the page as a landscape that one can explore and change at will is a specifically browser mindset. I wasn't even considering the possibility when I was doing Windows Forms.

In React, when I was thinking of a way to add help icons to existing controls via a small script, the React gurus told me to not break encapsulation. That was "not the way". Well, great, Mandalorian! That's how you work a lot more to get to the same thing we have done for years before your way was even invented! In the end I had to work out wrapper elements that I had to manually add to each form control I wanted to enhance.

In the same app I used Material Design components, which I thought only needed a theme to change the way they look and feel, only to learn that React controls have to be individually styled and that the theme itself controls very few things. Even if there is support for theming, if you want to significantly change the visuals and behaviour you will have to create your own controls that take what they need (much more than what Material UI controls do) from the theme provider.

A local desktop application is supposed to take most of the resources that are available to it. You can talk about multitasking all you want, but normal people focus on one complex application at a time. At its core a SPA is still a browser tab, using one thread. That means even with the great performance of React, you still get only one eighth (or something, based on the number of processors) from the total computer resources. There are ways of making an application use multiple threads, but that is not baked in React either. Check out Neo.js for an attempt to do just that.

You can't go too far in the other direction either. Web user experience is opening many tabs and switching from one to the other, refreshing and closing and opening others and even closing the browser with all the tabs open or restoring an entire group of bookmarks at once. And while we are at the subject of URLs and bookmarks, you will find that making a complex SPA consistently alter the address location so that a refresh or a bookmark gets you to the same place you were in is really difficult.

A local Windows app usually has access to a lot of the native resources of the computer. A browser is designed to be sandboxed from them. Moreover, some users don't have correct settings or complete access to those settings, like in corporate environments for example. You can use the browser APIs, but you can't fully rely on them. And a browser tab is subject to firewall rules and network issues, local policies, browser extensions and ad blockers, external ad providers and so on.

You may think I am taking things to an unreasonable extreme. You will tell me that the analogy to desktop apps breaks not despite, but because of all of the reasons above and thus SPAs are something else, something more light, more reusable, webbier, with no versioning issues and instant access and bookmarkable locations. You will tell me that SPAs are just normal web sites that work better, not complex applications. I will cede this point.

However! I submit that SPAs are just SPAs because that's all they could be. They tried to replace fully fledged native apps and failed. That's why React Native exists, starting as a way to do more performant apps for mobiles and now one can write even Windows applications with it.

Single Page Applications are great. I am sure they will become better and better with time until we will forget normal HTML pages exist and that servers can render and so on. But that's going in the wrong direction. Instead of trying to emulate desktop or native apps, SPAs should embrace their webbiness.

Is Javascript rendering bad? No. In fact it's just another type of text interpreted by the browser, just like HTML would be, but we can do better.
Is Javascript URL manipulation bad? No. It's the only way to alter the address location without round trips to the server, but sometimes we need the server. Perhaps selective loading of component resources and code as needed will help.
Is single threaded execution bad? No, but we are not restricted to it.
Is component encapsulation bad? Of course not, as long as we recognize that in the end it will be rendered in a browser that doesn't care about your encapsulation.
The only thing that I am still totally against is CSS in Javascript, although I am sure I haven't seen the best use of it yet.

React is good for SPAs and SPAs are good for React, but both concepts are trying too hard to take things into a very specific direction, one that is less and less about the browser and more about desktop-like components and control of the experience. Do I hate SPAs? No. But as they are now and seeing where they are going, I can't love them either. Let's learn from them, choose the good bits and discard the chaff.  

A year or so ago I wrote a Javascript library that I then ported (badly) to Typescript and which was adding the sweet versatility and performance of LINQ to the *script world. Now I've rewritten the entire thing into a Typescript library. I've abandoned the separation into three different Javascript files. It is just one having everything you need.

I haven't tested it in the wild, but you can get the new version here:

Github: https://github.com/Siderite/LInQer-ts

NPM: https://www.npmjs.com/package/@siderite/linqer-ts

Documentation online: https://siderite.github.io/LInQer-ts

Using the library in the browser directly: https://siderite.github.io/LInQer-ts/lib/LInQer.js and https://siderite.github.io/LInQer-ts/lib/LInQer.min.js

Please give me all the feedback you can! I would really love to hear from people who use this in:

  • Typescript
  • Node.js
  • browser web sites

The main blog post URL for the project is still https://siderite.dev/blog/linq-in-javascript-linqer as the official URL for both libraries.

Have fun using it!

  Learning from React series:

  • Part 1 - why examining React is useful even if you won't end up using it
  • Part 2 - what Facebook wanted to do with React and how to get a grasp on it
  • Part 3 - what is Reactive Programming all about?
  • Part 4 - is React functional programming?
  • Part 5 (this one) - Typescript, for better and for worse
  • Part 6 - Single Page Applications are not where they wanted to be

  Typescript is a programming language developed by Microsoft. It is a superset of Javascript that allows a lot of type checking and manipulation, hence the name. React and Vue fully support it while Angular requires it. So what is the reason for the adoption of this new language? What are its advantages and disadvantages?

  First of all, what is it? I would start metaphorically, if you can forgive that. Imagine a vast jungle, grown organically since time immemorial, chaotic and wild. Many developers went in, but few have come out unscathed, some never to be seen again. That's Javascript for you. It was released in 1995 as a basic scripting language for browsers, but it was designed as so flexible and complete that it could be used as a programming language in any context with minor modifications. For a very long time tightly coupled with its (very inefficient) browser implementations, it was dismissed from being a proper programming language. But that ended pretty much when V8 was launched, a performant Javascript engine that could be used separately to run the language in whatever situation the developer wanted. With V8, Chrome was launched and soon enough Node.js, which ran Javascript on the server as a proper language.

  The worst and best feature of Javascript is flexibility. You can do pretty much whatever you want in it, as it is a dynamic language unencumbered by such silly things as encapsulation, classes, types and so on. So if you started in a structured way, you could do a lot, if not - like most people unfamiliar with the language - you created a mess that no one could understand, including yourself. So if Javascript is a jungle, Typescript is Duke Nukem coming to cut the trees, wall off vast swathes of forest and only allow a narrow path for life to exist. Only, on that narrow path you get the same chaotic and wild proliferation. A lot fewer software developers traverse the forest and come out with PTSD, but a lot more people go through than before and mistakes can and will be made.

  I guess what I am trying to say is that Typescript sometimes feels like a square peg forced into a round hole. It is not a bad language. In fact, it is amazing in some parts. The type system introduced by Microsoft acts like a kind of system of annotations that inform on what you are actually doing. Tools are aware now of the types of values you use, can optimize code, find errors, warn devs, autocomplete code, help with development, etc. And I am willing to bet that people working on the language are having the time of their lives, because it has to be fun to work on abstract computer science and getting paid, too.

  But what does that mean for the frontend industry? It means that people are getting pushed on that narrow jungle path, for better or for worse. As a small business, you will have to either accept a shitty website created by cheap Javascript and vanilla HTML cavemen or get a lot out of your pocket to hire people who spend time and effort to understand Typescript and some, if not most, of the frontend frameworks that are fashionable at the moment. As a large company you will get tectonic shifts in technology, leaving a large part of your workforce in limbo, while having to spend a lot on hiring and redesigning flows. As an industry, we become dependent on several companies that spend the effort of keeping their frameworks up to date and documented. 

  Let me give you some Typescript questions (that I will not answer) to test your knowledge:

  • can you tell me what all of these types are and how they differ from each other: undefined, null, any, unknown, never, void ?
  • how can you tell if a Typescript object is of a specific form (the equivalent of the .NET 'is' or 'as' functionality)?
  • what is the difference between a union of literal types and an enum?
  • what are and how can you use BigInt, ReadOnlyArray, Partial, NonNullable, Required?
  • what is the difference between a private member of a Typescript class and one starting with #?
  • do you know how to use unions in interpolated strings?
  • what is the difference between interface, type, class, type intersection, class expression and module?

 I could go on and on. On how the possibility of null is now something you have to declare explicitly, for example. I didn't (dare to) ask about type guards and how narrowing works and what conditional types are. And there are so many gotchas for developers coming from other languages, because the language features have been added by people who worked on C#, so they are kind of the same, but actually not. Type meaning and conversion is a large bit of confusing difference between Typescript and C#/Java. For example you can define a class and then cast some data to it, but you don't get what you expect:

class MyClass {
  public name: string='';
  public sayHello() { console.log(`Hello ${this.name}`); }
}

const my:MyClass = { name: 'Siderite' } as MyClass;
console.log(my); // { "name": "Siderite" }
console.log(typeof(my)); // "object"
console.log(my instanceof MyClass) // false
console.log(my.sayHello()); // ERR: my.sayHello is not a function 

There are still web sites dedicated to the inconsistencies of Javascript. Typescript doesn't solve these issues, it mostly hides them. I am sure it's fun to play with types, but is that the optimal solution for the problem at hand, mainly the many ways you can do Javascript wrong? I would argue no. It's fun to work in, but there is a clear dependency between Typescript and Javascript, which forced so many changes in Typescript from Javascript and the other way around, as they have to be kept in sync. All while Javascript needs to remain backwards compatible, too.

"But what about React? Weren't you talking about that, Siderite?"

Yes, I was. I only looked deeper into Typescript because I did this project in React. Before, I had used it with Angular and frankly I didn't feel the friction that I felt now. Angular is designed with Typescript in mind, the development experience is smoother. Angular also uses two directional bindings to propagate changes and that means less Typescript code. The only code you actually need to write is network API code, for which you have out of the box HTTP services, and some limited interface logic. React doesn't do that.

First of all, React has been designed within a kind of declarative/functional mindset, as I explained in previous chapters of this series. It focuses a lot on immutability and functions that are passed around and declaring what your expectations are. Typescript is fundamentally an imperative language. After forcing it through the round hole, the square peg now has to go through a triangular hole, too. The immutability forces one to use a lot of code for changes coming from the UI towards the Typescript logic.

Then, React is a library. It was designed as such and has less levers to force the developer in a direction or another. Even when following a clear development strategy, there are many of which to choose from, all tried and tested and valid, but very different from one another. The jungle was tamed, but now you must consider a multiverse of jungles, each with a different shape.

Finally, React started out in Javascript. Many documentation pages are still just about Javascript. New innovations in the field of React are developed and tested out independently, by various people with various skills and motivations. The learning curve is not steep, but the paths are many.

So in the end, Typescript is an interesting experiment in programming languages, one that will probably surprise me in the near future with ideas that can only be implemented using it. However it is not perfect and its dependency on Javascript is unfortunate, even if its inspiration was not. The purpose of the language was to guide and help developers mired in Javascript confusion, but using it with React goes against that very purpose, as React is still something relatively new and evolving wildly in all directions, so React doesn't help Typescript. Does Typescript help React? I would say yes. However I don't feel that it is enough in its current form. The friction between the two concepts is palpable and I dare any of you to prove me wrong.

It seems I've talked a lot about the problems of React rather than its benefits. I blamed it on things ranging from confusing and obsolete documentation to inconsistent goals of the library and underlying programming language. That's the way I work, focusing on problems so I can find one I can fix. In the next chapter I want to discuss about React in the wild and what are the good things people are saying about it. The most interesting question however, the one that I want to answer with this entire series, is how can we improve our work by adapting lessons learned, either from React to whatever we do or the other way around. What concrete ideas should we adopt from React and which we should condemn to the pit of failed concepts?