sabato 29 marzo 2008

politiche economiche e fiscali for dummies

Della serie: "Io sono di parte, ma le cifre no!"
Bel lavoro!

venerdì 22 febbraio 2008

yaari spam (capitato anche a me)

Mi sono iscritto a questo sito di social network (yaari) causa di un "invito" arrivatomi via mail presumibilmente da una persona che conosco.
Effettivamente i dati coincidevano quasi.
Errore: dopo che mi sono iscritto, sono partiti altrettanti falsi inviti a mio nome verso indirizzi presi dalla mia rubrica (tra cui un mio secondo account).

A quel punto mi sono disiscritto (o almeno spero) ed ho invitato i miei amici a cestinare questo tipo di inviti.

Probabilmente anche io sono incappato nel problema quanto descritto da questo articolo.

Ovviamente cercano di fare piu' utenti possibili, ma questa politica scredita i siti di social network (anche quelli piu' seri), e poi non so fino a che punto funzioni davvero.

Immagino che le segnalazioni anti-spam ed anti-abuse che ne seguono finiscano per far aggiornare i filtri anti-spam dei vari providers, in modo da filtrare gli inviti provenienti da quel sito, compresi quelli leciti (volontari).

(p.s. pero' una cosa buona come conseguenza e' capitata: l'invito involontario e' arrivato a persone che non sentivo da anni, le quali, pur declinando, hanno sentito il bisogno di rispondere, insomma ho avuto occasione per riallacciare dei contatti ;-) )

lunedì 18 febbraio 2008

Bash: come capire quale .jar contiene una certa classe

Se sei nella directory contenente i jar da cercare:

for i in `ls *.jar`; do echo $i; jar -tvf | grep eventuale.package.NomeCasse; done;

Se i jar possono essere in diverse sottodirectory a partire dalla directory corrente:

for i in `find . -name | egrep ".*\.jar$"`; do echo $i; jar -tvf | grep eventuale.package.NomeCasse; done;


(Non ho provato su Windows)

martedì 12 febbraio 2008

martedì 5 febbraio 2008

Torneo Refactoring parte 2

Sempre a riguardo della prova relativa al torneo refactoring, provo a continuare con la mia proposta di soluzione, iniziata nel post precedente.

la prova03 evidenzia che nella classe printSlip la evaluate non sarebbe testabile perché usa lo standard output:
public void evaluate(Object aResource) {
System.out.println(((Resource)aResource).name());
System.out.println(((Resource)aResource).salary());
}
incidentalmente questa implementazione corrisponde al layout sintetico, descritto più avanti, che ha output tipo:
"Francesco\n1000.00\n"

Esiste anche un layout più dettagliato, che viene chiesto di implementare:
Il layout dettagliato della busta paga di una risorsa ha il seguente formato: "Nome: , Salario: \n". Per esempio, per Francesco con salario 1000 euro, il sistema produrrà: "Nome: Francesco, Salario: 1000.00\n"

Abbiamo due obiettivi:
1)rendere testabile la printSlip,
2)poter gestire più di un layout.

Per il n.1, astraggo sulla modalità di gestione dell'output, quindi la "stampa" userà un generico OutputStreamer (interfaccia che creiamo poi, che prescrive un unico metodo "print") e posso usare un mio OutputStreamer "fittizio" (mock) solo per i test.

Per il n.2, rendo astratta la classe PrintSlip stessa, delegandone la concreta implementazione della evaluate (sintetica o analitica), che implementeranno i due di layout:


public abstract class PrintSlip implements Block {

protected OutputStreamer outputStreamer = new OutputStreamer()
{
public void print(Object object) {
System.out.print(object);
}
};

public void setOutputStreamer(OutputStreamer outputStreamer) {
this.outputStreamer=outputStreamer;
}

public OutputStreamer getOutputStreamer() {
return outputStreamer;
}

public abstract void evaluate(Object aResource);

}


Implementazine "sintetica":


public class PrintSlipImplSyntetic extends PrintSlip {
public void evaluate(Object aResource) {
outputStreamer.print(((Resource)aResource).name());
outputStreamer.print("\n");
outputStreamer.print(((Resource)aResource).salary());
}
}



