It’s time to stop supporting all Internet Explorer versions

Observation

We are in 2020, I manage a website used all over the world and some people are still using Internet Explorer.
At the same time I work on the new version of that website and I have to decide which kind of tool I will use.

The global consensus is to use webpack and babel, providing all polyfills, for supporting old browsers.
While it was a good idea before 2020, when it was complicated to change habits and IT systems, now it’s bad for everyone to continue like this.

Why stop support?

When something works since years you don’t want to change for no real reasons.
For example I don’t update drivers for my graphic card until I’m forced.

By using polyfills, bootstrap, and tools that allow us to produce code for everyone, we don’t encourage people to change or update their browsers.
Since their navigation keeps working, why do they want to change?

Some others are just too lazy to change and count on developers to maintain that status quo on it.
Finally there are companies which stay in the past because of their previous tools using activex, flash, etc…

Furthermore for developers, when it’s time to create a new website, we always choose the same solution.
Because it’s what we have to do by the tech pressure.
We add a lot of tools and processes for transpiling code while it’s maybe not useful.
And Internet Explorer continues to annoy us because we continue to support it.
Take a deep breath and now refuse that scheme.

Solution

Hence it’s time to end this period of compliance with a radical solution: simply stop supporting Internet Explorer.
When I said that I mean to simply block access to websites to those browsers.

Be careful!
If your site is intended for use by the government, the medical sector, or developing countries it’s not a good idea to block access (maybe in 2030).

How to do that? With special HTML headers and javascript for detecting Internet Explorer and redirect them to a page listing all other browsers compatible.
First you have to create a new HTML page called ie.html and you will put this code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <title>My website is not for Internet Explorer</title>
    <meta name="description" content="My website is not for Internet Explorer" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta http-equiv="Content-Language" content="en" />
</head>
<body>
    <h1>My website is not for Internet Explorer</h1>
    <p>This website, is not available for Internet Explorer from version 5.5 to 11, consequently you have to use a modern browser.<br />
        So this a list of compatible browsers with this website.</p>
    <ul>
        <li><a href="https://brave.com">Brave - https://brave.com</a></li>
        <li><a href="https://www.google.com/chrome">Chrome - https://www.google.com/chrome</a></li>
        <li><a href="https://www.microsoft.com/edge">Edge - https://www.microsoft.com/edge</a></li>
        <li><a href="https://www.mozilla.org/firefox/new/">Firefox - https://www.mozilla.org/firefox/new/</a></li>
        <li><a href="https://www.opera.com">Opera - https://www.opera.com</a></li>
        <li><a href="https://vivaldi.com">Vivaldi - https://vivaldi.com</a></li>
    </ul>
</body>
</html>

For some of you, you have recognize an old doctype XHTML 1.0 Strict (it’s been a long time my friend).

Then you will add inside the head tag of all your other pages:

<head>
    <!--[if IE]>
        <meta HTTP-EQUIV="REFRESH" content="0; url=/ie.html">
    <![endif]-->
<head>

This will work for Internet Explorer from 5.5 to 9.

Finally you have to add this script before all other your scripts:

if(window.navigator.userAgent.toUpperCase().indexOf("TRIDENT") !== -1 || window.navigator.userAgent.toUpperCase().indexOf("MSIE") !== -1) {window.location.assign('/ie.html');}

This will work for Internet Explorer from 10 to 11.

How viewers can be actors in streams on Twitch

I have been streaming and viewing on Twitch for several years but I haven’t discovered new innovations in a long time.
When I don’t stream, I try to find new streamers with new ideas in any kind of categories. Sadly, they use the same services, overlays, alerts, sounds and even scenes.
Therefore if i have to sum up the life of a streamer to someone I would say: “Launch stream, switch scenes, read messages, do stuff and disconnect”
Streaming is new in the life of the Internet, we have more to discover and to innovate. With this in mind I try to search something new.
So I looked at how social networks came up in the last years and I came to this conclusion: the next step of streaming will be having streamers and viewers becoming both actors of the stream.

