Les bonnes pratiques dans la gestion de votre équipe de développeurs

Par défaut

Une équipe de développement efficace se gère souvent en mode autopilote. L’équipe définit elle-même ses critères de qualité et d’efficience.Les juniors sont souvent accueillis et accompagnés pour les faire monter en compétences rapidement sur un sujet spécifique.


Dans cet article, je vais mettre en avant quelques facteurs clés que je considère comme essentiels pour toute équipe de développement.


Comment créer une équipe qui correspond parfaitement à votre projet ?

Comment mettre en place un processus pour améliorer la productivité ?


1) Créer une équipe qui correspond parfaitement à votre projet.


Il y a 3 types d’équipes de développement, les généralistes, les spécialistes et l’équipe hybride.Chacune de ces équipes peut être vraiment efficace sur un projet mais peut en même temps se retrouver bloquée sur un autre projet.Comme développeur, j’ai eu l’occasion de travailler dans les 3 différentes catégories, sur différents types de projets, et ce aussi bien à l’Ile Maurice qu’en France, aussi bien dans un environnement anglo-saxon que dans un environnement francophone, avec des cultures de développement très différentes.Pour éviter que votre équipe soit bloquée, il faut prendre en compte la complexité de votre projet, le temps et votre budget. Ensuite il vous faudra décider quel type d’équipe correspondra le plus à votre projet.

Les points fortsLes points faiblesQuand choisir ?
GénéralistesLivraison rapide
Les membres de l’équipe peuvent avancer en autonomie, au lieu d’avoir comme responsabilité un sujet spécifique qui dependrait des autres membres de l’équipeL’équipe peut grandir et fonctionner d’une facon optimale, oui, mais avec l’arrivée d’un développeur experimenté. Sinon il faut penser à externaliser le projet en mi-cheminLes projets modéremment complexes qui doivent etre livrés avec une serie de fonctionalités prédéfinis et qui est géré selon les principes agiles ( Scrum, Kanban ) et dans lequel les délais de livraisons sont courts.
L’équipe se concentre dans l’amélioration du logiciel sur un point de vue macroLes temps d’arrets due à un manque d’expertise en profondeur.
SpécialistesLes membres de l’équipe peuvent développer un système composé de modules de haut niveau et peuvent vraiment etre éfficace dans leur domaine d’expertise respectifs.La possibilité de construire des éléments séparémment et qui ne s’imbriquent pas d’une facon optimale dans la solution finale.Les projets complexes qui requiert une expertise technique spécifique dans un domaine spécifique ( médical, géologie, spatial…)
Manque de communication dans l’équipe
Equipe HybridesLes spécialistes gèrent les sujets qui requiert une expertise en profondeur alors que les généralistes intègre le systemeEtablir les processus de travail est plus complexe et vous devrez gérer et faire la coordination entre des développeurs qui ont chacun leur approche spéficique du travailDes projets de grande envergure avec plus de 10 personnes.
Construire une équipe hybride est souvent compliqué et plus difficile à gérer qu’une équipe de généralistes ou de spécialistesDes projets agile complexes qui requiert la fléxibilité des généralistes pour délivrer à temps et l’expertise des spécialistes pour couvrir un ou plusieurs défis spécifiques

2) Construire des petites équipes


Les équipes de développement qui sont petites sont plus productives parce qu’il est plus facile de faire la coordination et de reconnaître les contributions individuelles de chaque développeur. En me basant sur mon expérience, je pense que la taille idéale d’une équipe est entre 4 et 8 personnes. Je n’inclue pas les ’Subject Matter Experts’, qui sont les experts fonctionnels ou la MOA et les testeurs, qui doivent eux aussi être présents et en communication étroite avec les développeurs. Si votre projet est conséquent ( plus de 300 jours hommes), vous devriez commencer par diviser votre équipe en sous-équipes, avec un Tech-Lead à la tête de chacune d’entre elles.


3) Assurez vous que votre équipe de développeurs évolue dans un environnement dynamique


Les équipes de développement doivent évoluer dans un environnement enrichissant et où elles voient le résultat final de leurs travaux.L’entreprise doit promouvoir l’échange d’idées, avec le concours de spécialistes dans leurs domaines, ou la présence de managers qui prennent le taureau par les cornes et vont avancer l’équipe.

4) Mettre en place des processus de travail qui améliorent la productivité.


