Twister's blog

Aller au contenu | Aller au menu | Aller à la recherche

mardi, avril 23 2013

PWGen

J'ai découvert aujourd'hui l'extension .pw et je n'ai pas pu m'en empêcher : http://pwgen.pw. Et voilà un petit générateur de password. :-)


vendredi, décembre 7 2012

Arretez de recoder ce qui existe !!!

Dans un moment d'égarement, je viens de regarder en détail une des classes de mon projet qui est très utilisée. StringHelper...

Les 9/10è des fonctions présentes dans cette classes font les même choses que leurs homonymes dans StringUtils de Apache.commons-lang. La même chose, non, pas tout à fait, elles le font en moins bien codées...

Je vais vous fournir ici quelques unes des gemmes de cette classe, à vous de me trouver ce qui en fait des fonctions stupides par rapport à celles de StringUtils.

Facile :
	public static final boolean isBlank(final String str) {
		return str == null || str.trim().isEmpty();
	}
Dans la famille "je ne fais pas tout à fait ce que je dis que je fais" :
	public static final int compare(final String one, final String two) {
		if(one == two) {
			return 0;
		}
		if(one != null) {
			if(two != null) {
				return one.toUpperCase().trim().compareTo(two.toUpperCase().trim());
			}
			return -1;
		}
		return 1;
	}
Suivie dans la classe par "je fais ce que je dis que je fais" :
	public static final int compareIgnoreCase(
			final String one,
			final String two) {
		if(one == two) {
			return 0;
		}
		if(one != null) {
			if(two != null) {
				return one.compareToIgnoreCase(two);
			}
			return -1;
		}
		return 1;
	}
Et par "je le fais, mais je ne le fais pas vite" :
	public static final String concat(final String...strs) {
		if(strs != null) {
			final int nbStr = strs.length;
			if(nbStr > 0) {
				final StringBuilder sb = new StringBuilder();
				for(int index = 0; index < nbStr; ++index) {
					sb.append(strs[index]);
				}
				return sb.toString();
			}
		}
		return null;
	}
Et par "alors moi je suis méga pas pressé, le CPU et la RAM je m'en cogne, alors je m'éclate" :
	public static final boolean isNumber(final String str) {
		if(str != null) {
			return str.matches("[0-9]*");
		}
		return false;
	}
Un petit peu plus compliqué :
	public static String rightPad(String stringToPad, String padder, int size) {
		if (padder.length() == 0) {
			return stringToPad;
		}
		StringBuffer strb = new StringBuffer(stringToPad);
		StringCharacterIterator sci = new StringCharacterIterator(padder);

		while (strb.length() < size) {
			for (char ch = sci.first(); ch != CharacterIterator.DONE; ch = sci
					.next()) {
				if (strb.length() < size) {
					strb.append(String.valueOf(ch));
				}
			}
		}
		return strb.toString();
	}
Une de mes préférées :
	public static <T> String loopAppender(
			final Iterable<T> iterable,
			final CollectionHelper.Stringuifier<T> stringuifier,
			final String appender
	) {
		final StringBuilder sb = new StringBuilder();
		if(iterable != null) {
			final Iterator<T> it = iterable.iterator();
			while(it.hasNext()) {
				sb.append(stringuifier.stringuify(it.next())).append(appender);
			}
			cleanStringBuilder(sb, appender);
		}
		return sb.toString();
	}

	public static void cleanStringBuilder(
			final StringBuilder sb,
			final String appender
	) {
		final int finalSize= sb.length() - appender.length();
		if (finalSize > 0) {
			sb.setLength(finalSize);
		}
	}
Suivi par une téléportation rapide dans NumberUtils (ou alors les int sont des String travesties ???) :
	private static final int minimum(final int a, final int b, final int c) {
		return Math.min(a, Math.min(b, c));
	}

Bref, arrêtez de recoder des trucs qui existent dans des jar classiques, surtout quand ces jar fournissent des méthodes bien plus efficaces que les vôtres ! Sachez reconnaître que des fonctions existantes depuis des dizaines d'années et utilisée par des dizaines de milliers de développeurs sont sûrement plus efficace que les votre! Surtout quand votre projet inclus déjà ces JARs !!! Et oui StringHelper existe alors que apache.commons-lang est dans les dépendances du projet. sic...

