Friday, December 27, 2013

Refactoring - Invest in your future

Legacy code


Legacy code - This phrase gives most of us the shivers. We imagine legacy code as a messy, unreadable, complicated, written-with-old-technology-and-conventions code. We embrace the dreadful phrase "if it works - don't touch it". We try to avoid as much as possible touching this horrible thing called Legacy code.

Smelly code: Picture taken from here

What exactly is legacy code?


I tried to get an answer to this question. Is it a code written using old technology? A code written by somebody who doesn't work for the company anymore? A code that is very fragile or complicated?

Well, I guess all of the above are correct. But I believe code becomes legacy code the moment it is too intimidating to be changed. No matter what the reason is. If you wrote a new feature today, which took you a lot of mental energy and time, and tomorrow you'll be afraid to change it, then I've got news for you - you have a new-born-healthy-two-days-old legacy code. Congratulations!!!


Refactoring


As time passes, our code becomes harder and harder to understand and maintain. The developers who touch the code come-and go, functionality evolves which causes much more flows that serve an ever-growing demand of use-cases to appear, technologies change but each of them leaves its signature on the code-base. 

Refactoring is our way, as engineers, to clean up the mess.  Some people think that refactoring is a matter of aesthetics. While this may be true, aesthetics is merely a mean to an end - making the code more easily-maintainable and more readable to others. And when I say others, I also mean - the future you. You are the one who most likely will read this code in the foreseeable future, and I bet you prefer not to struggle with it.


Invest in your future


A lot of engineers fail to realize that refactoring is an investment. You invest in order to save much more later. Every minute that is spent trying to understand the code, is a minute wasted. If the code is read by different people, in different times, and each of them struggles to understand it because it's complicated - that's a lot of time wasted. If only one of them would break the habbit and invest in a one time effort for a better future - a lot of development time would be spared and could be invested in new features.



The fear factor


And still, people, mostly, but certainly not exclusively, juniors, afraid of refactoring. And I have to admit, there are good reasons to be afraid. How do you start to read this code? It's so complicated and full of variables and branches and try-catches and too many lines of-code and code-duplications.

It's also very intimidating to refactor when the person who wrote most parts of the code does not work with you anymore. Or maybe it was you who wrote it but you just can't remember why the hell you did it this way, but you're sure there was a reason.


Eliminating the fear factor

Luckily we have so many tools in our disposal that, when you think about it, completely reduce the amount of fear one should have when refactoring.

You can always revert back to the way things were before the change using the source control.

Tests are key for an efficient refactor processYou need to have tests that test the code. If you don't have tests (or don't have enough) - write tests before starting to refactor. Not only will it improve your confidence that you don't break anything while refactoring, but it will also help you to better understand the code. 

Try to find ways to control and monitor your changes. For example, in Outbrain, we use feature flags in order to control new features. When we want to implement a new change, we create a flag that instructs the service on whether to use the new feature or not. This can be easily used for refactoring. And of course, it helps reverting in no-time. Just turn-off the feature and you're back to the way you were before the change. We also monitor a lot of metrics in every part of the flow. Usually, I can easily monitor the behaviour of a flow and see if anything changes. Even if you don't have advanced monitoring tools, you could utilize the log for monitoring the changes. Find your way to control and monitor the changes, this will greatly ease your fear.

Suspect comments. Comments are deceiving. They lead you to think that the code does something which it may or may not do. Computers don't understand comments, they just read the code. You should trust the code. If there are comments, use them as a guidance, but be very suspicious about them. Comments rot much faster than code. Also try to write code that is readable without comments when you refactor.

Take baby steps. Don't ever ever ever try to make too many changes at once. Always do one simple change and try to test it. You should allow yourself to be certain what was the exact change that caused problems. Don't make a project out of it. Refactoring is not a "all or nothing" deal. Every change you make, even the tiniest one, is blessed.

Boy scouts rule. Aside from taking baby steps, try to embrace the boy scouts rule - always leave the place cleaner than it was when you got there. While you work, do minor refactorings all the time. It's pretty easy and doesn't take a lot of time or effort. If everybody does that, the accumulating affect will create a much more robust code-base.

Invest only where necessary. If you see an ugly code which is very rarely touched, don't refactor it (aside from, maybe, very minor refactorings). It's not worth the effort. Invest in places to which you come back again and again. 

