<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Cadoret Théo</title>
    <description>The latest articles on Forem by Cadoret Théo (@cadorettheo).</description>
    <link>https://forem.com/cadorettheo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F399539%2F22a8b0c7-8c03-4865-8e6e-d47ef4be794d.jpg</url>
      <title>Forem: Cadoret Théo</title>
      <link>https://forem.com/cadorettheo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/cadorettheo"/>
    <language>en</language>
    <item>
      <title>Randomness, what did you expect ?</title>
      <dc:creator>Cadoret Théo</dc:creator>
      <pubDate>Mon, 24 Aug 2020 06:46:45 +0000</pubDate>
      <link>https://forem.com/stack-labs/randomness-what-did-you-expect-1i7k</link>
      <guid>https://forem.com/stack-labs/randomness-what-did-you-expect-1i7k</guid>
      <description>&lt;p&gt;Randomness is, at first glance, a hard to grasp philosophical concept that we are absolutely not going to tackle in this article. Definitely not. &lt;/p&gt;

&lt;p&gt;Rather, we are going to use a pretty common and globally accepted definition, and what could be better for that than a community maintained definition such as Wikipedia's ? &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Randomness is the apparent lack of pattern or predictability in events”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yes, we are going to talk about &lt;strong&gt;patterns&lt;/strong&gt; and &lt;strong&gt;predictability&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;But wait I'm getting ahead of myself, first, let's see why I am even writing about it. &lt;/p&gt;

&lt;h2&gt;
  
  
  Randomness is needed everywhere
&lt;/h2&gt;

&lt;p&gt;Well, actually randomness is everywhere in software.  &lt;/p&gt;