In other words I mean for the streamer it’s not only reading the chat and interacting with viewers, but they will have a real involvement on the stream by acting inside it.

What tools does Twitch give to viewers?

Before creating something, I always searched what are the tools we already have on the platform. So I try to list on Twitch how a viewer can interact with the streamer using free access or with some money.

Chatting

It’s free and it’s the first thing for interacting between viewers and streaming

Subscriptions and Cheers

It’s a paid option and not all channels can enable it.
Viewers in chat will be displayed differently from others with a badge, special emotes.

Extensions

There are 3 types of extensions which are showing additional content below, above or inside the stream.
All those extensions had to be added by the streamers, it’s free (sometimes you have to link your account). But some overlays are limited to be used only on desktop. Also it fit only for specific situations and games.

Channel Points

Viewers earn channel points by being faithful to streamers (by watching streams) and with these points they can buy a reward.
By default there is five rewards (which can be disabled):

  • viewer send message on sub chat
  • highlight viewer message
  • select one emotes to unlock
  • customize one emote
  • random emote to unlock

Streamers can customize them by adding rewards and change how much it costs, how many times viewers can use them during one stream, etc…

How channels points are used

I listen to a lot of streamers and viewers complaining about how channel points are useless for them.
A big part of streamers don’t care about it and leave the default settings and rewards. For the others I made a list (non exhaustive) about how they use them:

  • lose channel points
  • add specific rule in a game
  • claim ingame money
  • claim vip
  • claim a sub
  • claim versus on a game
  • unban someone
  • timeout random viewer
  • chat switch to emote only
  • chat switch to sub only
  • offer an item from shop

Channel points API

Because there is no alert after claiming a reward, if there are a lot of viewers some of them can not be seen by the streamer.
So Twitch gave us a page called reward queue.

There is no API for channel points.
But you can have the information on each message sent by a user in your chat if a reward is associated, and what its ID is.

Channel points versus Chat commands

Some people will say: “Reward can be a simple chat command” or “channel points can be made with a bot”.
I agree but I also know by experience, viewers can spam the same command just for annoying you, they can spell wrong a command and retry a lot of time, type some commands to see if you have enabled them…
Even if you give a list of commands below the stream, a lot of users don’t look at it.
For counting channel points by yourself, you will have to find a bot and do some code about, not easy for everyone.
Some of them can detect if a command is usable by regular or admin viewers, but you have to configure them.

There is also a big difference in the cost.
When you set a high price on reward, using them is not a joke anymore. Because viewers have to spend time on your streams, some of these users won’t lose time for fun.
With this purpose in mind a reward with the right price will have a value for viewers and also for streamers. For example I have a reward that costs 100,000 channel points, it’s a lot. When users claim it, I have to make a presidential speech during 30 minutes minimum, dressed as a president and inside the official office.

Example: Viewers control streamers with channel points

As I have said in the introduction, viewers are not part of the journey in the stream.
However rewards from channel points are here to engage viewers by using them wisely if they cost a lot.

I made a little proof of concept on my channel about how viewers can control my OBS with a reward.

For example, viewers can claim a reward for asking medical advice.
It costs 1,000 points and they have to add some text.
When the reward appear on my chat my OBS react like that:

  1. Scene switch automatically
  2. Play a video
  3. At the end of the video I display my webcam on a background picture

In this case my stream journey is completely changed.
Consequently I have to improvise, change my clothes, search for some accessories and think how I can respond when the video is finished.

Because rewards cost channel points, viewers need to feel that acting inside the stream is important and have to act wisely at the good timing.

The downside is when streamers are not comfortable with the improvisation and or letting viewers control stream.

How to do it?

I will post later how you can do it.

Unreal Engine 4 : SwarmAgent distribute rendering

Swarm Agent is a tool shipped with Unreal Engine.
It’s useful for distributing tasks with multiple computers.

Setup