Après avoir choisi une structure d’équipe qui correspond à votre projet, il est essentiel de définir ensuite une méthode de travail pour éviter tout goulot d’étranglements. En tant que développeur .NET, je suis amené à utiliser la plateforme Azure DevOps dans ce cas de figure.Le but final dans l’utilisation d’un outil comme Azure DevOps est l’élimination de processus répétitifs. Les tâches de routine passent par une série d’actions prédéfinies jusqu’à leurs complétion.Par exemple, un développeur commit son code sur sa branche, ensuite il l’envoie pour un Peer-Review et fait un Pull Request sur la branche Master. Le Tech Lead examine la Pull Request et met ses commentaires au cas où pour que le développeur travaille sur la partie du code à revoir en question. Une fois terminé, le commit suit son cours, le build est déclenché, ensuite la Release.Les testeurs prennent le relais et testent chacune des fonctionnalités définis dans les User Stories. Les résultats des tests sont communiqués au Tech Lead et à l’équipe. Le processus prend une forme itérative. Azure DevOps permet à chaque développeur de voir comment son travail est interconnecté avec le travail des autres développeurs. Donc il voit comment sa contribution aide à faire avancer le projet dans son ensemble.


5) Toujours s’assurer de la à mise à jour fréquente de la documentation

La documentation, qu’elle soit fonctionnelle ou technique, doit être toujours à jour. C’est important car ça aide les développeurs à avoir une vision sur la direction que prend le projet. Vous devez aussi vous assurer que les compte-rendus de réunions, le code source et les standards UX-UI par exemple soient toujours accessibles à tous les membres de l’équipe.Si vous travaillez avec une entreprise en mode offshore, vous devez vous assurer que celle-ci vous livre régulièrement une documentation à jour sur le processus de développement.


6) Adopter des standards de développement dès le départ. Cette adoption va vous aider dans le processus de développement. Si les normes de codage sont suivies, le code est cohérent et peut être facilement maintenu. En effet, n’importe qui ensuite le comprendre et le modifier à tout moment.

Je ne vais pas vous parler ici de la nécessité d’avoir une très bonne communication entre les différentes membres de l’équipe, ou le fait d’avoir des sessions spécifiques pour résoudre les conflits.


NextCog vous accompagne dans la gestion de votre équipe de développeurs. Elle les accompagne en mettant en place les bonnes pratiques de développement dès le démarrage de votre projet.On vous aide à mettre en place Azure DevOps et à former votre équipe dans l’utilisation de cette plateforme.Le suivi et l’accompagnement, le conseil et la proposition d’audits font aussi partie de notre expertise.

C# – Soit 2 tableaux de n entiers chacun, trouvez une paire d’éléments issue des 2 tableaux {n1,n2} dont la somme se rapproche le plus d’une cible n.

Par défaut

Ce petit problème fort intéressant peut etre résolu de divers manières, mais j’ai voulu montrer comment on pouvait créer un dictionnaire en C# qui contient 2 clés, en utilisant les tuples.

[code language= »csharp »]
using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace Exercises

{

class Program

{

static void ClosestToTarget(int[] array1, int[] array2, int target)

{

int i,
j = 0;

var dictionary = new Dictionary < Tuple ,
int > ();

int x = 0;

int[, ] totals = new int[array1.Length, array2.Length];

for (i = 0; i < array1.Length; i++)

{

for (j = 0; j < array2.Length; j++)

{

int total = array1[i] + array2[j];

totals[i, j] = total;

var key = new Tuple (i, j);

dictionary.Add(key, array1[i] + array2[j]);

}

}

foreach(KeyValuePair < Tuple , int > kvp in dictionary)

{

Console.WriteLine(« Clé = {0},{1} », kvp.Key, kvp.Value);

}

var bestMatch = dictionary.OrderBy(e = >Math.Abs(e.Value – target)).FirstOrDefault();

i = bestMatch.Key.Item1;

j = bestMatch.Key.Item2;

Console.WriteLine(« Elément issu du premier tableau : {0} , Elément issu du deuxième tableau : {1}, La Somme = {2} qui se rapproche le plus de la cible : {3} », array1[i], array2[j], array1[i] + array2[j], target);

}

static void Main(string[] args)

{

Console.WriteLine(« Ce programme prend en entré 2 tableau de taille n et vous donne quel pairs d’éléments des 2 tableaux se rapproche le plus d’une cible x »);

Console.WriteLine(« Veuillez entrer la taille des tableaux: »);

int size = 0;

while (!int.TryParse(Console.ReadLine(), out size))

Console.Write(« Attention, la valeur doit être un entier. Veuillez réessayer »);

int[] array1 = new int[size];

int[] array2 = new int[size];

int i;

Console.WriteLine(« Entrez les {0} chiffres pour le premier tableau: », size);

for (i = 0; i < size; i++)

{

while (!int.TryParse(Console.ReadLine(), out array1[i]))

Console.Write(« Attention, la valeur doit être un entier. Veuillez réessayer »);

}

Console.WriteLine(« Entrez les {0} chiffres pour le deuxième tableau: », size);

for (i = 0; i < size; i++)

{

while (!int.TryParse(Console.ReadLine(), out array2[i]))

Console.Write(« Attention, la valeur doit être un entier. Veuillez réessayer »);

}

Console.WriteLine(« Entrez la cible: »);

int target = Convert.ToInt32(Console.ReadLine());

ClosestToTarget(array1, array2, target);

Console.ReadLine();

}

}

}
[/code]