Cela dit c'est peut être un autre problème qui est à la source de cette aberration : les développeurs ont peut être juste oublié de chercher sur internet s'il n'existait pas déjà quelque chose qui faisait ce qu'ils voulaient faire et du coup ont codé ces fonctions la tête dans le guidon! C'est mal!


mardi, octobre 16 2012

Anonymat sur internet...

Il y a quelques années on pouvait être sûrs d'une chose : il était dur de retrouver quelqu'un sur internet. Aujourd'hui on peut être sûrs d'une autre chose : il est très aisé pour certaines personnes de vous pister sur internet !

En effet certaines sociétés sont présentes partout sur Internet et peuvent facilement vous pister d'un site à un autre. Ces sociétés ne sont pas nombreuses et la plus à même de réaliser cette exploit n'est autre que notre cher ami Google.

En effet si vous réfléchissez à votre manière de surfer vous commencez très souvent par aller sur Google et par taper une requête (google est même probablement votre page d'accueil?). Ensuite vous cliquer sur pleins de sites pour voir s'ils collent avec ce que vous cherchez, revenez sur google, repartez, etc... Google peut donc déjà posséder vos habitudes de recherches. Pour peu que vous ayez un compte Google (gmail, google+, ...) et que vous êtes connectés au moment de vos recherches Google peut même associer ces rechercher à un profile voir à une personne nommée ! Savez vous par exemple que Google garde l'historique de vos recherches par défaut ? Connectez vous sur https://history.google.com/ pour voir si vous ne retrouvez pas votre historique sur 10 ans ;). Vous pouvez bien sûr supprimer votre historique, mais bon qui vous prouve que c'est bien le cas ? Que ce n'est pas juste une question d'affichage ? Que Google ne garde pas les infos chez eux ? Rien.

Après la recherche vous vous sentez peut être libres, Google et autres ne peuvent plus vous tracer ? Détrompez vous. Avez vous noté le nombres de sites que vous visitez qui affichent des pubs Google ? Et oui ça représente un point d'entrée pour Google puisque au moment où votre navigateur affiche les pubs, Google sait quelles pubs vous avez affichées et sur quel site elles ont été affichées ainsi ils savent que vous avez visiter ce site. Vous ne vous vous êtes jamais dis que c'est bizarre le nombre de pubs que vous voyez qui collent à vos habitudes, votre mode de vie ? Et oui les pubs sont contextuelles, elles s'affichent en fonction de vos recherches, de vos visites et de tout ce qui peut servir à mieux vous cibler. Aller, allez vite bloquer les pubs avec un plugin adéquat pour votre navigateur... Et installer au moins le plugin Google qui empêche l'affiche de pub contextuelles : Plugin Google.

Certaines personnes se disent sûrement qu'il suffit de ne pas être connecté à un compte Google pour être à l'abri, qu'il suffit de couper les cookies, d'activer le mode privé du navigateur, malheureusement ce n'est pas le cas... En effet chaque personne sur internet possède une empreinte qu'il est facile de reconnaitre. La première emprunte est celle de votre navigateur, vous avez l'impression que votre navigateur n'est pas différent de celui de votre voisin d'open space ? Détrompez vous, vous avez sûrement des plugins différents, un numéro de version légèrement différent, une résolution écran différente, une liste de polices disponibles différente... tant de choses qu'un serveur web peut détecter pour vous reconnaitre. Chaque petit paramètre de votre ordinateur fait baisser l'entropie et permet de vous identifier plus facilement. Ensuite depuis l'avènement de l'ADSL de plus en plus de personnes ont une IP fixe[1] résultat c'est encore plus simple de vous identifier, aller ressortez vos modems RTC :)