Implementazione "analitica":



public class PrintSlipAnalitic extends PrintSlip{
public void evaluate(Object aResource) {
outputStreamer.print("Nome:"+((Resource)aResource).name()+",Salario:"+((Resource)aResource).salary()+"\n");
}
}




Per testare queste due novità mocko la evaluate in modo che l'output sia diretto in una stringa:


@Test
public void testPrintSlip() {
Contract nov1 = new Contract(nov1st2005());

PrintSlip printSlip = new PrintSlipImplSyntetic();

printSlip.setOutputStreamer(
new OutputStreamer() {
public void print(Object object) {
result += object;
}
}
);

MockedEmployee employee1 = new MockedEmployee("Francesco", nov1);
employee1.setPrintSlip(printSlip);
employee1.printSlip();
String results = printSlip.getOutputStreamer().getResult();
assertEquals("Francesco\n1024.89",results);

}



@Test
public void testPrintSlipAnaliticWithFactory() {
Contract nov1 = new Contract(nov1st2005());

PrintSlipFactory factory = new PrintSlipFactory();
factory.setCurrentLayout(PrintSlipFactory.ANALYTIC);
PrintSlip printSlip = factory.getPrintSlipWithCurrentLayout();

printSlip.setOutputStreamer(
new OutputStreamer() {
public void print(Object object) {
result += object;
}
}
);

MockedEmployee employee1 = new MockedEmployee("Francesco", nov1);
employee1.setPrintSlip(printSlip);
employee1.printSlip();
String results = printSlip.getOutputStreamer().getResult();
assertEquals(results, "Nome:Francesco,Salario:1024.89\n");
}






Btw sia in questa prova (prova03) che in quella precedente sembra che si suggerisca di incapsulare le PrintSlip e InForce per rendere alcuni oggetti meno... "tristi"

Io le ho spostate entrambe in Resource:


abstract public class Resource {
protected Block printSlip = new PrintSlipImplSyntetic();

public boolean isInForce()
{
InForce inForce = new InForce();
return inForce.is(this);
}

public void setPrintSlip(PrintSlip printSlip)
{
this.printSlip=printSlip;
}

public Block getPrintSlip()
{
return printSlip;
}

public Resource(String name, Contract contract) {
_name = name;
_contract = contract;
}

abstract public double salary();

public Contract lastContract() {
// Semplifichiamo :) la ricerca dell'ultimo contratto
return _contract;
}

public String name() {
return _name;
}

public String toString() {
return _name + ":" + _contract + ".";
}

private String _name;
private Contract _contract;

public void printSlip() {
printSlip.evaluate(this);
}

}


In questo modo il test precedente può diviene:


@Test
public void testPrintSlipDefaultWithFactory() {
Contract nov1 = new Contract(nov1st2005());

PrintSlipFactory factory = new PrintSlipFactory();
factory.setCurrentLayout(PrintSlipFactory.SINTETIC);
PrintSlip printSlip = factory.getPrintSlipWithCurrentLayout();

printSlip.setOutputStreamer(
new OutputStreamer() {
public void print(Object object) {
result += object;
}
}
);

MockedEmployee employee1 = new MockedEmployee("Francesco", nov1);
employee1.setPrintSlip(printSlip);
employee1.printSlip();
String results = printSlip.getOutputStreamer().getResult();
assertEquals(results, "Francesco\n1024.89");

}


posto, comunque, che abbia preso come decisione di adottare una factory che consenta di settare un layout, e restituire poi la printSlip relativa al layout così settato:



public class PrintSlipFactory {
public static String SINTETIC="SINTETIC";
public static String ANALYTIC="ANALYTIC";
private OutputStreamer currentOutputStreamer= new OutputStreamer() {
public void print(Object object) {
System.out.print(object);
}
};

private String currentLayout="SINTETIC";

private static HashMap mapLayouts=new HashMap();
static {
mapLayouts.put("SINTETIC",PrintSlipImplSyntetic.class);
mapLayouts.put("ANALYTIC",PrintSlipAnalitic.class);
}

public void setCurrentLayout(String layout) {
this.currentLayout = layout;
}

public void setCurrentOutputStreamer(OutputStreamer outputStreamer)
{
this.currentOutputStreamer=outputStreamer;
}

public PrintSlip getPrintSlipWithCurrentLayout() {
try {
PrintSlip toReturn = (PrintSlip)((Class)mapLayouts.get(currentLayout)).newInstance();
toReturn.setOutputStreamer(currentOutputStreamer);
return toReturn;
} catch (Exception e)
{
// unable to set layout
}
// default
return new PrintSlipImplSyntetic();
}
}




