Libellés

mardi 28 juin 2011

Compiler des fichers less -> css en Groovy

Less-css est un CSS amélioré.

Pour citer quelques exemples on peut :
- créer des variables et les réutiliser partout
- imbriquer des blocs css, dans d'autre bloc css.
- ...

Par exemple :

@import "global.less";

@size: 14px;

#col{

.odd{
color: red;
font-size: @size;
}

.even{
color: blue;
font-size: @size;
}

}


Les fichiers less sont transformés en CSS par un script js. Ce qui permet de tester en live sur son site web, mais la conversion less/css est plutôt lente.

Il est donc préférable de compiler les fichiers less avant la prod.

Je vous livre donc un code groovy qui permet très facilement de convertir un fichier less en CSS. A vous de le transformer en JAVA et de l'intégrer dans votre environnement de développement.

Pour info, il existe lessc, le compilateur less officiel qui repose sur nodeJS. Si vous ne voulez pas installer node.js, cette version Java vous plaira (elle utilise Rhino).


@Grab(group='com.asual.lesscss', module='lesscss-engine', version='1.0.43')
@GrabResolver(name='asual', root='http://www.asual.com/maven/content/repositories/releases')

import com.asual.lesscss.*

new LessEngine().compile(new File("/home/romain/Bureau/less/root.less"),new File("/home/romain/Bureau/less/root.css"));

lundi 27 juin 2011

Groovy et l'immutabilité

Depuis la version 1.8, Groovy permet de rendre des classes entièrement immutables, c'est à dire des classes qui ne peuvent pas changer d'état.

Ceci peut être pratique pour écrire du code thread safe.