https://dotnetfiddle.net/4cKdGc

Normes ISO 20022 : Génération d’un XML avec C# en suivant le schéma xsd pain.001.001.03 , « Customer Credit Transfer Initiation »

Par défaut

La norme ISO 20022 une norme ISO régissant l’échange de données informatisé entre les institutions financières. Standard international et ouvert, ISO 20022 n’est pas contrôlé par un seul intérêt: il peut être utilisé par n’importe qui dans l’industrie et implémenté sur n’importe quel réseau. Il a des processus entièrement établis pour sa maintenance, son évolution et sa gouvernance.

Première publication en 2004, l’ISO 20022 est largement reconnue comme la norme du futur. En plus d’être assez flexible pour travailler avec les dernières technologies,
ISO 20022 peut également s’adapter aux nouvelles technologies à mesure qu’elles emergent.

La norme ISO 20022 est décrite dans le document «ISO 20022 Financial Services – Système de messages de l’industrie financière universelle».

L’édition actuelle de la norme comprend huit parties, publiées en mai 2013:

ISO 20022-1: Métamodèle
ISO 20022-2: profil UML
ISO 20022-3: Modélisation
ISO 20022-4: Génération de schémas XML
ISO 20022-5: Ingénierie inverse
ISO 20022-6: Caractéristiques de transport des messages
ISO 20022-7: Enregistrement
ISO 20022-8: génération ASN.1
Les commandes d’ISO 20022 et d’autres normes internationales ou publications ISO peuvent être obtenues sur http://www.iso.org. Dans la zone Rechercher, tapez 20022, puis Rechercher. Les huit parties de la norme sont disponibles à l’achat en format PDF ou papier

Dans l’example qui va suivre, nous allons voir comment générer un XML sur C# en utilisant plus spécifiquement le message « Customer Credit Transfer Initiation » : pain.001.001.03

Je vous invite à consulter le lien ci dessous de la CFONB ( Comité Francais d’Organisation et de Normalisation Bancaire ) pour avoir plus de details sur le virement SEPA (Single Euro Payments Area ) et les instructions de paiements.

Pour commencer, prenons l’example ci-dessous.

Nous avons une table Emetteur avec les informations suivantes.

em

Nous avons aussi une table Recepteur qui a  la meme structure que la table Emetteur.

re

Les données à partir de ces 2 tables peuvent etre assignees dans une DataTable à partir de la requete sql suivante.

Emeteur.

[code language= »sql »]
select Libelle_Emetteur,BIC_Emetteur_IBAN_Emetteur from Emetteur
[/code]

Recepteur

[code language= »sql »]
select Libelle_Recepteur,BIC_Recepteur,IBAN_Recepteur from Recepteur
[/code]

La generation du XML

