Only one MessageDialog may be displayed

On Windows 8, a call to "await aMessageDialog.ShowAsync()" can only be made once, otherwise System.UnauthorizedAccessException will be thrown (E_ACCESSDENIED 80070005). This is a helper method to display dialogs although it's not thread-safe. It's inspired on StackOverflow answers:

  1. public static class DialogDisplayer {
  2. private static IAsyncOperation currentlyShownDialog;
  4. public static async Task TryToShowDialog(MessageDialog messageDialog){
  5. try{
  6. RequestPreviousDialogCancelation();
  7. await WaitForUIThreadToBeReady();
  8. await ShowDialog(messageDialog);
  9. }
  10. catch (TimeoutException ex){
  11. //Logger.Information("Time out waiting for a MessageDialog to be closed");
  12. }
  13. catch (TaskCanceledException ex){
  14. CancelDialog();
  15. }
  16. catch (UnauthorizedAccessException ex){
  17. //Logger.Information("Multiple dialogs are being opened at the same time. There is a direct call to ShowAsync somewhere. Instead of using ShowAsync, use this method");
  18. }
  19. }
  21. private static void CancelDialog(){
  22. currentlyShownDialog = null;
  23. }
  25. private static void RequestPreviousDialogCancelation(){
  26. if (IsThereAnyOpenedDialog()){
  27. currentlyShownDialog.Cancel();
  28. }
  29. }
  31. private static async Task ShowDialog(MessageDialog messageDialog){
  32. currentlyShownDialog = messageDialog.ShowAsync();
  33. await currentlyShownDialog;
  34. }
  36. private static async Task WaitForUIThreadToBeReady(){
  37. var attempts = 0;
  38. while (IsThereAnyOpenedDialog()){
  39. await Task.Delay(TimeSpan.FromMilliseconds(100));
  40. attempts++;
  41. if (attempts > 5){
  42. throw new TimeoutException();
  43. }
  44. }
  45. }
  47. private static bool IsThereAnyOpenedDialog(){
  48. return currentlyShownDialog != null && currentlyShownDialog.Status == AsyncStatus.Started;
  49. }
  50. }


  1. var messageDialog = new MessageDialog("Hello world");
  2. await DialogDisplayer.TryToShowDialog(messageDialog);

Polymorphic test setup with template method

We had a kind of duplication in our tests that we didn't know how to deal with. The refactoring "Introduce Polymorphic Creation with Factory Method" explained by Joshua Kerievsky in his brilliant book "Refactoring to Patterns" gave me the solution to avoid duplicated tests.

  1. [TestFixture] public class
  2. ChangingColorWithImplicitExclusionsShould : ConfigurationTests {
  3. [Test] public void
  4. not_allow_change_when_its_compulsory_has_the_same_family_than_a_configured_equipment() {
  5. CatalogBuilder
  6. .AddEquipmentWithFamily("PR1", "Radio")
  7. .AddEquipmentWithFamily("PR2", "Radio")
  8. .AddColor("red", WithEquipmentsCompulsory("PR2"));
  9. var configuration = Agiven.ModelConfiguration()
  10. .With(Agiven.ConfigEquipment("PR1"))
  11. .Build();
  13. Expect.CallTo(() => ExecuteChangeColor("red", configuration))
  14. .ToThrow<EquipmentsWithSameFamilyException>();
  15. }
  16. }
  18. [TestFixture] public class
  19. ChangingInteriorWithImplicitExclusionsShould : ConfigurationTests {
  20. [Test] public void
  21. not_allow_change_when_its_compulsory_has_the_same_family_than_a_configured_equipment() {
  22. CatalogBuilder
  23. .AddEquipmentWithFamily("PR1", "Radio")
  24. .AddEquipmentWithFamily("PR2", "Radio")
  25. .AddInterior("xyz", WithEquipmentsCompulsory("PR2"));
  26. var configuration = Agiven.ModelConfiguration()
  27. .With(Agiven.ConfigEquipment("PR1"))
  28. .Build();
  30. Expect.CallTo(() => ExecuteChangeInterior("xyz", configuration))
  31. .ToThrow<EquipmentsWithSameFamilyException>();
  32. }
  33. }