&lt;p&gt;Video games make an extensive use of randomness to make each game different from the last. Sometimes to make enemies (or allies for what it's worth) unpredictable. Sometimes to generate a whole new world that the the player will explore.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fs3pom6ful30aadvl9z3z.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fs3pom6ful30aadvl9z3z.jpg" alt="Don't Starve map" width="800" height="410"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;center&gt;_Randomly generated map in Don't Starve_&lt;/center&gt;   

&lt;p&gt;But it's not only for "adventure" games, it is also very useful in virtual card games which are often based on the unpredictability of the deck shuffling.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fy14nshrebbxjusgb2435.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fy14nshrebbxjusgb2435.jpg" alt="Alt Text" width="786" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;_Online poker game_&lt;/center&gt;    

&lt;p&gt;One can also think of Spotify who offers to shuffle your playlists (&lt;a href="https://engineering.atspotify.com/2014/02/28/how-to-shuffle-songs/" rel="noopener noreferrer"&gt;actually their algorithm is based on random but is rigged&lt;/a&gt;, because we humans don't like it when it's too random).  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft3crz2au0ydpmflfnyaw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft3crz2au0ydpmflfnyaw.png" alt="Alt Text" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;_Spotify's shuffling algorithm schema_&lt;/center&gt;   

&lt;p&gt;Light simulators also make extensive use of randomness to simulate light diffusion on matter in every direction of space. Instead of modelling every light beam we randomly select few of them to save the machine from a certain death.&lt;/p&gt;

&lt;p&gt;Optimisation algorithms as well, such as &lt;a href="https://en.wikipedia.org/wiki/Monte_Carlo_algorithm" rel="noopener noreferrer"&gt;Monte-Carlo&lt;/a&gt;, could use some randomly chosen initial values.&lt;/p&gt;

&lt;p&gt;Finally security is also a great playground for random based algorithms, especially for generating encryption keys. Indeed they must be absolutely &lt;strong&gt;unpredictable&lt;/strong&gt; to be of any use. If someone could predict which key you're going to use, then it's easy for them to decrypt your message. &lt;/p&gt;

&lt;p&gt;There are many more fields of application for this peculiar concept, but I think I made my point.&lt;br&gt;
We need randomness.&lt;/p&gt;

&lt;p&gt;Ok that's cool, but what's the big deal? If I just go Math.random() I'm fine right ? &lt;/p&gt;

&lt;p&gt;Both "yes" and "no". That's where it gets interesting. &lt;/p&gt;
&lt;h2&gt;
  
  
  Randomness is far from innate
&lt;/h2&gt;

&lt;p&gt;Let's go back to fundamentals, what is a computer and what is its purpose ? &lt;/p&gt;

&lt;p&gt;In essence, a computer has an initial defined state, and a set of predefined instructions which will, by their execution, lead it to another state. &lt;/p&gt;

&lt;p&gt;There is no place for actual randomness. Everything is fully deterministic and that's pretty useful actually. &lt;/p&gt;

&lt;p&gt;So how do we cope with our needs being completely out of reach of our means ? &lt;/p&gt;

&lt;p&gt;Donald Knuth gives us a clue for what could be our first move:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“In a sense, there is no such thing as a random number. For example, is 2 a random number ? Rather, we speak of a sequence of independent random numbers with specified distribution.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Which matches pretty well with our definition of a computer that executes a set of instructions that lead it to a sequence of consecutive states. &lt;/p&gt;

&lt;p&gt;So our first approach will be based on generating a sequence of numbers that seem random. &lt;/p&gt;
&lt;h2&gt;
  
  
  Pseudo-Random Number Generators (PRNGs)
&lt;/h2&gt;

&lt;p&gt;This is where pseudo-random number generators come into play. They are entirely defined by two parameters : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A seed&lt;/li&gt;
&lt;li&gt;A function&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The seed is the starting point of the algorithm, the first value of the sequence. &lt;br&gt;
Then to generate the sequence, one just has to apply that function to the seed, recursively. Each obtained value is part of the sequence. &lt;br&gt;
The challenge is to choose a couple &lt;code&gt;(seed, function)&lt;/code&gt; that will produce random looking values. &lt;/p&gt;
&lt;h3&gt;
  
  
  Middle square algorithm
&lt;/h3&gt;

&lt;p&gt;The middle square algorithm is very simple :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Define an initial value
Seed = 5678

// Square it
5678^2 = 32239684

// Take the 4 middle digits (if it's not 8 digits long, add leading 0s)
32[2396]84 = 2396

// Start over with the new value
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://sadale.net/27/online-middle-square-method-generator" rel="noopener noreferrer"&gt;Here&lt;/a&gt; you can find an online generator if you want to try it yourself. &lt;/p&gt;

&lt;p&gt;The middle square algorithm applied to the seed &lt;code&gt;5678&lt;/code&gt; gives this sequence : &lt;/p&gt;

&lt;p&gt;&lt;code&gt;2396 7408 8784 1586 5153 5534 6251 0750 5625 6406 0368 1354 8333 4388 2545 4770 7529 6858 0321 1030 0609 3708 7492 1300 6900 6100 ...&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Which indeed seems very random to a human.&lt;/p&gt;

&lt;p&gt;But the next iterations of this sequence point out one of the main issues of PRNGs : &lt;/p&gt;

&lt;p&gt;&lt;code&gt;... 6100 2100 4100 8100 6100 2100 4100 8100 6100 ...&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As soon as the PRNG falls on a value it has already visited, it gets trapped in a loop. The length of this loop is called the period and can be very short as in this example : &lt;code&gt;4&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Any PRNG will eventually cycle as the range (number of possible values) is limited and defined by the function itself. For the middle square algorithm the range is &lt;code&gt;[0-9999]&lt;/code&gt;=&amp;gt; &lt;code&gt;10 000&lt;/code&gt; possible values. And the best possible period is proved to be &lt;code&gt;4096&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But PRNGs are not dead. Middle square algorithm is just one of their soldiers, and not the mightiest. &lt;/p&gt;

&lt;p&gt;Actually their Achilleus, the gold standard when it comes to PRNGs, is the Mersenne Twister algorithm. We are not going to it discuss in details though as it is fairly complex (&lt;a href="https://en.wikipedia.org/wiki/Mersenne_Twister" rel="noopener noreferrer"&gt;for the curious and rather mathematical ones&lt;/a&gt;).   &lt;/p&gt;

&lt;p&gt;But it's worth discussing the Linear Congruential generator which can be viewed as a base for the Mersenne Twister.&lt;/p&gt;

&lt;h3&gt;
  
  
  Linear Congruential generator
&lt;/h3&gt;

&lt;p&gt;The function for this PRNG is based on 3 parameters : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A : the multiplier&lt;/li&gt;
&lt;li&gt;C : the increment&lt;/li&gt;
&lt;li&gt;M : the modulus
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;f(x) = ( x * A + C ) mod M
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the range is defined by M so that &lt;code&gt;f(x) ∈ [0, M-1]&lt;/code&gt;.&lt;br&gt;
Choosing M to be a power of 2 is very efficient as the modulus operation can be simply truncating the binary representation.&lt;br&gt;
By correctly tuning all 3 parameters it is possible to obtain a very large range and period. One of the best sets of parameters involve choosing M a power of 2 so that &lt;code&gt;M-1=2^N-1&lt;/code&gt; is prime.&lt;/p&gt;

&lt;p&gt;And a prime that is one less than a power of two is called... a Mersenne Prime !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fltlam1yafzd2i9zsv1y0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fltlam1yafzd2i9zsv1y0.gif" alt="Alt Text" width="330" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Okay so let's sum up what we've got. &lt;/p&gt;

&lt;p&gt;PRNGs : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;do look random&lt;/strong&gt; : Given a not too absurd set of parameters and a correct algorithm, the output sequence seems random to us humans.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;can provide a uniform distribution&lt;/strong&gt; : Before the first loop, values appear only once in the sequence. From an external point of view, they are equiprobable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;are fast to compute&lt;/strong&gt; : They are rather basic algorithms and easy to compute&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;are deterministic&lt;/strong&gt; : Meaning sequences can be reproduced if you know the seed and parameters. Which is good when used in tests for instance.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And for most use cases it's enough. One can think of video games, light simulator, card games... card games ? &lt;br&gt;
It depends, if it is to draw your Solitaire initial state, PRNGs are widely sufficient, but when it comes to online card games such as Poker, where people bet real money and would have solid reasons to try to take advantage of our Achilleus heel, we need a different approach.&lt;br&gt;
As you can imagine, it is also the case for encryption keys, which job is to protect from bad intentioned intruders. &lt;/p&gt;

&lt;p&gt;For these use cases, we will need more than random looking sequences, we will need true unpredictability. &lt;/p&gt;

&lt;h2&gt;
  
  
  True Random
&lt;/h2&gt;

&lt;p&gt;If you aim for true randomness, you must seek first for true &lt;strong&gt;unpredictability&lt;/strong&gt;, a property that is inherently out of reach of a software. &lt;br&gt;
One must search for it on the other side of the keyboard, in the real world, which is an incredible source of disrupted events. We call it entropy. &lt;/p&gt;

&lt;p&gt;Entropy sources are everywhere and can take various forms, from atmospheric noise to radioactive decay.&lt;/p&gt;

&lt;p&gt;For instance, Cloudflare (who is responsible for the security of about 10% of the overall internet traffic) uses a video stream from a camera pointed 24/7 at a wall of lavalamps to encrypt data. &lt;/p&gt;

&lt;p&gt;This is the wall I'm talking about :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmxk96jtwc9u26cwcfldl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmxk96jtwc9u26cwcfldl.jpg" alt="Alt Text" width="800" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Online card games are not outdone either as PokerStars chose another option. Their card drawer algorithm relies partly on a light beam shot at a semi-opaque mirror.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvv7qkk6wgwi8oafagjkh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvv7qkk6wgwi8oafagjkh.png" alt="Alt Text" width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the photon passes the mirror that's a 0, if it gets reflected that's a 1.&lt;/p&gt;

&lt;p&gt;As a last example I'll mention the Linux kernel which makes use of both hardware metrics and user inputs to fill its entropy pool. &lt;br&gt;
Hardware metrics can take the shape of an SSD access time, which is not deterministic. User inputs can be timestamps of a keyboard pressure, or a mouse movement etc. &lt;a href="http://www.russellcottrell.com/mousePointerRNG.htm" rel="noopener noreferrer"&gt;This website&lt;/a&gt; gives an example of what can be done with a cursor movement to generate random strings. &lt;/p&gt;

&lt;p&gt;But &lt;strong&gt;unpredictability&lt;/strong&gt; is not sufficient to provide randomness. We also need a uniform distribution of probability among the possible values. Meaning we need the absence of &lt;strong&gt;pattern&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;In order to provide this, we'll need CSPRNGs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cryptographically Secure Pseudo Random Number Generators (CSPRNGs)
&lt;/h3&gt;

&lt;p&gt;CSPRNGs are basically just badass PRNGs often based on hash functions. It's an algorithm that takes a seed as input and outputs a value. They have 2 very important properties that make them way more secure than classic PRNGs :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Withstand the 'Sate compromise extension'&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In the event that part or all of its state has been revealed (or guessed correctly), it should be impossible to reconstruct the stream of random numbers prior to the revelation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Satisfy the next bit test&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We say that a sequence of bits passes the next bit test for at any position &lt;code&gt;i&lt;/code&gt; in the sequence, if any attacker who knows the &lt;code&gt;i&lt;/code&gt; first bits (but not the seed) cannot predict the &lt;code&gt;(i+1)st&lt;/code&gt; with reasonable computational power.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Reasonable computational power means with less than the overall computing power on the planet, pretty safe.)&lt;/p&gt;

&lt;p&gt;A good CSPRNG is SHA256 for instance ! (Secure Hash Algorithm)&lt;/p&gt;

&lt;p&gt;On linux you can access this truly random source by reading from &lt;code&gt;/dev/urandom&lt;/code&gt;...&lt;br&gt;
... or &lt;code&gt;/dev/random&lt;/code&gt;? &lt;/p&gt;

&lt;h3&gt;
  
  
  /dev/random vs /dev/urandom
&lt;/h3&gt;

&lt;p&gt;When Linux OS receives &lt;em&gt;entropy&lt;/em&gt; from the outside world, it stores it in an entropy pool. Entropy pool from which both /dev/urandom and /dev/random draw. The only difference is that /dev/random will block when it estimates that the entropy level is too low, whereas /dev/urandom can draw from this pool almost endlessly providing perfect randomness ("u" stands for unblocking).   &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;center&gt;&lt;em&gt;You are safe using /dev/urandom for cryptographic purposes.&lt;/em&gt;&lt;/center&gt;
&lt;/h3&gt;

&lt;p&gt;The nitty-gritty details can get a bit too technical for this article, the curious ones though can choose the red pill and &lt;a href="https://www.2uo.de/myths-about-urandom/" rel="noopener noreferrer"&gt;dive into the rabbit's hole&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Random numbers don't exist, we speak of a random sequence of numbers. This is something that software can easily simulate and fool human brains with a rather basic algorithm. They look unpredictable and uniformly distributed. This is more than sufficient for the vast majority of use cases, but it is inherently flawed. These pseudo random number generators won't fool well designed attacking software. In use cases where attacks are awaited, such as encryption keys, these simple algorithms won't do, we'll  need a more robust source of unpredictability which can only be found through interactions with the real world.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>security</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>À quoi bon écrire des tests ?</title>
      <dc:creator>Cadoret Théo</dc:creator>
      <pubDate>Fri, 10 Jul 2020 13:50:05 +0000</pubDate>
      <link>https://forem.com/stack-labs/a-quoi-bon-ecrire-des-tests-157k</link>
      <guid>https://forem.com/stack-labs/a-quoi-bon-ecrire-des-tests-157k</guid>
      <description>&lt;p&gt;On entend souvent que le Test Driven Development est une bonne pratique, qu'elle permet d'avoir une base de code &lt;strong&gt;clean&lt;/strong&gt;, plus &lt;strong&gt;maintenable&lt;/strong&gt;, plus &lt;strong&gt;robuste&lt;/strong&gt; etc.&lt;br&gt;
À tel point que cette implication semble acceptée par ses adeptes comme un lien direct. &lt;br&gt;
Quelqu'un m'a posé la question justement, pourquoi ? En quoi le TDD aide-t-il a obtenir tout ça ? &lt;br&gt;
J'ai bafouillé et n'ai su poser des arguments. J'avais fini par accepter le TDD sans plus pouvoir l'expliquer.&lt;/p&gt;

&lt;p&gt;Dans cet article allons considérer l'écriture des tests dans un contexte de TDD. &lt;br&gt;
Le but ici n'est pas de décrire et d'expliquer comment pratiquer le TDD ni comment écrire de bons tests, les méthodes pour y parvenir sont nombreuses et déjà très bien renseignées dans d'autres articles.&lt;br&gt;
Non, ici j'aimerais m'intéresser au &lt;strong&gt;&lt;em&gt;pourquoi&lt;/em&gt;&lt;/strong&gt; des tests, est-ce bien utile après tout ? &lt;/p&gt;

&lt;p&gt;Je vais donc revenir sur certains points qui me semblent pertinents vis à vis de l'écriture de tests dans un contexte de TDD.&lt;br&gt;
Ça n'est pas un top. Ça n'est pas exhaustif.&lt;/p&gt;
&lt;h3&gt;
  
  
  Parce que notre code répond à un besoin métier
&lt;/h3&gt;

&lt;p&gt;Le code que nous écrivons, que ce soit dans un contexte personnel ou professionnel, doit répondre  à un besoin métier.&lt;br&gt;
Ce besoin peut ainsi se décomposer en une série de spécifications qui ensuite pourront être traduites en tests.&lt;br&gt;
Une fois ceux-ci implémentés, nous savons que nous avons répondu au(x) besoin(s) dans la plupart de ses aspects métiers et de manière durable.&lt;br&gt;
Écrire des tests n'est rien d'autre qu'ancrer les spécifications métier dans le code source du système de manière à en assurer la validité sur le long terme.  &lt;/p&gt;

&lt;p&gt;Je vais prendre un exemple simple sur le &lt;strong&gt;Game of Life&lt;/strong&gt; de John Conway, l'une des spécifications / règles du jeu qui sera toujours vraie :   &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CellTest&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;dead_cell_with_3_neighbors_should_come_alive&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Cell&lt;/span&gt; &lt;span class="n"&gt;cell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Cell&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CellState&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;DEAD&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;CellState&lt;/span&gt; &lt;span class="n"&gt;nextRoundCellState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cell&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withLiveNeighbors&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;computeNextState&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nextRoundCellState&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;isEqualTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CellState&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ALIVE&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ainsi, on s'assure que cette spécification sera toujours vérifiée quelles que soient les modifications qui peuvent survenir par la suite. Une cellule morte possédant 3 voisins vivants va &lt;em&gt;naître&lt;/em&gt;.&lt;br&gt;
Il est même envisageable d'annoter ce test avec un tag Jira / Gitlab / Whatever, renvoyant directement vers la story concernée.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parce que nous ne sommes pas seuls
&lt;/h3&gt;

&lt;p&gt;Le code évolue continuellement, mais il n'est pas le seul. L'équipe de développement aussi !&lt;br&gt;&lt;br&gt;
Il est possible que nous ayons une vue d'ensemble claire du système dont nous avons la garde, mais il arrivera un moment où nous devrons partager le bébé, voire même le transmettre à quelqu'un d'autre.&lt;br&gt;
Cette personne ne sera pas aussi au fait que nous du pourquoi du comment de certaines fonctionnalités, la documentation - même mise à jour régulièrement - n'a pas vocation à couvrir l'intégralité du code.&lt;br&gt;
Peut-être que nous avons introduit de la complexité pour, par exemple, éviter que certains données d'entrée ne causent des problèmes.&lt;br&gt;
Ajouter un test pour ça est comme documenter ce choix :   &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Je sais que cet évènement peut se produire, nous l'avons vu en prod et ça a causé des problèmes.&lt;br&gt;
Voici les inputs en question, ils ne devraient plus poser de soucis car l'oracle (comportement spécifié par le métier) est celui-ci. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Le nouveau venu sera alors alerté si par mégarde il-elle modifie inconsciemment le comportement par un test rouge pointant directement sur la spécification en question.&lt;/p&gt;

&lt;p&gt;De plus, nous sommes parfois amenés à designer des systèmes qui se doivent d'être génériques, ce qui passe très souvent par une large utilisation d'interfaces et autres niveaux d'abstraction.&lt;br&gt;
Plus il y a de niveaux d'abstraction, plus il est difficile et long d'appréhender le code dans son ensemble et de s'approprier son comportement.&lt;br&gt;
Avoir des tests qui implémentent de manière concrète certaines entités abstraites va grandement faciliter la construction d'un modèle mental global du système au nouveau venu.&lt;br&gt;
C'est exactement comme illustrer un cours très théorique à l'aide d'exemples concrets, ça aide à fixer les idées.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parce qu'on veut refactorer l'esprit tranquille
&lt;/h3&gt;

&lt;p&gt;Plus le système évolue pour intégrer de nouvelles fonctionnalités, corriger des comportement anormaux etc. plus il se complexifie.&lt;br&gt;
Ce phénomène se manifeste par l'apparition d'une complexité essentielle, inhérente aux besoins métiers que l'on essaie de traduire algorithmiquement, et d'une complexité accidentelle souvent due à l'ajout de pièces les unes au dessus des autres.&lt;br&gt;
Dans un certain ordre. En un temps donné.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkjebnjqcv8hnwf0zpytn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkjebnjqcv8hnwf0zpytn.jpg" alt="Alt Text" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;C'est donc l'empilement de nouvelles fonctionnalités qui transforme du code bien pensé et lisible en legacy lourd difficile à lire et à maintennir.&lt;br&gt;
C'est la règle et il faut faire avec. Mais il est possible d'atténuer cette transformation en réécrivant ce vieux code au fur et à mesure, et pour ça, nos vieux tests de non régression sont nos meilleurs atouts.&lt;br&gt;
Nous, on code, on redesign, on repense l'architecture. Eux ils nous protègent si l'on fait une erreur et nous évitent de tout se prendre dessus si ça tombe. Ils sont les garants du respect des spécifications.&lt;br&gt;
Il arrive souvent qu'un petit refactoring prenne de plus en plus d'ampleur à mesure que l'on tire sur le fil. &lt;br&gt;
Avoir confiance en sa couverture de tests (en terme de spécifications, pas de lignes de code) nous permet de nous arrêter quand on veut, tant qu'ils sont verts. &lt;br&gt;
On peut donc garder les MR de refactoring courtes, faciles à merger, et fréquentes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parce qu'on veut une review
&lt;/h3&gt;

&lt;p&gt;Les code reviews peuvent parfois être un exercice prenant, elles demandent une charge mentale très importante à la personne qui s'y colle. Il s'agit de lire, comprendre, et critiquer (constructivement, toujours) du code qui a pu prendre plusieurs jours à son/ses développeur(s).&lt;br&gt;&lt;br&gt;
&lt;span&gt;&lt;em&gt;Bon très bien, il est 9h30, j'ai du café, j'y vais. Mais par quoi je commence ?&lt;/em&gt;&lt;/span&gt;   &lt;/p&gt;

&lt;h5&gt;
  
  
  La lecture / compréhension
&lt;/h5&gt;

&lt;p&gt;En tant que reviewer on n'a pas nécessairement tout le contexte de la fonctionnalité, quels peuvent être les points sensibles. Les tickets / issues / post-its / whatever de stories sont bien souvent incomplets, et de toute façon ne relatent pas les difficultés techniques rencontrées qui ont pu pousser à certains choix.&lt;br&gt;
Souvent les problèmes se posent à l'implémentation et le programmeur prend des décisions de design en fonction de ceux-ci, ce qui rend la mise en contexte plus difficile.&lt;br&gt;
Sans aucun guide de lecture nous devons donc lire le code et comprendre par rétro-ingénierie ce qui a été implémenté et pourquoi les choix ont-été faits. (Même si certaines formes de documentation peuvent aider, voir &lt;a href="https://blog.stack-labs.com/code/adr-to-remember-past-archiectural-decisions/" rel="noopener noreferrer"&gt;cet article sur les ADR&lt;/a&gt; 😉 )   &lt;/p&gt;

&lt;p&gt;&lt;span&gt;&lt;br&gt;
Exemple :&lt;br&gt;&lt;br&gt;
La merge request présente les plans d'un attelage avec 3m de rênes, 2 mors, 2 avaloirs etc. Celle-ci fait également état de points de ravitaillement espacés de 50km avec de l'eau et d'autres espacés de 100km possédant eau et nourriture.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span&gt;&lt;em&gt;Hmm ok, on veut parcourir une raisonablement longue distance en peu de temps avec deux chevaux sans les laisser se déssecher ni mourrir de faim.&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  La critique / Le biais
&lt;/h5&gt;

&lt;p&gt;Une fois compris, nous devons avoir un regard critique (constructif, toujours) par rapport à ce qui a été développé. &lt;br&gt;
Il faut donc réussir à être critique vis à vis d'une solution à un problème que l'on a compris à la sueur de nos cellules grises en se basant sur cette même solution. Vous voyez le biais ?&lt;br&gt;&lt;br&gt;
Difficile de prendre du recul, notre esprit est déjà polarisé par la solution avant même de pouvoir y réfléchir. C'est l'oeuvre d'un biais cognitif bien connu : &lt;strong&gt;&lt;a href="http://www.biaiscognitif.com/le-biais-cognitif-dancrage-mental/" rel="noopener noreferrer"&gt;le biais d'ancrage&lt;/a&gt;&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;&lt;span&gt;&lt;em&gt;Pour des chevaux, des ravitaillements espacés de 40km et 80km seraient plus avisés sinon on risque de les épuiser rapidement. J'aurais plutôt pris 4m de rênes, il faut compter l'espacement entre les chevaux et la calèche, et se garder du mou pour être plus confortable&lt;/em&gt; &lt;/span&gt;(Valeurs prises un peu au hasard, j'avoue 😅)&lt;/p&gt;

&lt;h5&gt;
  
  
  Les tests comme guide
&lt;/h5&gt;

&lt;p&gt;Pour une code review de qualité, à mon sens, le reviewer doit avoir une vision claire du problème avant d'attaquer la lecture de la solution.&lt;br&gt;
C'est là que les tests entrent en jeu. Ils définissent à plus ou moins haut niveau les spécifications de la fonctionnalité.  &lt;/p&gt;

&lt;p&gt;&lt;span&gt;&lt;br&gt;
Exemple :&lt;br&gt;&lt;br&gt;
On devrait couvrir la distance de 300km en deux jours maximum.&lt;br&gt;&lt;br&gt;
On devrait pouvoir tracter un chargement de X kilos. &lt;/span&gt;    &lt;/p&gt;

&lt;p&gt;Simplement à la lecture des tests le reviewer peut avoir une vision d'ensemble des possibilités et contraintes de la fonctionnalité implémentée.&lt;br&gt;
Ensuite seulement il-elle peut se plonger dans l'étude de notre solution avec un esprit clair et proposer des critiques pertinentes et constructives.&lt;/p&gt;

&lt;p&gt;&lt;span&gt;&lt;em&gt;Hmmm si tu remplaces l'attelage par un moteur devant la calèche tu peux te passer des points de ravitaillement&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Enfin, il va sans dire qu'un reviewer à qui on évite la charge mentale de devoir faire une rétro-ingénierie sera plus enclin à prendre en charge la merge request et notre fonctionnalité ira en prod plus vite !&lt;/p&gt;

&lt;h3&gt;
  
  
  Parce que ça marche !
&lt;/h3&gt;

&lt;p&gt;Mesurer l'efficacité d'un développeur ou d'une équipe sur le long terme est une tache fastidieuse car elle dépend de nombreux facteurs.&lt;br&gt;
Il est donc impossible d'être sûr de l'efficacité du TDD dans un environnement donné et je ne peux pas vous assurer que ça rendra votre système parfait, ni même meilleur.&lt;br&gt;
Mais j'aimerais néanmoins mettre en valeur certains chiffres obtenus par des études sur le TDD dans des conditions de test qui méritent qu'on s'y attarde un peu.&lt;/p&gt;

&lt;h5&gt;
  
  
  Temps de développement / Qualité du code
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://link.springer.com/article/10.1007%2Fs10664-008-9062-z" rel="noopener noreferrer"&gt;Cette étude&lt;/a&gt;, conduite avec des équipe d'IBM et de Microsoft, montre que le temps de développement d'un produit avec TDD est supérieur à celui sans TDD d'environ 15 à 35%.&lt;br&gt;
Ce qui peut s'expliquer par beaucoup de choses. Évidemment le nombre de tests est supérieur, ce qui risque d'allonger le développement, mais il faut également voir que la méthodologie est loin d'être instinctive et facile à mettre en place !&lt;br&gt;
Écrire les tests d'abord c'est commencer par se poser des questions sur ce que l'on veut obtenir, mettre en place ses interfaces etc. On renverse la logique et au début c'est pas facile.&lt;br&gt;&lt;br&gt;
Cette même étude met ces résultats en balance avec le nombre de défauts trouvés dans les pre-releases des produits issus ou non du TDD : Avec TDD ils sont de l'ordre de 40 à 90% moins fréquents. &lt;br&gt;
On observe donc une réelle différence avec ou sans TDD en terme de qualité et de robustesse du code produit.&lt;br&gt;
Il est alors intéressant de mettre ces résultats en perspective avec le coût d'un défaut à différentes étapes du cycle de développement.&lt;/p&gt;

&lt;h5&gt;
  
  
  Coût d'un bug
&lt;/h5&gt;

&lt;p&gt;Pour illustrer cette grandeur, et comme on trouve beaucoup d'études et de résultats différents à ce propos, j'ai choisi de prendre la plus prudente des estimations que j'ai trouvée, présentée dans &lt;a href="//ftp://ftp.software.ibm.com/software/rational/info/do-more/RAW14109USEN.pdf"&gt;cette étude&lt;/a&gt; conduite par IBM Science Institute :    &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fb2atbdodrr72gb4jack2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fb2atbdodrr72gb4jack2.png" alt="Alt Text" width="800" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;D'après IBM System Sciences Institute, corriger un bug en prod coûte 6x plus cher qu'à l'implémentation.&lt;br&gt;&lt;br&gt;
Cela s'explique notamment par le coût du changement de contexte. &lt;br&gt;
Corriger un défaut en prod c'est changer de contexte de travail, se réapproprier le code en question (parfois vieux si l'agilité n'est pas la qualité première de l'équipe, mais c'est une autre histoire), diagnostiquer la cause, fixer ledit défaut et enfin rechanger de contexte pour poursuivre son travail.&lt;br&gt;
Le défaut en question peut aussi être un mauvais choix d'implémentation qui, au fur et à mesure, a pu se propager : plus tard on s'en rend compte, plus il a pu servir de socle à d'autres développements. Les impacts de la réécriture sont donc décuplés.&lt;br&gt;
Ça va sans dire que trouver l'origine d'un bug dans son environnement de développement est plus rapide qu'en se basant sur des extraits de logs de prod en level 'INFO'.&lt;br&gt;
Enfin on peut noter qu'un défaut trouvé en prod risque fortement d'impacter le service, voire le tomber pour les plus graves, ce qui peut avoir un coût financier monstrueux dans le cas d'un service d'e-commerce, ou pire dans le médical...&lt;/p&gt;

&lt;p&gt;La diversité des résultats issus des études sur les coûts des défauts s'explique très bien au vu de la difficulté de les quantifier.&lt;br&gt;
Il reste néanmoins que tous les arguments, bien que qualitatifs plus que quantitatifs, sont tous orientés dans la même direction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Écrire des tests c'est bien plus que garder sa couverture au dessus des 80% pour rassurer des gens qui n'y toucheront jamais.&lt;br&gt;&lt;br&gt;
Écrire des tests c'est expliciter son code, valider son travail, avoir confiance en son système, s'assurer de sa qualité, communiquer ses intentions etc.&lt;br&gt;
Bref si on écrit des tests c'est avant tout pour nous aujourd'hui, et pour nous demain !&lt;/p&gt;

</description>
      <category>testing</category>
      <category>tdd</category>
    </item>
    <item>
      <title>Learning curve : Inject physical properties into digital interfaces</title>
      <dc:creator>Cadoret Théo</dc:creator>
      <pubDate>Fri, 10 Jul 2020 13:49:05 +0000</pubDate>
      <link>https://forem.com/stack-labs/learning-curve-inject-physical-properties-into-digital-interfaces-3pdh</link>
      <guid>https://forem.com/stack-labs/learning-curve-inject-physical-properties-into-digital-interfaces-3pdh</guid>
      <description>&lt;p&gt;As a UI/UX designer, if your end users need documentation, then you’ve already lost, no matter how usable is your interface. Nowadays, especially on the web, solutions are everywhere and users allow very little time on an interface to understand its behavior and interact with it. If they don’t learn quickly enough how to use a piece of software, they’re likely to switch on another available solution. &lt;br&gt;
That's why learnability is a key factor in human computer interfaces and it's important to take a special care of it.&lt;/p&gt;

&lt;p&gt;This article does not aim to lead to perfect learnability, but focuses on a widely used trick to improve it.&lt;br&gt;&lt;br&gt;
But first let's focus on defining what exactly is learnability, so we can make it easier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Learnability
&lt;/h3&gt;

&lt;p&gt;Learnability is a difficult concept to catch. What does it mean for a software to be easy to learn ?&lt;br&gt;&lt;br&gt;
According to Grossman T. et al.  who did a review of how researchers define learnability during the past 25 years, it can firstly be divided in two : Initial Learning and Extended learning.&lt;br&gt;
Here we'll focus more precisely on initial learning as extended learning is more about mastering the use of a software.&lt;br&gt;&lt;br&gt;
Even in initial learning, definitions in scientific documentation vary, but let's take Shneiderman's view :  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;”The time it takes members of the user community to learn how to use the commands relevant to a set of tasks.”  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From this definition we can extract two important things that initial learning relies on :  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The user community, its initial knowledge and habits
&lt;/li&gt;
&lt;li&gt;Learning process itself
Learning is about creating mental and conceptual models of a system. Therefore, when facing something new, users will try to find its familiar features in order to conceptualise and categorise it. So the learning process is mainly about building knowledge upon existing experience, especially physics laws, mechanics and so on.
This is where the concept of affordance becomes a very powerfull tool to ease learning. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Affordance
&lt;/h3&gt;

&lt;p&gt;Affordance designates the ability of a device to suggest a particular kind of use by virtue of some physical attribute. In Don Norman’s 1988 book, The Design of Everyday Things, affordances became defined as :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Perceivable action possibilities—i.e., only actions users consider possible  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The real world offers tons of examples of great interfaces using affordances&lt;/p&gt;

&lt;p&gt;How would you open this door ?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fijj1i4i3jsrekc6zr5n6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fijj1i4i3jsrekc6zr5n6.jpg" alt="Alt Text" width="800" height="704"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you answered by pushing on the grey plate, congrats your brain is fully functionnal. &lt;/p&gt;

&lt;p&gt;You just faced an unknown object (you’ve - probably - never interacted with it before) and two things happened:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;By seeing it you inferred it’s behaviour.
&lt;/li&gt;
&lt;li&gt;You had enough confidence in this inference to try to interact with it without using a manual.
This door just afforded its behavior. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Physical objects tend to have great affordances because their behaviour relies upon basic physics laws that everyone is familiar with. (By applying a force on the right side of a door which rotation axis is on the left will cause it to rotate around it.)&lt;/p&gt;

&lt;p&gt;Here is an example of how a simple change in design can increase the affordance of the system :&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8mneog51s97ltedpbo5q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8mneog51s97ltedpbo5q.png" alt="Alt Text" width="800" height="305"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;center&gt;_How would you switch on the top-right one ?_&lt;/center&gt;

&lt;p&gt;Unfortunately, 1s and 0s, first components of the digital world, tend to be less explicit about that. That is why UXs tried to represent real world into softwares to use physical affordances so the user could try to infer behaviour based on an existing knowledge.&lt;br&gt;&lt;br&gt;
That is what metaphors are all about.&lt;/p&gt;

&lt;h3&gt;
  
  
  Metaphors
&lt;/h3&gt;

&lt;p&gt;It all began with Alan Kay's "Desktop Metaphor" :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcla3h578orj0l0elb8h6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcla3h578orj0l0elb8h6.png" alt="Alt Text" width="800" height="537"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;center&gt;_The original 1984 Mac OS desktop that popularized the new graphical user interface._&lt;/center&gt;

&lt;p&gt;These familiar items (desktop, folders, files etc.) have the same rules as their physical equilvalent:&lt;br&gt;&lt;br&gt;
Everything is represented on the desktop, usual working environment, where you can put files and folders. Files gather data and can go into folders if you drag and drop them in.&lt;br&gt;
Files and folders can be thrown away by putting them into the trash bean that you will empty once in a while.&lt;br&gt;&lt;br&gt;
Thinking about it for a minute is enough to realise it makes no sense at all to put files into a trash bean and then empty it to actually free some disk memory. But it is easy to learn.&lt;/p&gt;

&lt;p&gt;Nowadays one does not see these similarities as we're more used to computers than dealing with actual files and folders, but back then it was a key point to acceptation of new born computers.&lt;/p&gt;

&lt;p&gt;Implementing these similarities allows us to build on something we know, to reuse a known mental model. &lt;/p&gt;

&lt;p&gt;Metaphors are present within the smaller detail of interfaces guiding us on how to interact with it.&lt;br&gt;
Skeumorphic design makes metaphoric use of physical analogies that indicate which parts a user can press, click, or slide, etc. These phenomena have been described as ‘indicating functions’ in product semantics, and as ‘affordances’ in cognitive psychology.&lt;br&gt;&lt;br&gt;
Theses metaphors are everywhere in software interfaces. I'll take an Apple product as example once again (sorry windows lovers, I really tried...).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fiqq1p32f4dv1ax47udup.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fiqq1p32f4dv1ax47udup.png" alt="Alt Text" width="800" height="244"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;center&gt;_iOS 3 unlock slider._ &lt;/center&gt;

&lt;p&gt;Here it seems pretty obvious what action the UX designer wants us to perform, and its output.&lt;br&gt;
Apple used skeumorphic design to suggest that the white 'slider' could be moved within the boundaries defined by its black environment, from left to right.&lt;br&gt;
Using signs like the arrow and text, they finish to encourage the user to perform the action and make the interface predictable.&lt;/p&gt;

&lt;p&gt;But users evolve constantly, and one must nuance this result.&lt;br&gt;&lt;br&gt;
In 2001 Prensky introduced the term &lt;em&gt;Digital Natives&lt;/em&gt; to describe a new generation of users who ‘have spent their entire lives surrounded by and using computers, videogames, digital music players, video cams, cell phones, and all the other toys and tools of the digital age’. &lt;br&gt;
The idea that interfaces are being learned by transferring knowledge from the ‘real’ (i.e. analogue) world to the digital world may be loosing its dominance.&lt;br&gt;
Experienced Digital Immigrants rather transfer knowledge they previously acquired using other interfaces,&lt;br&gt;
That is why design is evolving and flat design is a great example of this dynamic. Skeumorphism is becoming less usefull, in favor of clean, neat design that satisfies the eye.&lt;br&gt;&lt;br&gt;
A perfect example of this dynamic is the new Iphone's unlocker :&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Foh2q95l62ru0oo503rgs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Foh2q95l62ru0oo503rgs.png" alt="Alt Text" width="800" height="244"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;center&gt;_iOS 7 unlock slider._&lt;/center&gt; 

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Finally, injecting physical properties into digital interfaces is an efficient way to improve its learnability, especially initial learning.&lt;br&gt;
But one must not forget that the learning process deeply relies on already known mental models as it is all about building over it and finding similarities.&lt;br&gt;
Users have been evolving since the birth of computers and their global knowledge over this technology follows. Where complex interactions will highly benefit in term of learnability from rich skeumorphic design, more usual interactions will satisfy from a more minimalist design.&lt;br&gt;
Wether or not you choose skeumorphism of flat design, consider taking a great care of affordances, they're a - complex - way to make your interface simple to use.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Simple can be harder than complex: You have to work hard to get your thinking clean to make it simple. But it’s worth it in the end because once you get there, you can move mountains.”&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>ux</category>
    </item>
  </channel>
</rss>