Voici un exemple de classe immutable en Groovy.
PS : ne surtout pas oublier le import groovy.transform.Immutable, sinon c'est l'ancien groovy.lang.Immutable qui est utilisé (Cf : http://comments.gmane.org/gmane.comp.lang.groovy.user/55021)


import groovy.transform.Immutable

@Immutable
final class Punter {
String first
String last
Map params
}

@Immutable
final class PunterWrapper {
String name
Punter punter
}


def wrapper = new PunterWrapper(
name: 'hi',
punter: new Punter(
first: 'Foo',
last: 'Bar',
params: [k: 'value']
)
)


println wrapper

try{
wrapper.punter.params.toto = 3
}catch(Exception e){
println('Exception catched ')
}

try{
wrapper.punter.last = 'Tutu'
}catch(Exception e){
println('Exception catched ')
}

try{
wrapper.name = 'Toto'
}catch(Exception e){
println('Exception catched ')
}

PunterWrapper(name:hi, punter:Punter(first:Foo, last:Bar, params:[k:value]))
Exception catched
Exception catched
Exception catched




Mais écrire des classes immutables en Groovy peux s'avérer complexe à gérer.

Pour éviter récrire le constructeur complet de l'objet à chaque fois que l'on souhaite modifier une valeur, voici une solution que j'ai trouvé :


println new PunterWrapper(wrapper.properties + [
name: 'Titi',
punter: new Punter(wrapper.punter.properties + [
first: 'Mickael'
])
])​

PunterWrapper(name:Titi, punter:Punter(first:Mickael, last:Bar, params:[k:value]))



Un nouvel objet est créé à partir des attributs modifiés de l'ancien objet.



On peut également travailler avec les Collections de la même façon :

def list = [a: 1,b: 2,c: 3].asImmutable()
println list

try{
list​.d=4
}catch(Exception e){
println 'Exception catched'
}


def list2 = (list + [d:4]).asImmutable()
​println list2


def listMutable = list2 + [e:5]
listMutable.f = 6
println listMutable


[a:1, b:2, c:3]
Exception catched
[a:1, b:2, c:3, d:4]
[a:1, b:2, c:3, d:4, e:5, f:6]



Mais il ne faut pas oublier le asImmutable() à chaque modification de la collection.


Groovy nous donne donc quelques possibilités pour travailler dans un environnement immutable, mais ce n'est pas encore très pratique.

Scala est mieux sur ce point là.

lundi 20 juin 2011

JAVA et Groovy

Groovy est un langage de programmation, basé sur Java et s'intégrant très bien avec tout son écosystème.

Pour vanter quelques mérites de Groovy voici des exemple Groovy VS Java :



JAVA
--------
String name "World"
System.out.println("Hello " name);

GROOVY
-----------
def name "World"
println "Hello $name"


JAVA
--------
Map<StringStringparams new HashMap<StringString>();
params.put("key""value")
System.out.println(params.get("key"))

GROOVY
-----------
def params [key"value"]
println params.key



JAVA
--------
public class Customer {

    private String name;

    private int age;

    Customer({
    }

    Customer(String nameint age{
        this.age age;
        this.name name;
    }

    public String getName({
        return name;
    }

    public void setName(String name{
        this.name name;
    }


    public int getAge({
        return age;
    }

    public void setAge(int age{
        this.age age;
    }

    @Override
    public boolean equals(Object o{
        if (this == oreturn true;
        if (== null || getClass(!= o.getClass()return false;

        Customer customer (Customero;

        if (age != customer.agereturn false;
        if (name != null !name.equals(customer.namecustomer.name != nullreturn false;

        return true;
    }

    @Override
    public int hashCode({
        int result name != null name.hashCode(0;
        result 31 result age;
        return result;
    }

    @Override
    public String toString({
        return "Customer{" +
                "name='" name '\'' +
                ", age=" age +
                '}';
    }

    public static void main(String[args{
        Customer toto new Customer("Toto"7);

        Customer toto2 new Customer();
        toto2.setName("Toto");
        toto2.setAge(7);

        System.out.println(toto.equals(toto2));
    }
}


GROOVY
-----------
import groovy.transform.

def toto new Customer(name'Toto'age7)

def toto2 new Customer()
toto2.name 'Toto'
toto2.age 7

assert toto == toto2

@ToString 
@EqualsAndHashCode 
class Customer{

  String name

  int 
age


}






Comme vous le voyez, Groovy permet d'avoir une syntaxe bien plus concise que l'équivalent en Java.

Moins de code à écrire == plus facile à développer == plus facile à lire (une fois que l'on a l'habitude) == plus facile à maintenir...


Et la liste est longue des Groovyness utilisables : 
  - la gestion des collections : filtrage, trie, modification, .... (simplifié grâce à la programmation fonctionnelle) : http://groovy.codehaus.org/Collections
  - la gestion des dates : http://groovy.codehaus.org/JN0545-Dates
  - la création de script dépendant de librairies présent sur Maven : http://groovy.codehaus.org/Grape
  - éviter les null pointer exceptions avec les opérateurs ?. et ?: : http://docs.codehaus.org/display/GROOVY/Operators#Operators-ElvisOperator%28%3F%3A%29
  - la gestion des fichiers : http://groovy.codehaus.org/JN2015-Files
  - toute les exceptions sont gérées comme des RuntimeException
  - ...

Groovy est un langage qui évolue vite, actuellement nous sommes à la version 1.8. Cette version ci rajoute un certain nombre de fonctionnalités intéressantes comme le support natif du JSON, l’annotation @Log qui permet d'injecter un logger (slf4j, log4j, ...), @ToString et @EqualsAndHashCode que je viens de vous montrer et encore pleins d'autres choses merveilleuses à découvrir ici : http://docs.codehaus.org/display/GROOVY/Groovy+1.8+release+notes






Depuis plus d'un an que j'utilise groovy tous les jours, je n'ai toujours pas rencontré de bug. Nous l'avons utilisé pour des scripts, des tests et des applications en production (http://www.grails.org/). C'est un langage que je recommande vraiment. Pour un développeur Java, c'est vraiment une bouffé d'air frais.

Il n'y a pas que des avantages, Groovy est lent, mais je trouve que le temps gagné lors de la phase de développement en vaut la chandelle.

Groovy est dynamique et n'est pas fortement typé, ce qui nécessite d'écrire plus de test unitaire. C'est peut être là sont plus gros défaut. 

Néanmoins, ces problèmes disparaîtront peut être un jours car les performance de Groovy ne font que s'améliorer avec le temps. De plus groovy++ est un projet prometteur car il ajoute un typage statique et des performances équivalentes à celles de Java. Mais je ne l'ai encore jamais testé.

L'intégration avec les IDE n'est pas forcement parfaite : 
  Netbeans -> moyen, 
  IntelliJ -> excellent, équivalent à Java

Mais l'integration avec Maven ne pose aucun problème : http://docs.codehaus.org/display/GMAVEN/Building+Groovy+Projects

Concernant les tests je conseille le framework Spock, sinon un simple JUnit fait très bien l'affaire. Pour du BDD, on peut utiliser EasyB, mais je préfère quand même Spock.

Come Java, Groovy ne favorise pas l'immutabilité (contrairement à scala) est c'est bien dommage pour les applications multi-threadées.

GPars a été intégré avec Groovy depuis la version 1.8 pour simplifier la programmation multi-threadée, mais j'ai encore un peu de mal à l'utiliser. Je ne trouve pas l'API intuitive. Mais bon je vais surement m'y habitué.

Pour avoir également testé Scala quelques jours, Groovy est peut être moins puissant mais est plus facile à prendre en main lorsque l'on est habitué à Java. Mais Scala semble quand même plus robuste et plus simple pour tout ce qui concerne le développement d'applications multi-threadées, tolérantes aux pannes et scalable  : http://akka.io/

lundi 6 juin 2011

TopCoder Arena

Ce soir je vais sur le site de recrutement de Google, et dans la section Préparation de l'entretien, Google nous conseil de s’entraîner sur TopCoder Arena.

Aller je tente.

Après un processus d'enregistrement super chi..., où l'on me demande ma couleur de peau (merci les Etats-Unis) je peux enfin avoir des accès.

Top Coder Arena est une Applet Java qui affiche des problèmes informatiques à résoudre. On se croirait en cours pendant un TD d'info. L'appli permet de compiler et de tester son code avant de le soumettre.

J'ai commencé facile avec un problème à 150 points. Je vous le donne :


Problem Statement
    
***Note: Please keep programs under 7000 characters in length. Thank you


Class Name: HowEasy
Method Name: pointVal
Parameters: String
Returns: int

TopCoder has decided to automate the process of assigning problem difficulty
levels to problems. TopCoder developers have concluded that problem difficulty
is related only to the Average Word Length of Words in the problem statement:

If the Average Word Length is less than or equal to 3, the problem is a 250
point problem.
If the Average Word Length is equal to 4 or 5, the problem is a 500 point
problem.
If the Average Word Length is greater than or equal to 6, the problem is a 1000
point problem.

Definitions:
Token - a set of characters bound on either side by spaces, the beginning of
the input String parameter or the end of the input String parameter.
Word - a Token that contains only letters (a-z or A-Z) and may end with a
single period. A Word must have at least one letter.
Word Length - the number of letters in a Word. (NOTE: a period is NOT a letter)

The following are Words :
"ab", "ab."

The following are not Words :
"ab..", "a.b", ".ab", "a.b.", "a2b.", "."

Average Word Length - the sum of the Word Lengths of every Word in the problem
statement divided by the number of Words in the problem statement. The
division is integer division. If the number of Words is 0, the Average Word
Length is 0.

Implement a class HowEasy, which contains a method pointVal. The method takes
a String as a parameter that is the problem statement and returns an int that
is the point value of the problem (250, 500, or 1000). The problem statement
should be processed from left to right.

Here is the method signature (be sure your method is public):
int pointVal(String problemStatement);

problemStatement is a String containing between 1 and 50 letters, numbers,
spaces, or periods. TopCoder will ensure the input is valid.

Examples:

If problemStatement="This is a problem statement", the Average Word Length is
23/5=4, so the method should return 500.
If problemStatement="523hi.", there are no Words, so the Average Word Length is
0, and the method should return 250.
If problemStatement="Implement a class H5 which contains some method." the
Average Word Length is 38/7=5 and the method should return 500.
If problemStatement=" no9 . wor7ds he8re. hj.." the Average Word Length is 0,
and the method should return 250.
Definition
    
Class: HowEasy
Method: pointVal
Parameters: String
Returns: int
Method signature: int pointVal(String param0)
(be sure your method is public)
    


Et je vous donne ma solution.


import java.util.regex.*;

public class HowEasy{

Pattern regex = Pattern.compile("[a-zA-Z]+\\.?$");

public int pointVal(String problemStatement){
String[] words = problemStatement.split(" ");
int matchingWords = 0;
int wordLength=0;
for(String word: words){
Matcher m =regex.matcher(word);
if(m.matches()){
matchingWords++;
wordLength+=word.length();
}


}

if(matchingWords==0) return 250;

int avgWordLength = wordLength / matchingWords;
if(avgWordLength<=3){
return 250;
}else if(avgWordLength==4){
return 500;
}else if(avgWordLength==5){
return 500;
}else{
return 1000;
}


}

}


150 points / 250, c'est pas terrible, je peux mieux faire.
Je pense que j'ai oublié d'enlever les points pour calculer la longueur des mots.

A vous !!!