Tests are very similar, the differences are in lines 8 and 25, and also in lines 13 and 30. First tests tries to change the color of a configuration whereas the second one tries the interior. Part of the handling business logic is the same. This is just one scenario but we had many of them, with same expected behavior for color, interior, equipment, and more. Eventually there was a lot of "duplication".

After refactoring, we have a base abstract class with the tests, exposing template methods that child classes have to implement in order to populate the catalog and also to execute the corresponding action:

  1. [TestFixture] public abstract class
  2. CantChangeConfigurationBecauseThereisImplicitExclusionWhen : ConfigurationTests {
  3. [Test] public void
  4. its_compulsory_has_the_same_family_than_a_configured_equipment() {
  5. CatalogBuilder
  6. .AddEquipmentWithFamily("PR1", "Radio")
  7. .AddEquipmentWithFamily("PR2", "Radio");
  8. AddImplicitExclusionItemWithCompulsories("PR2");
  9. var configuration = Agiven.ModelConfiguration()
  10. .With(Agiven.ConfigEquipment("PR1"))
  11. .Build();
  13. Expect.CallTo(ChooseConflictiveItem(configuration))
  14. .ToThrow<EquipmentsWithSameFamilyException>();
  15. }
  17. protected abstract void AddImplicitExclusionItem(string code);
  18. protected abstract Func<ModelConfiguration> ChooseConflictiveItem(ModelConfiguration configuration);
  19. }
  21. [TestFixture] public class
  22. ChangingColor : CantChangeConfigurationBecauseThereisImplicitExclusionWhen
  23. private const string itemCode = "irrelevant";
  25. protected override void AddImplicitExclusionItem(string code){
  26. CatalogBuilder
  27. .AddColor(itemCode, WithEquipmentsCompulsory(code));
  28. }
  30. protected override Func<ModelConfiguration> ChooseConflictiveItem(ModelConfiguration configuration){
  31. return () => ExecuteChangeColor(itemCode, configuration);
  32. }
  33. }

The base class "ConfigurationTests" contains just helper methods such as ExecuteChangeColor, or ExecuteChangeInterior, but no tests at all. Otherwise tests would run twice.

Refactoring katas with your own codebase

When it comes to refactoring, my preferred katas consist of experimentation with the actual code base I am working on. I just create a new branch from a certain commit, play with several refactorings and then throw it away. I usually end up with several experimental branches starting from the same commit. Sometimes if I end up with a better design, I apply the changes to the default or master branch, but that is not the goal. The goal is to improve my refactoring and design skills.

Pretty much every day, as I am coding, I find out slices of the code that smell. I find out room for a better design. However, if the code is working fine, I mean, if there are no known defects, if there is no real need to change, it's probably not worth spending work time to refactor it. At least not now. But I do write down a note about the smell to think about it later. This note often becomes the subject of the code kata.

When you approach your code base as a code kata, you don't have to care about time, you can just spend as much time as you want enjoying and learning. That code deals with a degree of complexity that is often hard to find in code katas. It's a real challenge. A big chance to improve your skills. The fact that I can experiment without any pressure, sometimes lead me to much better designs that the code base end up benefiting from. Eventually it's also good for my customers and colleagues.

Try it out and let me know whether you find it useful 😉

Mind the age and context of the book

Usually IT books don't age very well, things change very fast in the sector. This is specially true of books on particular tools, libraries, frameworks... but even books about methods and techniques require critical thinking when studying them. If the book is 5 or 10 years old, it's very likely that the author himself doesn't code the way he described in his book. We evolve as programmers - hopefully. However that doesn't mean that the book is no longer valuable. Many things are still valuable for sure, we just have to figure out what slices are useful today given our current context. Reasoning may be different if the programming language is not the same you use today, or even if its version is not the same. The paradigm may be different as well. Tools change and evolve very fast so unit tests written today, with all the fancy assertion libraries we have plus all the modern features of xUnit frameworks,  have to be very different to the unit tests you can find in a book written a decade ago.

