Good Chat Documentation

Transcription

Good Chat Documentation
Good Chat Documentation
Version 1.0.0
Rémy Sanchez
15 October 2015
Table des matières
1
L’application Good Chat
1.1 Maquette . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2 Technologie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.3 Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
3
3
3
2
Bibliothèques
2.1 goodchat.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2 randname.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
5
5
3
Démarer le TP
3.1 Prérequis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2 Installer les sources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.3 Démarer le serveur HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
7
7
10
4
Stories
4.1 1. Avoir un nom automatique . . . . . . . . . . . . . . . . . . . .
4.2 2. Changer son nom . . . . . . . . . . . . . . . . . . . . . . . . .
4.3 3. Voir les messages reçus . . . . . . . . . . . . . . . . . . . . . .
4.4 4. Envoyer un message . . . . . . . . . . . . . . . . . . . . . . . .
4.5 5. Ne pas envoyer de message quand le message ou le nom est vide
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
11
11
11
12
14
14
Coding Style (and related)
5.1 All-languages recommendations
5.2 Javascript . . . . . . . . . . . .
5.3 Python . . . . . . . . . . . . .
5.4 LESS/CSS . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
17
17
19
22
22
5
6
Indices and tables
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
27
i
ii
Good Chat Documentation, Version 1.0.0
Bienvenue dans la documentation de Good Chat.
L’objectif de ce TP est de mettre en pratique les enseignements du cour associé “Faire du JS”. Si vous ne deviez retenir
qu’une seul chose de ce cours, la leçon serait la suivante : l’essentiel est de rester cohérent avec votre équipe, pour
qu’en dépit de nombreuses contradictions dans le monde réel (et dans Javascript) votre code soit simple à reprendre et
maintenir.
“Always code as if the person who ends up maintaining your code is a violent psychopath who knows
where you live.”
—Code For The Maintainer
Vous allez donc pour cela travailler en équipe et maintenir le code de vos collègues. La façon de procéder sera simple :
— Le TP est découpé en différentes petites stories
— À chaque fin de story, vous changerez aléatoirement de poste et continuerez le projet codé par un autre binome
— Cela signifie que tous les groupes doivent terminer en même temps. Les groupes avançant plus rapidement
seront invités à aider les autres pour accélérer le processus
Pour le bon déroulement de ce mode de travail, il sera entre autre impératif de coder en respectant le guide de style
fourni.
L’application que vous devez développer est une application web. Elle inclu donc le trio classique HTML/CSS/JS. Elle
a également besoin d’un serveur pour permettre la communication entre les clients. Cependant, l’objectif de ce TP est
centré sur le JS. De ce fait, seule cette partie sera à coder, le reste étant fourni dans ce dépôt.
Table des matières
1
Good Chat Documentation, Version 1.0.0
2
Table des matières
CHAPITRE 1
L’application Good Chat
Good Chat est une application très simple de chat en ligne. Elle permet à ses utilisateurs de communiquer entre eux
instantannément via des messages texte.
Fig. 1.1 – On ne parle pas de ce chat là
1.1 Maquette
Une maquette de l’application est disponible en ligne.
http://ky9up3.axshare.com
1.2 Technologie
Pour servir l’exercice, l’application est conçue de la façon la plus simple possible.
— On considère qu’on utilisera forcément un navigateur digne de ce nom (c’est à dire pas Internet Explorer)
— Le code HTML est écrit directement
— Javascript
— On utilise ES5
— Pas de framework (pas de jQuery)
— Style
— Basé sur Bootstrap
— Écrit en LESS et compilé grâce à WebStorm
— On utilise Firebase pour faire communiquer les clients
— Les dépendances sont gérées par Bower
1.3 Architecture
Le TP est livré des fichiers qui n’ont pas besoin d’être modifiés
— index.html contient le code HTML de la page ainsi qu’une balise <script
type="application/template" id="tpl-message-row"> qui contient le template HTML
d’un message.
— style.less (et la version compilée style.css) contient quelques ajouts à Bootstrap.
— goodchat.js est une abstraction au dessus de Firebase qui permet d’envoyer/recevoir des messages.
— randname.js est une petite bibliothèque JS qui génère des noms aléatoires, pour le pseudo.
3
Good Chat Documentation, Version 1.0.0
De ce fait, l’ensemble du code que vous devrez écrire sera rangé dans le fichier app.js qui est prévu à cet effet.
4
Chapitre 1. L’application Good Chat
CHAPITRE 2
Bibliothèques
Deux bibliothèques simples codées pour l’occasion doivent être utilisées directement pour réaliser ce projet.
2.1 goodchat.js
goodchat.js est en charge de gérer la communication avec le backend (Firebase). Il permet simplement d’envoyer
et de recevoir des messages en temps réel.
goodChat.onMessage(callback)
Arguments
—callback – Le callback est appelé à chaque fois qu’un nouveau message est reçu. Au chargement de la page, tous les messages déjà échangés par le passé sont reçus d’un coup.
Le message reçu est simplement un objet contenant 3 clefs : userName, message et time
(qui est le timestamp en millisecondes du message).
goodChat.sendMessage(userName, message)
Arguments
—userName – Le nom de l’utilisateur
—message – Chaîne du message
Cette fonction envoie un message à tous les autres participants du Good Chat.
2.2 randname.js
randname.js est simplement une petite librairie pour générer un nom aléatoire à l’utilisateur, et le stocker dans la
session du navigateur.
randName.genName()
Génère un nom aléatoire et le retourne.
randName.setName(name)
Arguments
—name – Nom de l’utilisateur à stocker
Stocke ce nom d’utilisateur en session.
randName.getNameForSession()
Retourne le nom de l’utilisateur stocké en session. Si le nom n’a pas encore été défini, alors génère automatiquement un nom à l’aide de randName.genName().
5
Good Chat Documentation, Version 1.0.0
6
Chapitre 2. Bibliothèques
CHAPITRE 3
Démarer le TP
Cette section rentre dans les détails de comment mettre en place l’environnement de travail pour pouvoir travailler.
Vous mettrez en place l’environnement de travail, puis changerez de poste. Faites donc attention à configurer l’ensemble correctement car c’est quelqu’un d’autre qui utilisera cet environnement.
3.1 Prérequis
Vous aurez besoin d’outils pour effectuer ce TP.
3.1.1 IDE
Un IDE est un outil essentiel pour le développeur. Il faut donc en choisir un avec lequel on est à l’aise, et qui permette
de collaborer efficacement avec ses collègues. En l’occurence, WebStorm a été choisi, car même s’il est payant, il a de
nombreux arguments fonctionnels, et particulièrement une intégration efficace à JSLint.
Vous devez configurer WebStorm de manière cohérente avec le reste de l’équipe. Pour cela, vous devez vérifier que la
configuration correspond aux screenshots suivants.
3.1.2 Bower
Bower est un outil de gestion des dépendances client. Il permet de télécharger et mettre automatiquement à jour les
dépendances telles que Bootstrap ou Firebase.
Pour l’installer, taper npm install -g bower dans un terminal.
3.1.3 HTTP Server
Pour servir les fichiers statiques, nous allons utiliser un serveur HTTP simple. Il peut également être installé grâce à
npm : npm install -g http-server.
3.2 Installer les sources
Vous aurez besoin des sources de base de ce TP. Pour cela, rendez-vous sur le dépôt GitHub. De là vous trouverez
l’adresse du dépôt Git à cloner pour pouvoir commencer le TP.
7
Good Chat Documentation, Version 1.0.0
8
Chapitre 3. Démarer le TP
Good Chat Documentation, Version 1.0.0
3.2. Installer les sources
9
Good Chat Documentation, Version 1.0.0
3.3 Démarer le serveur HTTP
Dans un terminal, rendez-vous dans le dossier où vous avez téléchargé les sources, et lancez le serveur HTTP :
http-server src.
Vous pouvez vous rendre à l’adresse http://localhost:8080/ pour admirer l’application vide que vous venez de démarer.
Vous êtes maintenant prêts à commencer le travail.
10
Chapitre 3. Démarer le TP
CHAPITRE 4
Stories
Pour simplifier, le nom des stories est rédigé de la façon suivante : L’utilisateur peut X, X étant le titre de la story.
Chaque story comporte 3 sections :
— Une liste des fonctions à coder pour réaliser cette story. Vous avez la liberté du nommage des fonctions, mais
vous devez respecter le découpage indiqué.
— Des liens vers la documentation des fonctions utiles
— Éventuellement, des morceaux de code desquels vous pouvez vous inspirer
4.1 1. Avoir un nom automatique
Au premier lancement de l’application pour la session, un nom est automatiquement généré. Ce nom est enregistré
pour la durée de la session.
4.1.1 Fonctions à coder
— Une fonction qui retourne l’input du nom de l’utilisateur
— Une fonction d’initialisation qui rempli le champ avec le nom fourni par randName.
4.1.2 Documentation
— Document.querySelector()
— randName.getNameForSession()
4.1.3 Exemples
Définir la valeur d’un input
document.querySelector('#my-input').value = 'foo';
4.2 2. Changer son nom
En changeant le champ texte en haut à droite, l’utilisateur change son nom pour la durée de la session.
11
Good Chat Documentation, Version 1.0.0
4.2.1 Fonctions à coder
— Une fonction qui surveille le champ du nom de l’utilisateur, et l’enregistre quand il est changé
4.2.2 Documentation
—
—
—
—
EventTarget.addEventListener()
keyup
HTMLInputElement (s’intéresser à value)
randName.setName()
4.2.3 Exemples
Surveiller les valeurs d’un input
var input = document.querySelector('#my-input');
input.addEventListener('keyup', function () {
console.log('new value', input.value);
});
Sauvegarder un nom dans randName
randName.setName('Alice');
4.3 3. Voir les messages reçus
À la réception d’un message, il est ajouté à la liste des messages reçus.
4.3.1 Fonctions à coder
— Une fonction qui, à partir d’un timestamp Unix en millisecondes, retourne l’heure au format “hh :mm”. Les
messages reçus ont comme attribut time un timestamp Unix, et l’affichage nécessite de montrer l’heure au
format “hh :mm”, cette fonction est donc un outil pour aider à passer de l’un à l’autre.
— Une fonction qui, à partir d’un message reçu, génère le code HTML (ou plutôt le DOM) à insérer
dans la liste des messages. Pour information, le template des messages est disponible dans la balise
script#tpl-message-row qui se trouve à la fin de index.html.
— Une fonction qui reçoit en argument un message, le transformes en HTML, l’ajoute à la liste des messages et
enfin s’assure que le nombre de messages affichés ne dépasse pas un nombre prédéterminé (10 par exemple).
— Et enfin, une fonction qui utilise l’API goodChat pour recevoir les messages.
4.3.2 Documentation
—
—
—
—
12
Date.getHours() Retourne les heures d’un objet Date.
Date.getMinutes() Retourne les minutes d’un objet Date.
Element.innerHTML Permet de changer le code HTML à l’intérieur d’un nœud du DOM.
Node.textContent Permet de changer le texte à l’intérieur d’un nœud du DOM. À privilégier pour afficher du
contenu provenant d’un utilisateur, par exemple un message.
Chapitre 4. Stories
Good Chat Documentation, Version 1.0.0
— Node.insertBefore() Insère un nœud enfant juste avant le nœud indiqué en paramètre. Utile pour insérer un
élément en début de liste, par exemple.
— Node.removeChild() Supprime l’enfant spécifié de la liste des descendants.
— ParentNode.childElementCount Compte le nombre d’enfants d’un nœud du DOM.
— goodChat.onMessage() Permet d’enregistrer un callback qui sera appellé à la réception d’un nouveau
message.
4.3.3 Exemples
Ajouter un zéro devant un entier
if (x < 10) {
return '0' + x;
}
return x.toString()
Obtenir les heures d’un timestamp
var date = new Date(timestamp);
console.log(date.getHours());
Transformer un template en nœud du DOM
<script type="application/template" id="my-template">
<h1 class="my-title"></h1>
</script>
var newItem = document.createElement('div');
newItem = document.querySelector('#my-template').innerHTML;
newItem.querySelector('.my-title').textContent = 'Foo Title';
Insérer un élément du DOM en premier sous un parent
<ul id="my-list">
<li>Un item</li>
<li>Et un autre</li>
</ul>
var newItem = document.createElement('li'),
list = document.querySelector('#my-list');
newItem.textContent = 'Foo Item';
list.insertBefore(newItem, list.firstChild);
Limiter le nombre d’enfants à un nombre donné
4.3. 3. Voir les messages reçus
13
Good Chat Documentation, Version 1.0.0
var node = document.createElement('#my-node');
while (node.childElementCount > 10) {
node.removeChild(node.lastElementChild);
}
Recevoir les message
goodChat.onMessage(function (message) {
console.log('nom d\'utilisateur', message.userName);
console.log('message', message.message);
console.log('date', new Date(message.time));
});
4.4 4. Envoyer un message
Si l’utilisateur tape un message puis qu’il tape la touche Entrée ou qu’il clique sur le bouton Envoyer, alors le message
saisi est envoyé à tout le monde, puis affiché.
4.4.1 Fonctions à coder
— Une fonction qui réagit à la soumission du formulaire pour envoyer le message via l’API goodChat.
4.4.2 Documentation
— Event.preventDefault()
— submit
— goodChat.sendMessage()
4.4.3 Exemples
Intercepter la soumission d’un formulaire
var form = document.querySelector('#my-form');
form.addEventListener('submit', function (event) {
event.preventDefault();
console.log('This form is no longer being submitted');
});
4.5 5. Ne pas envoyer de message quand le message ou le nom est
vide
Si l’utilisateur n’a pas saisi de message ou de nom, alors il faut désactiver l’envoi du formulaire et ajouter la classe
disabled au bouton d’envoi pour qu’il comprenne qu’il ne peut pas cliquer dessus.
14
Chapitre 4. Stories
Good Chat Documentation, Version 1.0.0
4.5.1 Fonctions à coder
— Une fonction qui surveille les modifications du message.
— Une fonction qui vérifie qu’il y a bien du contenu dans les champs de message et de nom d’utilisateur. Si
non, alors elle ajoute une classe disabled au bouton du formulaire, et désactive l’envoi (pour cela, modifier
la fonction d’envoi de message). Appeller cette fonction à chaque modification du nom d’utilisateur et du
message.
4.5.2 Documentation
— Element.classList
4.5. 5. Ne pas envoyer de message quand le message ou le nom est vide
15
Good Chat Documentation, Version 1.0.0
16
Chapitre 4. Stories
CHAPITRE 5
Coding Style (and related)
Getting the style right is easy : a simple glimpse at the code will tell you if it looks nice, and anyway most of IDEs are
able to fix most of it by themselves.
This is why there is absolutely no excuse to get the style wrong. Having a code uniformly-looking helps reading the
code afterwards, by a peer or by yourself, and also helps seeing the structure of it. This does reduce the number of
bugs in the code you write and in the changes others will make as well.
Basically, once the good habits taken, they are totally painless to apply. We wouldn’t want to reject free improvement,
right ?
5.1 All-languages recommendations
Those recommendations apply for all languages or kinds of text file you might have to create.
5.1.1 White spaces
There is two kinds of whitespaces in a source code :
indentation Whatever indentation you choose, keep it consistent in all the project.
trailing whitespaces Often, some whitespaces will be found after the line itself. This is bad. For each trailing space,
a kitten dies.
In order to prevent any of those two to get wrong, there is two things to do :
— Enable the display of whitespaces in your IDE
— Enable the option that removes trailing whitespaces on save
5.1.2 File “format”
Plain-text/source code files must respect a few conventions
— All files are encoded in UTF-8.
— If possible, start the file with a Vim modeline, even if you don’t use Vim, this is helpful to guess the indentation
and line length settings.
— Use Unix (n) line endings.
— The last line must include a line ending.
— No caps nor non-ASCII characters in file names, as those lead to problems due to inconsistencies accross
operating systems.
17
Good Chat Documentation, Version 1.0.0
Note : Why the fuck shoud the last line include a line ending you ask ? Well, all lines are terminated with a line
ending, why would the last one not be ? Furthermore, if in a further revision of the code a line is added after the ex-last
line, well that ex-last line will be considered by Git as modified because a line ending was added to it, which is not a
good thing since that line was not actually modified.
5.1.3 Lines length
Why should we bother about lines length since text editors of this century all know how to wrap text ?
The answer is quite simple and lies in the fact that even if editors can wrap lines, I am sorry to tell you that your brain
cannot hold too much information at once. By convention, a line width is fixed, and should your line get longer than
this, it probably means that it has too much information and that it should be chopped down for clarity.
Take the following example :
if some_shitty(thing(unreadable)) == some(other_stuff) and a < b and pouet \
& BLAH and (something or (something_else and shit)):
pass
Now consider this :
if some_shitty(thing(unreadable)) == some(other_stuff) \
and a < b \
and pouet & BLAH \
and (something or (something_else and shit)):
pass
The most readable snippet appears clearly.
5.1.4 Spelling, grammar and meaning
The official language for everything related to the code is English. The reason behind this is that everybody speaks
english, so if the team ever had to get international this wouldn’t be a hurdle. And anyways, code in any other language
feels awkward.
Meaning
However, not everybody is fluent, and there is a lot of false friends around. This is why when you name something,
you have to be 100% positive that the meaning is right. Especially in data models, where any change can be painful.
For this reason, in case of any doubt just use a dictionnary. And check carefully the meaning of any database field
before commiting it.
Grammar
Please use a correct order of words in variables. It is basically “adjective”_”subject”_”complement”. Like in
max_brace_area. Not like area_max_brace.
18
Chapitre 5. Coding Style (and related)
Good Chat Documentation, Version 1.0.0
Spelling
No spelling mistakes are allowed in variable names. Beyond the fact that it makes them look nicer, since most of the
languages we use are dynamic, it helps avoiding typos.
By example, if you type my_stuff.attrbute and that your IDE indicates a spelling mistake, then you will notice that
indeed you did want to write my_stuff.attribute.
Again, this is a simple way to make less bugs.
Not all words will be in the dictionnary, but if you are absolutely sure that the word exists, then feel free to add it to
your dictionnary so it won’t bother you anymore.
Common pitfalls
Let us go through some common issues met in variable names :
— nb_objects makes a few mistakes
— Avoid using abbreviations, as they could be misunderstood
— Maybe it’s just me, but number feels awkward in this case, count sounds better
— The order of words is wrong, the correct way would be objects_count
5.1.5 Conventions
Most languages have established conventions on formatting the source code, like the PEP8, jslint, PSR-2, etc.
One might like or not the style of those conventions, however since they are widely used, there is no reason not to
follow them. Other developpers will know them and will be more confortable reading the code.
5.2 Javascript
Javascript leaves so much freedom to the developper that it becomes really easy to make low quality and buggy code.
Of course, we want quality code, but even more, we want code that comes without surprises and that any developper
used to the style can easily read. Those guidelines are thus very important if we want the Javascript development to go
smoothly.
5.2.1 Linting
As stated before, Javascript leaves too much freedom. In fact, some things that can be done are harmful and error-prone.
This is why Douglas Crockford created a tool named jslint. It ensures that your code keeps a consistent formatting,
and that you do not use dangerous features. He explains most of his reasons in a talk that anyone is strongly advised
to watch, as well as in this page.
Here is how we configure jslint in ActivKonnect :
/*jslint indent: 4, maxlen: 100*/
indent : 4 As expected, the indentation is of 4 spaces. This is the default, but let’s state it explicitly just to make it
very clear.
maxlen : 100 The PEP8 explains it well, your brain can’t handle an infinitely long strong. The industry standard
would be around 80 columns, however as we have control over our own screens, we think it is best to use a 100
columns conventions.
5.2. Javascript
19
Good Chat Documentation, Version 1.0.0
5.2.2 Variable naming
The rules are pretty simple :
Constants All constants (aka content that should never vary, even though constants do not actually exist in JS) should
be named in all-uppercase, and words must be separated by underscores. Ex : THIS_IS_A_CONSTANT
Objects Any constructor (aka something you have to call with new) must be named in camel case and begin with an
upper case. Ex : MyObjectName
Variables and the rest Everything else comes in camel case and must not begin with an upper case. Ex : myVariableName
5.2.3 File template
All Javascript files must be structured this way
/*vim: fileencoding=utf8 tw=100 expandtab ts=4 sw=4 */
/*jslint indent: 4, maxlen: 100 */
/*global angular */
// Good Morning Planet Website
// (c) 2014 ActivKonnect
(function (ng) {
'use strict';
// Code goes here
}(angular));
—
—
—
—
—
There is a vim modeline, as explained in File “format”.
The JSLint options, that should never vary.
List of global variables. This helps keeping track of dependencies. Usual suspects are angular, _ and jQuery.
The copyright statement, quite obviously.
All the code is included in a IIFE in order to :
— Minify the name of the global variables by passing them as arguments
— Enable the strict mode
5.2.4 Object template
There is many ways to create objects in Javascript, but we have to stay consistent in the way we do it. The stucture
presented below results of many trials and errors, and should work well in all situations.
Without inheritance
MyObject = function (argument1, argument2) {
var self = this,
privateMember1,
privateMember2,
// Methods
method1,
method2,
method3;
20
Chapitre 5. Coding Style (and related)
Good Chat Documentation, Version 1.0.0
// Public members
self.publicMember1 = 42;
self.publicMember2 = false;
// Method bodies
method1 = function () {
// Method 1 code
};
method2 = function () {
// Method 2 code
};
method3 = function () {
// Method 3 code
};
// Exports
self.method1 = method1;
self.method2 = method2;
(function () {
// Constructor code
}());
}
Some explanations on the motivations behind this template :
— Checkout out what Crockford has to say on the matter.
— The self = this allows you to safely access the object from its methods and avoid the tricky behaviour of this.
— Private members are declared as local variables of the constructor’s closure. They can never be accessed from
the outside, so be careful about what you put there.
— Public members are defined as members of self.
— All methods (public and private) are declared in a var statement. Why declare them here and not use regular
named functions ? Because according to JSLint, you can’t reference a symbol that hasn’t been defined yet (let’s
skip the reasons of that), so if methods were not defined this way, then you wouldn’t be able to call method2()
from method1(), by example.
— Public methods methods are declared with statements like self.method1 = method1.
— Doing so makes it possible to switch a method from private to public without any refactoring.
— It helps minification a lot. If you call method3() directly, the minifier can rename it as it pleases him.
However, if you call self.method3(), then the minifier will only be able to rename self and will leave
method3 untouched.
— The code that would go in the constuctor if you used a traditionnal OO language goes into an IIFE.
— It helps readability, because you know exactly where the code begins and ends, and it is always located in
the same place.
— If you want a local variable that does not have to be a private member, you can declare it at the beginning
of the IIEF. This way, it will not stay in the object forever.
With inheritance
Some tests were conducted to see what inheritance patterns could be used, however currently there is not enough use
of it to actually decide anything.
Anyways, it’s best to create small orthogonal objects than a big comprehensive object with a huge genealogy tree.
5.2. Javascript
21
Good Chat Documentation, Version 1.0.0
5.3 Python
There is not much to be said here about Python, since the Python community is quite organized yet, and almost
everything already has best practices determined.
5.3.1 PEP8
The PEP8 provides an excellent guideline regarding the coding style.
5.3.2 Use the pythonic way
The Python language is very flexible, and you can very easily replicate what you would write in other languages.
However, this is a trap, as many things have a pythonic way of doing them, and it’s often different from other languages,
and especially from Java.
To name a few :
— Not everything has to be in classes. Stand-alone functions are fine too.
— There is many literals for maps, lists, tuples, sets, etc. Use them.
— Use the property built-in instead of creating getters and setters the way you would do it in Java.
5.4 LESS/CSS
No official documentation exists or stands out for CSS, and even fewer regarding LESS. However, the following
inspirations were used here :
@mdo’s Code Guide Written by @mdo, one of the guys behind Bootstrap, is basically interesting, except for a few
unexplained weird things like the choice to omit the 0 in small floats (0.5 vs .5), and the advice to make
one-liner declarations.
Github’s Guideliens A few interesting ideas, their style is documented with KSS, which is something we might end
up doing.
CSS Guidelines Some high-level rules for writing clean CSS, which are basically specialized in this document.
5.4.1 Whitespaces
— Use soft-tabs with a two space indent. Spaces guarantee that code renders the same way accross editors, and
two spaces is the most used convention in CSS.
— Put spaces after : in property declarations, but not before.
— Put spaces before { in rules declarations.
— Put line breaks between rulesets.
— When grouping selectors, keep individual selectors to a single line.
— Place } at the end of declaration blocks on a new line.
— No more than a single declaration per line, for readability and error reporting.
— Always put a space after a coma
5.4.2 Formatting
— For colors, use whenever possible, by order of priority
— The pre-defined variable for that color
— Color names, like white
22
Chapitre 5. Coding Style (and related)
Good Chat Documentation, Version 1.0.0
— Short-hand notations, like #abc
— Hex colors, like #fabb00
— rgba(), like rgba(1, 1, 1, 0.5)
— Don’t put units with zero. 0 is right, 0px is wrong.
A few exemple of what is right or wrong :
/* Bad CSS */
.selector, .selector-secondary, .selector[type=text] {
padding:15px;
margin:0px 0px 15px;
background-color:rgba(0,0,0,.5);
box-shadow:0px 1px 2px #CCC,inset 0 1px 0 #FFFFFF
}
/* Good CSS */
.selector,
.selector-secondary,
.selector[type="text"] {
padding: 15px;
margin-bottom: 15px;
background-color: rgba(0, 0, 0, 0.5);
box-shadow: 0 1px 2px #ccc, inset 0 1px 0 #fff;
}
5.4.3 Declaration Order
Place property declarations in that order :
1. Positioning
2. Box model
3. Animations
4. Typographic
5. Visual
6. Other
7. LESS Nested Declarations
Here is an exemple :
.declaration-order {
/* Positioning */
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 100;
/* Animation */
.lh-transition(300ms ease all);
/* Box-model */
display: block;
float: right;
width: 100px;
height: 100px;
5.4. LESS/CSS
23
Good Chat Documentation, Version 1.0.0
/* Typography */
font: normal 13px "Helvetica Neue", sans-serif;
line-height: 1.5;
color: #333;
text-align: center;
/* Visual */
background-color: #f5f5f5;
border: 1px solid #e5e5e5;
border-radius: 3px;
/* Misc */
opacity: 1;
}
5.4.4 Vendor prefixes
Many modern CSS features depend on vendor prefixes. In order to eliminate the difference between browsers, we
use the prefixed version of LESS Hat, which automatically generates styles for every browser, including for complex
properties like gradients.
It must always be used for properties that it handles, and vendor prefixes must not be written manually.
5.4.5 Selectors
A lot has been written about selectors, and it is mostly summarized in the CSS Guidelines. What is said in there has to
be kept in mind, but with the experience of GMP, a few rules seem to be especially important.
Try to scope CSS per component Each component (think “directive” or simply a noticeable UI component) should
get its own .gmp-X class. It helps namespacing things under it.
.gmp-my-directive {
.some-inside-class {
color: white;
}
// Rest of the code goes here
}
<div class="gmp-my-directive">
<h1 class="some-inside-class">Stuff</h1>
<!-- Rest of the code goes here -->
</div>
Avoid using selectors that go deep into the DOM If you use a selector like .gmp-my-stuff button, it will affect all the
buttons inside your component, including those from third party directives you could decide to include later
on.
Better solutions would be .gmp-my-stuff > button if possible or using a class for the button .gmp-my-stuff
.stuff-button.
Factorize styles In the previous example we select a button inside our component, however in the case of buttons
there is much to bet on the fact that this particular button will look like all buttons on the site. For this reason,
it could be considered as a component itself, and get its own namespace.
24
Chapitre 5. Coding Style (and related)
Good Chat Documentation, Version 1.0.0
<div class="gmp-my-stuff">
<p>
Do something
</p>
<p>
<button class="gmp-stuff-button">Action!</button>
</p>
</div>
5.4.6 LESS And Magic Numbers
One of the worst things that can happen to a CSS stylesheet, is to get it filled with many interdependant values (dimensions, positions, colors, ...) but without knowing where does the calculation comes from. In those cases, changing
even the smallest thing can lead to many unwanted side-effects.
In order to compensate that and to document the values, before starting to style, all the useful numbers/colors should
be put at the beginning of each component.
Note : Those variables will be scoped to the component, and will not be available outside of it, so you are free to
choose a straightforward name for it.
As example, we can take the following piece of abstract act :
The idea is basically to have a box, with a given padding, with two other boxes inside, that keep the padding rule but
have a bottom border that expands into the padding.
The following LESS code allows to produce just that, with a few configurable variables at the top.
<div class="gmp-box">
<div class="bottom-stuff"></div>
<div class="right-stuff"></div>
</div>
5.4. LESS/CSS
25
Good Chat Documentation, Version 1.0.0
* {
box-sizing: border-box;
}
.gmp-box {
@box-color: #aaa;
@box-to-top: 10px;
@box-to-left: @box-to-top;
@box-size: 300px;
@box-padding: 20px;
@bottom-stuff-width: (@box-size - 2 * @box-padding) * 2 / 3;
@bottom-stuff-height: @box-size / 3;
@bottom-stuff-border-size: 4px;
@bottom-stuff-color: red;
@right-stuff-border-size: 13px;
@right-stuff-color: blue;
position: absolute;
top: @box-to-top;
left: @box-to-left;
.size(@box-size);
background-color: @box-color;
.bottom-stuff {
position: absolute;
left: @box-padding;
bottom: @box-padding - @bottom-stuff-border-size;
width: @bottom-stuff-width;
height: @bottom-stuff-height;
background-color: lighten(@bottom-stuff-color, 20%);
border-bottom: @bottom-stuff-border-size @bottom-stuff-color solid;
}
.right-stuff {
position: absolute;
right: @box-padding;
bottom: @box-padding - @right-stuff-border-size;
top: @box-padding;
width: @box-size - (@box-padding * 2) - @bottom-stuff-width;
background-color: lighten(@right-stuff-color, 20%);
border-bottom: @right-stuff-border-size @right-stuff-color solid;
}
}
26
Chapitre 5. Coding Style (and related)
CHAPITRE 6
Indices and tables
— genindex
— modindex
— search
27
Good Chat Documentation, Version 1.0.0
28
Chapitre 6. Indices and tables
Index
G
goodChat.onMessage() (méthode goodChat), 5
goodChat.sendMessage() (méthode goodChat), 5
R
randName.genName() (méthode randName), 5
randName.getNameForSession() (méthode randName), 5
randName.setName() (méthode randName), 5
29

Documents pareils