lunedì 23 aprile 2012

Project management (background noise)

Quanto il rumore di fondo crea "discontinuità nella gestione di un progetto".
Credo che la situazione sia comune alla maggior parte delle persone che affrontano la gestione di un proggetto.
Il fenomeno si presenta sotto parecchi aspetti e forme ma l'effetto è sempre lo stesso "allontanarsi dalla meta" sia questa la data di fine progetto sia questa una milestone.
Nel corso della mia esperienza ho imparato a riconoscere/individuare alcuni fenomeni che portano alla creazione di rumore e ad oggi ne traggo dei benefici.

Rumore causato da Attori
Durante il corso di project management più volte si è discusso di quanto uno sponsor abbia interesse nella promozione del progetto, o quanto sia necessario veicolarlo nella stessa.
Di contro è proprio lo sponsor ad essere il primo ( e in molti casi involontario ) generatore di rumore.
Nel caso specifico l'atto di promuovere un progetto comporta, da parte dello sponsor stesso delle azioni di p.r. per cui il rischio di presentare o raccogliere requisiti in corso d'opera, solo per rendere più appetibile la soluzione.
Come figura cardine o come desunta tale, "io sto facendo questo per il progetto, sarebbe quindi utile dar seguito anche queste implementazioni", lo sponsor potrebbe introdurre nuovi elementi ( validi o fronzoli ) che tuttavia potrebbero farci allontare dalla meta.
Per gestire questa situazione ci sono differenti vie di fuga, non sempre eleganti e non sempre attuabili.
La prima e l'essere propositivi, "queste nuove specifiche ci faranno ritardare la consegna, se il ritardo è tollerato, rivediamo il piano di progetto in tal senso, caso contrario dobbiamo comprendere se queste nuove specifiche possono essere incluse in una fase successiva".
In questo modo l'entropia è contenuta, e le redini rimangono nelle nostre mani, ma si dà piena visibilità allo sponsor della nostra completa disposizione a riorganizzare il lavoro.
La seconda è molto restrittiva, "queste nuove specifiche stravolgono il progetto originale. Istruiamo un tavolo perchè cambiando i requisiti quanto fatto ad oggi potrebbe non essere più valido."
In questo modo creiamo due possibili effetti il primo e di creare un punto d'attenzione, il secondo di rivedere tutto il progetto, il rischio in questo è molto alto, ma di contro il nostro compito è di portare a termine il progetto, creare quindi un momento di riflessione può far comprendere che la strategia di presentazione del prodotto non può eccdere.
Sempre per il secondo caso è necessario essere dei buoni mediatori e nel caso specifico dell'apertura di un tavolo di discussione dovrà essere nostro compito individuare cosa è realmente necessario al nostro proggeto e cosa è un "fronzolo".
Diciamo che bisogna essere diplomatici ma senza perdere il focus sul progetto.

Gli Stakeholder sono figure direttamente o indirettamente conesse al progetto, che tuttavia hanno / nutrono interessi nello stesso.
Per la mia esperienza ho potuto notare differenti tipi di influenze da parte di questo Attore, in molti casi si tratta di mail, di chiacchere al caffè, di "uscite estemporanee" in breve asserzioni, non ben definite e nella maggior parte non condivise.
"Sarebbe bello che fosse più blu" per evidenza di fatti questa frase, detta in contesti diversi assume pesi diversi.
Se questa asserzione è fatta durante un caffè, certo la si può considerare ma lascia il tempo che trova, se al contrario si presenta in più occasioni e in più incontri ufficiali assume il peso di un dicta. La viralità di un asserzione porta alla convinzione che sia corretta.
Per ovviare a questi problemi è necessario comprendere il peso dello Stakeholder se si tratta di figure influenti e irremovibili si deve scendere a compromessi, con tutti i rischi che comporta il gesto stesso.
Mi è capitato di dover "incastrare" in una soluzione di 40 giornate, altre 5 giornate solo per un "pò di blu in più". Ma mi è anche capitato di rispedire al mittente la richiesta con un categorico "questa modifica non è in capitolato, e non sarà implementata".
E' necessario ricordarsi che "il progetto noi lo si conduce e il committente lo paga", il nostro compito è di affrontare con il committente anche questo tipo di decisione, avvalandoci di dati, e nello specifico il "quanto" di tempo necessario per assolvere alla richiesta.

Le risorse di progetto.
L'argomento è esteso e molto dipende dal team, dalla comunicazione, della esperienza del team e di tutte le regole che lo governano.
Un team coeso, con un forte orientamento alla comunicazione è un buon punto di partenza, ma spetta a noi e ai senior nel team stesso mantenerlo nella stessa condizione. Gli attori discussi in precedenza potrebbero e in molti casi è l'aspetto più difficile da gestire, intervenire direttamente sulle risorse.
"Hai tempo ? devo chiederti se mi modifichi questo" in molte occasioni questo evento si verifica in assenza del p.m. causando sia l'interruzione della comunicazione, sia una variazione non "prevista".
A giochi fatti, l'unica è avere ( e dovrebbe sempre essere così ) la possibilità di effettuare un rollback ma non sempre è possibile, prevenire questa situazione è altrsì complesso, anche spiegando quanto questa situazione possa essere pericolosa, potrebbe non esserci .

Noi stessi...
Noi per primi rischiamo di essere causa di rumore per noi stessi. Questo dipende dal fatto, che in molti casi la pressione, lo stress rischia di giocarci brutti scherzi. In questo caso ci si può avvalere di vari strumenti per monitorare le attività per non perdere il focus, per accentrare le informazioni e per "non mollare il colpo sul più bello".


venerdì 13 aprile 2012

How To Get Date & Time from NTP SERVER

 

Se mai vi dovesse servire Sorriso

