giovedì 28 giugno 2012

Retribuzioni nel settore ICT

Dr. Dobb's, storica rivista del settore, ha realizzato e pubbliato un'indagine sulla retribuzione di 3500 lavoratori del mondo ICT (dallo sviluppatore al manager).
 
I Software Engineer contattati dichiarano compensi di circa 100 mila dollari! Voi come siete posizionati? :-)

L'accesso all'articolo è libero (questo il link).

mercoledì 13 giugno 2012

Usare JAXB con StAX+XPath per prestazioni e comodità d'uso (2)

Come visto nella prima parte, JAXB permette di implementare velocemente l'accesso a documenti XML, tuttavia l'approccio presenta lo svantaggio di non scalare rispetto alla dimensione dei documenti. Infatti il framework di binding cercherà di creare in memoria un insieme di oggetti Java che rappresenta interamente il documento XML e, al crescere della dimensione di questo, si scontrerà con il limite di memoria della JVM.

In molti casi i documenti XML di grandi dimensioni presentano una struttura con elementi ripetuti. E' il caso, ad esempio, di documenti XML che rappresentano dati statistici: la struttura XML che rappresenta le osservazioni è ripetuta all'interno di un tag contenitore. In questi caso è (spesso) possibile procedere a una elaborazione in streaming aggirando il problema dell'esaurimento della memoria.

Abbiamo già visto in un precedente post come utilizzare un parser StAX per accedere agli elementi di un documento XML effettuando opzionalmente anche la validazione. Ora vediamo come effettuare con JAXB l'unmarshalling dei soli elementi ripetuti, uno per volta.
In prossimi articoli analizzeremo una tecnologia alternativa per il trattamento di XML e faremo un'analisi comparativa anche in termini di prestazioni.

Supponiamo di avere il seguente documento, in cui la struttura corrispondente al tag mrSneerObj è ripetuta diverse volte.

<root xmlns="http://ict-tic.blogspot.com">
  <elements
   <mrSneerObj><!--other xml content--></mrSneerObj>
   <mrSneerObj><!--other xml content--></mrSneerObj>
   <mrSneerObj><!--other xml content--></mrSneerObj>
   <mrSneerObj><!--other xml content--></mrSneerObj>
   <mrSneerObj><!--other xml content--></mrSneerObj>
   <mrSneerObj><!--other xml content--></mrSneerObj>  
   <!--other mrSneerObj tags-->    
  </elements>
</root>