Ultima cosa, in relazione alla gestione dell'output su file di testo, penso ad una logica che sfrutti l'outputStreamer pensato per gestire il mock, e faccio un test allo scopo per vedere se può funzionare:


@Test
public void testPrintSlipAnaliticWithFactoryFileTextOutputStreamer() {
Contract nov1 = new Contract(nov1st2005());

PrintSlipFactory factory = new PrintSlipFactory();
factory.setCurrentLayout(PrintSlipFactory.ANALYTIC);
PrintSlip printSlip = factory.getPrintSlipWithCurrentLayout();

final MockedEmployee employee1 = new MockedEmployee("Francesco", nov1);

printSlip.setOutputStreamer(
new OutputStreamer() {
public void print(Object object) {
try {
File outputFile = new File("./" + employee1.name());
FileOutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(((String) object).getBytes());
outputStream.flush();
outputStream.close();
}
catch (Exception e) {
fail(e.toString());
}
}
}
);

employee1.setPrintSlip(printSlip);
employee1.printSlip();

File file = new File("./" + employee1.name());
assertTrue(file.exists());
file.delete();

}




Infine arricchisco la classe department (che contiene una collezione di cui esegue la printSlip rispetto a tute le risorse in forza), in modo che questa stessa classe essa stessa possa gestire i layout e l'OutputStreamer:





public class Department {

private PrintSlipFactory printSlipFactory = new PrintSlipFactory();

public void setPrintSlipLayout(String layout) {
printSlipFactory.setCurrentLayout(layout);
}

public void setPrintSlipOutputStreamer(OutputStreamer outputStreamer) {
printSlipFactory.setCurrentOutputStreamer(outputStreamer);
}

public Department(List resources){
_resources = resources;
}

public void printSlips() {
new OrderedCollection(_resources).select(new InForce()).forEachDo(printSlipFactory.getPrintSlipWithCurrentLayout());
}

private List _resources;
}




Mancano la parte R5 ed R6 della prova03, ed infine la prova4.

Al prossimo post, magari.

Bye.

sabato 2 febbraio 2008

Torneo Refactoring

E' partito un torneo di refactoring.

Non partecipando, comunque ho deciso di affrontare il problema, per il momento commento come avrei affrontato la prova01:

Il codice e' versionato nel repos. aziendale.

prima di fare il refactoring richiesto, che chiede di sfruttare la somiglianza tra evaluate e forEachDo, creo dei test appositi per essi, e poi rifattorizzo, e verifico che i test passano anche dopo il refactoring.

Per testare la forEachDo:
mi appoggio ad una implementazione di Block che implementa la evaluate concatenando i toString degli oggetti processati in una unica stringa globale.
Se applico la evaluate con questa implementazione di Block, ad una collezione contenente "first" e "second" mi aspetto che dopo il test la stringa globale abbia concatenato "first" e "second".

public class BlockImplForTest implements Block {
public static String references="";
public static void reset() {
references="";
}

public void evaluate(Object object)
{
references+=object.toString();
}
}

Il test e' il seguente:

@Test
public void testSelect() {
OrderedCollection col = new OrderedCollection();
col.add("first");
col.add("second");

Block stringRefAppender=getFreshBlockImplForTest();
col.forEachDo(stringRefAppender);

assertEquals(BlockImplForTest.references,"first"+"second");
assertFalse(BlockImplForTest.references.equals("wrong"));

}

Per rendere piu' evidente che Il Block che uso deve essere "fresco", lo reperisco tramite questo metodo che fa anche un reset dello stato:

BlockImplForTest getFreshBlockImplForTest() {
BlockImplForTest.reset();
return new BlockImplForTest();
}

Forse, come design, e' discutibile aver usato una variabile globale, ma allo scopo del test va piu' che bene.

Il test del select crea una classe anonima che implementa il PredicateBlock in modo che che la is restituisca true solamente se la stringa vale "second".
In questo modo, mi aspetto che la lista filtrata attraverso questo PredicateBlock contenga solamente la stringa second. Sfrutto parte della logica del precedente test per scandagliare la collezione restituita e verificare che contenga solamente "second".

@Test
public void testSelector() {
OrderedCollection col = new OrderedCollection();
col.add("first");
col.add("second");

Block stringRefAppender=getFreshBlockImplForTest();

assertEquals("",BlockImplForTest.references);
PredicateBlock getOnlySecond= new PredicateBlock()
{
public boolean is(Object object) {
return "second".equals(object);
}

};

OrderedCollection ordCol = col.select(getOnlySecond);
ordCol.forEachDo(stringRefAppender);
assertEquals("second",BlockImplForTest.references);

}

Il test ci assicura che l'attuale implementazione dei metodi di OrderCollection fanno quello che ci aspettiamo, ed ora la si rifattorizza cercando di sfruttare la somiglianza tra forEachDo e select.
Entrambe eseguono la scansione della collezione, solo che una esegue una certa operazione, e lo fa su tutti gli elementi, senza restituire nulla, l'altra restituisce una sottocollezione di tutti i membri della collezione che soddisfano un certo predicato.

Ragionando un attimo, dal punto di vista logico possono essere due casi particolari di una unica operazione che scandisce gli elementi , valuta il predicato, esegue l'operazione ed (eventualmente) restituisce gli elementi processati.

Il caso particolare della forEachDo e' che il predicato restituisce sempre true, che non ci interessa utilizzare il valore restituito, mentre il caso particolare della select e' che la evaluate non esegue nulla.

La rifattorizziamo dunque creando due implementazioni di Block e PredicateBlock in accordo con questi due casi particolari:

1) Creiamo il Block e il PredicateBlock corrispondente ai casi particolari appena discusi:

private static final PredicateBlock passesAll =
new PredicateBlock() {
public boolean is(Object object) {
return true;
}
};

private static final Block neuterBlock =
new Block() {
public void evaluate(Object object) { }
};


2) Aggiungiamo un metodo "evaluate and select":

private OrderedCollection evaluateAndSelect(PredicateBlock pb, Block b)
{
OrderedCollection result = new OrderedCollection();
Iterator iterator = _items.iterator();
while(iterator.hasNext()) {
Object object = iterator.next();
if (pb.is(object)) {
b.evaluate(object);
result.add(object);
}
}
return result;
}

3) Trasformiamo la ForEach e la Select in modo che siano appunto casi particolari dell'utilizzo di evaluateAndSelect sfruttando le implementazioni "neutre" di Block ed PredicateBlock:

public OrderedCollection select(PredicateBlock aBlock) {
return evaluateAndSelect(aBlock,neuterBlock);
}

public void forEachDo(Block aBlock) {
evaluateAndSelect(passesAll,aBlock);
}

sabato 29 dicembre 2007

Attributi per dichiarare le relazioni tra diverse rappresentazioni concrete di un tipo

Nel testo "Structure and Interpratations of Computer Programs", c'è una sezione che tratta di rappresentazioni multiple per dati astratti, con l'esempio delle due possibili rappresentazioni dei numeri complessi: forma polare e forma cartesiana, o rettangolare.

Vi è una corrispondenza biunivoca tra le due rappresentazioni, e la conversione da una rappresentazione all'altra è possibile sfruttando le seguenti relazioni:





Ho creato un progettino (in java) che investiga su questo argomento.

Una factory restituisce una rappresentazione concreta piuttosto che un'altra e lo fa reperendo i mapper che associano una rappresentazione ad un'altra.

Ogni costruttore di ogni implementazione, in modo dichiarativo, ovvero tramite attributi, mostra di essere mappabile in altri costruttori. Sa come trasformare la n-pla di parametri di inizializzazione nella equivalente n-pla usata da un altro costruttore e/o da un'altra implementazione.

