пятница, 20 марта 2015 г.

Developing a New Feature

I recently finished working a new piece of functionality on my job and it was a whole lot of experience. Even though that's not the first significant feature that I produced and I do know what the process usually looks like, some of its aspects caught me off-guard once again. It is wonderful how many surprises the process of development bears for a developer and how these same surprises continue to happen even after one passes through the process several times.

Of course it all starts with enthusiasm. If you don't hate your job, new challenging tasks always spur eagerness in you. Interestingly, the process of reading through the feature specification and long lists of requirements usually even makes it grow. The same is true about the attempts to lay out the general ideas about the solution and outline each of its components. More broadly, any planning and preparation activities increase willingness to get the problem solved and even despite seeing numerous problems, we tend to maintain motivation and good mood when getting ready for the actual work. Indeed, no matter what, we plan for success and the more we plan the more real it feels even when one sees that there are plenty of issues to overcome. One may even interpret this observation as a bit of advice - whenever you feel overwhelmed with problems and questions it may be a good idea to go and do a bit of planning - even though it might feel like you have already laid out everything, rethinking a particular piece of work might not only help understand it better, but also encourage you to do it.

However, once everything is planned and scheduled, one has to start development and produce some, preferably working, code. While the process usually starts smoothly, on some stage you smash into a seemingly impenetrable obstacle - confusion. Speaking of me, when planning I tend to thoroughly analyze various details of the future solution and study the existing bits of code, but I am not required to produce anything working right away on this stage and can be satisfied with a set of ideas and questions pinned down on a sheet of paper. On the other side, when getting down to implementation one has to squeeze new code into the mass of the application in such a manner that both old and new bits work. The sources of confusion are plenty here: sometimes you will try to add a new line of code in a method only to notice that you need to carry in 5 more arguments for it, which would make the method much less comprehensible and elegant (let alone the case when it is not elegant already). Or rather, you may find yourself in a situation when you want to change a long run of code, but feel that you miss some important ideas about it.

In my case this confusion - or maybe we should call it frustration? - is usually caused by a combination of two factors: the lack of understanding of the domain and imperfections of the legacy code on top of which (or more likely, inside which) I add new functionality. This doesn't mean that I start working on a feature or project without any knowledge of the domain - there's just always something that one doesn't understand and this is the norm. Similarly, the people who wrote the code that I have to work with are usually smart professionals, but their code is good for the task that they were solving - not always for the problem that I am currently addressing. While one cannot escape these difficulties, there is a way to tackle them - in the world of programming this is done well by refactoring the existing program or component and gradually injecting new pieces into it. While refactoring for its own sake might well be considered a bad practice, refactoring as a way to understand the code is a totally different story. Judging from my experience, there is hardly any other way to comprehend a considerably large class or method. Additionally, if you are changing the code anyway why shouldn't you make it more succinct and elegant as well?

Now, let's pretend I have paved my way around first obstacles and tackled the difficulties - what next? First of all, there are first pieces of a reward waiting for me. After I put some time into a feature, my head gradually wraps around it and I start feeling that I am able to address all the problems in a holistic and elegant manner and even make the existing solution a bit more efficient. This confidence alone greatly helps to move forward. Bad news is that these moments of high spirits usually alternate with periods when one notices more and more unforeseen issues. It feels like the more problems you solve, the more of them jump at you from nowhere. Even though good preliminary analysis and planning are supposed to reduce the amount of surprises of this flavor to minimum, they are never totally avoided. Sources might be different: sometimes a customer visits you with a shiny new idea or a forgotten nuance, in other cases you find out that a little change in one place impacts a distant component in an unpleasant way, or maybe you notice that what seemed a perfectly efficient and elegant redesign turns into an ugly muddle in light of a tiny edge case that you missed. The general idea is that one should expect the unexpected, because it always happens - usually in large amounts.

Fortunately, at some stage the task that looked like a mess of deeply intertwined problems becomes manageable and the carefully crafted solution takes the form of a solid thing. You start to address newly found problems with great ease and with even more impressing speed. You know the answers for most questions that one might ask in relation to the feature and to its neighbors. Furthermore, you are able to explain yourself and anyone willing to listen why the answers are those that you give. This is the state of expertise - both in the problem and in the solution (read implementation) - that is by itself a perfect reward for all efforts, weekends spent at the office and even sleepless nights marked with never ending search for a solution to some nasty problem. No matter whether the feature is small or large, isolated or integrated with a dozen other modules, one should feel proud when they reach this level of understanding and familiarity with it.

When the thing is almost done, however, new surprises come in. Like the final of any Hollywood movie provides some clue to a sequel, any feature added to a software product opens the door to dozens other enhancements, improvements and, well, bugs. I thought that my inability to foresee all these consequences is caused by the lack of experience, but it looks like even a group of experts can't always predict which problems a portion of new functionality may bring to existence. This basically means that there is no end to any particular feature or component. More precisely, the development can only be finished when we decide to finish it - you can't just do all of it. While this might feel depressing, there is hardly anything bad about the fact that there is always some work to be done. One should just remember this and be ready to postpone or reject some of the new ideas when they block completion of the feature. This will free you from the current burden and let you analyze all these new pieces together in a calm and reasonable manner. What's more important however, is that this way you will finally be able to mark the work item as resolved in the issue tracker or move the sticker forward on your Agile board, face the sweet feeling of achievement and have some celebration, because the thing is shipped!

While the process of developing new functionality is often an interesting and challenging activity, it might be difficult at times. You should just be ready to find yourself confused, frustrated and overwhelmed. These bad moments are simply a part of the process and their presence by no means suggests that something is wrong with the feature being developed or with you, as the developer. Eventually, these feelings will give place to satisfaction and pride with the awesome component that you deliver and with the new level of expertise that you reach through this undertaking.