Use refactoring to learn. You already need to change and extend a piece of code. While refactoring you make the code readable for yourself. You start with minor refactoring, and bit-by-bit you unravel the code and learn how to extend it as you go.


What's the worst that could happen?


When I started working at Outbrain, I had an on-boarding with Ori Lahav, Co-Founder of Outbrain. Ori told us to embrace the phrase "What's the worst that could happen?" and told us to not let fears limit our progress.

When you refactor you should think exactly that - what's the worst that could happen? If you're not touching an extremely sensitive component, then it's no biggy. If you do refactor a sensitive component, there are probably, and hopefully, enough tests around it, and monitoring, and backups, and failover mechanisms and so on. And, of course, you'll take baby-steps and test and monitor the change carefully. So go ahead and refactor. What's the worst that could happen??

What's the worst that could happen?

My next post will include a video tutorial that shows how to refactor a piece of legacy-code using TDD. Hope you already can't wait!


Find me on Twitter: @AviEtzioni



More interesting posts from this blog:

Friday, December 20, 2013

Code Review - Just Do It! (Part 3 - What's Your Excuse?)

In my last 2 posts I talked about code-review as a great feedback tool, and after that I tried to give some numbers and reasons as to why you should do it. If you got up to this post, you probably a bit more convinced about code-review. And yet, people tend to give me (and themselves) a lot of excuses as to why they shouldn't code-review. 

This final post about code-review, will be dedicated to the various excuses and their refutation.


It takes too much time


The first excuse is the one I most strongly refuse to accept. Saying that code-review takes too much time implicitly implies that it's a waste of time. In my opinion, a software-engineer's work is to provide quality code in order to allow future maintenance of the software. A lot of other things take time - like talking about and writing designs, like monitoring our app and let us not forget automatic tests that require us a lot of time as well.
Code review is not a waste of time - it's an investment of time that will later save us much more time.


I'm not familiar with the code


I relate to this excuse more as more of a "reason" or "concern". That's true, it's harder to review code that you're not familiar with. But it's much easier than you'd might expect. It's so easy to spot code-smells - too many branching in a method, long methods/classes that do much more than they should, bad-namings, irrelevant and misleading comments, etc...

Let's look at the following code:


Almost every java developer would see that concatenating over and over will cause the heap to be filled with unused objects and the GC to work harder (let's assume no compiler-optimization). These examples (maybe a bit less trivial) happen a lot, and they need you to spot them.

Another great insight you can provide would be in a form of a question. "Did you run tests?", "How does this change affect other components?" and so on. These insights are very valuable. When we code, we don't always remember the full-picture around our feature, and it's great to have someone reminding us (before we discover the issues the hard way).


It's too subjective


That's true. Code-reviews are subjective. And yet, researches show an average of 82% of agreement amongst reviewers. This means that in 82% of the times, it's not that subjective. Also, you could always add more reviewers to help you decide when there is a difference of opinions. And lastly, you don't have to agree, but at least hear what others have to say. It might be useful.


It's just a minor change


Oh, what a devious excuse is this one. No matter if we're totally noobs in software-engineering, or we're experts with 20 years of experience, we fall for this one time after time. We just wanted to change a little string, maybe even a log line and BOOM (!!!), an exception is thrown. Let's take this "minor" example:





Won't it be sad when the NullPointerException will be thrown?

In our line of work, even this minor change can cause problems. Problems that could easily be avoided during a code-review.




JUST DO IT

If you've come this far, I hope I managed to convince you that code-review is something you should embrace in your organization. The best way to start is just doing it. Stop making excuses as to why it won't work and just start. The rest will follow.



Hope you enjoyed and learned from this 3-posts-long topic. In my next post I'll talk about refactoring of legacy code. Stay tuned ;)


Find me on Twitter: @AviEtzioni


More interesting posts from this blog:

Friday, December 13, 2013

Code Review - Just Do It! (Part 2 - What's in it for me??)

In my previous post, I talked about code-review as one of the great mechanisms we have to provide and accept feedback during our coding-process. In this post I'll try to talk about what you will really gain by code-reviewing.


Code Review (ha!) What is it good for?? (Absolutely something!)


When I try to convince people they should apply and use code-review, I tend to encounter lots of excuses. Well, perhaps it would be too accusing to say excuses, so let's say "concerns". Before addressing the various excuses (I mean, concerns) for not applying code-review as part of the development cycle, let's try and figure out why you should do code-review and what you gain from it. In my next post, I'll talk about the different excuses for refraining from it.


Defect types 


Let's try and understand what are the common defect-types code-review can reveal; In a research conducted in the University of Helsinki ("Defect Detection Efficiency: Test Case Based vs. Exploratory Testing") they tried to identify the types of issues found in a review. We can group those issues into three groups:
  1. Functional - The code doesn't do what it supposed to
  2. Maintainability - The code structure would be hard to maintain (classes that do too much, code style, strong coupling and so on...)
  3. False positives
While one might think that the functional problems are the main problems found in a code review, turns out these problems comprise only 21% of the problems found in a review. It means that usually, when you reviewing code, the code actually works exactly how the author claims it works. The majority of the problems are the maintainability problems which comprise 71% of the problems. This means that by code-reviewing you help keeping your code clean, maintainable and defend it from rotting. 




Defect Reduction


I tried to the dig around the web for numbers of defect reduction for different methods. I wasn't able to find any concrete scientific numbers, but I did find some less-official estimations. But between pair-programming (15%-50% of defect reduction), unit-tests (30%-60%) and code-review meeting (45%-50%) - I found the method I like most, the asynchronous code-review (in which you send the diff of your changes to your peers and they respond on their own time), to be considered as the most affective one with 60%-65% of defect reduction.



Still not sure?


Even when the numbers are so solid, people often can't see what they can gain, personally, from code-reviewing. Let's take a moment to talk about that.

Why should I seek this feedback?


Better code inspection

Before I publish my changes to review, I usually take a few minutes and read it again. Ensure I haven't left out any commented code or tweaks I had done while working, making sure the variables and methods are named with readable names, and so on. I do it because I know people will dig through my code, and I don't want to embarrass myself with poor quality code. This alone, helps me find issues even before the actual code review.


Get feedback from unbiased eyes

Your code does not necessarily do what you think it does. It's also not as readable as you might expect it to be. Having someone that was not part of the code-writing, inspecting your code, reveals the true readability, and true purpose of your code.


Find your problems sooner than later

I've already met a lot of people that prefer ignoring their problems. And why won't they? You're about to finish a feature you have been working on for a few days, you can't wait for it to be committed and deployed, and now you're getting all sorts of feedbacks and comments that require you to make changes to this state-of-the-art piece of code. But the fact is that the problems aren't going anywhere. You should embrace feedback and fix your problems as soon as you find them, while your mind is still on this mission. Fixing it later will cost you more as you will try to remember and understand the things you did, and why you did them.
You'll commit and deploy your code, don't worry. You'll be even more proud of it after you have fixed the issues.


Learn new stuff

You'd be surprised about what your peers can teach you. From a simple review you can learn about design patterns, quality-patterns, performance issues, design issues and a whole lot of other stuff. Try to learn from your peers, it's important in our line of work.


Teach the others

And your peers can also learn a lot from you, if you just give them the chance. By conducting code-review, they get a chance to see how you do stuff. And they'll most probably love to learn from you.


Why should I provide feedback to others?


Improve code-reading skills

One of the most important skills for a programmer is the ability to read other people's code. Practice code-review and you'll see how it allows you to get into new-code in no-time.


Learn new stuff

I already mentioned it in the previous section. This is your chance to learn how your peers work. Learn from it!


Better understanding of the code

By consistently reviewing your peers work, you'll learn what happens outside your zone. You'll get a complete view of the system you're working on, which will allow you to understand the affect of your code on all of the system.


Common goal

People tend to forget it. Your peer's success, is your organization's success which means your success! Help your peers improve their work, and your organization will become more successful, which you can only benefit from.


Let your voice be heard

How many times have you looked into others code and thought to yourself "what the hell they were thinking"? This is your time to prevent it! Let people know how you think things should be done. Not always will it work, but when it will, the future reader of the code (which might be you) will thank you for not letting things deteriorate.



What about the organization?


Organizations that encourage code-review will benefit greatly from the process. By creating more capable employees (which learn new-stuff all the time and improve their code-reading skills), by having a process the encourages knowledge-sharing. Also, new employees won't clutter the code due to their lack of understanding on how things work in the organization. The quality of the product will increase - allowing faster development of new feature and less bugs that the customers will have to face.
Lastly, code-review encourages discussion. An organization that wants to move forward should allow discussions and criticizing the process. Discussion is one of the most fruitful ways of taking the organization forward.


Hope I convinced you a bit more about code-review. In the next post I will cover the excuses I tend to hear as to why not to perform code-review. Stay tuned....



Find me on Twitter: @AviEtzioni



More interesting posts from this blog:

Friday, December 6, 2013

Code Review - Just Do It! (Part 1 - Feedback)

I cannot over-estimate how important I think code-quality is. And yet, some people believe that code-review is not for them. Perhaps they think it takes too long, or they're too good for being reviewed by other team members.

Recently I gave a talk about the importance of the code review in my opinion. You can find it here:



For those of you who don't speak hebrew, or prefer to just read instead of watching the video, I'll try to summarize here. I split the lecture into 3 different posts, don't forget to follow up for the next posts.

Review - Not only for developers


I guess it wouldn't come to you as a complete surprise that review was not invented by or for the software engineering industry. Students at the university ask peers to review their work and sometime even pay good money for getting a professional review. Authors and journalist wouldn't dream of releasing their writings without them being reviewed by someone (usually more than one). And even this blog is reviewed by native English speakers to make sure I don't write in Hebrish (an un-understandable mixture of Hebrew and English).

How can that be that not all of the software-engineers think their work should be reviewed?

 Feedback is all around us


I have worked in agile methodologies for more than 3 years already. When we try to be agile we try to seek feedback in every step of the way in order to solve problems as soon as possible. In the "Lean Start Up" book, by Eric Ries, it's described as "The Feedback Loop".

 

During our work, we encounter a lot of feedback loops. I tried to map the main feedback loops on my work at Outbrain. I found 6 main feedback loops during a feature's development from when its requirements are passed from the PM to the development team and until it's released:




We start with writing a design, usually followed by a review and feedback from our peers. When we feel comfortable with the design, we start coding. And, while we code, the IDE warns us about errors in an extremely short feedback cycle. We then use automation tests to get feedback on whether we break the code, and when the code is committed it goes through a build process which provides us with a feedback on how our code is integrated in the system.
After the code is released, we have a great monitoring system in Outbrain to monitor the features affect (on the users or on the server load, or any other KPI). Lastly, when things go wrong, we conduct a take-in to make sure we learn from our mistakes.

Looking at all of those great feedbacks, we can group those into two groups. The first group would be "Automatic Feedback" and the second would be "Human Feedback" as described in this picture:


Interesting observations on these two groups would be that the "Automatic Feedback" group exposes symptoms, whereas the "Human Feedback" group exposes problems.
This actually means that we start our coding process by asking feedback, and only after we're done, and the feature's out, we try to learn from our mistakes. During the time between these two human interactions, we're pretty much on our own. Adding a code-review cycle gives us another opportunity to get human feedback and improve our code before it's committed/deployed.

In my next post, I'll try to convince you that code review is great for the reviewer, the reviewee and of course - the organization.

To be continued...


Find me on Twitter: @AviEtzioni



More interesting posts from this blog:

Friday, November 29, 2013

My Retrospective About My Retrospective

Business as (too) usual


Back when I was working for my previous employer, we used SCRUM as our development methodology. As part of this methodology we used to end every sprint (3 weeks of work) with a retrospective.

During the retrospective, the team would sit down together and discuss what had been done well and what had not.

This was a recurring ceremony in which the team-leader guided us into talking about the painful pain points (along with the good things we've done - we don't want to be ALL negative). We used to discuss various issues; a lot of those times it was done with a lot of enthusiasm, maybe even some arguing.



Let's make things more exciting


During one of our 1x1s, my team-leader told me that he felt like we had to shake the dust from the retrospective process a bit, make it more exciting and, more importantly, more productive. His suggestion was to have a rotation between team members and let each of us lead a retrospective. We were encouraged to freshen things up, any way we deemed fit.

What should I do?


I started thinking about what I wanted to do when it was my turn to lead a retrospective. Should it be around one specific topic? Should it be a game? Should I stick with the original format?

I decided to think about what was bothering me in our retrospective process. It was a sort of a retrospective with myself about our retrospective.

I narrowed it down to 3 issues:
  1. Priorities: I realized that we don't always address the most important issues. We let our emotions, instead of our common-sense, affect the topics we discuss. Instead of finding 1 or 2 things that can improve us best, we discussed things that really annoyed us. We could not always change these things , or know that the change would have a great impact on the team or productivity, even if it happened.
  2. Not everyone's voice can be heard: Some people are more passionate when they speak, some are shy and some are more verbal and can convince others. It's hard to let everyone be equally heard and it was really important for me to try.
  3. Action items: We all want to change the world, or at least our organization, for the best. But we have to be realistic and set feasible goals that, in each sprint, would improve us a little more. 
So I decided to create a flow in my retrospective which will allow everyone to speak their minds, and will lead to an extremely focused set of 2-3 feasible and improving action items.


So that's what I did


Step 0: Preparations


I booked a room with a big erasable board. Before the team arrived I wrote down all of the stories we worked on during this sprint with different colors (in order to make it very clear where we were at the end of this sprint):


  • GREEN - ACCEPTED
  • ORANGE - IN PROGRESS
  • RED - NOT STARTED
I put some papers and pens on the table for the team to use later on.


This is how the board looked like when the team arrived



Step 1: Map the problems


I asked the team (myself included) to take 3-5 minutes and write down the four impediments which bothered them most. After all were finished we took turns in reading our notes and then wrote each of those on the board, near the stories that were already written there. Everyone could speak their minds about what was bothering them, without interruptions.



In Step 1 we added our painful impediments


Step 2: Suggest solutions


Pointing what's wrong or what's painful is fairly easy. Coming up with a solution to the problem, may sometimes be a bit more complicated. I, again, asked everybody to write down their suggested solutions to the impediments that were raised. When finished we took turns of reading the solutions and wrote down these suggestions on the board as well. This uncovered two interesting issues:
  1. Unsurprisingly - some of the problems had the same solution
  2. For some of the problems we couldn't find a solution with a good ROI (ROI = Return Of Investment: Meaning - all the solutions we found weren't worth their effort) 
This step made us focus on a smaller set of problems and their solutions. And again, everyone had their chance to suggest solutions.


Lastly - we added our suggested solutions


Step 3: Let's vote!


Lastly, I told the team that each team member gets 10 points. Those points were used for voting on the solutions that were suggested in the previous step. Each team member was allowed to distribute the points in any way (s)he wanted to. At the end, the top 3 solutions were chosen as our action items for the next sprint.

Step 4: Leave with a good taste


Before wrapping up I asked everyone to say what they thought was good during the sprint. I wanted the retrospective to end with a positive note. Also, it's important to preserve what we do well.


Conclusion



After the retrospective, I again did a little retrospective with myself. I tried to figure out if I managed to address the 3 problems I tried to face at the beginning. The democratic nature of the retrospective allowed everyone's voice to be heard, as I wanted, and prevented unnecessary arguments about the priorities. Also, at the end, we had to vote on some action items. Having time to think about what's really important and what we can really change, made us choose action items that were feasible. Those action items were tracked during the next sprint - I sent an email that sums up the retrospective right after this meeting. During the sprint I sent a reminder when we encountered an issue that was brought up in the retrospective. Finally, before the next retrospective I sent an email describing our decisions from the previous retrospective and whether we applied the action items or not. At the next retrospective we made sure we followed on those action items, but that's another team member's story to tell :)


A word of thanks to Gal Zellermayer, my team-leader at the time, who pushed me into thinking out of the box and conduct this retrospective.



Find me on Twitter: @AviEtzioni



More interesting posts from this blog:

Friday, November 1, 2013

Welcome!

I'm not sure when was the exact moment in which I knew I wanted to become a software-engineer. My first "Hello World!" was at the age of 10. But it wasn't until I was 18 that I started to actually work in this profession.

At first I was a bit intimidated by the assumption that software-engineer's work is usually lonely. You sit by the computer and code. By yourself. And, considering myself a people's person, it made me rethink whether this line of work was for me.

Over the years I have come to the realization that software-engineering is not lonely. Quite the opposite. Software-engineering is about people almost as much as it is about technologies. Only great teams build amazing products.

In this blog I write about technology and culture. I hope you will enjoy it.



Find me on Twitter: @AviEtzioni



More interesting posts from this blog: