Les Mêlées
Libellés
jeudi 10 janvier 2013
Reading xml from PowerShell is really easy !
lundi 16 janvier 2012
SpecFlow : StepArgumentTransformation
When writting BDD test features and feature steps, we often need to convert strings to types. Testing strings with a serie of if statement within steps does not maximise reusability and readability. The best would be to get the string recognise as a Type every time we use it in a feature without taking care of the conversion.
SpecFlow provides a StepArgumentTransformation attribute to achieve this :
https://github.com/techtalk/SpecFlow/wiki/Step-Argument-Conversions
Exemple :
[Then(@"the value of the Shoulder mode is (.*) in the method file")]
public void ThenTheValueOfTheShoulderModeIsDropInTheMethodFile(string shoulderModeString)
{
ShoulderModeType shoulderMode = ShoulderModeType.OFF; ;
if (ShoulderModeType.Drop.ToString() == shoulderModeString) shoulderMode = ShoulderModeType.Drop;
else if (ShoulderModeType.OFF.ToString() == shoulderModeString) shoulderMode = ShoulderModeType.OFF;
else if (ShoulderModeType.Tangential.ToString() == shoulderModeString) shoulderMode = ShoulderModeType.Tangential;
else Assert.Fail("Invalid shoulderModeString: " + shoulderModeString);
...
Assert.AreEqual(expectedShouldMode, shoulderMode)
}
Can be refactored as
[StepArgumentTransformation]
public ShoulderModeType ShoulderModeTransform(string shoulderModeString)
{
ShoulderModeType shoulderMode = ShoulderModeType.OFF;
if (ShoulderModeType.Drop.ToString() == shoulderModeString) shoulderMode = ShoulderModeType.Drop;
else if (ShoulderModeType.OFF.ToString() == shoulderModeString) shoulderMode = ShoulderModeType.OFF;
else if (ShoulderModeType.Tangential.ToString() == shoulderModeString) shoulderMode = ShoulderModeType.Tangential;
else Debug.Assert.Fail("Invalid shoulderModeString: " + shoulderModeString);
return shoulderMode;
}
[Then(@"the value of the Shoulder mode is (.*) in the method file")]
public void ThenTheValueOfTheShoulderModeIsDropInTheMethodFile(ShoulderModeType shoulderMode)
{
...
Assert.AreEqual(expectedShouldMode, shoulderMode)
}
jeudi 20 octobre 2011
Converting Enum values to user frendly strings
public enum ErrorLevel { None, Low, High, }
public static class ErrorLevelExtensions { public static string ToLocalizedString(this ErrorLevel me) { switch (me) { case ErrorLevel.None: return "Everything is OK"; case ErrorLevel.Low: return "SNAFU, if you know what I mean."; case ErrorLevel.High: return "Reaching TARFU levels"; } return ""; } }
1: Console.WriteLine(ErrorLevel.Low.ToLocalizedStrings())
This uses Extensions Methods
jeudi 6 octobre 2011
Tool to remove useless references in .net projects
Including too much references in projects can lead to tricky dependency graphes. Checking all references is just boring and long; it’s why we have searched for a way to remove useless references automatically. Resharper provide the Clean Code feature which remove useless using directrives but it does not remove the references.
Googling made me discover a free VisualStudio extension that does just but exaclty what we need (ie remove useless references and using directives) : Reference Assistant
It works perfectly well so I think it is a must have tool !
mardi 22 février 2011
CHAPTER 4: Preparing for Sprint Planning
My notes out of the book “A Practical Guide to Distributed Scrum”
Sprint planning =
- Review of highest priority items with PO + decision on how much work could be done according to previous sprints and velocity
- Task break down to decide how the work will get done
- Commit to the sprint plan
Risk at the sprint planning is that PO cannot answer team’s questions without contacting stakeholders who are not available in the meeting. This is often the sign that the team is not ready to do the Sprint Planning meeting.
There is no official pre-planning meeting in SCRUM but the team needs to have ready for the sprint planning the following points
- A prioritized Poduct BackLog
- User stories the team can complete within a sprint
- Clear acceptance conditions for each user story
Preplanning meeting can make the sprint planning meeting shorter
Preplanning
- Discuss and clarify acceptance conditions for high-priority user stories.
- Provide a relative estimate to help the PO identify their priorities
- Break down high priority user stories so that they can fit within a sprint
- Consider story dependencies owned by different teams
Clarification of user stories
The participants have to confirm that the stories have the same meaning to everyone and that they understand what the deliverables for a user stories are.
Hint: A good mean to make sure participants have the same understanding is to make them rephrase it with their own words.
- The product owner answers questions or take note of them if he cannot answer to get ready for the Sprint Planning
- The team can identify what needs to be investigated technically speaking to be able to commit at sprint planning
- The participant confirm if the estimates seem accurate
Breaking down User Stories
Looking at the stories only at the sprint planning – particularly at the beginning of projects – may lead to long time of disaggregating user stories instead of planning for the sprint. The can lead to create user stories sprint after sprint and the team may never understand the quantity of work they need to do for the release.
KEY POINT: The large user stories must be breakdown the soonest possible in the release to make the team understand how much work they need to do. Teams should not create user stories for the release from sprint to sprint
Estimating user stories
When new stories are added to the backlog, the team can estimate them at pre planning meeting
Dealing with dependencies
3 types of dependencies
- Simple dependency : A user story needs another user story done within the same team
- Solution : reorder priorities to do first standalone user stories
- External dependency : A user story needs another user story done from and other team
- Negotiate integration and delivery dates and reorder priorities
- The team should not commit the dependent user stories before integration of the other
- Intertwined dependency: Two user stories need each other to get done.
- Rework user stories breakdown to get simple dependencies
Cleanup of Product Backlog
The Product Backlog is not a Parking lot for every possible feature that could potentially be in the product.
The Product Backlog must be cleanup up so that it reflects what the team is likely to address. Stories with very low priority can be removed from the PB.
Approaches for the sprint preplanning meeting
- 1 meeting at each sprint or 1 meeting every week or as needed
- The regular meeting is best to get into a rhythm and limit interruptions
- Time box the meetings to remain focused. 1 hour is good.
- Sprint preparation can be 5 to 10% of team time
A ) The Full Team Approach
Regular meeting that involves the entire team.
PROS :
- Provide a sense of team ownership
- All team members can ask questions or voice concerns
- The team can use meeting to size the stories
- It allows the PO to get info from stakeholders before the Sprint Planning meeting
CONS :
- It is harder to keep focus of the meeting with many distributed participants.
- It may be difficult to schedule a time that works well for all Scrum Team members
B ) The Preplanning Team Approach
Weekly preplanning meeting with PO and the smallest subset of team representatives able to select and describe stories
PROS :
- A smaller group of participant is more effective for teleconferences
- It allows the PO to get info from stakeholders before the Sprint Planning meeting
- It reduce the disruptions on the work of team members for the current Sprint
CONS :
- There is a potential loss of communication or information by not having the full team present.
- Neglecting to go back to the whole team for their contributions can result in a loss if team ownership.
- This approach can easily slip from Scrum to a command and control center
C ) The Balanced Team Approach
Compromise between Full-Team and Preplanning Team approach.
Weekly meeting with a core group of participant and the entire team as optional participant. The entire team is present only for the last meeting before the sprint planning
PROS :
- A smaller group of participant is more effective for teleconferences
- It allows the PO to get info from stakeholders before the Sprint Planning meeting
- It provides a sense of team ownership
- All team members can ask questions or voice concerns
- It allows the optional team members to manage the disruptions on their work for the current sprint
CONS :
- There may be a loss of communication or information because the full team is not always present
mardi 1 février 2011
CHAPTER 2: Challenges faced by distributed teams
My notes out of the book “A Practical Guide to Distributed Scrum”
Communication
Generally speaking, communication is a lot about non verbal channel. Indeed, verbal channel is only 35% of communication. As a consequence distributed teams communicate with a real handicap.
Meeting at least once help to know each other’s personalities, mannerisms, communication style and culture.
Time zone and working hours
Every meeting is a challenge
Cultural differences
In some countries, it is inappropriate to say “I don’t understand” the speaker. This can result to a big waste of time and energy.
Humor can differ from country to country. Handle it with care.
Words can have different meaning.
Management style can also be different.
Language differences
A scrum team needs to communicate a lot so the language difference makes it harder. Keeping language simple will help those who are not speaking mother language.
Give everyone a chance to speak.
Use chat tools to share links
Confirm understanding
Address communication tools issue such bad phone or poor network connection.
Software Engineering practices
“Good software engineering practices are important for both collocated and distributed teams BUT for distributed teams poor engineering practices are much more obvious and are a greater problem”
- TDD helps delivering high quality tested code. It helps the team to evolve design over the time.
- Continuous integration helps teams to integrate their work frequently
- CI running automated tests detect regression problem quicker
Generally speaking, any tool helping to discover problems soon is a good tool because the later issues are discovered, the more expensive they are.
Delivering value at every 2-3 weeks sprint is a challenge and good engineering practices will considerably help distributed teams.
Schedule difference
Take into account holidays of the different zones to help commitment.
Team dynamics
“Making the daily scrum a priority is one example of how to keep the whole team engaged”
Telephone dynamics
Providing access to call -> toll free numbers (very important for home workers)
The Scrum Master takes the responsibility everyone hears and participates
Identify the speaker (Luc’s speaking : “bla bla bla”)
Handling visual cues encourage participation and limit side conversation
Check for agreement and disagreement.
Impact of Communication problems
Obvious problems: Team members not doing the right task, doing the task correctly or doing the task at the expected time.
More subtle problems: tasks outside team’s mission can pull away members to work on lower priority matters. This is more difficult to see on distributed teams.
Scrum helps mitigate this problem through the daily Scrum.
“KEY POINT: The more closely a distributed team can adopt Scrum as designed by its creators, the more likely a team will experience success. The design of Scrum promotes good communication. At the same time, with some minor adaptations for distributed teams, Scrum can help teams deliver the right product, at the right time, with the right quality”.
Forming-Storming-Norming-Performing model: http://en.wikipedia.org/wiki/Tuckman's_stages_of_group_development
- Distributed teams easily block at the storming stage. When the team changes, it can start over at forming stage. The performing stage is fragile and because of the limited personal contact, remote teams take longer to get through this stage.
How does Scrum help?
It does not help fixing problems! It just puts a spotlight on them so that the teams can identify and address them. All scrum artifacts are designed to help the team seeing progress and issues. Sprints, daily scrums, retrospectives, sprint planning are all important and mastering them can lead the team to performance. Scrum is like glasses, it makes more visible dysfunctions.
lundi 31 janvier 2011
A Practical Guide to Distributed Scrum – IBM Press
By Elizabeth Woodward, Steffan Surdek, Matthew Ganis.
http://www.ibmpressbooks.com/bookstore/product.asp?isbn=0137041136
Here are my notes picked up when reading the book
CHAPTER 1 : The Evolution of Scrum
Collocation is no longer the norm: only 45% of collocated teams – from a recent survey –
Advantages of distributed teams
- Use time shift for 24/24 h development effort
- Reaching market more quickly with the “follow the sum model” :
- Multinational companies produce more ideas than domestic counterparts
A lot of distributed teams are the result of acquisition.
Four level of distribution with more and more difficulties
Collocated
Collocated part-time
- dailies with remote callers,
- “out of sight, out of mind”,
- biggest challenge is to invite remote people to planning and design sessions.
Distributed with overlapping hours
- Not easy to plannify sprint planning and review
- Scrum meetings lack of body language
- Cultural / language difference
Distributed with no overlapping hours
- Every meeting is a challenge
Three ways of handling distributed teams
Isolated Scrums model
- No synchronization needed between teams
- Each location has a cross functional team.
- Usually the first two level of distribution
Distributed Scrum of scrum
Scrum of scrum daily (Ken Schwaber 2004)
- What did you team do yesterday?
- What will your team do today?
- What blockers have you met?
- + What blockers might you be throwing into another team’s way?
- Longer meeting fewer time to give all members time to communicate
- Several Product owners who make a single team : Need to speak with single voice
Totally Integrated teams
- Each team has members in several location (Ex : All testers in a single location)
- In such a context, Scrum can improve productivity by 5 to 10 compared to industry average
Comments are welcome ; Comming soon : Chapter 2 : Challenges faced by distributed teams
vendredi 24 décembre 2010
How to implement a generic “waiting for” function with C#
In order to avoid repeating myself in the code of my team’s project where we need several times to wait for something to happen such as waiting for a file, I learned how to use the type “Func”.
Here is how was the code before the refactoring :
public static bool WaitForFile(string filePath, int timeOutMs) var startTime = DateTime.Now; timeElapsed = span.TotalMilliseconds > timeOutMs; fileFound = System.IO.File.Exists(filePath); } |
And here is the new generic implementation :
public static bool WaitForSynchrone(Func<bool> function, int timeOutMs) public void WaitFile() |
So, now, we have a new function WaitForSynchrone that take 2 arguments :
- Func<bool> function : A function that returns a boolean
- int timeOutMs : A timeout to prevent freezing !!
And we use it thanks to lambda expression for the first argument :
- () => File.Exists("C:\myfile.txt") : This is a function that takes no arguments and returns and boolean according to the left part of the expression
So now, we can use WaitForSynchrone for many other purpose instead of violating the DRY principle = ‘Do Not Repeat yourself ‘.
jeudi 25 novembre 2010
Agile Grenoble 2010 – 10 Messages que j’ai retenu
“Nombre de WTF par minute = métrique représentant la qualité du code”
– Aslak Hellesoy - WTF = What the fuck
_
“Loi de Little : Moins on en fait à la fois, plus on va vite”
– Hervé Lourdin, Cyril Mégard
_
“Il faut garder du mou pour absorber la variabilité”
- Hervé Lourdin, Cyril Mégard
_
“L’Agilité est un long voyage. Elle évolue depuis la fin des années 90 et va continuer à évoluer”
– Claude Aubry – Laurent Bossavit
_
“Le TDD dans le Legacy Code, c’est possible et bénéfique”
– Bernard Huguet, Cyrille Roy, Johan Martinsson, Luc Jeanniard ;o)
_
“La programmation fonctionnelle permet de résoudre des problèmes de façon élégante et efficace”
– Emmanuel Gaillot
_
“Bonjour Mr Orsier, je vous apporte le cahier des charges (un énorme classeur) – c’est presqu’ … le définitif”
– Rémy Sanlaville, Bruno Orsier
_
“Il faut commencer le dev le plus tôt possible pour obtenir du feedback rapidement”
– Alexandre Boutin
_
“Portfolio agile : synchroniser les releases pour être réactif au changement”
- Jean Dupuis, Jean-François Jagodzinski
_
“'jcQualitystreet #agilegrenoble: On est loin mais on attend des tweets et du feedback! @NicoRuffel @claudeaubry @agilex @LucJeanniard @jfjago @calton13”
– Jean Claude GROSJEAN via Twitter !
_
Il y a très certainement d’autres messages importants mais c’est la loi de ce genre d’événement, il faut faire des choix, on ne peut pas tout voir, tout entendre, tout retenir … Rendez-vous en 2011 !
Le programme complet est sur http://agile-grenoble.org/
.
jeudi 30 septembre 2010
Tester unitairement du “Legacy Code” : un exemple
(Note au utilisateur de GoogleReader : Pour une raison inconnue, les couleurs ne sortent pas … lisez plutôt ici)
Je souhaite vous montrer dans ce billet un exemple d’ajout de test unitaire dans du legacy code. Du legacy code, c’est du code non testé automatiquement. Je travaille tous les jours sur du code non couvert par des tests automatiques alors capitaliser en ajoutant petit à petit des tests est un réel enjeu pour éviter les régressions.
Le Problème
Voici une classe développée il y a presque 10 ans pour dessiner des annotations sur un graphique. Il se trouve que dans certaines rares conditions, l’annotation sort du graphique et ceci ne fait pas propre lors de son impression. Nous avons donc souhaité corriger ce défaut.
__________________________________________________________________
TSKRAnnotDrawer = class
private
FAnnotList: TList;
FSquaring: TSquaringType;
FHorizontalMaille: Real;
FVerticalMaille: Real;
procedure Sort;
function GetAnnot(Index: Integer): PAnnotRec;
procedure FindCorrespondingSquaringRectangle(aRect: TRect;
X, Y: Integer;
var SquaringRow, SquaringCol: Integer);
procedure CalculateSquaringRectanglesNumber(aRect: TRect;
W, H: Integer; var SquaringWidth, SquaringHeight: Integer);
function FindFreeSpace(SquaringRow, SquaringCol,
SquaringWidth, SquaringHeight: Integer;
var SquaringFreeRow, SquaringFreeCol: Integer;
var UpOrDown: Boolean): Boolean;
function TestIfItIsInTheGraphic(row, col,
SquaringWidth, SquaringHeight: Integer): Boolean;
function TestIfTheSpaceIsFree(row, col,
SquaringWidth, SquaringHeight: Integer): Boolean;
procedure UpdateFSquaring(row, col, SquaringWidth, SquaringHeight: Integer);
public
PeakAnnotation: TSKRPeakAnnotationPrefs;
EventAnnotation: TSKREventAnnotationPrefs;
procedure Create;
procedure Destroy; override;
procedure ClearList;
procedure AddToList(aAnnot: TAnnotRec);
procedure Draw(Canvas: TCanvas3D; arect: TRect);
end;
__________________________________________________________________
Nous allons nous intéresser à la méthode “Draw”. Après investigation, l’erreur provient du calcul de la hauteur de la première annotation. En effet, la ‘font size’ est assignée après le calcul de la hauteur du texte : voir ci-dessous le texte en rouge.
__________________________________________________________________
procedure TSKRAnnotDrawer.Draw(Canvas: TCanvas3D; aRect: TRect);
var
i, Width, Height: Integer;
UpOrDown: Boolean;
w, h: Integer;
AnnotationPrefs: TSKRAnnotation;
row, col: Integer;
SquaringRow, SquaringCol: Integer;
SquaringWidth, SquaringHeight: Integer;
SquaringFreeRow, SquaringFreeCol, XFree, YFree, YFreeTemp: Integer;
begin
assert(EventAnnotation <> nil);
assert(PeakAnnotation <> nil);
// sort annotation according time
Sort;
Width := 0;
Height := -1;
//initializing the squaring array.
for row := 0 to Pred(SquaringSize) do // Iterate
begin
for col := 0 to Pred(SquaringSize) do // Iterate
begin
FSquaring[row, col] := True;
end; // for
end; // for
for i := 0 to Pred(FAnnotList.Count) do
with GetAnnot(i)^ do
begin
if Typ = 0 then
AnnotationPrefs := EventAnnotation
else
AnnotationPrefs := PeakAnnotation;
UpOrDown := AnnotationPrefs.AutoUpDown = apUp;
if AnnotationPrefs.Orientation = aoOblique then
begin
//We take the size of the rectangle projection on a vertical axis
H := round(Sin(Pi / 4) * (Canvas.TextWidth(Text) + Canvas.TextHeight(Text)));
//and for W the size of the rectangle projection on the horizontal axis
W := round(Cos(Pi / 4) * (Canvas.TextWidth(Text) + Canvas.TextHeight(Text)));
end
else if AnnotationPrefs.Orientation = aoVertical then
begin
H := Canvas.TextWidth(Text);
W := Canvas.TextHeight(Text);
end
else //Horizontal
begin
H := Canvas.TextHeight(Text);
W := Canvas.TextWidth(Text);
end;
H := H + 4;
if AnnotationPrefs.AutoUpDown = apAuto then
begin
Canvas.Font.Name := AnnotationPrefs.Font.name;
Canvas.Font.Size := AnnotationPrefs.Font.Size; //INTERVIENT TROP TARD
end;
if AnnotationPrefs.LinkType = ltNone then
begin
... 6 lines
end
else
begin
... 30 lines
end;
DrawAnnotation(Canvas, Text, Point(XFree, YFree),
XFree, AnnotationPrefs, UpOrDown, Width, Height, X, Y, aRect);
end;
end;
__________________________________________________________________
La correction est triviale, il suffit de remonter l’affectation de la font size avant la première utilisation du Canvas.
Mais comment tester ce que l’on souhaite modifier?
Le cheminement vers le test unitaire
Ma première idée fut d’instancier la classe et appeler la méthode Draw dans un test unitaire. En effet, le constructeur ne prend pas de paramètre alors ça paraissait facile. Ensuite, il a fallu ajouter des assertions à mon test et là les ennuis commençaient. En effet, je n’avais aucune envie de vérifier le rendu sur le graphique (via le Canvas) car je ne savais pas comment m’y prendre.
Donc je suis reparti de zéro afin d’isoler mon problème. J’ai suivi les étapes suivantes :
1- Extraction de la partie de code problèmatique
Je ne prend pas de risque à ce niveau là et je fais confiance au compilateur pour m’indiquer les éventuels problèmes.
__________________________________________________________________
procedure TSKRAnnotDrawer.getTextHeightAndWidth(
const aCanvas: TCanvas3D;
const aAnnotationPrefs: TSKRAnnotation;
const aText: string;
var oTextHeight, oTextWidth: integer);
begin
if AnnotationPrefs.Orientation = aoOblique then
begin
//We take the size of the rectangle projection on a vertical axis
H := round(Sin(Pi / 4) * (Canvas.TextWidth(Text) + Canvas.TextHeight(Text)));
//and for W the size of the rectangle projection on the horizontal axis
W := round(Cos(Pi / 4) * (Canvas.TextWidth(Text) + Canvas.TextHeight(Text)));
end
else if AnnotationPrefs.Orientation = aoVertical then
begin
H := Canvas.TextWidth(Text);
W := Canvas.TextHeight(Text);
end
else //Horizontal
begin
H := Canvas.TextHeight(Text);
W := Canvas.TextWidth(Text);
end;
H := H + 4;
if AnnotationPrefs.AutoUpDown = apAuto then
begin
Canvas.Font.Name := AnnotationPrefs.Font.name;
Canvas.Font.Size := AnnotationPrefs.Font.Size; //INTERVIENT TROP TARD
end;
end;
__________________________________________________________________
Là, ça devient plus simple de tester cette fonction mais celle-ci n’est pas publique et changer l’API, c’est à dire le contrat de la classe, à des fins de tests n’est pas élegant. En effet, cette méthode n’a pas d’intéret pour l’utilisateur de la classe.
2- Extraction de la méthode vers une classe spécifique
En ayant en tête les principes SOLID et plus particulièrement celui qui dit qu’une classe ne doit avoir qu’une responsabilité, je n’ai pas d’état d’âme à créer une classe pour isoler ma méthode:
__________________________________________________________________
TTextPixelSizeHelper = class
public
class procedure GetTextHeightAndWidth(
const aCanvas: TCanvas3D;
const aAnnotationPrefs: TSKRAnnotation;
const aText: string;
var oTextHeight, oTextWidth: integer);
end;
class procedure TTextPixelSizeHelper .getTextHeightAndWidth(
const aCanvas: TCanvas3D;
const aAnnotationPrefs: TSKRAnnotation;
const aText: string;
var oTextHeight, oTextWidth: integer);
begin
... idem ...
end;
__________________________________________________________________
Je ne prend toujours pas de risque et je fais confiance au compilateur pour les éventuelles erreurs de refactoring. Je n’ai changé aucun comportement.
La méthode Draw peu maintenant utiliser cette nouvelle classe :
__________________________________________________________________
procedure TSKRAnnotDrawer.Draw(Canvas: TCanvas3D; aRect: TRect);
var
...
begin
...
for i := 0 to Pred(FAnnotList.Count) do
with GetAnnot(i)^ do
begin
if Typ = 0 then
AnnotationPrefs := EventAnnotation
else
AnnotationPrefs := PeakAnnotation;
UpOrDown := AnnotationPrefs.AutoUpDown = apUp;
TTextPixelSizeHelper.GetTextHeightAndWidth(Canvas, AnnotationPrefs, Text, H, W);
...
DrawAnnotation(Canvas, Text, Point(XFree, YFree),
XFree, AnnotationPrefs, UpOrDown, Width, Height, X, Y, aRect);
end;
end;
__________________________________________________________________
Au passage, nous avons diminué la complexité cyclomatique de la fonction et facilité sa compréhension.
3- Ecriture d’un test qui échoue
Le principe du test est d’appeler deux fois de suite la fonction ‘GetTextHeightAndWidth’ avec le même texte et de vérifier qu’elle donne deux fois le même résultat.
__________________________________________________________________
procedure TSKRAnnotDrawerTest.testPeakNamesMightBePrintedBeOutisdeOfTheChartArea;
const
TEXT1_TO_DRAW = 'TestPeakAnnot';
TEXT2_TO_DRAW = TEXT1_TO_DRAW;
PEAK_ANNOTATION_TYPE = 1;
var
chart: TOrlandoChart;
form: TForm;
canvas: TCanvas3D;
peak_annotation_prefs: TSKRPeakAnnotationPrefs;
text1_height_result, text2_height_result: integer;
text1_width_result, text2_width_result: integer;
begin
peak_annotation_prefs := TSKRPeakAnnotationPrefs.Create;
form := TForm.Create(nil);
chart := TOrlandoChart.Create(form);
chart.ParentWindow := form.Handle;
canvas := chart.Canvas;
try
canvas.Font.Size := 4;
assert(canvas.Font.Size <> peak_annotation_prefs.Font.size, 'Font size must be different to show the defect problem');
TTextPixelSizeHelper.GetTextHeightAndWidth(
canvas, peak_annotation_prefs, TEXT1_TO_DRAW,
text1_height_result, text1_width_result);
TTextPixelSizeHelper.GetTextHeightAndWidth(
canvas, peak_annotation_prefs, TEXT2_TO_DRAW,
text2_height_result, text2_width_result);
CheckEquals(text1_height_result, text2_height_result,
'calling twice the function with same text should provide the same Height result!');
CheckEquals(text1_width_result, text2_width_result,
'calling twice the function with same text should provide the same Width result!');
finally
peak_annotation_prefs.Free;
chart.Free;
form.free;
end;
end;
_________________________________________________________________
4- Correction du bug
La correction conciste à déplacer quelques lignes de code afin d’assigner la “font size” du canvas avant de s’en servir:
_________________________________________________________________
procedure TTextPixelSizeHelper.getTextHeightAndWidth(
const aCanvas: TCanvas3D;
const aAnnotationPrefs: TSKRAnnotation;
const aText: string;
var oTextHeight, oTextWidth: integer);
begin
if AnnotationPrefs.AutoUpDown = apAuto then
begin
Canvas.Font.Name := AnnotationPrefs.Font.name;
Canvas.Font.Size := AnnotationPrefs.Font.Size;
end;
if AnnotationPrefs.Orientation = aoOblique then
begin
//We take the size of the rectangle projection on a vertical axis
H := round(Sin(Pi / 4) * (Canvas.TextWidth(Text) + Canvas.TextHeight(Text)));
//and for W the size of the rectangle projection on the horizontal axis
W := round(Cos(Pi / 4) * (Canvas.TextWidth(Text) + Canvas.TextHeight(Text)));
end
else if AnnotationPrefs.Orientation = aoVertical then
begin
H := Canvas.TextWidth(Text);
W := Canvas.TextHeight(Text);
end
else //Horizontal
begin
H := Canvas.TextHeight(Text);
W := Canvas.TextWidth(Text);
end;
H := H + 4;
end;
_________________________________________________________________
La barre est verte! Donc place au refactoring si nécéssaire.
Conclusion
Tester du legacy code peut décourager bon nombre de développeurs. Ce n’ai pas très compliqué mais ça demande une petite gymnastique intellectuelle. Tout m’a semblé plus facile après quelques essais et la lecture du bien connu livre de Michael C. Feathers “Working Effectively with Legacy Code” . Ce n’ai pas toujours possible à un coût raisonnable alors dans notre équipe, nous ne nous demandons pas une obligation de résultat.
Avec quelques amis développeurs Grenoblois, nous allons présenter une session dédiée à ce sujet sur du vrai code lors de la conférence Agile Grenoble 2010; venez nous voir ;o) !
jeudi 2 septembre 2010
Les vacances sont finies !
Je vous ai proposé il y a quelques semaines un sondage pour connaitre vos motivations à me suivre sur ce blog. Vous êtes près de 70 abonnés aux flux RSS et je n’ai eu que 13 réponses à ce jour. Je ne vous cache pas ma déception!
Voici mes motivations à écrire :
- Partager mes connaissances
- Obtenir du feedback sur ma façon de voir les choses
- Consigner ce que j’apprends
- M’entrainer à écrire, art qui se perd sans pratiquer
- Me faire connaitre un peu
Vous pouvez m’aider de deux façons :
- En répondant au sondage qui ne comporte qu’une question à choix multiple ICI : 30 secondes montre en main.
- En me donnant du feedback car les commentaires des billets sont souvent aussi intéressant que les billets eux-mêmes.
jeudi 29 juillet 2010
mercredi 30 juin 2010
CARA – Grenoble : Rétrospective des Dojos 2009-2010
Lundi 28 Juin 2010 se tenait la dernière séance des Dojos du CARA pour cette année. Nous l’avons consacré à une rétrospective afin de nous améliorer pour l’année prochaine. J’ai eu le plaisir d’être facilitateur et voici le compte-rendu :
Nous étions 6 participants présents et plusieurs amis Agilistes nous ont envoyé leurs entrées.
Voici le plan :
En guise de check-in pour se mettre dans l’ambiance : Mr Face pour décrire son état d’esprit !
Puis nous avons fais une BrainStorming afin de rassembler
- les points qui ont bien marché et que nous voulons conserver (+)
- les points qui ont moins bien marché et que nous voudrions améliorer (-)
Nous avons ensuite regroupé en thèmes tous les points afin d’en choisir deux à améliorer :
Donc en point positifs, nous pouvons noter :
- la qualité des échanges avec une confiance de haut niveau.
- la variété des sujets abordés
- la qualité des dojos lorsqu’ils sont préparés
- la localisation de la salle
- la permutation des animateurs
- la mise en pratique des principes de programmation /TDD
- le travail sur du code de production
- … (jetez un oeil sur les post-its)
Nous avons voté et les deux sujets choisis pour amélioration sont :
- La gestion du temps
- Travailler sur du code réel
Voici les fruits de nos réflexions sur ces deux thèmes :
Bon, ça nécessite des petites explications :
- Pour gagner un peu de temps lors des séances, nous avons estimé que les rétrospectives de 30 minutes / 2 heures n’étaient pas une bonne utilisation de notre temps. C’est pourquoi nous allons les réduire à 10 minutes en commençant par le ROTI. Nous pourrons expliquer notre choix et en particulier les notes extrêmes. Les Post-its ne seront plus un passage obligatoire! Nous déciderons également lors de ces 10 min si le sujet doit être poursuivi ou non.
- Nous n’avons pas été très fort sur le démarrage des Dojos à 12h. Nous avons régulièrement commencé 15 ou 20 minutes en retard. Plusieurs causes sont à l’origine de cette dérive dont le fait qu’il ne soit pas évident de quitter son lieu de travail avant 12h et que nous avons eu plusieurs soucis d’utilisation du projecteur. Nous avons donc décidé de commencer à l’heure prévue quoi qu’il arrive; cette heure de début fera l’objet d’un sondage (12h, 12h10, 12h15, 12h20 ?). Nous rédigerons également un document de trouble shooting du projecteur. (Je vois deux actions sans propriétaire! … qui s’en occupe?)
- Le fait de travailler sur du code réel / legacy code plutôt que sur des sujets très simples fait l’unanimité. Nous aimerions donc travailler sur une même base de code pendant plusieurs séances avec comme fil conducteur le fait de s’améliorer sur la prise en main de legacy code (code non testé).
Nous aurions bien poursuivi sur d’autres thèmes mais la time-box était terminée. Nous avons identifier le besoin de discuter sur le “recrutement” de nouveaux participants. Nous pouvons le faire via le groupe de discution : http://groups.google.fr/group/cara-dojo . (entrée perso : les séances planifiées sur jours tournants ne satisfont au final pas grand monde; il serait bien qu’on en discute également.)
Nous avons conclu par un ROTI pour noter la qualité du temps investi pour l’année des Dojos et pour cette rétrospective: 0 – J’aurais mieux fais de rester chez moi –> 5 – J’ai très bien investi mon temps
Merci à tous pour votre participation aux dojos!
Luc
lundi 7 juin 2010
Test Scrum sur Scrum.org
Scrum.org propose un nouveau cadre de formation et certification. La certification Scrum est validée par un test de 50 questions sélectionnées au hasard dans une liste. Il faut obtenir 75% de bonnes réponses pour obtenir la certification!
J’ai fais le test, certaines questions ne sont pas évidentes. Voici mon résultat :
_____________________________
41 bonnes réponses sur 50, soit 82%
33 minutes
_____________________________
Faites le test ! http://www.scrum.org/scrumopen/
mercredi 31 mars 2010
Une rétrospective pas comme les autres
Introduction
Lundi 30 mars 2010 se tenait l'étape Suisse des XP Days 2010. La session que j'ai le plus aimé fut
"Apprenez les techniques de coaching avec le magicien d'Oz" de Portia Tung et Pascal Van Cauvenberghe
Cette session avait pour but de nous faire découvrir le Co-Coaching au travers d'un Jeu. En deux mots, le co-coaching permet à deux personnes de s'améliorer mutuellement en travaillant chacune leur tour sur un problème. Le jeu, quant à lui permet d'acquérir des techniques simple de coaching autour du questionnement, de l'observation de l'écoute et du feedback.
En pratique, il faut trois joueurs:
- Dorothy (le coaché)
- Le coach
- L'Observateur
Les trois joueurs réfléchissent à un problème qui leur tient à cœur personnellement
Puis trois cycles vont se succéder afin que chaque joueur puisse s'entraîner dans chaque rôle.
Le coach va tout d'abord questionner Dorothy avec des questions ouvertes (pas de réponse par oui ou par non), des questions de contrôle pour caractériser le problème puis avec des questions de vérification pour être certain que le coach et le coaché se comprennent bien. Puis, le coach va demander à Dorothy de se mettre dans la peau d'un personnage et de décrire ce qu'il ferait. Ceci permet de changer d'état d'esprit sur son problème et d'imaginer des solutions non intuitives.
Par exemple : Arthur, si tu es Lion, c'est à dire courageux et courtois, que ferais-tu pour solutionner ton problème
Arthur, si tu es Singe Volant, c'est à dire pratique et prêt à aider, que ferais-tu?
De cette façon, Arthur, le coaché va trouver des solutions à ses problème.
Enfin, l'observateur commente ce qu'il a vu et entendu pour que tout le monde puisse progresser!
Seule Portia Tung peut expliquer le jeu dans les règles de l'art alors je vous invite à assister à l'une de ses présentations avec Pascal Van Cauvenberghe!
Le jeu peut être téléchargé sur Agile Fairy Tales : http://www.agilefairytales.com/dist/The-Yellow-Brick-Road-2-0.zip
Jai profité de ce que j'ai appris lors de cette session pour voir comment je pouvais l'appliquer en interne dans mon entreprise et je me suis dis pourquoi pas la rétrospective de sprint! Ca tombait bien, il y avait 3 participants. D'où la rétrospective pas comme les autres ...
Le plan
10h30 - 10h45 : Introduction / Check-in
- Présentation du plan
- Si vous aviez été un animal, qu'auriez vous été?
Voici les réponses des 3 participants ! Nous avons bien rigolé !
- Un hibou car je n'ai pas beaucoup été présent (Vacance, support chez un client, 5 jours avec l'équipe en 2 fois)
- Un singe car j'ai changer plusieurs fois d'activité (Développement de User Story, Support, Enquête sur problème de build)
- Un âne car nous avons échoué plusieurs User Stories alors que nous avions largement le temps de finir.
10h30 - 11h40 : Le jeu de "La Route de Brique Jaune" expliqué brièvement ci-dessus
Nous avons pris 10 minutes pour expliquer le jeu et pour que chaque participant identifie le problème sur lequel il voulait travailler
Voici les problèmes choisis
- Je crains que nous ayons d'autres problèmes tels que celui que j'ai du investiguer ce sprint
- On a cru que toutes les User Stories étaient finies mais à la fin du sprint il y avait plusieurs grains de sables qui ont fait que seule la moitié des User Stories ont pu être montré.
- Des tests automatisés se sont mis à échouer sans que l'on comprenne pourquoi
Nous avons effectué 3 tours de jeu de 10 minutes et chacun a pris son rôle très au sérieux. De vraies idées d'actions ont été trouvées par les coachés!
11h40 - 11h55 : Débriefing et choix des actions
Nous avons ensemble fait le tour des actions potentielles et finalement l’équipe les a toutes adopté!
11h55 - 12h00 : ROTI / Conclusion
En fin de rétrospective, il est bien d'obtenir un feedback sur la qualité du temps investi. Tous les participants ont voté pour la note maximale (0-J'aurais mieux fais de rester chez moi --> 5-J'ai vraiment bien fait de venir)
- 5 +
- 5 ++ Nous avons identifié des solutions à nos problèmes qui ne seraient pas sorties dans une rétrospective plus classique.
- 5+
Conclusion
Merci à Portia Tung et Pascal Van Cauvenberghe de m'avoir fait découvrir le Co-Coaching à travers le jeu de "la route de la brique jaune"
Merci à l'Equipe d'avoir joué le jeu !
Le co-coaching est très facile à mettre en place et un outil très efficace pour progresser.