La chiamata

public class Program
 {
      public static void Main(string[] args)
     {
         var t =NTP.GetNTPTime();
     }
 }

 

La Funzione

public class NTP
   {
       public static DateTime GetNTPTime()
       {
           try
           {
               // 0x1B == 0b11011 == NTP version 3, client - vedi RFC 2030
               byte[] ntpPacket = new byte[] { 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };


               var ntp = (from p in (Dns.GetHostEntry("pool.ntp.org").AddressList).Take(1)
                          select new { Client = new UdpClient(), EP = new IPEndPoint(p, 123) }
                        ).ToArray().FirstOrDefault();

               ntp.Client.Connect(ntp.EP);
               ntp.Client.Send(ntpPacket, ntpPacket.Length);

               var TmpEP = ntp.EP;
               byte[] data = ntp.Client.Receive(ref TmpEP);

               // dal 32 byte inizia la data
               byte[] ConvertedSeconds = new byte[4];
               ConvertedSeconds[0] = (byte)(data[32 + 3] & (byte)0x7F); // disabilita l'MSB (sui server che lo usano)
               ConvertedSeconds[1] = data[32 + 2];
               ConvertedSeconds[2] = data[32 + 1];
               ConvertedSeconds[3] = data[32 + 0];

               uint seconds = BitConverter.ToUInt32(ConvertedSeconds, 0);

               return (new DateTime(1900, 1, 1)).AddSeconds(seconds);
           }
           catch (Exception ex )
           {
               Console.WriteLine(ex.Message);
               return DateTime.MinValue;
           }
   
       }
   }

lunedì 2 aprile 2012

System.Security.Cryptography.RSACryptoServiceProvider

 

Esempio per un semplice utilizzo di crittografia a chiave asimmetrica…

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;

public static class AsymmetricEncryption
{
    private static bool _optimalAsymmetricEncryptionPadding = false;

    public static void GenerateKeys(int keySize, out string publicKey, out string publicAndPrivateKey)
    {
        using (var provider = new RSACryptoServiceProvider(keySize))
        {
            publicKey = provider.ToXmlString(false);
            publicAndPrivateKey = provider.ToXmlString(true);
        }
    }

    public static string EncryptText(string text, int keySize, string publicKeyXml)
    {
        var encrypted = Encrypt(Encoding.UTF8.GetBytes(text), keySize, publicKeyXml);
        return Convert.ToBase64String(encrypted);
    }

    public static byte[] Encrypt(byte[] data, int keySize, string publicKeyXml)
    {
        if (data == null || data.Length == 0) throw new ArgumentException("Data are empty", "data");
        int maxLength = GetMaxDataLength(keySize);
        if (data.Length > maxLength) throw new ArgumentException(String.Format("Maximum data length is {0}", maxLength), "data");
        if (!IsKeySizeValid(keySize)) throw new ArgumentException("Key size is not valid", "keySize");
        if (String.IsNullOrEmpty(publicKeyXml)) throw new ArgumentException("Key is null or empty", "publicKeyXml");

        using (var provider = new RSACryptoServiceProvider(keySize))
        {
            provider.FromXmlString(publicKeyXml);
            return provider.Encrypt(data, _optimalAsymmetricEncryptionPadding);
        }
    }

    public static string DecryptText(string text, int keySize, string publicAndPrivateKeyXml)
    {
        var decrypted = Decrypt(Convert.FromBase64String(text), keySize, publicAndPrivateKeyXml);
        return Encoding.UTF8.GetString(decrypted);
    }

    public static byte[] Decrypt(byte[] data, int keySize, string publicAndPrivateKeyXml)
    {
        if (data == null || data.Length == 0) throw new ArgumentException("Data are empty", "data");
        if (!IsKeySizeValid(keySize)) throw new ArgumentException("Key size is not valid", "keySize");
        if (String.IsNullOrEmpty(publicAndPrivateKeyXml)) throw new ArgumentException("Key is null or empty", "publicAndPrivateKeyXml");

        using (var provider = new RSACryptoServiceProvider(keySize))
        {
            provider.FromXmlString(publicAndPrivateKeyXml);
            return provider.Decrypt(data, _optimalAsymmetricEncryptionPadding);
        }
    }

    public static int GetMaxDataLength(int keySize)
    {
        if (_optimalAsymmetricEncryptionPadding)
        {
            return ((keySize - 384) / 8) + 7;
        }
        return ((keySize - 384) / 8) + 37;
    }

    public static bool IsKeySizeValid(int keySize)
    {
        return keySize >= 384 &&
                keySize <= 16384 &&
                keySize % 8 == 0;
    }
}

E relativo utilizzo…

public class UseEnryption {
   
    private string privatekey=string.Empty;
    private string publickey=string.Empty;
    private int keylength = 4096;

    string Crypt(string plaintext) {
        try
        {
            if (publickey == string.Empty)
            {
                GenerateKeys(keylength);
            }
            return AsymmetricEncryption.EncryptText(plaintext, keylength, publickey);
        }
        catch (Exception ex)
        {

            return ex.Message;
        }
  
    }
    
    string Decrypt(string encryptedtext) {
        try
        {
            if (privatekey == string.Empty)
            {
                GenerateKeys(keylength);
            }
            return AsymmetricEncryption.DecryptText(encryptedtext, keylength, privatekey);
        }
        catch (Exception ex)
        {

            return ex.Message;
        }
      
    }
    public void GenerateKeys(int keylength) {
        AsymmetricEncryption.GenerateKeys(keylength, out publickey, out privatekey);
    }

    }

P.S le chiavi vengono rigenerate ogni volta che si invoca il metodo GenerateKeys. Salvare le chiavi su un supporto fisico per mantenerle.

Spero vi sia utile.