L'idea per limitare l'uso della memoria è di scorrere il documento XML con il parser StAX fino al tag relativo al primo degli elementi ripetuti (nell'esempio <mrSneerObj>). Raggiunto questo tag è possibile usare JAXB per effettuare l'unmarshalling solo della porzione di XML corrispondente a uno degli elementi ripetuti. Al termine dell'unmarshalling è possibile pilotare nuovamente il parser StAX in modo da posizionarsi al successivo elemento ripetuto, preparandosi per un nuovo unmarshalling. E così in ciclo finché tutti gli elementi ripetuti sono elaborati.

Un primo approccio per navigare con StAX tra gli elementi XML fino a raggiungere il punto di interesse (gli elementi ripetuti) è quello di guidare il parser con un automa a stati finiti. Tuttavia questo approccio è abbastanza laborioso in quanto è necessario specificare esplicitamente tutti gli stati e le transizioni in funzione degli eventi StAX. E' anche poco leggibile e manutenibile.

Una tecnologia che permette di accedere comodamente a porzioni di XML è XPath. Purtroppo le implementazioni delle specifiche XPath non sono compatibili con un parser di tipo streaming, ma richiedono un parser DOM. Questo sembra escludere la possibilità di usare implementazioni standard di XPath che, usando DOM, amplificherebbero il problema della saturazione di memoria della JVM.

Esistono tuttavia implementazioni parziali delle specifiche XPath che sono compatbili con parser di tipo streaming. Uno di questi è Simple XML Compiler (SXC). SXC è un tool che permette di creare parser XML ottimizzati. Dispone, in particolare, di un modulo XPath che è capace di pilotare un parser StAX per navigare il documento XML, individuando gli elementi XML che soddisfano una o più espressioni XPath. In corrispondenza dei punti in cui si ha il "match" dei nodi con le espressioni XPath, SXC invoca un Hanlder fornito dal chiamante.

Di seguito è mostrato come utilizzare SXC per accedere ai nodi /root/elements/mrSneerObject del documento di esempio invocando l'handler matchHandler.

XMLStreamReader streamReader = ...

XPathBuilder builder = new XPathBuilder();
builder.addPrefix("c", "http://ict-tic.blogspot.com");
builder.listen("/c:root/c:elements/c:mrSneerObj", matchHandler);
XPathEvaluator evaluator = builder.compile();      
evaluator.evaluate(
streamReader);

Ad ogni "match" l'handler di seguito riportato permette di effettutare l'unmarshalling con JAXB. A parte le porzioni di codice utilizzate per gestire gli errori di validazione (che è opzionale - l'integrazione tra StAX e MSV è descritta in questo articolo), il pattern d'uso di JAXB resta quello standard. L'unica differenza è che il riferimento al parser è recuperato dall'evento SXC e non tramite Factory.

JAXBContext jc = JAXBContext.newInstance("it.mrsneer");
final Unmarshaller u = jc.createUnmarshaller();

XPathEventHandler matchHandler = new XPathEventHandler() {
  public void onMatch(XPathEvent event) throws XMLStreamException {
    try {
      if (!listOfProblems.isEmpty()) {
        // gestisce problemi nel parsing 
        // tra due istanze di MrSneerClass
        // ...
        listOfProblems.clear();
      }

      XMLStreamReader streamReader = event.getReader();
      JAXBElement<MrSneerClass> obj;
      obj = (JAXBElement<MrSneerClass>) u.unmarshal(streamReader,  
                                                 MrSneerClass.class);
      if (listOfProblems.isEmpty()) {
           // usa obj.getValue();
      } else {
        
        // gestisce problemi durante l'unmarshalling 
        // di una istanza di MrSneerClass
        // ...
        listOfProblems.clear();      
      }
    } catch (Exception e) {
        
        // gestisce Exception
        // ...
    }
  }
}; 


martedì 12 giugno 2012

Concorso funzionario informatica Agenzia Italiana del Farmaco

E' indetto un concorso pubblico per esami per il conferimento di due posti a tempo indeterminato e pieno nel profilo di Funzionario informatico Area III posizione economica F1 nei ruoli dell'Agenzia Italiana del Farmaco.

Per l'ammissione al concorso i candidati devono essere in possesso dei seguenti requisiti di sutdio:
  1. laurea in scienze e tecnologie informatiche ovvero
  2. diploma di laurea in informatica ovvero
  3. una qualunque delle classi di lauree specialistiche o magistrali  di possibile equiparazione ai sensi del D.M. 9 luglio 2009 nonché altro titolo agli stessi equipollente per disposizione di legge anche ottenuti all'estero. 
Il link al bando.

Il periodo più favorevole ai dirigenti Italiani?

Quanti di voi hanno la sventura di aver assistito (o subìto) una discussione tra un dirigente (D) e un suo sottoposto (S) che, più o meno, ricalca i ritmi indicati di seguito?

D : "Se tu mi avessi informato prima dei problemi con l'altra area, io sarei intervenuto in modo decisivo per risolverli"
S : "In verità l'ho fatto, ti ho inviato due email a riguardo diversi mesi fa"
D : "Sì, vero, ma se tu fossi stato più chiaro nell'email, io avrei capito la criticità e sarei intervenuto"
S : "Pensavo che, durante la riunione che hai indetto a seguito della seconda email, il problema fosse stato ben analizzato e compreso da tutti noi"
D : "Se fosse stato ben analizzato e compreso da tutti noi, come sostieni tu, io l'avrei gestito!"

...e così la colpa ricade sul sottoposto oppure, se il Dirigente ha un minimo di dignità, il problema viene ridefinito come "di comunicazione", attribuendolo quindi a una entità impersonale.

Dopo aver assistito a molte conversazioni simili, sono giunto alla conclusione che il periodo più favorevole ai dirigenti italiani è quello "ipotetico del terzo tipo o dell'immpossibilità"!

Cosa è un periodo ipotetico del terzo tipo? E perché è quello più favorevole ai dirigenti italiani?

Il periodo ipotetico (da Wikipedia) è una struttura sintattica composta da una proposizione subordinata condizionale (detta anche protasi) e dalla sua reggente (detta anche apodosi). La subordinata è introdotta dalla congiunzione se ed esprime la premessa, cioè la condizione da cui dipende quanto predicato nella reggente; la reggente indica la conseguenza che deriva o deriverebbe dal realizzarsi della condizione espressa dalla proposizione subordinata.

Il periodo ipotetico viene tradizionalmente distinto in tre tipi, a seconda del grado di probabilità dei fatti indicati nella condizionale. Si parla allora di periodo ipotetico
  1. di primo tipo o della realtà quando l'ipotesi è presentata come un fatto reale o sicuro; 
  2. di secondo tipo o della possibilità quando l'ipotesi è presentata come un fatto non sicuro ma probabile;
  3. di terzo tipo o della impossibilità quando l'ipotesi è presentata come un fatto impossibile;

In particolare nel periodo ipotetico di terzo tipo la protasi è al congiuntivo trapassato e l'apodosi è al condizionale passato.

L'uso del congiuntivo trapassato fa ben capire che l'azione indicata nella premessa non è più realizzabile. Ma proprio essendo oramai irrealizzabile, questo costrutto linguistico presenta un vantaggio per il dirigente non da poco: è difficile da confutare!

venerdì 8 giugno 2012

Usare JAXB con StAX+XPath per prestazioni e comodità d'uso (1)

Una delle tecnologie Oracle per l'elaborazione di documenti XML è Java Architecture for XML Binding (JAXB).

Questo framework permette di effettuare il collegamento tra Java e XML; in particolare JAXB fornisce la possibilità di serializzare oggetti Java in XML (marshalling) e di effettuare l'operazione inversa (unmarshalling).

Immagine dal sito Oracle
Il collegamento Java-XML può essere effettuato a partire dallo Schema Xml che rappresenta il modello di documento da elaborare. Il compilatore JAXB produce le classi Java da utilizzare nell'applicazione per effettuare il marshalling e l'unmarshalling dei documenti istanza.

Supponiamo di avere il seguente documento e il relativo Schema Xml.

<root xmlns="http://ict-tic.blogspot.com">
  <elements
   <mrSneerObj><!--other xml content--></mrSneerObj>
   <mrSneerObj><!--other xml content--></mrSneerObj>
   <mrSneerObj><!--other xml content--></mrSneerObj>
   <mrSneerObj><!--other xml content--></mrSneerObj>
   <mrSneerObj><!--other xml content--></mrSneerObj>
   <mrSneerObj><!--other xml content--></mrSneerObj>  
  </elements>  
</root>

L'approccio classico di JAXB prevede, dopo la generazione delle classi a partire dallo Schema, la creazione di un contesto JAXB relativo al package prodotto dal compilatore JAXB e del relativo Unmarshaller.

L'Unmarshaller può quindi essere usato per produrre gli oggetti Java che rappresentano il documento XML. L'invocazione del metodo unmarshal accetta diverse rappresentazioni del documento XML di input. Di seguito è mostrata l'invocazione usando un reader StAX come parametro.

JAXBContext jc = JAXBContext.newInstance("it.mrsneer");
final Unmarshaller u = jc.createUnmarshaller();
JAXBElement<Root> obj = (JAXBElement<Root>) u.unmarshal(streamReader, Root.class);

L'oggetto restituito corrisponde al tag <root> e può essere navigato tramite i metodi getter come un normale POJO. Ovviamente in memoria, nella JVM, ci sarà un albero di oggetti Java collegati tra loro in modo da rappresentare tutti i nodi del documento XML di partenza.

giovedì 7 giugno 2012

E' possibile sostituire i dirigenti con un algoritmo? (1)

Osservando attentamente, per anni, il lavoro di diversi dirigenti (nel settore ICT in Italia, ma credo si possa generalizzare ben oltre questo contesto) ho riscontrato un modo di lavorare abbastanza omogeneo tra le diverse persone. Quasi come se tutti i dirigenti che ho incontrato avessero seguito lo stesso corso di "management"! Forse, semplicemente, i comportamenti da me notati sono quelli che più facilmente permettono di ottenere un avanzamento nella carriera. Credo che il modo con cui le organizzazioni selezionano il personale da promuovere alla carriera direttiva sia una delle maggiori cause della loro inefficienza.

Già dopo poco tempo di osservazione si è insinuato in me il dubbio... E' possibile sostituire questo tipo di dirigenti con un algoritmo? 

Lasciando l'analisi degli effetti di questo approccio a un prossimo post, di seguito provo a riportare i lineamenti dell'algoritmo che vorrei provare. In futuro penso di creare un progetto open source per implementare l'algoritmo (si cercano collaboratori). Il software si potrebbe validare in azienda utilizzando qualche dirigente reale come oracolo.

Il dirigente è modellato come un agent: reagisce a richieste che gli vengono sottoposte dall'esterno.

Request è la richiesta che perviene al dirigente. Una richiesta è caratterizzata da un mittente (from), una domanda a cui rispondere (question) e una data di scadenza opzionale (due_date).
 L'elaborazione delle richieste avviene nel metodo onRequest dove si innesca un ciclo in cui ciascuna iterazione si compone di due fasi (round). Durante la prima fase sono raccolte le opinioni dai propri collaboratori; mentre durante la seconda il dirigente cerca di raggiungere un consenso.

Il ciclo termina quando viene raggiunto il consenso ovvero quando il tempo a disposizione si esaurisce.

In grassetto le funzioni che saranno analizzate in un prossimo articolo.


Request : {
  from : senderDomain
  question : string;
  due_date : date;
}

onRequest(initial_req :
Request) { 
  try { 
    due_date = due_date != null ? 
             initial_req.due_date : determine_due_date(initial_req);

    priority = prioritize_request(initial_req.from, due_date);
 
    first_iteration = true;
     
    repeat {
      // first round : ask for candidate solutions
      if (first_iteration) {
        interpreted_req1 = new Request();

        interpreted_question = randomized_summarization(initial_req);
        interpreted_req1.question = ask_for_candidate_solution();
        interpreted_req1.priority = priority;
        interpreted_req1.due_date = calculate_due_date(priority, due_date);
      } else {
        interpreted_req1 = new Request();
        interpreted_req1.question = ask_for_new_candidate_solutions(response, most_frequent_res1);
        interpreted_req1.priority = priority;
        interpreted_req1.due_date = calculate_due_date(priority, due_date);
      }
         
      responses1 = send_request_and_collect_responses(team, interpreted_req1);
      most_frequent_res1 = randomized_mode_scoring(responses1);
         
      // second round : ask to to vote for the most common solution
      interpreted_req2 = new Request();
      interpreted_req2.question = proposal_with_default_on_due_date(most_frequent_res1);
      interpreted_req2.priority = priority;
      interpreted_req2.due_date = calculate_due_date(priority, due_date);
         
      responses2 = send_request_and_collect_responses(team, interpreted_req2);
      most_frequent_res2 = randomized_mode_scoring(responses2);
         
      // loop until convergence
      has_converged = most_frequent_res2 == YES;
    } until (has_converged);
     
   solution = most_frequent_res1;
  } catch (timeout) {
    // no convergence in allowed time-frame
    solution = randomized_select(most_frequent_res1, responses1);
  }
 
  reply(initial_req.from, team, solution); 

}