Master PC

  • Go to D:\Program Files\Epic Games\UE_4.18\Engine\Binaries\DotNET
  • Make a shortcut to SwarmAgent.exe and SwarmCoordinator.exe
  • Launch SwarmAgent.exe
  • Go Tab Settings
  • AgentGroupName and AllowedRemoteAgentGroup so change to Default
  • AllowedRemoteAgentnames -> change value to *
  • CoordinatorRemotingHost -> change to localhost

Slave PC

  • Launch SwarmAgent.exe
  • Go Tab Settings
  • AgentGroupName and AllowedRemoteAgentGroup so change to Default
  • AllowedRemoteAgentnames -> change value to *
  • CoordinatorRemotingHost -> change with the IP adress of your Master PC (192.168.1.xxx)

Use Case

Slave PC

Launch SwarmAgent.exe

Master PC

Launch SwarmCoordinator.exe and you will see all the computers available with an instance of SwarmAgent.exe started

.gitignore for Unreal Engine

A simple .gitignore file when you work on Unreal Engine.
I exclude non-vital files generated by Unreal Engine with Visual Studio or Xcode, on Window and macOS.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# Unreal Generated Files
Binaries/*
Build/*
!Build/**/*.ico
Content/StarterContent/*
DerivatedDataCache/*
Intermediate/*
Saved/*
SourceArt/**/*.png
SourceArt/**/*.tga
 
# Visual Studio Generated Files
*.a
*.app
*.dll
*.dylib
*.exe
*.gch
*.ipa
*.la
*.lai
*.lib
*.lo
*.mod
*.o
*.obj
*.opensdf
*.out
*.pch
*.sdf
*.sln
*.slo
*.so
*.suo
*.VC.db
*.VC.opendb
.vs/*
 
# XCode Generated Files
contents.xcworkspacedata
*.xcodeproj
**/xcuserdata
 
# Windows
ehthumbs.db
ehthumbs_vista.db
Thumbs.db
 
# macOS
.apdisk
.AppleDB
.AppleDesktop
.AppleDouble
*.DS_Store
.LSOverride
Network Trash Folder
Temporary Items

Setup Visual Studio pour Unreal Engine

Toolbar

Tool > Customize > Onglet Commands > Toolbar > Standard

  • 200 pour Solution Configurations
  • 160 pour Solution Platforms

setup_vs_ue_1

Il faut que config, platform et debugger soient affichés sur la toolbar

Optimisations

Il faut passer par Tools > Options

Project And Solutions

Décocher “Always Show Error List if build finishes with errors”

Text Editor > C/C++ > View

Mettre à False “Show Inactive Blocks” (dans liste Inactive Code)

Text Editor > C/C++ > Advanced

Mettre à True “Disable External Dependencies Folder” (dans liste Browsing/Navigation)
Mettre à True “Auto Quick Info” (dans liste IntelliSense)
Mettre à False “Disable IntelliSense” (dans liste IntelliSense)
Mettre à False “Disable Auto Updating” (dans liste IntelliSense)
Mettre à False “Disable Error Reporting” (dans liste IntelliSense)
Mettre à False “Disable Quiggles” (dans liste IntelliSense)
Mettre à False “Disable IntelliSense” (dans liste IntelliSense)

Debugging

Décocher “Enable Edit and Continue”

Window Layout

Layout des fenêtres, ne garder que Solution Explorer, Output et le code.
Pour enregistrer la config Window > Save Window Layout

UnrealVS

  1. Double cliquer sur le fichier [UE4RootLocation]/Engine/Extras/UnrealVS/2015/UnrealVS.vsix
  2. Faire l’installation
  3. Ajouter à la toolbar le composant UnrealVS et enregistrer le layout

Symboles de débogage

  1. Copier le fichier [UE4Root]/Engine/Extras/VisualStudioDebugging/UE4.natvis
  2. Coller le fichier UE4.natvis dans les dossiers suivants :
    [VisualStudioInstallPath]/Common7/Packages/Debugger/Visualizers/UE4.natvis
    [UserProfile]/My Documents/Visual Studio 2015/Visualizers/UE4.natvis

Macro, UCLASS, UFFUNCTION, etc

  1. Aller sur https://marketplace.visualstudio.com/items?itemName=RxCompiLe.UE4Intellisense
  2. Cliquer sur donwload
  3. Installer le programme en double cliquant sur le fichier