I am currently reading a classic book, a great one from Martin Fowler Signature series - not written by Martin though. The book is terrific, I wander why didn't I read it then years ago! I am getting a lot of value from it, but I also notice certain old fashion techniques with well-known downsides.

I wrote a book on TDD 6 years ago. Since then my programming style has changed quite a lot. The way I do TDD today is different, and there are certain examples in the book that I even consider anti-patterns. I don't know when will I be able to rewrite it, although I wish, but the reality is that time flies.

Consider the age and context of books, don't just assume everything is valid today

Reflexiones tras una emotiva CAS2015


No habia participado en una Conferencia Agile Spain desde el 2010 que fué en Madrid, la primera. En aquel entonces iba ilusionado con 50 ejemplares en mi maleta de nuestro flamante libro de TDD, que colocamos en el stand de Plain Concepts porque amablemente me brindaron su espacio y hasta los vendían ellos. Plain aun era una empresa pequeña. Mi segundo arranque como autónomo había sido a penas un año atrás, antes del AOS 2009, primer gran evento de la comunidad, tambien en Madrid. Llevaba la ilusión de ver a todos aquellos nuevos amigos que había conocido en el AOS. No diré nombres para no dejarme a nadie fuera.

Después de aquella CAS, la avalancha de trabajo y la gran cantidad de viajes de avión que ello implica, hizo que tuviese menos disponibilidad. Me esforcé por conocer otras conferencias y otras comunidades. Quería salir por Europa y estuve en conferencias en Berlin y Londres. Y así los años han volado hasta llegar a CAS 2015. De nuevo en Madrid, la ciudad de las oportunidades para mí. Este año no podíamos faltar, teníamos que apoyar y de hecho es la primera vez que patrocinamos un evento de la comunidad. Estamos muy orgullosos de haber patrocinado, para nosotros es poner un granito de arena para que haya sido posible, aunque si no hubiesemos sido nosotros, había patrocinadores en cola, ... ¡qué éxito!

La organización de la conferencia ha sido brillante, para quitarse el sombrero. Los que me conocen saben que soy sincero, no lo diría si no lo pensase. Todo el equipo de organización y voluntarios se ha dejado la piel para que disfrutásemos. Me asombra especialmente lo tranquilos y confiados que veía a Alberto, Tino, Rubén, Vanesa, Gonzalo y Javier a pesar del monstruo que habían montado, un evento con 700 personas. Me resolvieron todos los contratiempos de última hora y me permitieron hacer la charleta de apertura cuando Javier Acero causó baja por su lesión de rodilla. Y debo decir que me lo pasé muy bien preparando la charla y luego sobre el escenario.

Desde hace unos años no me apetece dar charlas sino que prefiero formatos interactivos en plan taller donde podemos mantener conversaciones. Es porque no siento que aporte tanto valor con un monólogo durante tanto tiempo, no creo sinceramente que tenga cosas tan importantes que decir, creo que es más importante la sinergia que surge de la conversación. Pero en esta ocasión tenía que ser charla forzosamente así que como no me apetecía meter una chapa, quise que la gente se echase unas risas y se diviertiese, por lo que me propuse ensayar un baile y hacer un poco el payaso en el escenario. Pensé que sería una buena forma de abrir el día. Gracias a que Autentia lo grabó todo, queda ahí para los curiosos 😀

Había tanta gente que no pude hablar con muchos amigos, a penas pude decirles "hola" y a otros ni eso. Es lo que ocurre cuando el evento es masivo. Durante los breaks de comida y café, si me movía a buscar bebida me encontraba a gente por el camino y ya no volvía al sitio, dejaba las conversaciones a medias por más que no quisiera, una pasada. Un chute de socialización a los bestia, a lo loco. Conocí y "desvirtualice" a gente pero no nos dió tiempo a profundizar. Sabor agridulce por ese lado.
No pude asistir a las charlas que hubiese querido, de hecho practicamente no pude elegir charla pero por suerte estan grabadas.