Un complesso è definito come segue.

public interface ComplexNumber {
public double getReal();
public double getImg();
}

Il come costruirlo lo gestiremo nella factory.

Abbiamo le due seguenti implementazioni, Cartesiana e Polare:
public class ComplexNumberCartesian implements ComplexNumber {
protected double real;
protected double img;

@instanceConverter(instanceConverterMap = CartesianToPolarMapper.class)
public ComplexNumberCartesian(double real, double img) {
this.real=real;
this.img = img;
}

public double getReal() {
return real;
}

public double getImg() {
return img;
}

...


}





Polare:

public class ComplexNumberPolar implements ComplexNumber {
protected double magnitude;
protected Angle angle;

protected double real;
protected double img;

@instanceConverter (instanceConverterMap = PolarToCartesianMapper.class)
{
this.magnitude = magnitude;
this.angle = angle;

this.real = magnitude*Math.cos(angle.getValue());
this.img = magnitude*Math.sin(angle.getValue());
}

public double getReal() {
return real;
}

public double getImg() {
return magnitude*Math.sin(angle.getValue());
}


public boolean equals(Object object)
{
...
}

public int hashCode()
{

}
public String toString()
{
}
}

Nel costruttore abbiamo l'attributo @instanceConverter, che indica a sua volta la classe mapper, che associa a (real, img), l'equivalente coppia (ampiezza,angolo).

Ecco la definizione di questa annotation:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.CONSTRUCTOR)
public @interface instanceConverter {
Class instanceConverterMap() default IdentityToObject.class;
}

Identity è il caso banale appunto dell'identità.

Noi sfruttiamo il mapper dalla forma cartesiana (o rettangolare) a quella polare:

public class CartesianToPolarMapper implements WrapperToObject{
public Wrapper getWrapperForClassConstructorWithParameters(
Class targetClass,
Class targetParamsTypes[],
Class[] originParamsTypes)
{

if (targetClass.equals(ComplexNumberPolar.class)) {
return new CartesianToPolar();
}
throw new RuntimeException("wrapper not defined for the target class");
}
}

In teoria la conversione specifica dipende anche dal tipo di costruttore della classe target invocato, e quindi si specifica anche il targetParamsType che è un array di classi (che consente di reperire il costruttore che accetta quelle classi come parametri).

Questo non viene considerato nel nostro caso perché abbiamo un solo costruttore per Polar.

Viene restituito un "wrapper", che è il seguente:

public class CartesianToPolar implements Wrapper {
public Object[] wrap(Object[] object) {
return new Object[] {Math.sqrt((Math.pow((Double) object[0],2.0))+Math.pow((Double) object[1],2.0)),new Angle(Math.atan2((Double) object[1], (Double) object[0]))};
}
}


Il wrapper inverso, cioè da Polare a Cartesiano, che può essere reperito tramite l'annotazione associata al costruttore della implementazione polare, è il seguente:


public class PolarToCartesian implements Wrapper{
public Object[] wrap(Object[] object) {
return new Object[]{(Double)object[0]*
Math.cos(((Angle)object[1]).getValue()),
(Double)object[0]*Math.sin(((Angle)object[1]).getValue())};
}
}


La factory sfrutta queste informazioni:


public class ComplexNumbersFactory {
....
public static ComplexNumber getComplexFromCartesianPar(double first ,double second)
{
if (CARTESIAN.equals(implementation))
{
return new ComplexNumberCartesian(first,second);
}

if (POLAR.equals(implementation))
{

ComplexNumber converted = (ComplexNumber) Utilities.getInstanceOfThisActualGivenConstructorOfOther(
ComplexNumberPolar.class,ComplexNumberCartesian.class,
new Object[]{first,second},
new Class[]{double.class,double.class},
new Class[]{double.class,Angle.class});
return converted;
}
throw new RuntimeException("unadmitted implementation mode "+implementation);
}

}

Questo è il codice che reperisce il tutto reperisce il codice di conversione, esegue la conversione, e restituisce l'equivalente istanza nell'oggetto target:


public static Object getInstanceOfThisActualGivenConstructorOfOther(
Class targetClass,
Class originClass,
Object[] instanceOriginCompatible,
Class[] instanceOriginClasses,
Class[] instTargetClass)
{
try {
Constructor constructor = originClass.getConstructor(instanceOriginClasses);
WrapperToObject wrapper = (WrapperToObject) constructor.getAnnotation(instanceConverter.class).instanceConverterMap().newInstance();
Object[] convertedPars = ((wrapper.getWrapperForClassConstructorWithParameters(targetClass, instTargetClass,instanceOriginClasses).wrap(instanceOriginCompatible)));
Constructor targetConstructor = targetClass.getConstructor(instTargetClass);
Object convertedObject = targetConstructor.newInstance(convertedPars);
return convertedObject;

} catch (Exception e) {
throw new RuntimeException(e);
}
}


Se la factory è settata in modo cartesiano, restituisce l'implementazione cartesiana senza nessuna conversione.

Se la factory è settata in modo polare, allora essa utilizza una funzione di conversine interrogando la classe ComplexNumberCartesian. Cioè chiede al suo costruttore, di fornire un wrapper in grado di eseguire il mapping tra parametri di istanza per il tipo concreto Cartesian, a parametri di istanza per il tipo concreto Polar.


Eventuali nuove estensioni non implicano cambiamenti al codice che ne faccia uso (salvo che eventualmente dover settare una proprietà), ma solo nella factory, purché queste nuove implementazioni rispettino il vincolo di dichiarare come mapparsi nelle implementazioni preesistenti (e viceversa).

La conversione, dovrebbe anche rispettare il principio che la conversione B->A applicata alla conversione A->B dovrebbe essere l'identità.

Verifichiamo con junit la creazione di due diverse implementazioni dello stesso numero, e ne testiamo l'uguaglianza:

     ComplexNumber first = new ComplexNumberCartesian(1.0,1.0);
ComplexNumbersFactory.setImplementation(ComplexNumbersFactory.POLAR);
ComplexNumber second= ComplexNumbersFactory.getComplexFromCartesianPar(1.0,1.0);

assertEquals(((ComplexNumberPolar)second).getAngle(),new Angle(Math.PI/4));
assertEquals(((ComplexNumberPolar)second).getMagnitude(),Math.sqrt(2.0));

assertEquals(first,second);


Il tipo concreto restituito dopo che abbiamo settato la factory in modo polar è appunto polare, e quindi il cast non da eccezione, ed inoltre sfruttiamo dei metodi aggiuntivi che solo il polar mette a disposizione, che sono getAngle e getMagnitude che restituiscono i valori che ci aspettiamo coerenti per il numero 1+i.


Riassumendo

Rispetto a diversi scopi un tipo concreto piuttosto che un altro può avere vantaggi di efficienza in casi particolari, ma bisogna nascondere la rappresentazione concreta per evitare che il programma chiamante dipenda da queste nuove implementazioni.

Usiamo attributi per rafforzare il legame che c'è tra classi imparentate tra loro.

"Extends" o "implements" garantisco che sintatticamente possono essere applicati a metodi deifiniti in termini della loro classe astratta (o interfaccia) ma niente di più.

Il dover mettere anche questa metainformazione dichiarativa può significare: ehi... se stai creando una nuova implementazione dovresti anche occuparti di dichiarare come fare a rendere possibile sostituire la tua implementazione al posto di quelle preesistenti, garantendo che tutto funzioni allo stesso modo di prima.


(nota: il codice versionato è stato rifattorizzato rispetto a quanto scritto in questo post, quindi potrebbe non corrispondere in nomi di classi packages).


Saluti e Buon Anno!

T.

Informazioni personali

La mia foto
I have been coding from the old C64 times. Studied Computer Sciences at Milan University. I also worked there in technical operations. Many years of experiences in coding Java and C#, desktop and web applications, with practices like unit testing. I used to play with 3d graphics in architecture recently with Blender 3d. Now I look for support related to some projects I am working on, oriented in automation in tourism related services, using functional programming framework, specifically F# and Suave.IO. email
tonyx1 (at) gmail.com github https://github.com/tonyx