Posts Tagged ‘agile’
It has been a while since we started using unit tests (and other types of tests) in our projects. But test driven design has always been something that once in a while I feel unskilled enough to do from start!?
Many people (including myself), for many reasons, that TDD is the way to go… but what happens when I have no clue on what I am building?
In the last 3 open source projects that I have worked at, only one started with TDD since its conception. 2 of those projects are actually tools (TestSlicer and VRaptor) while the other one is an continuous integration server.
The first project is about running integration builds faster by running only the required tests. In other words, it should only run the tests affected by the change log.
The problem with creating this tool is that, while coding it for the first time, it is so unclear how it will work or what it will exactly do that it was impossible to test it prior to creation. The first attempt was to use TDD and some code was created. After a few days, it was clear that the way the tool was going to achieve its purpose was way unclear in order to create integration tests for it. Some days afterwards everything was even more clear:
- unable to keep up coding it due to the lack of more advanced tests
- it was possible to create such a tool
After the first version was used in production, the conclusion was that it was a great approach to use and drop and re-use TDD in this project, because the idea was way so unclear that it would require anyway a complete coding of the project from scratch – again. Due to the very early stage of the project and Its purposes and ideas evolving too fast in a short period, it felt/was counter-productive to keep tdd-ing.
VRaptor started from scratch with TDD and went just fine. We all knew its purpose and had a somehow clear vision of what we desired (a refactor friendly framework), not knowing exactly how to implement it – but in the end, achieving it. TDD win.
The third project suffered from the same problem that the first one had. We just had a short (unclear) glimpse of what we wanted: “run all our tests in parallel” instead of “running our builds in parallel“. But how?
Should it be the job of our agent machines to consume what our servers make available? Or should the servers manage the agents (as cruise) to do their job? Should it be implemented through low-level sockets or http based resources? Everything was so unclear and changed so fast in the first couple of days that it was impossible to test first, code afterwards at that time.
After the first trial on a private project, it was clear how to and even more clear what we wanted to achieve, so it was time to refactor and start TDD’ing.
This is the common feeling that I have found about TDD bugging people</a… whenever your project is a prototype to check that something is possible of doing, or you are just creating something completely new that you have no idea what it is, it sounds you should first create the prototype, throw it away and restart it with TDD.
Maybe typical web-based app’s won’t suffer of this problem because sprint plannings will help getting things clear in the developer’s mind. But developing a library or a tool for other developers it not the same type of task. At least during the first few moments…
There is a short slide show to illustrate some thoughts. There will be better ones in the near future.
When is the right timing to break compatibility of a public api regarding its previous versions?
Whenever has a major change (i.e. 1.2.0 to 2.0.0) it might be completely rewritten in such a way that even allows its users to adopt both versions at the same time.
Some projects use the version number as a marketing technique in order to keep themselves up-to-date with their competitors.
Some products are famous for, whenever a new release appears, breaking compatibility with code written so far, requiring all programmers to rewrite part of their code. If you check Visual Basic’s life, every one-to-two years there was a major release with (usually) incompatibility.
VB programmers were used to that issue and kept coding the old projects using the previous release until the project was finished. Companies just got used to it and learned how to live on.
If your code is well tested through the use of automated tests, updating a library or a compiler/language version is an easier task because all incompatibility issues will be found prior to packing a new release of your product to your clients. testing++!
If you do not write code for your tests, as soon as you update a library/compiler/language, well….. have fun as it will probably be an unique adventure.
The java developers
Unfortunately, there is still a big part of the java community who do not write automated tests. Aside with the java legacy code that exists lacking any lines of automated tests in the world, sticking to compatibility between java releases can be seen as a good thing for the world, in general.
But for those who already write their tests, all that care with compatibility might be seen as a overestimated issue: due to the tests, we are ready to change and embrance those changes.
The java 7 crew is aware that there is a lot more that we can add to the language, but afraid because it will not preserve high levels of compatibility and usability.
What happens if the language has to worry so much about compatibility? It will evolve so slow that other languages have the chance to overcome it. This is the danger that the language itself faces. Java might not lose its position but one can find a lot more people arguing about language changes that could be done to the language – but are not… because preserving compatibility has been a main issue.
At the same time, some of the changes proposed might create huge incompatibility issues for those users who still do not write tests or that software who was not written using TDD practices. There is also another document on the same issue on the internet.
This proposes that methods defining a void return type should be considered as returning this. This way one can easily use it with Builder-patterned apis:
final JFrame jFrame = new JFrame()
.setBounds(100, 100, 100, 100)
There are a few issues with that proposal that do not match the “let’s keep it backwards compatible” saying.
The first thing is that, nowadays, builder (or construction pattern) apis are already created returning something specific instead of void, as we can see from Hibernate‘s API, and the new date and time api.
The second point is that builders are used nowadays to create Domain Specific Languages and their implementation in Java do not use a single object because it would create a huge (and nasty) class. DSL’s are usually built in Java by using different types, i.e. the criteria API from Hibernate.
Even the given example is actually no builder api… JFrame configuration methods and real-time-usage methods are all within… itself! There is no JFrameBuilder which would build a JFrame, i.e.:
Builder b = new Builder();
JFrame frame = b.build();
Notice that in the simple example above, it would be a good idea to have two different types (Builder and PanelBuilder) thus the language modification do not achieve what we want our code to look like (or be used like). Instead, it will only allow us to remove the variable name from appearing 10 times in our code, making it easier for programmers to write lines of code like this:
// ugly line which has too much information at once
JFrame frame = new JFrame().setA("a").setB(2,3).setC("c").setD("d").andOn().andOn().andOn();
But why does it go against Java’s saying ‘we should not break compatibility’? Because it creates a even higher degree of coupling between my code and the api i am using.
Well, imagine that I used the swing api as mentioned above. In a future release of Swing, some of those methods might have their signature changed and therefore break my existing code. Why would an api change their method return type? Well, because if the return type was defined as void so far, no one was using it… so I can change it.
It creates the same type of coupling found while using class-inheritance in Java while using APIs. Parent methods being invoked might change their signature
Well, it was true until today. If this functionality is approved for the Java API, it will make a simple task of changing a “void” return type to something useful a hard task, where I have to think about those who have tightly-coupled their code to mine.
The questions and answers which come to my mind are…
a) is the existing Java codebase around the world usually automated tested? unfortunately, no
b) does Java want to be backward compatible? this change will not help it
c) does it want to help the creation of dsls? this change is not the solution
d) does Java want us to avoid writing the variable name multiple times? my IDE already helps me with that
as a friend pointed out: “if you use a full time scrum master (in a small team), you do not need a scrum master, you need a gun”…
if you need too much to sort things out, someone should take control and change everything…
The Agile Brazil 2009 meeting gave me something really nice to think about (and play with).For those who still do not know, I have studied Applied Math at USP and switched to Computer Applied Math. During my earlier years at the university, I have had a mentor who had his specialization in dynamical systems and chaos.
As a programming geek, many of my early efforts at Java and bytecode compilation using Janino were to build a software that was able to run iterative methods in order to qualitatively find specific conditions in a dynamical system, that was Pulga.
Mathematically thinking, an attractor is a set which over continuous iteration of a function f, attracts some sets in such a way that, no matter how close i want to get to my attractor, i can get, in other words there is a finite number of iterations over f which, after those iterations, the distance of the result of any following iteration to this set is lesser than the distance that i want.
This – unformal – definition of an attractor is broad enough to let me define either a point or an open set as an attractor.
An initial condition over constant iteration through the f function can lead someone closer and closer to this set (which might not be unique) but all of the sudden, after a finite number of iterations, revert its situation to something else, as a chaotic behaviour for instance.
But who is attracted? The set of points whose orbit converges to this attractor is called that attractor’s basin of attraction. This means, that whichever point your start at, if its contained in that attractor’s basin, its orbit will converge to the attractor.
During the event, one of the presenters made an really interesting comment on agile iterations and iterative methods. Iterative methods can be used to find minimums and maximums of functions – either locals or globals. Non-linear programming is (hated by many students) a subject which studies those methods and most of the comments I heard were somehow connected to either this subject or simulated annealing.
In an iterative development process, one can think of the retrospective as f function, which – we believe – will improve our situation over every iteration (time). The methodology used in the first iteration is the starting condition of our system and the infinite open set of possible methodologies is our domain.
Every time the retrospective takes place, f is applied, and we get a different methodology which will be applied. This does not mean that it will converge to a local or global minimum as it might converge to a local or global maximum. Even more complex, its orbit might converge to an attractor set which is composed by methodologies situations that we perceive both as good and bad or our project and our team’s health.
During the talk, i was in doubt on how could we tell that applying f (the retrospective), the results were better. Of course, we have a lot of subjective ideas that might give us the perception of “improving”. The presenter also told about a good way of measuring results, the velocity.
Velocity is based on perception as the importance of features for the client might not be the improvement reality for the company. The guys at globo.com told me they were using “new open bugs” and “received calls” at the support desk as a measure of improvement. It seems like the “new open bugs” approach is really good to measure quality improvement but still not so good to measure “new features capability” improvements.
Mathematically thinking, improvement itself can be temporary and “f” can be leading us to even a worse attractor as it might not yet have reached a fixed orbit (or any similar set), giving us the impression that we are better right now and surprising us in the next year, when everything corrupts.
One of the fastest ways to find such attractors is to iterate many starting conditions instead of just one. The odds of finding attractors sooner is bigger. Even better, after a specific number of iterations over f, one can combine the conditions and create different ones – “genetically modifying your conditions”.
In the development world, that would be similar to, after realizing that the retrospectives are not helping any further, grab ideas which improved other projects within your company and bring them to your project, leaving the old ones to who else wants it. This leads to even more different conditions and increases, again, the odds of finding global minimums or attractors.
Why is it interesting for you?
I was really happy to see someone talking about development processes in such a way that we can mathematically define. Although it seems not yet mature for (myself) writing papers on it, the idea of iterative methods was always close to my life, and i have never noticed how it was part of my professional life.
Its the mix of math and other areas that allows us to see how we can create and innovate the way of thinking. So far we created a lot of things with our science base, now its time to take it to another level. Iteratively improving might help myself, what about you?