Es muy bonito ver cómo han crecido durante estos años, profesionales de la comunidad a la que tuve la suerte de conocer en algunos de mis cursos y conferencias durante 2009, 2010, 2011... Hoy en día tengo ganas de visitarles y de trabajar con ellos porque tienen muchísimo que enseñarme. Esto es un éxito de la comunidad. Habiendome movido por otras comunidades de práctica en Europa sé que no tenemos nada que envidiar. Estamos a la altura para compartir con ellos lo que sabemos.

En cierto modo tengo la sensación de que la CAS se está distanciando del desarrollo de software, pero no me atrevería a decir si eso es bueno o malo. El taller de Tim Ingarfield y Diego Rojas fue para mi oro puro, me encantó estar allí y lo volveré a ver en video. Son unos genios. Me aportó muchísimo valor.
De alguna manera me gustaría que no nos olvidásemos de que una de las ideas de "Agile" cuando nació era acercar a gerentes y a técnicos, alinearnos todos. Y a veces tengo una sensación de que el trabajo técnico no está igual de valorado que la gestión de proyectos. Yo valoro mucho la gestion del proyecto, el cuidado de las personas, las dinámicas de equipos, la facilitación como via para quitar impedimentos... y necesito que tambien valoremos nuestro trabajo técnico. Que no se olvide que la calidad del software es tan importante como la calidad de las relaciones humanas. Que no se piense que para hacer carrera hay que dejar de programar y saltar a la gestión, sino que los que disfrutan de programar puedan hacer carrera como profesionales de la programación en sus empresas.
Me gustaría que la gente que fuese a la CAS no se fuese de allí sin saber por ejemplo que el método original se llama Extreme Programming y que estaba basado en unos valores y unos principios. Volver a recordar la raíz.
Dudo que sea buena idea que futuras ediciones de CAS sean incluso más grandes, ya me ha parecido que esta edición era gigantesca. Me pregunto, ¿por qué algunas personas hablaban de crecer en magnitud con cada edición futura, ¿qué tendría eso de bueno?
Crecer por crecer, no tiene por que ser bueno. Se me quedó grabada una idea de Joan Antoni Melé en una charla suya que vi hace tiempo donde comparaba a empresas cuyo objetivo era crecer por crecer, con un cáncer .

La keynote de Leo tuvo un fondo que me gustó mucho, el de no ser dogmaticos. Al menos eso entendí yo y me gusta porque el sentido común y el pragmatismo debe primar sobre los procesos y normas establecidos. Pero sus formas me parecieron agresivas y quizás un poco contraproducentes. Me pareció ofensiva la foto de "Manolo y Benito" cuando habló del movimiento de la artesanía del software, porque ese movimiento está buscando que se reconozca la importancia del trabajo técnico, al mismo nivel que se reconoce una buena gestión y facilitación. Ni más ni menos.
Tanto en su keynote como en alguna otra charla creí entender que se hablaba de programadores que se recrean más de la cuenta tratando de hacer florituras en el código. Creo que Artola dijo poeta del código. Bien, en mi experiencia, jamás he visitado una empresa o equipo donde pecasen de exceso de refactoring o de exceso de pair programming o mob programming. Si entendemos el refactoring por hacer el código existente, más legible y fácil de mantener y NO por un rediseño, entonces de veras que nunca he visto a nadie pecar de exceso de refactoring. El refactoring siempre se hace de menos, nunca de más. Yo recomiendo media horita de refactoring al dia, igual que el médigo recomiendo caminar media hora al día. Para que luego no haya que dedicar dias o semanas a intentar poner orden cuando está ya todo desordenado y sucio.
Lo que sí me suelo encontrar es sobreingeniería, hacer diseños de software demasiado grandes y complejos, arquitecturas gigantescas que no hacen falta. Y tambien veo gente invirtiendo tiempo en frameworks, librerías y otras herramientas, que luego no tiene un retorno de inversión. A veces se eligen porque parecen muy chulas, porque son modernas y acaban costando una fortuna. A veces esas herramientas se escogen para suplir lo que en realidad debería ser una arquitectura adaptada a las necesidades concretas del proyecto y esa falta de diseño se convierte en un cuello de botella con un coste matador.
El legendario Joshua Kerievsky en su libro "Refactoring to Patterns" habla de "underengineering" y de "overengineering". Técnicas como refactoring a diario y pair programming a diario ayudan a mitigar el riesgo de la infraingeniería y la sobreingeniería. Pero nadie dice que hay que estar todo el dia refactorizando ni todo el dia en pair programming! Uselo usted con sentido común!

