Avec cet article, j’aimerai revenir sur les ressorts qui poussent chaque année les développeurs du monde entier à
participer à une compétition sur la base d’un calendrier de l’avant un peu spécial : advent of code.
Depuis la version 1.4.0, le fameux plugin sbt-dependency-graph est inclus nativement dans sbt. La
chose à savoir en revanche, c’est que seule la tâche dependencyTree est utilisable dans les configurations Compile
et Test. Pour avoir accès aux autres tâches, il faut rajouter cette ligne dans project/plugins.sbt :
Qu’est-ce qui ne va pas avec ScalaTest 3.2.2 ? Dans cet article je vais revenir sur un bug introduit dans ScalaTest
et comment le comprendre, l’analyser, le résoudre et éviter qu’il ne se reproduise à l’avenir.
Après avoir présenté l’architecture hexagonale, j’ai eu le droit à une question piège de la part d’un de mes
collègues : est-ce que cette architecture est compatible avec la programmation fonctionnelle. Plus précisément : si
j’isole mes effets de bords, ai-je toujours besoin de la partie infrastructure ?
Après trois ans à ne coder que du backend, je suis un peu - voire beaucoup - rouillé sur le front. Je vais donc me
remettre un peu dans le game en commençant par décrire la prise en main d’Angular et de son getting started.
La bonne pratique sur un projet est de toujours être à jour sur ses dépendances. Or c’est assez fastidieux d’aller
vérifier ça à la main sur chacune des dépendances. C’est là que sbt-updates peut nous aider à nous en sortir.
Prometheus est une base de données timeseries qui permet de stocker des informations de métriques afin de les restituer
dans un grafana. akka-http est une librairie qui permet d’écrire des serveurs web en scala. Le but de cet article est de
montrer comment faire fonctionner ces deux technologies ensemble.
Do you know that you can turn your mac into hibernation mode whenever you want ? Not after it runs out of battery power.
With this blog entry I will describe how do I used to do this until Snow Leopard and how do I do it now with Mountain
Lion.
Last day I was unattentively listen
last podcast from javaposse and they were talking
about a great peace of software called SourceTree from
Atlassian. It gave me the idea about finding a better git browser for my mac.
Since first time I was using git I installed and started to like GitX much. I was really happy
with this simple yet powerful tool. But I was really confused about some screens on mac’s friends of mine that show me a
different GitX. I wasn’t ever understand why my last updated GitX was really something else compared by their last
updated GitX. Then time has passed.
So javaposse’s guy wake up my motivation about maybe replace GitX with a better tool. Unfortunately after a dowload and
install of source tree then extreme simplicity of GitX just missed me very much.
I decided to dig deeply into GitX versions and realize very soon that there are
many forks onto github. But how to choose the better/maintained/stable fork ?
gitx.org help me really efficiently in this task : I choose GitX (L).
At last UI reminds me what I have seen onto my friends screens.
I just started to read Domain-Driven Design by Eric Evans and some part of this book exactly describes what we do
wrong at work :
Other projects use an iterative process, but they fail to build up knowledge because they don’t abstract. Developers
get the experts to describe a desired feature and then the go build it. They show the experts the result and ask
what to do next. If the programmers practice refactoring, they can keep the software clean enough to continue
extending it, but if programmers are not interested in the domain, they learn only what the application should do,
not the principles behind it. Useful software can be built that way, but the project will never arrive at a point
where powerful new features unfold as corollaries to older features.
To avoid what it is described it seems that we need to think about building a strong model with behaviors :
Developing a knowledge-rich model. The objects had behavior and enforced rules. The model wasn’t just a data schema;
it was integral to solving a complex problem. It captured knowledge of various kinds.
It will be long and painful to catch up but I think that it worth it.
Since 1.7.11 git subtree has
been released as an official contrib. Here are commands that I had to type in into my Terminal in order to makes this
script available:
$ cd /usr/local/share/git-core/contrib/subtree
$ make
$ sudo make prefix=/usr/local/Cellar/git/1.7.12 install
I think that theses commands may be more accurate (prefix is dependent to current version of git that is currently
installed) but does the job. Hopes this help.
I have a very simple use case and I’ve come to conclusion that it is not possible to use regular expression to achieve
it.
I want to parse this string and get all numbers in it :
(string) "what is the largest number : 384, 90, 6, 15"
That is the best I can with regex:
(regexp) "what is the largest number : ((?:\d+, )+ \d+)"
(group1) "384, 90, 6, 15"
Then result have to be splitted manually. This it clearly not the best pattern matching I have ever seen.
The thing is if I reverse the first group by using a capturing group into a non-capturing group then this is the last
captured group that I just can get it back:
(regexp) "what is the largest number : (?:(\d+), )+ \d"
(group 1) "6"
(group 2) "15"
J’aime bien les singletons et je n’ai jamais vraiment pris le temps de comprendre pourquoi tant de gens déconseillent ce
design pattern (d’ailleurs
le singleton est-il un design pattern ?). J’ai eu un
exemple très récemment des dangers que cela peut provoquer.
Le projet sur lequel je travaille a une base de code plutôt impressionnante et plutôt pas trop mal testée (de l’ordre de
13000 classes et 56% de couverture de code). Tous ces tests exécutés chaque jour n’auront finalement permi de détecter
ce problème de singleton qu’aujourd’hui. Je résume la situation : une classe héritant de ArrayList<MaClasse> a été
écrite il y a plusieurs années afin d’ajouter des comportements à ce type de listes bien particulières. Jusque là :
pourquoi pas. Problème : cette classe déclare une variable de classe (donc static) nommée EMPTY. Elle permettait à
l’origine d’économiser les instanciations pour l’utilisation de la liste vide à l’extérieur. Cela ne choque pas plus de
ça - d’autant plus que des
classes du JDK offrent ce genre de
fonctionnalités.
Une chose primordiale à noter dans la documentation est la notion d’immuabilité. La liste EMPTY découverte dans le
code n’est pas immuable et n’interdit donc pas ce type d’instructions :
MaListe.EMPTY.add(newMonObjet());
Inévitablement, ce code a fini par être écrit (en fait, l’ajout dans la liste vide était fait beaucoup plus loin que
son initialisation). Et les effets de bord néfastes se sont donc produits.
Pour corriger ce problème, il est nécessaire de créer une implémentation spécifique de MaListe<MaClasse> qui soit
immuable.
Moralité : de grands pouvoirs impliquent de grandes responsabilités. Il faut toujours bien savoir ce que l’ont
fait quand on parle de singleton, surtout dans un environnement concurrent.
Un article qui couvre une autre dimension du singleton :
le lazy singleton.
C’est cet article datant d’octobre 2000 (!) qui m’a
montré la voie. Il explique en détail le mécanisme utilisé par la JVM pour invoquer le bon composant permettant
d’interpréter correctement un protocole décrit dans une java.net.URL.
Pour montrer l’utilité de ce mécanisme dans un cas de programmation orientée par les tests, je vais prendre l’exemple de
l’écriture d’une classe permettant de géocoder une adresse à travers
l’API Google Maps.
Cette API est accessible à travers le protocole HTTP. Pour ne pas solliciter constamment le service web nous allons donc
mocker l’appel en se basant sur
la documentation du service.
Remplacer le composant HTTP standard
Lors de l’appel à java.net.URL.openStream() la JVM interprète le protocole contenu dans l’URL. Si c’est "http" la
JVM instanciera par défaut une sun.net.www.protocol.http.HttpURLConnection qui gèrera le dialogue avec le serveur. En
définissant la propriété java.protocol.handler.pkgs avec un nom de package, la JVM introspectera ce package suivi du
nom du protocole et de la classe nommée Handler et devant étendre java.net.URLStreamHandler.
Cela se traduit par le code suivant dans notre test unitaire :
Cette seconde classe ouvre un fichier dont le chemin dans le classpath est la même que celle de l’URL.
Mise en oeuvre dans l’exemple
Maintenant qu’on a remplacé l’envoi d’une requête HTTP par l’ouverture d’un fichier du classpath on peut donc tester
notre service dont voici un extrait du code :
Puisque le code à tester se connecte à l’URL http://maps.googleapis.com/maps/api/geocode/xml il suffit donc maintenant
de créer un fichier nommé xml dans le package maps.api.geocode et dont le contenu sera envoyé lors de l’éxécution du
test. Ce fichier XML pourra donc ressembler à ceci :
importjava.util.regex.Pattern;importorg.hamcrest.BaseMatcher;importorg.hamcrest.Description;importorg.hamcrest.Factory;importorg.hamcrest.Matcher;publicfinalclassMatchPatternextendsBaseMatcher<String>{privatefinalPatternpattern;privateMatchPattern(finalPatternpattern){if(pattern==null){thrownewIllegalArgumentException("pattern cannot be null");}this.pattern=pattern;}@Overridepublicbooleanmatches(Objectarg0){returnpattern.matcher((CharSequence)arg0).matches();}@OverridepublicvoiddescribeTo(Descriptionarg0){arg0.appendText("String that matches pattern \"").appendText(pattern.pattern()).appendText("\"");}@FactorypublicstaticMatchermatchPattern(finalPatternpattern){returnnewMatchPattern(pattern);}}
Rappel de l’importance des dépendances dans un projet
Il fut un temps où gérer les dépendances d’un projet JEE consistait à copier tous les jars téléchargés au fil de l’eau
depuis sourceforge vers le répertoire magique de son application web : le fameux WEB-INF/lib. Le temps où les
ClassNotFoundException ou les NoSuchMethodError pouvaient arriver à tout moment (ou presque). Comment gérait-on les
migrations des librairies tierces ? Comment déterminions-nous le degré de dépendance de notre code avec les frameworks ?
Mon avis est qu’on ne s’en souciait peu – Java ayant une forte tradition de non-régression dans ses évolutions.
Tout le monde s’accorde pour dire que la puissance de la plateforme Java est justement la multitude de librairies
tierces et la réactivité potentielle d’une communauté très présente. Mais ce foisement implique de fait une gestion plus
rationnelle des liens de dépendances tissées entre ces différents produits. C’est entre autre ce que maven essaie de
faire en mettant en place des conventions dans la construction et le packaging des librairies.
Nous allons donc voir comment maven peut nous aider à optimiser voire minimiser les dépendances afin de consommer moins
d’espace mémoire dans la JVM pendant l’exécution d’un programme.
Les niveaux de dépendances définis par maven
Dans tout langage il existe plusieurs niveaux de dépendance. Nous allons voir les principaux niveaux que maven défini
pour java :
Le premier niveau est le plus important : compile. Si une dépendance n’est pas satisfaite à ce niveau, le projet ne
compile pas.
Le second niveau permet justement d’éviter les ClassNotFoundException et les NoSuchMethodError citées plus haut :
runtime. Il indique que certaines librairies tout comme votre projet peut invoquer du code de manière dynamique
(c’est la réflexion). C’est le cas de Spring-context par exemple qui essaie d’instancier des classes sur la base d’une
chaîne de caractères qu’il aura parsé dans un fichier XML.
Les troisième et quatrième niveaux ont été introduits suite aux différentes absorbtions de librairies vraiment
centrales dans le cœur de la plateforme ou bien dans le classpath global d’une JVM : system et provided. Ce niveau
ne nous intéresse pas vraiment.
Enfin le dernier niveau permet de définir des dépendances qui ne sera jamais embarqués dans les applications de
production mais sont nécessaires pour tester le logiciel : test. Le meilleur exemple de ce niveau est bien entendu
la librairie JUnit.
Pour chaque librairie (appelons-les artifact), ces dépendances permettent de construire un graphe. Ce graphe permet de
gérer de manière cohérente et reproductible les classpath lors de la compilation, les tests, la construction et
l’exécution de l’artifact. L’ensemble des dépendances contenues dans le graphe sont déterminées en résolvant les
dépendances de chacuns des artifacts récursivement en commençant par l’artifact initial et cela récursivement jusqu’à ce
qu’il ne reste plus aucune dépendance transitive à résoudre.
À la main
Commencer par supprimer toutes les dépendances (les mettre en commentaires dans le pom). Le scope le plus proche du code
étant compile, la première étape est donc de pouvoir faire compiler le projet. Toute dépendance qui n’aide pas à la
compilation doit avoir un scope différent de compile ou supprimée si elle ne sert à rien.
Une fois que le projet compile on doit pouvoir valider le scope runtime. Pour cela deux solutions plus ou moins
élégantes :
Soit votre projet dispose d’une bonne couverture de tests unitaires et l’exécution de ces tests vous permet de
valider qu’un maximum d’instanciations dynamiques seront réussies.
Soit votre projet ne dispose pas de tests unitaires auquel cas vous devrez exécuter le projet dans un environnement
proche de la production. Vous noterez qu’en fonction de l’ordre avec lequel vous ajoutez au fur et à mesure vos
dépendances il se peut que vous puissiez oublier des dépendances de niveau compile (utilisées directement dans
votre code) mais résolues par une dépendance transitive. Or cela est problématique car rien ne vous garantie que la
dépendance transitive ne soit pas un jour supprimée par la librairie qui la porte.
À l’aide d’outils
Maven dispose d’un outil très utile pour minimiser les dépendances inutiles mais aussi pour garantir une bonne qualité
des dépendances de niveau compile : il s’agit de maven-dependency-plugin.
Placez-vous dans un projet mavenisé et exécutez le goal suivant :
mvn dependency:analyze
L’exécution doit vous indiquer :
Les dépendances de niveau compile qui ne sont pas déclarées dans votre projet
Les dépendances qui sont déclarées mais qui ne servent pas à la compilation
Ces informations vous seront très utiles pour optimiser les dépendances. Exemple pour un projet fwk :
Dans ce rapport on voit que 8 dépendances sont utilisées par le code source sans être déclarées (le code compile car il
se repose sur les dépendances transitives). 13 dépendences sont déclarées alors qu’elles ne sont pas utilisées par le
code source. Il faut toutefois nuancer ce deuxième résultat : en effet seule le niveau compile est intéressant pour
cette mesure. Le niveau provided ou test reste dans bien des cas utile à déclarer.
Je viens de suivre
cette procédure. Ça a
fonctionné parfaitement pour moi.
J’apporte quelques précisions par rapport à l’article :
J’ai téléchargé
iOS 3.1.3
grâce à cette page. Le md5 du fichier est
82e93e4e51b0e4503a8165507b8a3df2.
Une fois dézippé, RecBoot propose deux
binaires. Il faut évidemment exécuter RecBoot exit only.
Ajouter les droits d’écriture de mon compte sur /etc/hosts n’a pas suffit à pouvoir l’enregistrer après
modifications avec TextEdit. J’ai dû faire un $ sudo vi /etc/hosts...
Une fois l’iPhone débloqué j’ai supprimé cette entrée dans mon fichier hosts sans que cela ne pose problème.
J’espère que ces indications supplémentaires vous permettrons enfin de récupérer votre iPhone 3G dans le meilleur de sa
forme. J’attends maintenant une mise à jour de iOS 4 en tenant compte du processeur et de la RAM vieillissants de mon
iPhone 3G.
Cette expérience de mise à jour m’aura au moins appris à ne pas faire une confiance aveugle dans les logiciels d’Apple -
confiance qu’ils avaient pourtant su gagner assez facilement lors de mon passage sur Mac OS X.