Adding programs to path.

By default, some programs will be installed while automatically being setup in order to be run from the command line.
For ex., [Win]+R ‘devenv’ launches Visual Studio.

I happened to run into this article which precises how to add some more:

Registry: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\App Paths

  1. Create a new sub-key with the name of the executable file that you wish to add to the path (ex. eclipse.exe)
  2. In this new key, add a string variable named “Path” containing the value of the the path to your new executable file (ex. “C:\Program files\eclipse\”)
  3. The new key will already have an empty variable (Default). Edit it to have the string value of entire address of the new program executable (ex. “C:\Program files\eclipse\eclipse.exe”)
  • english
  • french

Java foreach.

Java 5 got a bit closer to its twin C# by adding the possibility of directly accessing entities of a list or collection through its own “foreach” functionality :

C# :

  1. foreach(type var in arr){
  2.   // implement body
  3. }

Java :

  1. for (type var : arr) {
  2.     // implement body
  3. }
  • english
  • french

List.Find() use of delegates.

Delegates make it easier to find stuff in generic lists.
Let’s consider the following simple class:

  1. Public Class Person{
  2.   private string m_name;
  3.   private int m_age;
  4.  
  5.   // .Net3.0 syntax only.
  6.   public string Name{get;set}
  7.   public int Age{get;set}
  8.  
  9.   public Person(string name, int age){
  10.     m_name = name;
  11.     m_age = age;
  12.   }

Instanciating :

  1. List<Person> lstPpl = new List<Person>();
  2. lstPpl.Add(new Person("Christian", 1));
  3. lstPpl.Add(new Person("Noah", 0.3));

We can easily find Noah:

  1. Person myson = lstPpl.Find(delegate(Person p) { return "Noah" == p.Name; });
  • english
  • french

Encrypted binary serialization

For re-use: a small class that does encryption and binary serialization:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.IO;
  5. using System.Runtime.Serialization.Formatters.Binary;
  6. using System.Security.Cryptography;
  7. using System.Windows.Forms;
  8.  
  9. namespace Infotel_Quiz_Manager.quiz
  10. {
  11.     class Tools
  12.     {
  13.         // change me…
  14.         private static string m_encryptionKey = "password";
  15.  
  16.         public static byte[] Encrypt(byte[] plainData, string sKey)
  17.         {
  18.             DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
  19.             DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
  20.             DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
  21.             ICryptoTransform desencrypt = DES.CreateEncryptor();
  22.             byte[] encryptedData = desencrypt.TransformFinalBlock(plainData, 0, plainData.Length);
  23.             return encryptedData;
  24.         }
  25.  
  26.         public static byte[] Decrypt(byte[] encryptedData, string sKey)
  27.         {
  28.             DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
  29.             DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
  30.             DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
  31.             ICryptoTransform desDecrypt = DES.CreateDecryptor();
  32.             byte[] decryptedData = desDecrypt.TransformFinalBlock(encryptedData, 0, encryptedData.Length);
  33.             return decryptedData;
  34.         }
  35.  
  36.         public static void SaveObjectToFile(object obj, string path){
  37.             try
  38.             {
  39.                 MemoryStream memStream = new MemoryStream();
  40.                 BinaryFormatter binFormatter = new BinaryFormatter();
  41.                 binFormatter.Serialize(memStream, obj);
  42.                 byte[] encryptedBytes = Encrypt(memStream.ToArray(), m_encryptionKey);
  43.                 memStream.Close();
  44.                 Stream streamToFile = File.Open(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
  45.                 streamToFile.Write(encryptedBytes, 0, encryptedBytes.Length);
  46.                 streamToFile.Flush();
  47.                 streamToFile.Close();
  48.             }
  49.             catch (Exception e)
  50.             {
  51.                 MessageBox.Show(e.Message);
  52.             }
  53.         }
  54.  
  55.         public static object LoadObjectFromFile(string path)
  56.         {
  57.             try
  58.             {
  59.  
  60.                 Stream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
  61.                 byte[] encryptedObj = new byte[fileStream.Length];
  62.                 fileStream.Read(encryptedObj, 0, (int)encryptedObj.Length);
  63.                 MemoryStream memStream = new MemoryStream(Decrypt(encryptedObj, m_encryptionKey));
  64.                 BinaryFormatter binFormatter = new BinaryFormatter();
  65.                 object decryptedObj = binFormatter.Deserialize(memStream);
  66.                 memStream.Close();
  67.                 fileStream.Close();
  68.                 return decryptedObj;
  69.             }
  70.             catch (Exception e)
  71.             {
  72.                 MessageBox.Show(e.Message);
  73.             }
  74.             return null;
  75.         }
  76.     }
  77. }
  • english
  • french

Masters without style.

Everytime I start digging into a new technology, I find myself quickly pointed towards some of the most talented computer science geek’s home page. And when I say talented, I mean “genius”… Those are the founding fathers of CS; those are the Ones who shift right four times the price tags of their supermarket nachos to know how much their 3 friends will owe them… In their head of course… Doing so, I eventually find myself hitting their own personal page, clicking that mouse link with as much enthusiasm as a little boy opening up his first nintendo…

And everytime, it happens… I find myself mixed with feelings of admiration and deception. Something like : “this guy is a genius… but he sure has an ugly personal webpage…”

Why is that??

Those guys are pioneers, they have proved to be inovative and creative… When one would expect to see some webpage using advanced techniques, stunning css, unique algorithms, or a perfect mix of simplicity, beauty and speed; we usually end up seeing repulsive design. Instead of seeing an echo of their genius, we see our screen filled up with 100% width / height text, using a max of 3 tags (”a”, “li” & “p”), and webpages that smell like old history books, the web’s first steps, my first 2400bps modem, …

Apart from the nostalgia it creates, I can understand how such a page can have some advantages : “who cares about heavy pages, buggy javascripts that slow down everything, bling-bling UIs that compensates for crappy contents? Let’s make a simple page, it’s fast, easy to maintain, it works everywhere the same, it’s stable, etc…” But still people, there is a balance in all things, even in web design… A little padding here, a little line-height there, some fonts, colors, divs, a bit more space and TADA! Your page becomes so much easier to read, much more attractive and friendlier. All of those little details that keep the speed and the functionalities while bringing a bit of warmth to a rich-yet-cold webpage.

Or has it become a stamp for quality? An ugly, old website now stands for quality content… ? It seems that’s the case for a couple of amazing books, including SICP… :

Or is it a question of humility? pride? I display myself as somewhat simple while having done extraordinary things?

Anyways… I’m not here to judge, I don’t have a personal web page! just this simple wordpress generated blog… I just found it somewhat funny. See it for yourself :

  • english
  • french

Les blocs conditionnels If, Case, etc…

Il m’arrive souvent de voir des blocs de code de contrôle inutilement complexes, mais je suis tombé récemment sur un bloc qui m’a particulièrement bluffé :

  1. if( iNb < 100 ) {
  2.   if( iNb > 50 ) {
  3.      [bloc 1]
  4.   } else if( iNb > 30 ) {
  5.      [bloc 2]
  6.   } else if( iNb > 10 ) {
  7.      if( iNb <= 20 ){
  8.         [bloc 3]
  9.      } else {
  10.         [bloc 4]
  11.      }
  12.   }
  13. }

Lorsque l’on remplit les [...] avec des dizaines de lignes de code (ce que je déconseille aussi fortement), on se retrouve vite à oublier le contrôle mal organisé qui se planque dans le code…

Il existe une pratique simple, qui doit être mise sous forme de théorie quelque part sur le net, qui consiste d’abord à visualiser les ensembles sur lesquels on fait le contrôle. Ici, on peut facilement déterminer 4 ensembles que l’on essaye de distinguer:
iNb dans ]50, 100[ (bloc 1)
iNb dans ]30, 50 [ (bloc 2)
iNb dans ]20, 30 [ (bloc 3)
iNb dans ]10, 20 [ (bloc 4)

Ensuite, le principe de base est le suivant : on conditionne sur le plus grand conteneur d’abord, et on restreint par la suite. On se retrouve alors avec un code beaucoup plus clair :

  1. if( iNb < 100 ){
  2.   [bloc 1]
  3. } else if( iNb < 50 ) {
  4.   [bloc 2]
  5. } else if( iNb < 30 ) {
  6.   [bloc 3]
  7. } else if( (iNb < 20) && (iNb > 10) ){
  8.   [bloc 4]
  9. }

Autre possibilité, encore plus lisible je trouve :

  1. if((iNb > 50) && (iNb < 100)){
  2.   [bloc 1]
  3. } else if ((iNb > 30) && (iNb < 50)){
  4.   [bloc 2]
  5. } else if ((iNb > 20) && (iNb < 30)){
  6.   [bloc 3]
  7. } else if ((iNb > 10) && (iNb < 20)){
  8.   [bloc 4]
  9. }

On redécrit les ensembles directement au sein des conditionnelles, de manière à ce que l’on ait pas à retrouver la condition précédente pour bien comprendre l’actuelle… Enfin tout du moins c’est ce que je pense…

Bien implémenter son singleton

Lorsque plusieurs membres d’un programme vont utiliser les mêmes données, on se retrouve confronté au choix entre le singleton et la classe statique. Ce choix est assez important, et dépend entièrement de la visibilité de ces données. Il sera parfois plus judicieux d’utiliser une classe statique qu’un singleton. Par exemple, en programmant un jeu de tennis en C# (que je n’ai pas encore complètement terminé d’ailleurs…), j’avais besoin d’accéder souvent au calendrier ATP. La visibilité de ce calendrier était pratiquement globale, beaucoup de classes devaient y avoir accès et il était plus facile d’en faire une classe statique avec ses méthodes statiques… Dans d’autres cas, le singleton était plus approprié. Il n’est pas limité en accès aux membres statiques, il est sérializable, etc…

Récemment, en révisant du code sur un projet au boulot, je suis tombé sur des mauvaises implémentations de singletons de ce type :

  1. public class SinglePart {
  2.      private static SinglePart oPart = null;
  3.  
  4.      public static SinglePart getSinglePart() {
  5.          if (oPart == null){
  6.              oPart = new SinglePart();
  7.          }
  8.          return oPart;
  9.      }
  10.  }

La classe fonctionnait bien, puisque le programmeur avait fait attention à ne l’instancier qu’une seule fois. En fait, il y a 2 erreurs avec cette implémentation :

- Il manque un constructeur privé pour remplacer le constructeur public et donc éviter une autre instanciation via ce dernier.
- Rien n’assure que le singleton ne soit créé deux fois en même temps par deux threads séparés.

La solution consiste donc à ne pas oublier le constructeur privé, ainsi que l’utilisation du mot clef synchronized :

  1. public class SinglePart {
  2.      private static SinglePart oPart = null;
  3.  
  4.      // constructeur privé
  5.      private SinglePart() {}
  6.  
  7.      public synchronized static SinglePart getSinglePart() {
  8.          if (oPart == null){
  9.              oPart = new SinglePart();
  10.          }
  11.          return oPart;
  12.      }
  13.  }

Java : quelques bons réflexes à avoir (3)

Autre petit réflexe à avoir, et ceci ne se limite pas seulement au Java… La plupart du temps, on fait nos tests de manière simple et logique :

  1. if (sString.equals("machaîne")) {
  2.     // faire quelque chose
  3. }

ou encore…

  1. if (iNb == 2) {
  2.     // faire quelque chose
  3. }

La encore, un bon réflexe à avoir est d’inverser le test, de manière à comparer notre constante / chaîne à notre variable :

  1. if ("machaîne".equals(sString)) {
  2.     // faire quelque chose
  3. }

ou encore…

  1. if (2 == iNb) {
  2.     // faire quelque chose
  3. }

En effet, en prenant cette habitude, on ne lèvera jamais d’exception de type NullPointerException lorsque les variables sont mauvaises.

Java : quelques bons réflexes à avoir (2)

Dans la suite des évènements, je suis tombé sur de nombreuses conversions de types. Elles étaient bien sur contrôlées, ou du moins… La plupart étaient codées comme ceci:

  1. public int strToInt(String sString) {
  2.    try {
  3.       int iNb = Int.parseInt(sString);
  4.       return iNb;
  5.    } catch (Throwable t) {
  6.    }
  7. }

On pourrait croire que le code est juste. D’ailleurs, il marchait encore une fois très bien… Lorsqu’on lui demandait de faire ce qu’on attendait de lui. En fait, ce code peut être assez dangereux: si une exception est levée, il n’y a aucun moyen de le savoir, aucun avertissement pour dire que iNb n’a pas été initialisé correctement. Et si sString était nul?

Ce genre de problème se retrouve souvent, et j’ai malheureusement vu énormément de blocs try/catch vides, laissant au futur utilisateur un code ne marchant que dans certains cas…

La gestion des exceptions est quelque chose d’assez méticuleux en Java. On ne veut pas trop alourdir le code avec des nombreux blocs try/catch. Toutefois, ce genre d’erreur assez classique engendre facilement des problèmes par la suite. De nombreuses fois, le développeur mange les exceptions en laissant vide les blocs catch, un peu comme si ils avaient été créé un peu par hasard.

Il faut au moins enregistrer quelque part que l’exception a été levée (log d’erreur, message…). Le bon réflexe à avoir est bien sur de renvoyer l’exception.

Java : quelques bons réflexes à avoir (1)

Depuis peu de temps, je suis arrivé sur un projet J2EE pratiquement terminé. Mon but était de comprendre le fonctionnement de l’équipe, la structure du programme et du projet, d’en analyser les atouts et les défaillances. Pendant cette période, j’en ai profité pour regardé rapidement le code source. J’ai décidé de cataloguer les quelques petits problèmes que je voyais, tout en y apportant des solutions. Ce sont des petits reflexes à avoir lorsque l’on travaille en Java.

Attention au ramasse-miette

Demandez à n’importe quelle personne ayant travaillé en C/C++ et évolué sur du Java la chose qu’il a préféré, et cette personne vous répondra le ramasse-miette. C’est vrai qu’en C# comme en Java, le ramasse-miette est quelque chose d’exceptionnel, un aspect un peu magique qui rend la vie plus facile et le code plus souple. On n’a tout à coup plus à tenir compte de la gestion de la mémoire, ce qui peut représenter un énorme gain de temps, de production, et d’apétit le soir en rentrant chez soi.

Toutefois, le ramasse-miettes ne va pas s’occuper de tout. En effet, il existe des objets (pointeurs, poignées sur les fichiers, sémaphores, etc…) qui ont leur propres fonctions .close(), .destroy() ou .release() qu’il ne faut pas oublier d’appeller. Bien entendu, tout est automatiquement nettoyé par le dernier finalizer lorsque le programme se termine… Mais bien souvent, il vaut mieux s’en occuper de suite. (Imaginez un serveur multi-thread qui fait une fuite à chaque requête HTTP, la mémoire sera vite débordée…)

Ainsi, je suis tombé sur ce code:

  1. public static Properties loadFile(String sFileName) throws IOException {
  2.    FileInputStream sInputStream = new FileInputStream(sFileName);
  3.    Properties oProps = new Properties();
  4.    oProps.load(sInputStream);
  5.    sInputStream.close();
  6.    return oProps;
  7. }

Ce code compile parfaitement. De plus, l’application tournait aussi bien. Seulement, que se serait-il passé si la fonction load(sInputStream) avait relevé une exception? Le close() n’aurait pas eu lieu, et on aurait eu une fuite… jusqu’au dernier finalizer.

En fait, la solution consiste à utiliser un bloc try/finally pour vérifier que la fonction ne renvoie pas d’erreur :

  1. public static Properties loadFile(String sFileName) throws IOException {
  2.    FileInputStream sInputStream = new FileInputStream(sFileName);
  3.    try{
  4.       Properties oProps = new Properties();
  5.       oProps.load(sInputStream);
  6.       return oProps;
  7.    } finally {
  8.       sInputStream.close();
  9.    }
  10. }

Ainsi, le close() se fera toujours dans de bonnes conditions. J’avoue que cette pratique n’est pas très facile à mettre en oeuvre, surtout qu’elle risque facilement d’imposer la lourdeur des blocs try/finally imbriqués. On pourrait aussi revenir à une solution qui s’apparente au C/C++ et conserver quelque part une trace des différentes allocations mémoire pour les libérer manuellement, mais on perd l’intéret du ramasse-miettes… A méditer!