[code language= »csharp »]
public void WriteXML()
{

DateTime DateXml = Global.GetImportDate.AddDays(1);

string namespace_xml = "urn:iso:std:iso:20022:tech:xsd:pain.001.001.03";
xmlDoc.InsertBefore(xmlDoc.CreateProcessingInstruction("xml", "version=’1.0′ encoding=’UTF-8’"), xmlDoc.ChildNodes.Item(0));
XmlNode objXMLRootelement = xmlDoc.CreateNode(XmlNodeType.Element, "Document", namespace_xml);
xmlDoc.AppendChild(objXMLRootelement);

XmlAttribute attribute = xmlDoc.CreateAttribute("xsi:schemaLocation");
attribute.Value = @"urn:iso:std:iso:20022:tech:xsd:pain.001.001.03\\REPERTOIRE OU SE TROUVE LE SCHEMA\pain.001.001.03.xsd";
objXMLRootelement.Attributes.Append(attribute);
XmlAttribute attribute_1 = xmlDoc.CreateAttribute("xmlns:xsi");
attribute_1.Value = "http://www.w3.org/2001/XMLSchema-instance&quot;;
objXMLRootelement.Attributes.Append(attribute_1);

XmlAttribute attribute_2 = xmlDoc.CreateAttribute("xmlns:xsd");
attribute_2.Value = "http://www.w3.org/2001/XMLSchema&quot;;
objXMLRootelement.Attributes.Append(attribute_2);
XmlNode objXMLelement = xmlDoc.CreateNode(XmlNodeType.Element, "CstmrCdtTrfInitn", namespace_xml);
objXMLRootelement.AppendChild(objXMLelement);

//#####################################
//#           En Tête                 #
//#####################################

CreateNode("GrpHdr", namespace_xml, "CstmrCdtTrfInitn");

CreateNode("MsgId", namespace_xml, "GrpHdr", RandomString(3) + "/" + RandomString(2) + "/" + RandomInt(8));
CreateNode("CreDtTm", namespace_xml, "GrpHdr", DateXml.ToString("yyyy-MM-ddThh:mm:ss"));

CreateNode("NbOfTxs", namespace_xml, "GrpHdr", "1");
// Le montant du virement
CreateNode("CtrlSum", namespace_xml, "GrpHdr", MontantVirement());

CreateNode("InitgPty", namespace_xml, "GrpHdr");

CreateNode("Nm", namespace_xml, "InitgPty", "XXXXX");

//#####################################
//#           LOT Banque               #
//#####################################

CreateNode("PmtInf", namespace_xml, "CstmrCdtTrfInitn");

CreateNode("PmtInfId", namespace_xml, "PmtInf", "0000001");

CreateNode("PmtMtd", namespace_xml, "PmtInf", "TRF");

CreateNode("NbOfTxs", namespace_xml, "PmtInf", "1");

CreateNode("CtrlSum", namespace_xml, "PmtInf", MontantVirement());

CreateNode("PmtTpInf", namespace_xml, "PmtInf");

CreateNode("SvcLvl", namespace_xml, "PmtTpInf");

CreateNode("PmtTpInf", namespace_xml, "PmtInf");

CreateNode("Cd", namespace_xml, "SvcLvl", "SEPA");

CreateNode("ReqdExctnDt", namespace_xml, "PmtInf", DateXml.ToString("yyyy-MM-dd"));

CreateNode("Dbtr", namespace_xml, "PmtInf");
// GetDataTableEmetteur est une methode qui retourne un DataTable
// Le libelle_Emetteur dans la Table Emetteur
CreateNode("Nm", namespace_xml, "Dbtr", GetDataTableEmetteur.Rows[0].ItemArray[0].ToString());

CreateNode("DbtrAcct", namespace_xml, "PmtInf");

CreateNode("Id", namespace_xml, "DbtrAcct");
//Le IBAN_Emetteur dans la Table Emetteur
CreateNode("IBAN", namespace_xml, "Id", GetDataTableEmetteur.Rows[0].ItemArray[2].ToString());

CreateNode("DbtrAgt", namespace_xml, "PmtInf");

CreateNode("FinInstnId", namespace_xml, "DbtrAgt");
//Le BIC  dans la Table Emetteur
CreateNode("BIC", namespace_xml, "FinInstnId", GetDataTableEmetteur.Rows[0].ItemArray[1].ToString());

CreateNode("ChrgBr", namespace_xml, "PmtInf", "SLEV");

//#####################################
//#           Lot Transaction         #
//#####################################

CreateNode("CdtTrfTxInf", namespace_xml, "PmtInf");

CreateNode("PmtId", namespace_xml, "CdtTrfTxInf");

CreateNode("InstrId", namespace_xml, "PmtId", "XXXXXX-1");

CreateNode("EndToEndId", namespace_xml, "PmtId", "XX000");

CreateNode("Amt", namespace_xml, "CdtTrfTxInf");

CreateNode("InstdAmt", namespace_xml, "Amt", MontantVirement(), "Ccy=EUR");

CreateNode("Cdtr", namespace_xml, "CdtTrfTxInf");
//GetDataTableRecepteur est une méthode qui retourne une DataTable
CreateNode("Nm", namespace_xml, "Cdtr", GetDataTableRecepteur.Rows[0].ItemArray[0].ToString());

CreateNode("CdtrAcct", namespace_xml, "CdtTrfTxInf");

CreateNode("Id", namespace_xml, "CdtrAcct");
//
CreateNode("IBAN", namespace_xml, "Id", GetDataTableRecepteur.Rows[0].ItemArray[2].ToString(), "", 1);

CreateNode("RmtInf", namespace_xml, "CdtTrfTxInf");

CreateNode("Ustrd", namespace_xml, "RmtInf", "XXXXXXXXXXXXXXX XX" + GetDataTableEmetteur.Rows[0].ItemArray[2].ToString() + " COM " + Global.GetImportDate.ToString("MM/yyyy") + GetDataTableEmetteur.Rows[0].ItemArray[0].ToString());

string targetPath = @"\DOSSIER_SORTIES\" + Global.GetImportDate.ToString("yyyy MM dd");
// Creation d’un dossier pour sauvegarder le XML
if (!System.IO.Directory.Exists(targetPath))
{
System.IO.Directory.CreateDirectory(targetPath);
}

xmlDoc.Save(targetPath + "\\DOSSIER_XML" + Global.GetImportDate.ToString("yyyyMM") + "_1.xml");

}

[/code]