I got on the agile bandwagon fairly late considering people are now celebrating the 10-year anniversary of the agile manifesto. But it's been a good 2 years now and I feel like it's a good time to sum up some of my experiences. And I'll start by writing something about estimating that's recently been on my mind a lot.
I get the impression that a large part of what people use to sell Scrum to managers is the ability to get better estimates and more reliable long-term planning. That tracking velocity and assigning storypoints to your features somehow enables you to determine what exactly you can release half a year from now. I don't think that's entirely honest. You still have no way to reliably predict accidental complexity; and team fluctuation, shifting priorities and delays in external processes that you depend on will still leave you guessing when you'll have that big new release ready.
The constant feedback obviously helps to at least be able to react to some of these obstacles. A looming deadline works wonders to get stakeholders to prioritize the features they want implemented. But I think all of this is looking at agile development from an old-fashioned angle, that is likely to be more frustrating than necessary.
Those big releases and big new major versions of your products just don't make all that much sense if you're not actually burning your software to disks to be put onto shelves. If you have a new little feature that will help your customers have a better experience using your product why wait to release it? If that feature actually doesn't help your customers, why wait to find out about it?
If you're a long-term agilante (agilista? agilero?), that is probably pretty obvious. But personally, I don't think I really grasped the power of that until recently. Really taking the idea of short iterations with incremental changes to its conclusion is not something I've seen much of in the time I've been developing software. You may read about some of the big poster-child internet companies working that way and increasingly, little start-ups seem to have a lot of success with it. But once companies get to a certain size they seem surprisingly eager to hold back on actually releasing their software.
And, with that said, I have decided that I do not care about estimating any more. I do care about the people on the team, I care about splitting items up into fine-grained tasks [edit: 'features' is probably the better word]. I might even care about tracking time spent on tasks to get feedback on whether we've become stuck on something. I care and take pride in the quality of the code we deliver. I care about people using that software and the feedback they can give. I don't care about dates in the future that may as well be arbitrary.
I conveniently ignore any kind of marketing needs or grand c0mpany strategy. Because, really, why shouldn't I? If we can consistently release new features in a short timeframe and the quality is good, why shouldn't the company strategy adapt to this rather than the other way around?
This idea is fairly fresh in my mind and I'm really looking forward to seeing what it develops into. I'm pretty sure I've missed a few things. And I'm curious what other people think about this...
Edit:
And to aptly prove the motto of this blog, Naresh Jain wrote about this two ears ago. Well worth reading.
Friday, March 4, 2011
Wednesday, February 9, 2011
Code Retreat - was ist das?
Labels:
agile,
coderetreat
Edit: es hat sich viel getan. Code Retreats finden mittlerweile ziemlich häufig statt. Auf der Seite der Softwerkskammer findet man mehr dazu. Die Veranstaltungen sind immer kostenlos und es lohnt sich auf jeden Fall, mal teil zu nehmen.
Vor kurzem habe ich an einem Code Retreat teilgenommen (Leo gibt für "retreat" u.a. Klausurtagung, was das ganze einigermaßen trifft) und war davon sehr angetan. Ich plane gerade, selbst einen solchen Event zu organisieren und im Zuge dessen lohnt es sich einmal ein paar erklärende Worte auf deutsch zu schreiben.
Ich bediene mich dabei sehr ausgiebig bei dem was Corey Haines und andere schon zu diesem Thema geschrieben haben. Am Ende dieses Artikels verweise ich auch noch auf einige weiterführende englische Seiten.
Und wenn wir dann unter Zeitdruck stehen, fallen wir zurück auf die Techniken, die wir beherrschen, auch wenn wir wissen, dass es bessere Möglichkeiten gibt. Das klassische Beispiel hier sind Software-Tests. Es ist nahe liegend, dass ein Projekt mit hoher Testabdeckung mehr Sicherheit beim hinzufügen von Änderungen bringt. Damit aber sowohl die eigentliche Testabdeckung, als auch das Durchführen von Änderungen mit einem vertretbaren Aufwand erreicht werden können, braucht es einiges an Erfahrung und Übung. Und wenn man diese Erfahrung nicht hat und der nächste wichtige Termin naht, ist es dann doch einfacher, die Tests zu ignorieren und direkt drauf los zu programmieren.
Einige Leute bringen an dieser Stelle auch gerne den Vergleich zu Musikern. Genau wie diese ihre Fingerübungen machen, kann man auch als Entwickler sein Können trainieren. Statt dessen geben wir aber jeden Tag ein Konzert. Das hat natürlich auch seinen Wert und man wird auch nicht vermeiden können sich hier und da zu verbessern. Man kann sich wahrscheinlich auch eine ganze Weile diesem Trott hingeben. Aber irgendwann nimmt einem die Eintönigkeit dann doch die Freude an der Arbeit.
An dieser Stelle kann man auch gleich einen Strich ziehen. Wer mit seinem Können zufrieden ist und sich damit wohlfühlt, sollte wohl nicht weiter lesen. Zufriedenheit ist schwer genug zu erreichen. Lernen sollte freiwillig und aus eigenem Interesse passieren.
Mehr und mehr finden sich auch Code Katas im Netz. Hier werden überschaubare Aufgabenstellungen wieder und wieder gelöst, um in ähnlichen Alltagssituationen praktisch reflexartig darauf reagieren zu können. Diese sind sowohl ein guter Weg selber zu üben, als auch interessant anzuschauen. Es gibt eine ganze Reihe von Leuten, die freundlicherweise ihre Lösungen im Netz bereit stellen, zum Teil auch als Screencasts. (http://codingkata.org/ http://www.katacasts.com/ http://codersdojo.org [Link aus dem Kommentar hinzugefügt]) Gerade für Einblicke in neue Programmiersprachen sind konkrete, bekannte Beispiele sehr hilfreich.
Überhaupt ist natürlich die Zusammenarbeit mit anderen wahrscheinlich die beste Möglichkeit, neue Dinge zu lernen.
Darüber hinaus gibt es natürlich auch noch andere Dinge. Unter anderem halt Code Retreats, sonst würde ich ja nicht diesen Artikel schreiben.
Es geht ganz klar nicht darum, die Aufgabenstellung zu lösen, sondern auszuprobieren, wie man anders an die Aufgabenstellung heran gehen kann. Insbesondere eignet sich das Format auch gerade dazu test-getriebenes Entwickeln zu üben.
Für mich war außerdem auch sehr interessant zu sehen, dass der entstandene Code nur einen Teil des Produkts der 45 Minuten ausmachte. Das entstandene Wissen über die konkrete Problemstellung brachte jeden neuen Durchgang deutlich näher an das Ziel als den Vorherigen.
Vor kurzem habe ich an einem Code Retreat teilgenommen (Leo gibt für "retreat" u.a. Klausurtagung, was das ganze einigermaßen trifft) und war davon sehr angetan. Ich plane gerade, selbst einen solchen Event zu organisieren und im Zuge dessen lohnt es sich einmal ein paar erklärende Worte auf deutsch zu schreiben.
Ich bediene mich dabei sehr ausgiebig bei dem was Corey Haines und andere schon zu diesem Thema geschrieben haben. Am Ende dieses Artikels verweise ich auch noch auf einige weiterführende englische Seiten.
Was ist das Problem?
Im normalen Arbeitsalltag wird kaum Zeit darauf verwendet, seine Fähigkeiten zu verbessern. Man nimmt vielleicht hier und da an Schulungen teil oder arbeitet sich gegebenenfalls in neue Frameworks ein. Aber wir arbeiten nicht gezielt daran unsere Arbeitsweisen zu verbessern oder unser bestehendes Know-How zu vertiefen.Und wenn wir dann unter Zeitdruck stehen, fallen wir zurück auf die Techniken, die wir beherrschen, auch wenn wir wissen, dass es bessere Möglichkeiten gibt. Das klassische Beispiel hier sind Software-Tests. Es ist nahe liegend, dass ein Projekt mit hoher Testabdeckung mehr Sicherheit beim hinzufügen von Änderungen bringt. Damit aber sowohl die eigentliche Testabdeckung, als auch das Durchführen von Änderungen mit einem vertretbaren Aufwand erreicht werden können, braucht es einiges an Erfahrung und Übung. Und wenn man diese Erfahrung nicht hat und der nächste wichtige Termin naht, ist es dann doch einfacher, die Tests zu ignorieren und direkt drauf los zu programmieren.
Einige Leute bringen an dieser Stelle auch gerne den Vergleich zu Musikern. Genau wie diese ihre Fingerübungen machen, kann man auch als Entwickler sein Können trainieren. Statt dessen geben wir aber jeden Tag ein Konzert. Das hat natürlich auch seinen Wert und man wird auch nicht vermeiden können sich hier und da zu verbessern. Man kann sich wahrscheinlich auch eine ganze Weile diesem Trott hingeben. Aber irgendwann nimmt einem die Eintönigkeit dann doch die Freude an der Arbeit.
An dieser Stelle kann man auch gleich einen Strich ziehen. Wer mit seinem Können zufrieden ist und sich damit wohlfühlt, sollte wohl nicht weiter lesen. Zufriedenheit ist schwer genug zu erreichen. Lernen sollte freiwillig und aus eigenem Interesse passieren.
Was kann man tun?
Wenn man sich bewusst die Zeit nimmt, gibt es eine Menge Dinge die man tun kann. Eine gute Möglichkeit, die vor kurzem in der GOOS-Mailingliste erwähnt wurde ist, sich gelegentlich einfach mal eine halbe Stunde Zeit zu nehmen, bestehenden Code zu verbessern. Dies sollten wirklich nur kleine Änderungen sein und man sollte sich an seine Zeitvorgabe halten. Ist man nach dieser Zeit nicht mit dem Ergebnis zufrieden, verwirft man seine Änderungen. Da dies ja primär als Weiterbildung zu sehen ist, sollte man gar nicht davon ausgehen wirklich Code zu committen. Und wenn dann doch eine Verbesserung dabei heraus kommt, umso besser!Mehr und mehr finden sich auch Code Katas im Netz. Hier werden überschaubare Aufgabenstellungen wieder und wieder gelöst, um in ähnlichen Alltagssituationen praktisch reflexartig darauf reagieren zu können. Diese sind sowohl ein guter Weg selber zu üben, als auch interessant anzuschauen. Es gibt eine ganze Reihe von Leuten, die freundlicherweise ihre Lösungen im Netz bereit stellen, zum Teil auch als Screencasts. (http://codingkata.org/ http://www.katacasts.com/ http://codersdojo.org [Link aus dem Kommentar hinzugefügt]) Gerade für Einblicke in neue Programmiersprachen sind konkrete, bekannte Beispiele sehr hilfreich.
Überhaupt ist natürlich die Zusammenarbeit mit anderen wahrscheinlich die beste Möglichkeit, neue Dinge zu lernen.
Darüber hinaus gibt es natürlich auch noch andere Dinge. Unter anderem halt Code Retreats, sonst würde ich ja nicht diesen Artikel schreiben.
Was sind jetzt also Code Retreats?
Code Retreats folgen einigen relativ einfachen Regeln:- Aufgabenstellung ist Conways Spiel des Lebens
- Mittels pair-programming und, nach Möglichkeit, test-getrieben, versucht man das Spiel zu implementieren
- Das macht man für 45 Minuten. Danach wirft man den geschriebenen Code weg. Keine Backups, kein committen in ein Repository. Einfach nur löschen
- Man nimmt sich ein paar Minuten Zeit, um in der Gruppe darüber zu reden, was man gelernt hat
- Man fängt wieder von vorne an (6-7 mal)
Es geht ganz klar nicht darum, die Aufgabenstellung zu lösen, sondern auszuprobieren, wie man anders an die Aufgabenstellung heran gehen kann. Insbesondere eignet sich das Format auch gerade dazu test-getriebenes Entwickeln zu üben.
Für mich war außerdem auch sehr interessant zu sehen, dass der entstandene Code nur einen Teil des Produkts der 45 Minuten ausmachte. Das entstandene Wissen über die konkrete Problemstellung brachte jeden neuen Durchgang deutlich näher an das Ziel als den Vorherigen.
Weiterführendes
- http://coderetreat.com/how-it-works.html Eine kurze Beschreibung des Ablaufs eines Code Retreats
- http://programmingtour.blogspot.com/2011/01/on-goals-of-coderetreat.html Ein etwas weiterführender Beitrag zu den Zielen. Enthält auch ein Video mit der Einleitung, die Corey Haines zu Beginn eines Code Retreats vorträgt
- http://www.infoq.com/presentations/Software-Craftsmanship-Beyond-The-Hype Die Präsentation von der QCon 2010, durch die ich auf das Thema gekommen bin
- http://vanryswyckjan.blogspot.com/2010/11/code-retreat-ghent.html ein Erfahrungsbericht
- http://financialagile.com/reflections/8-software/38-coreys-code-retreat und noch einer
Sunday, January 9, 2011
Remember back then?
...back in 2010? That was a nice year. I have to say I'm pretty happy with how it turned out. There were some setbacks, first and foremost the departure of two colleagues whose knowledge and support I valued very highly, who left for new cities and new challenges. But such is life. But I learned a lot this year and got to make a lot of interesting experiences and meet a lot of interesting people.
It was a long year and this will be a long post. It will be self-indulgent and most likely only for my own benefit. So there.
First off, I finally took the time to finish reading Domain Driven Design, or "the great blue book in the sky" as I heard someone (probably Neil Robbins) call it. It was very timely as we were just in the process of redoing a fairly large part of our application. It gave me the confidence to split up the refactoring along the life cycle of our main entity, transforming it along the way. That way we were able to concentrate on the first step in the life cycle without having to change everything down the line, too.
Said refactoring was also the first time I remember of deliberately doing "refactoring toward deeper insight". The experience of taking what we had learned about the domain in the previous year and applying that to our domain model was surprisingly rewarding. The end result was a lot simpler and closer to how people actually worked. It gave us the opportunity to introduce new functionality that would otherwise have been extremely cumbersome to implement.
The whole process was not without its flaws though. We underestimated the amount of code we had to change, even with the reduced scope. Especially the front-end proved that good UI design is very hard and time-consuming. In hindsight we probably should have spent more time on considering how the changes might have been divided further into smaller, releasable pieces. In the end we were left with a long time between deployments and suffered all the communication issues that missing regular feedback loops can give you. It was still a good learning experience and it showed me how much I appreciated our previous, shorter deployment iterations.
In march I went to QCon, which I wrote about before. The inspiration I got turned out to have a fairly lasting effect. To get back to the kind of enthusiasm I had when I started out and to be able to really consciously enjoy coding again is something I am extremely grateful for. This wasn't necessarily all due to QCon but it encouraged me to be more introspective about how I work. In particular it had me putting more effort into getting better at TDD. At some point the whole "using tests to drive out the design" bit finally clicked and it made me a happier person.
There is still a lot left to improve though. Most of our bug-fixing work is now purely front-end stuff, ironing out layouting issues and Javascript behaviour across different browsers. But we're getting there. Writing jasmine tests is something I'll hopefully get better at and which integrates well enough into our builds. My colleague Benjamin put an amazing amount of work into getting a useful Selenium tool-set and tests for us. The environment for these is sadly still somewhat brittle but hopefully that will get better with Selenium 2.
We've made a lot of progress in automation anyway. Our test-environment gets automatically redeployed by Teamcity now. These are still very tiny baby-steps towards continuous delivery that conveniently ignore some of the larger issues like schema evolution and the need to switch to a DVCS but at least I think it's stumbling in the right direction.
I was also happy I got to help in making collaboration with our designers on different teams a little easier. Working on a bunch of projects in parallel while trying to consolidate on a consistent look & feel is something that has taken even more effort than I expected. And since look & feel is usually the most immediately apparent contact point for stakeholders, it is always under scrutiny. I underestimated that, too, even though I really should know better. All the more reason to push for further front-end test automation.
Later in the year our team worked on a new project and decided to base it on JSF 2, mostly so we could get the know-how. The other teams were already using it and it seemed reasonable to look for common ground there. I did learn a lot, but I didn't get much done. Having no one on the team with any prior experience meant we had to go through all the little beginners mistakes you get when you stumble into some new technology. Some of those early issues just rubbed me the wrong way which made me get increasingly frustrated. And I'm afraid my growing resentment probably didn't help the mood of the team.
This did bring up a few interesting questions about the effectiveness of aiming for a heterogeneous development environment. Questions which I don't really have answers for but still could ramble on about for hours. So I should probably put that in another post some day.
In November I was lucky enough to take part in a Code Retreat. Having been intrigued by that ever since I saw Corey Haines talk about it at QCon, I jumped at the chance to try it out. This, too, is worthy of its own post and so I won't go into details here. Suffice it to say that I liked it a lot and plan to organize a code retreat in Düsseldorf, to show it to more people.
(As an aside, I just stumbled over a google result for a code retreat in Wroclaw which brought a smile to my face. I always enjoyed my time there, when I visited there for another company, back in another time. And I always had a very high opinion of the people and their programming skills there. So, I guess this fits quite well.)
After Code Retreat Ghent came Google Developer Day Munich. It was nice to meet my now ex-colleague Sebastian again. And same as in Ghent, I was glad for the opportunity to chit-chat with other people in our profession. It never hurts putting things in perspective and hearing what others are passionate about. And of course, rambling about things I'm passionate about. (Something I find myself doing more of these days, I think. But maybe it was just the free beer provided by Google.)
The effort Google puts into these events was impressive and I really liked how non-partisan the speakers were. They openly acknowledged the existence of competitors (foremost Apple) without looking to discredit or awkwardly ignore their work.
I wasn't looking for anything in particular since my work currently targets neither HTML 5-capable browsers nor mobile phones, but at the end of the day I felt more sad about that fact. I wasn't aware how exciting some of the HTML 5 stuff is and I'm really looking forward to that becoming the norm and what people will be able to do with it.
Well, that about does it for two-oh-one-oh. Remaining, then, is the goals I've set myself for 2011 (I'm not yet convinced of spelling it 20!!).
Hmm... last and possibly least I just realized that I also started writing on this blog (and on twitter) this year. I guess I'll keep that up.
It was a long year and this will be a long post. It will be self-indulgent and most likely only for my own benefit. So there.
First off, I finally took the time to finish reading Domain Driven Design, or "the great blue book in the sky" as I heard someone (probably Neil Robbins) call it. It was very timely as we were just in the process of redoing a fairly large part of our application. It gave me the confidence to split up the refactoring along the life cycle of our main entity, transforming it along the way. That way we were able to concentrate on the first step in the life cycle without having to change everything down the line, too.
Said refactoring was also the first time I remember of deliberately doing "refactoring toward deeper insight". The experience of taking what we had learned about the domain in the previous year and applying that to our domain model was surprisingly rewarding. The end result was a lot simpler and closer to how people actually worked. It gave us the opportunity to introduce new functionality that would otherwise have been extremely cumbersome to implement.
The whole process was not without its flaws though. We underestimated the amount of code we had to change, even with the reduced scope. Especially the front-end proved that good UI design is very hard and time-consuming. In hindsight we probably should have spent more time on considering how the changes might have been divided further into smaller, releasable pieces. In the end we were left with a long time between deployments and suffered all the communication issues that missing regular feedback loops can give you. It was still a good learning experience and it showed me how much I appreciated our previous, shorter deployment iterations.
In march I went to QCon, which I wrote about before. The inspiration I got turned out to have a fairly lasting effect. To get back to the kind of enthusiasm I had when I started out and to be able to really consciously enjoy coding again is something I am extremely grateful for. This wasn't necessarily all due to QCon but it encouraged me to be more introspective about how I work. In particular it had me putting more effort into getting better at TDD. At some point the whole "using tests to drive out the design" bit finally clicked and it made me a happier person.
There is still a lot left to improve though. Most of our bug-fixing work is now purely front-end stuff, ironing out layouting issues and Javascript behaviour across different browsers. But we're getting there. Writing jasmine tests is something I'll hopefully get better at and which integrates well enough into our builds. My colleague Benjamin put an amazing amount of work into getting a useful Selenium tool-set and tests for us. The environment for these is sadly still somewhat brittle but hopefully that will get better with Selenium 2.
We've made a lot of progress in automation anyway. Our test-environment gets automatically redeployed by Teamcity now. These are still very tiny baby-steps towards continuous delivery that conveniently ignore some of the larger issues like schema evolution and the need to switch to a DVCS but at least I think it's stumbling in the right direction.
I was also happy I got to help in making collaboration with our designers on different teams a little easier. Working on a bunch of projects in parallel while trying to consolidate on a consistent look & feel is something that has taken even more effort than I expected. And since look & feel is usually the most immediately apparent contact point for stakeholders, it is always under scrutiny. I underestimated that, too, even though I really should know better. All the more reason to push for further front-end test automation.
Later in the year our team worked on a new project and decided to base it on JSF 2, mostly so we could get the know-how. The other teams were already using it and it seemed reasonable to look for common ground there. I did learn a lot, but I didn't get much done. Having no one on the team with any prior experience meant we had to go through all the little beginners mistakes you get when you stumble into some new technology. Some of those early issues just rubbed me the wrong way which made me get increasingly frustrated. And I'm afraid my growing resentment probably didn't help the mood of the team.
This did bring up a few interesting questions about the effectiveness of aiming for a heterogeneous development environment. Questions which I don't really have answers for but still could ramble on about for hours. So I should probably put that in another post some day.
In November I was lucky enough to take part in a Code Retreat. Having been intrigued by that ever since I saw Corey Haines talk about it at QCon, I jumped at the chance to try it out. This, too, is worthy of its own post and so I won't go into details here. Suffice it to say that I liked it a lot and plan to organize a code retreat in Düsseldorf, to show it to more people.
(As an aside, I just stumbled over a google result for a code retreat in Wroclaw which brought a smile to my face. I always enjoyed my time there, when I visited there for another company, back in another time. And I always had a very high opinion of the people and their programming skills there. So, I guess this fits quite well.)
After Code Retreat Ghent came Google Developer Day Munich. It was nice to meet my now ex-colleague Sebastian again. And same as in Ghent, I was glad for the opportunity to chit-chat with other people in our profession. It never hurts putting things in perspective and hearing what others are passionate about. And of course, rambling about things I'm passionate about. (Something I find myself doing more of these days, I think. But maybe it was just the free beer provided by Google.)
The effort Google puts into these events was impressive and I really liked how non-partisan the speakers were. They openly acknowledged the existence of competitors (foremost Apple) without looking to discredit or awkwardly ignore their work.
I wasn't looking for anything in particular since my work currently targets neither HTML 5-capable browsers nor mobile phones, but at the end of the day I felt more sad about that fact. I wasn't aware how exciting some of the HTML 5 stuff is and I'm really looking forward to that becoming the norm and what people will be able to do with it.
Well, that about does it for two-oh-one-oh. Remaining, then, is the goals I've set myself for 2011 (I'm not yet convinced of spelling it 20!!).
- Organize a code retreat, possibly making it a recurring event
- Look for more of these opportunities to learn from others
- Subversion is a nightmare to merge stuff with and I'm eager to switch to git but it would mean having to get used to a different workflow for everyone in the team. Maybe I'll start with a git kata.
- Follow through on all the "I should really write a blog post about that"
- Write more posts in german.
- Read GOOS, finish reading REST in Practice, glance over Continuous Delivery.
- Try to solve more problems event-driven
Hmm... last and possibly least I just realized that I also started writing on this blog (and on twitter) this year. I guess I'll keep that up.
Friday, November 26, 2010
Javascript TDD with jasmine and maven
Labels:
javascript,
maven,
tdd
Edit[04/2011]: Since I seem to get the odd google hit on this it is worth pointing out that Justin Searls has since updated the plugin to include a lot more useful configuration options and also made it available in the maven central repo. So you can just use it straight away by following the instructions.
Edit[05/2011]: and now there is also this awesome site where you can try out jasmine and even do it in coffee script - all in your browser. Happy pandas all around!
As the amount of javascript in our project has grown quite considerably, it was time to get rid of this black spot in our test coverage. And since I'm getting more and more used to test-drive the code I'm writing, it was especially annoying to have to regress to trial-and-erring for the javascript part of our code.
I was overwhelmed by the choice of testing frameworks but eventually settled on jasmine, as that seems to be the most widely supported one with a reasonable syntax.
As all testing that is not automated might as well not exist it was important that it was possible to integrate it into our Teamcity setup. Thankfully, seraching for jasmine and maven quickly pointed me to jasmine-maven-plugin.
This plugin builds a html test runner that includes all javascript files in your project and then gets accessed with htmlunit and can run during the maven test phase, requiring no changes to our Teamcity build configuration.
Since we have a bunch of library and legacy javascript code that takes offence to being included directly I needed a way to filter which files actually got included in the test. There was some slightly out-of-date fork on github that included changes to configure inclusion and exclusion patterns which I was able to adapt to the current version (Which is available here).
The nice thing here is that all files are still copied to the target directory and the exclusions only affect what files get loaded in the test runner which proved useful soon enough.
I wasn't really happy just expecting all files to be loaded in the tests since that is not likely how it would happen in the deployed code. I am hoping to have the test specs define what other files are required by a specific functionality. Since all files get copied it is easy enough just loading them from inside the tests. I'm not quite happy with that yet as globals don't get reset between different jasmine Specs but it should be easy enough to add that functionality at some point.
Another nice feature of the maven plugin is the inclusion of other javascript artifacts. This way you can deploy libraries like jquery to your local maven repository and have them automatically included in your test runner.
So, with that said, this is what I currently have in our maven configuration:
Most of the options are explained very well in the main jasmine-maven-plugin README. I've only changed the plugin version to our own locally deployed version and made use of the new include option. This will only include files named *_spec.js in the test runner. The specs will then load additional files themselves.
Edit[05/2011]: and now there is also this awesome site where you can try out jasmine and even do it in coffee script - all in your browser. Happy pandas all around!
As the amount of javascript in our project has grown quite considerably, it was time to get rid of this black spot in our test coverage. And since I'm getting more and more used to test-drive the code I'm writing, it was especially annoying to have to regress to trial-and-erring for the javascript part of our code.
I was overwhelmed by the choice of testing frameworks but eventually settled on jasmine, as that seems to be the most widely supported one with a reasonable syntax.
As all testing that is not automated might as well not exist it was important that it was possible to integrate it into our Teamcity setup. Thankfully, seraching for jasmine and maven quickly pointed me to jasmine-maven-plugin.
This plugin builds a html test runner that includes all javascript files in your project and then gets accessed with htmlunit and can run during the maven test phase, requiring no changes to our Teamcity build configuration.
Since we have a bunch of library and legacy javascript code that takes offence to being included directly I needed a way to filter which files actually got included in the test. There was some slightly out-of-date fork on github that included changes to configure inclusion and exclusion patterns which I was able to adapt to the current version (Which is available here).
The nice thing here is that all files are still copied to the target directory and the exclusions only affect what files get loaded in the test runner which proved useful soon enough.
I wasn't really happy just expecting all files to be loaded in the tests since that is not likely how it would happen in the deployed code. I am hoping to have the test specs define what other files are required by a specific functionality. Since all files get copied it is easy enough just loading them from inside the tests. I'm not quite happy with that yet as globals don't get reset between different jasmine Specs but it should be easy enough to add that functionality at some point.
Another nice feature of the maven plugin is the inclusion of other javascript artifacts. This way you can deploy libraries like jquery to your local maven repository and have them automatically included in your test runner.
So, with that said, this is what I currently have in our maven configuration:
Most of the options are explained very well in the main jasmine-maven-plugin README. I've only changed the plugin version to our own locally deployed version and made use of the new include option. This will only include files named *_spec.js in the test runner. The specs will then load additional files themselves.
Wednesday, October 20, 2010
Oh, you got me there, cygwin
I wonder if there's an actual technical reason for this. Especially since the auto option cannot possibly work with those constraints. Hilarious.
$ u2d --help
u2d is part of cygutils version 1.4.4
converts the line endings of text files from
UNIX style (0x0a) to DOS style (0x0d 0x0a)
Usage: u2d [OPTION...] [input file list...]
Main options (not all may apply)
-A, --auto Output format will be the opposite of the autodetected source
format
-D, --u2d Output will be in DOS format
--unix2dos Output will be in DOS format
-U, --d2u Output will be in UNIX format
--dos2unix Output will be in UNIX format
--force Ignore binary file detection
--safe Do not modify binary files
Help options
-?, --help Show this help message
--usage Display brief usage message
--version Display version information
--license Display licensing information
Other arguments
[input file list...] for each file listed, convert in place.
If none specified, then use stdin/stdout
$ u2d -U messages_de.properties
u2d: cannot accept any conversion type argument other
than --u2d (--unix2dos, -D) when the program is called with this name
$ d2u -U messages_de.properties
messages_de.properties: done.
Thursday, September 16, 2010
Fun with firewalls
One of the applications I've been working on uses Spring Webflow and, at a few crucial points in the application, renders data into a JavaScript dialog. Spring offers a JavaScript library to help with handling AJAX requests, including support for handling redirect-on-POST inside aforementioned JavaScript dialogs.
So, in one particular case, you would click on a button, an asynchronous request would be made to enter a new view-state in Webflow and, after redirecting, the content of the response would get rendered in a JavaScript pop-up.
Eventually, one or two of our customers complained about this button not working. This was puzzling since it didn't affect the vast majority of our customers. Screenshots from the customers' machines showed no errors or gave any clue as to what was broken. We had a hunch it might have something to do with security settings but had no way to verify that or reproduce the behaviour on our end. For the time being we just gave up, as we were already considering doing away with the pop-up anyway.
A few weeks later I was digging through Spring's JavaScript code for some other reason and noticed how the asynchronous redirecting is handled. Since sending a HTTP redirect status would mean that the browser would redirect the complete window, Spring checks for Ajax requests and in case it finds one, puts a special header into the response and answers with a normal 200 status. Spring's JavaScript then checks for that special header and, if it thinks the response should be rendered in a pop-up, follows the redirect by making another Ajax request and displays the response in the pop-up. It's pretty clever and gives a lot of flexibility.
Out of curiosity I wanted to know what would happen if that special header didn't make it to the browser. I fired up Fiddler and replaced our server's response with a version with Spring's headers removed. I clicked on the button and - nothing happened! I was pretty happy that I figured out a way to reproduce the problem but I still wasn't sure this was actually the cause. Because why would anyone want to filter HTTP headers?
To be certain, I changed the JavaScript to show a descriptive error message to the user in case the headers went missing. This wouldn't actually fix the functionality but at least the user would get some feedback on clicking the button. The code eventually found its way onto our servers and a few months later we had a customer mail in a screenshot of the new error message. And with a little back and forth with their IT person we found out that it was indeed the firewall of the customer filtering out headers. Eventually they changed their settings so that they could use our application without problems.
Which really only leaves the question of 'Why?' It's understandable that non-IT companies with a small IT staff just rely on the default settings of whatever firewall package they bought. But as a developer of said firewall, what security do I gain by filtering response headers? I can see how filtering specific request headers makes sense at least in obscuring the internal network to the outside. But what harm could possibly come in a response header that couldn't otherwise also come via one of the white-listed headers or just plain via the response body?
Oh, well. There's a ticket in the SWF JIRA and it might be worth a look if you're using Webflow.
So, in one particular case, you would click on a button, an asynchronous request would be made to enter a new view-state in Webflow and, after redirecting, the content of the response would get rendered in a JavaScript pop-up.
Eventually, one or two of our customers complained about this button not working. This was puzzling since it didn't affect the vast majority of our customers. Screenshots from the customers' machines showed no errors or gave any clue as to what was broken. We had a hunch it might have something to do with security settings but had no way to verify that or reproduce the behaviour on our end. For the time being we just gave up, as we were already considering doing away with the pop-up anyway.
A few weeks later I was digging through Spring's JavaScript code for some other reason and noticed how the asynchronous redirecting is handled. Since sending a HTTP redirect status would mean that the browser would redirect the complete window, Spring checks for Ajax requests and in case it finds one, puts a special header into the response and answers with a normal 200 status. Spring's JavaScript then checks for that special header and, if it thinks the response should be rendered in a pop-up, follows the redirect by making another Ajax request and displays the response in the pop-up. It's pretty clever and gives a lot of flexibility.
Out of curiosity I wanted to know what would happen if that special header didn't make it to the browser. I fired up Fiddler and replaced our server's response with a version with Spring's headers removed. I clicked on the button and - nothing happened! I was pretty happy that I figured out a way to reproduce the problem but I still wasn't sure this was actually the cause. Because why would anyone want to filter HTTP headers?
To be certain, I changed the JavaScript to show a descriptive error message to the user in case the headers went missing. This wouldn't actually fix the functionality but at least the user would get some feedback on clicking the button. The code eventually found its way onto our servers and a few months later we had a customer mail in a screenshot of the new error message. And with a little back and forth with their IT person we found out that it was indeed the firewall of the customer filtering out headers. Eventually they changed their settings so that they could use our application without problems.
Which really only leaves the question of 'Why?' It's understandable that non-IT companies with a small IT staff just rely on the default settings of whatever firewall package they bought. But as a developer of said firewall, what security do I gain by filtering response headers? I can see how filtering specific request headers makes sense at least in obscuring the internal network to the outside. But what harm could possibly come in a response header that couldn't otherwise also come via one of the white-listed headers or just plain via the response body?
Oh, well. There's a ticket in the SWF JIRA and it might be worth a look if you're using Webflow.
Tuesday, August 3, 2010
Windows 7, Eclipse, Mintty
I recently switched to Windows 7 at work and so had to reinstall and rethink a couple of things and learned a few new things along the way.
While I was looking for a way to pin a cygwin shell to the taskbar, I found someone mentioning mintty. If only I had known about it earlier. Finally I can have a shell in windows that does copy/paste right. It defaults to paste on middle-click and you can configure it to copy-on-select so you get a nice linuxish behaviour.
And reinstalling eclipse I ran into quite an annoying issue that I wish would have been easier to figure out. If you unpack things into windows' program folder, Windows 7 sets permissions so that you need admin privileges to change anything. This is probably a pretty good idea, I just wasn't aware of it at all.
So now when I tried to install plugins in eclipse, it couldn't put them into its installed directory but instead created a .eclipse folder in my home directory and put stuff there. And apparently a lot of plugins can't really cope with that and just silently fail.
So, if you ever wondered why, even though it says that subclipse is installed, you don't have SVN as a choice of Team Provider, that's why.
And that was some very random and lucky googling that saved me from wasting a few more hours on that problem.
While I was looking for a way to pin a cygwin shell to the taskbar, I found someone mentioning mintty. If only I had known about it earlier. Finally I can have a shell in windows that does copy/paste right. It defaults to paste on middle-click and you can configure it to copy-on-select so you get a nice linuxish behaviour.
And reinstalling eclipse I ran into quite an annoying issue that I wish would have been easier to figure out. If you unpack things into windows' program folder, Windows 7 sets permissions so that you need admin privileges to change anything. This is probably a pretty good idea, I just wasn't aware of it at all.
So now when I tried to install plugins in eclipse, it couldn't put them into its installed directory but instead created a .eclipse folder in my home directory and put stuff there. And apparently a lot of plugins can't really cope with that and just silently fail.
So, if you ever wondered why, even though it says that subclipse is installed, you don't have SVN as a choice of Team Provider, that's why.
And that was some very random and lucky googling that saved me from wasting a few more hours on that problem.
Subscribe to:
Posts (Atom)