En cierta forma me parece que algunos mensajes que se transmitieron pueden resultar muy confusos para los que no tienen suficiente bagaje. Me dió la impresión que echan por tierra parte del trabajo de reeducación y formación que hacemos en las empresas y en los equipos. Para mí el tema de fondo era clave y necesario pero las formas, arriesgadas.

He tenido profundas conversaciones con viejos y sabios amigos durante las cenas y el networking, que junto con el resto del evento me han hecho darme cuenta de lo mucho que la comunidad me apoya y me quiere. Pese a lo zoquete que he sido en varias ocasiones. Ver que ellos se quedan con lo bueno de uno y que son tan tolerantes con los defectos, me ha impactado. Me doy cuenta que la comunidad agile spain es un lugar donde crecer seguro, personal y profesionalmente, un sitio donde te permiten que te equivoques, que rectifiques, que cambies... y donde te apoyan a pesar de los fallos. Y esto es porque se trata de gente lista y madura. Estas conversaciones, esta revelación me está haciendo crecer. Me doy cuenta de que quiero aprender a comunicarme de forma no violenta. Que no quiero que mis malas formas estropeen el mensaje que quiero transmitir porque hieren a las personas y no ayudan a llegar a la meta, a ningún sitio. Sirva como ejemplo de lo que no quiero hacer, mi bronca con @semurat y @david_bonilla hace tiempo en twitter o mi bronca en el AOS de Tenerife.

Con esta comunidad y el apoyo incondicional de nuestro gran equipo CB&A, puedo prograsar cada día en constante mejora contínua. Podemos crecer juntos. Es un lujazo trabajar en un equipo donde, cuando te enteras que ha surgido cualquier problema ya tienes a un compañero trabajando en ello. No tienes que decirle a nadie que recoja los rollouts al terminar evento, cuando llega la hora de salir aparece Modesto con ellos al hombro. No tienes que pedirle a Alfredo que te traiga unas gafas para hacer el payaso, cuando llega la hora aparece con unas espectaculares. No tienes que pedirle a Luis que busque y hable con clientes nuestros que estaban allí en la CAS para pregunterles cómo les va, sino que cuando nos reunimos por la noche ya trae ya un resumen detallado de cada uno, con ideas y propuestas para ayudarles. No hace falta pedir feedback sincero, Nestor y Juan te lo dan así sea para ponerte en tu sitio. Fran se curró la landing page del evento por las noches aunque no pudiese venir.
Zazu estuvo ayudandome a maquetar las slides y el guión de mi presentación en todo momento.
La ilusión, las ganas y la sonrisa de nuestros aprendices, Ronny, Miguel y Dani son contagiosas fuentes de inspiración y motivación.

Gracias a todos los que han hecho posible la CAS2015, enhorabuena por conseguirlo.

Dejo por aqui las slides, ya actualizo el post con videos cuando se publiquen:

Pairing: don’t have to always agree on the plan

So your pair is proposing a route or plan that you don't agree on. Am talking about a refactoring, a redesign or just the way to test drive the next feature. You have told him your reasons no to agree with him and there is no way to get to an agreement. It's perhaps frustrating because you believe his strategy will fail but he definitely wants to proceed that way. What do you do? Argue forever?

I don't think you have to always agree on the path you are going to walk. The important thing is that both understand the plan so that driver and navigator can help each other get there. In those situations I end up saying... I believe this approach is not the best and I would try out something else - something I explained already... but anyway, I'll help you with your idea, let's do it.

Several times my pairs have proven that they were right and the plan was effective. Some other times it wasn't a good idea, but we built a trustworthy relationship, a supportive one.