Thread – Coder proprement

Un thread doit :
– respecter le principe de responsabilité unique
– limiter la portée des données
– utiliser des copies des données
– être aussi indépendants que possible
– utliser des api qui sont safe thread

Il existe des modèles d’exécution :
Ressources bornées
Ressources dont la taille ou le nombre est figé et qui sont employées dans un environnement concurrent. Il s’agit, par exemple, des connexions à une base de données ou des tampons de lecture/écriture de taille fixe.

Exclusion mutuelle
Un seul thread à la fois peut accéder à des données ou à des ressources partagées.

Famine
Un thread ou un groupe de threads est interdit de fonctionnement pendant une durée excessivement longue ou indéfiniment. Par exemple, si les threads d’exécution courte sont toujours privilégiés, les threads dont le traitement est plus long peuvent ne jamais être élus si les premiers ne se terminent pas.

Interblocage (deadlock)
Deux threads ou plus attendent chacun la fin de l’autre. Chaque thread dispose d’une ressource dont l’autre a besoin et aucun ne peut se terminer tant qu’il n’a pas obtenu la ressource de l’autre.

Interblocage actif (livelock)
Les threads sont synchrones, chacun tentant de faire son travail mais rencontrant toujours un autre thread “sur son chemin”. Un phénomène de résonance se crée et les threads tentent

Attention aux dépendances entre des méthodes synchronisées

Evitez d’utiliser plusieurs méthodes sur un objet partagé

Garder des sections synchronisées courtes

Il faut écrire le code d’arrêt pour se rendre compte des problèmes de locks entre threads

Pour tester du code multithread il faut :
– considérer les faux dysfonctionnements comme des problèmes potentiellement liés au multithread
– commencer par rendre le code normal (sans thread) opérationnel
– faire en sorte que le code multithread soit enfichable (utilisable dans différentes configurations)
– faire en sorte que le code multithread soit réglable (nombre de thread)
– exécuter le code avec plus de threads que de processeurs
– exécuter le code sur différentes plates-formes
– instrumenter (manuellement et/ou automatiquement) le code pour essayer et forcer des échecs

Emergences – Coder proprement

Une conception est “simple” si elle respecte les 4 règles suivantes, données par ordre d’importances :
elle réussit tous les tests
elle ne contient aucune redondance
elle exprime les intentions du programmeur
elle réduit le nombre de classes et de méthodes

L’écriture des tests conduit à de meilleures conceptions car :
– classes plus petites
– couplage moins étroit
– utilisations d’injection de dépendances, interface et abstractions

Grâce aux tests on peut modifier le code sans craindre de tout casser pour :
– augmenter la cohésion
– réduire le couplage
– séparer les préoccupations
– modulariser les préoccupations du système
– diminuer la taille de nos fonctions et nos classes
– choisir de meilleurs noms
– éliminer la redondance
– assurer l’expressivité
– minimiser le nombre de classes et de méthodes

Classes – Coder proprement

Une classe se structure dans cet ordre :
– constantes statiques publiques
– variables statiques privées
– variables d’instance privées
– fonctions publiques
– fonctions privées invoquées par une fonction publique juste après

Il faut garder les variables en privées jamais en publiques
On peut les mettre en protégées si c’est vraiment nécessaire pour un test unitaire

Faire de petites classes en se basant sur le principe de responsabilités

Le nom d’une classe doit décrire ses responsabilités

Etre en mesure de décrire brièvement la classe, en employant environ 25 mots, sans utiliser “si”, “et”, “ou” ou “mais”

Respecter le principe de responsabilité unique

Contenir un nombre réduit de variables d’instance

Chaque méthode d’une classe doit manipuler une ou plusieurs variables d’instance

Maintenir la cohésion mène à de nombreuses petites classes

Organiser les classes en vue du changement (ajout de concept)

Cloisonner les changements avec des interfaces pour réduire le couplage et adhérer au principe d’inversion des dépendances