Un autre moyen méconnu par les utilisateurs est l'utilisation de cookies LSO (Local Shared Object). Ce sont des cookies Flash qui ne sont pas cleanés par le navigateur, il faut utiliser un plugin dédié. Je vous invite à lire la page Wikipédia de ces petits gateaux monstres : Wikipédia. Leur gros avantages pour les pisteurs est qu'ils peuvent être lu d'un navigateur à un autre, permettant de lier vos navigateur entre eux afin de faire baisser l'entropie et donc de mieux pouvoir vous identifier.

Je n'irai pas dans les détails ici mais je vous conseil de lire l'article suivant (en anglais) pour vous faire un peu flipper : A Primer on Information Theory and Privacy. Après je vous recommande d'aller voir si votre navigateur est si unique que cela : Panopticlick.

Un dernier point auquel je pense personne ne fait trop attention, c'est Google Analytics qui permet aux webmaster d'avoir des statistiques d'utilisateurs de leurs services. Google Analytics se présente sous la forme de scripts JavaScript inclus dans les pages, ainsi ce code est exécuté par chaque personne venant sur le site. Et hop une porte de plus sur votre vie privée...

Aller bonne journée ;)

Notes

[1] Si vous ne savez pas ce que c'est, vous pouvez faire l'analogie avec une adresse postale, une adresse IP c'est votre identifiant unique sur internet qui permet de communiquer avec les serveurs


Comment {ne pas} faire un flux

J'ai récemment eu l’occasion d'implémenter l'intégration d'un flux assez conséquent : environ 4Go pour une initialisation (1 par an) puis plusieurs centaines de Mo pour les deltas hebdomadaires. Pendant les développements j'ai vu et j'ai pensé à certains trucs qu'il est bon de respecter lorsque l'on génère ou traite un si gros flux de données.

Tout d'abord il faut choisir son format. Pour ma part c'était du XML (imposé par le producteur). Il existe une multitude de format existant lisibles par une panoplie de librairies pour à peu près tous les langages. Le choix du format est fonction de ce que vous voulez (de ce que vous avez) à faire. Pour par part il fallait un format qui puisse être "lu" par un humain pour des questions d'analyse si jamais un jour l'algorithme d'intégration du flux décidait d'intégrer les choses à l'envers... ... (et de toutes façons le choix a été fait côté producteur)

Le XML est un format qui reste "humain", si ce n'est pas un de vos pré-requis optez pour des formats plus compacts, votre administrateur réseau vous remerciera sûrement et vous pourrez faire passer plus de données si jamais vous avec un très gros débit temps réel.

Un fois le format choisi il faut y mettre vos données, c'est là où il faut le plus faire attention. En effet vous aller créer un flux qui sera potentiellement consommé par n'importe qui utilisant n'importe quel langage/système donc faites attentions aux formats des données et typez les le plus fortement possible si votre format le permet (ie : ne déclarez pas tout en String dans votre XSD).

Si vous typez correctement vos données et que vous utilisez un format standard il y a de fortes chances que vous n'ayez pas à vous occuper de la sérialisation/de-sérialisation de vos données parce que la librairie que vous aurez choisie le fera très probablement à votre place (XStream en Java pour le XML par exemple). Cela à l'avantage de vous fournir à directement objets avec des champs typés et directement exploitable sans passer des heures à parser des Strings avec tous les risques que cela comporte. Cela évite donc les sorties non conformes parce que votre (dé)sérialiseur maison n'a pas lu/formaté la donnée correctement.

On pourrait parler encore des heures des flux mais ceci est le résultat de ma dernière expérience qui aurait être plus rapide à concrétiser si tout ceci avait été pris en compte. Je n'ai donc pas tout détailler mais voici d'autres point à prendre en compte :

  • Si vous êtes producteur :
    • Evitez tous les caractères inutiles comme les retours chariots (\r), les tabulations pour mettre en forme, les espaces multiples qui ne servent à rien...
    • Offrez la possibilité de compresser votre flux (avec un algo adapté comme GZip, BZip2)
    • Offrez la possibilité de ré émettre un flux
    • Prévoyez des tonnes d'exemples pour les développeurs qui consommeront votre flux.
  • Si vous êtes consommateur :
    • Faites attention à la charge que génèrera l'intégration de votre flux (insertions en base, moteur de calcul...) et décalez peut être l'intégration à des moments de la journée où la charge est plus faible.
    • Stockez l'original du flux ! Si jamais un problème arrive pendant l'intégration vous serez content d'avoir les données. Si votre flux est temps réel il serait sûrement intéressant d'avoir un 'recorder/replayer' de flux différent du système qui consomme le flux afin de pouvoir tester/développer/debugger
    • Mesurez, re mesurez, et encore... il est important de savoir qu'elle quantité de données vous recevez, combien de temps vous mettez à les lire puis à les traiter.
    • Ne faites jamais confiance au producteur s'il vous fourni des chiffres, revérifiez les ! Le flux a pu grossir depuis sa conception et les chiffres n'ont pas été remis à jour
    • Ne prenez pas pour argent comptant les dire du producteurs sur les contraintes 'fonctionnelles', 'techniques', 'sûres', 'sur la vie d'ma mère'. S'il vous garanti qu'un champs n'est jamais null ajoutez quand même le test dans votre code, s'il vous dit qu'il y a une clé unique faites quand même la votre ou vérifiez l'unicité à chaque traitement, ... bref soyez paranoïaque...

vendredi, juin 1 2012

Java code quality (Sonar, PMD, findBugs, ...)

Je viens de tomber sur quelques bugs sympa causés par un désir fou de faire baisser les niveaux d'alertes dans Sonar.

Et oui PMD (intégré à Sonar) râle lorsque l'on fait un new Integer(1). Cela dit la solution n'est pas de remplacer new Integer(1) par 1. Et oui faire ce changement la peu provoquer des problèmes. Si le new Integer(1) était un paramètre d'appel de méthode cela peut changer la méthode appelée. Dans mon cas il est arrivé sur une modification de ce genre que l'on passe d'un appel à une méthode add(Obect o, Object constraint) à add(Object o, int i) qui n'avait pas du tout les mêmes fonctions ! Et oui elles appellent toutes les deux la méthode add(Object o, Object constraint, int index)... Vous voyez où je veux en venir ??? :-)

Bref n'écoutez pas bêtement les outils de qualité de code ils peuvent vous faire faire des bétises, ou alors écoutez les bien. En l’occurrence sur une instanciation d'Integer PMD donne le message suivant :

Avoid instantiating Integer objects. Call Integer.valueOf() instead.

C'est d'ailleurs la solution sûr pour régler le warning puisque Integer.valueOf() va renvoyer un objet Integer et non un int. Son intérêt par rapport à l'instanciation brute d'un Integer et qu'il utilise un système de cache des Integers.

J'ai pu constater plusieurs commits sur d'autres projets qui, pour faire baisser des alertes sonar, ont sûrement provoqué des bugs. Par exemple un jour j'ai vu un petit rigolo s'amuser à remplacer plusieurs :

int a = 10;
StringBuffer sb = new StringBuffer();
//... bla bla ...
sb.append(" " + a);
return sb.toString();

par

int a = 10;
StringBuffer sb = new StringBuffer();
//... bla bla ...
sb.append(' ' + a);
return sb.toString();

(Là, maintenant comme ça, à chaud, vous voyez ce que ça change ? ;-))

Alors maintenant que faire, certaines modifications ont pû provoquer des bugs qui ont été fixés en amont, d'autres peuvent être toujours là. La question est : est ce qu'il faut les fixer. Essayer de les fixer pourrait provoquer d'autres problèmes (si par exemple d'autres bouts de code on été modifiés pour répondre aux modifs initiales...).

Bref ma conclusion est que ce genre d'outils c'est bien, mais qu'il faut faire attention. Rien ne remplace une charte de codage fourni au début d'un projet et à laquelle les développeurs doivent se tenir. Eventuellement il est bien d'avoir un outil de qualité qui remonte les effractions au fur et à mesure du développement. Mais déployer un tel outil quand le projet a déjà de l'âge et écouter les alertes sur le code existant peut être dangereux...


- page 1 de 33