Another lecture I gave a while ago (Hebrew).
I’m sorry for the video quality and mirroring, it was recorded with a face-camera. You can download a slightly differently formatted version of the slides from here [pdf].
This was the lecture banner:
One of the nicer things about being a CTO of a growing startup is being able to experience firsthand all the things the software engineering literature you read all the years talk about.
Hello Heart started as a B2C company. In our early days we built a product – blood pressure tracking apps, and sold these apps to our users. As we grew, we became a B2B2C company – we started selling our apps to employers who were looking for health benefits for their employees.
With this change, we had to shift our thinking in so many ways. Suddenly, marketing and sales became completely different, as did business development. Along with these changes, the new features we had to implement changed. We were required to implement more and more features that weren’t about the individual experience, but about the employees’ relationship with their employer. Are these employees eligible for Hello Heart? To which employer do they belong? Integrations with other benefit programs. That kind of stuff.
The most interesting thing for me was the way our thinking about the product changed as we started growing. Our “product” is no longer an appliccation that we sell. It’s a service. Complete with enrollment program and dashboards and operations and all the magic that goes into Hello Heart (did I write that? Yes, I did). Our software had to change as well in order to accommodate that. We started writing code to manage clients and enrollments and shipping centers.
Recognizing this change in the way we need to think took us a while and it has been fascinating to watch. For me, the key was noticing that we do a lot of things in a really hard way, and thinking – hey! Shouldn’t we have software to do that for us? It’s ok to do things in stupid and hard ways when you are a small startup and can’t afford to build all the software you need and just trying to figure out if your busines works. But when you find out it works and start operating as a business, this approach leaves you with a gap between what your business needs and what your technology provides, and your next challenge is to align the two.
We are have been doing that for a while now and it is exciting and fun. I feel like I live in a
fairy tale case study from a software engineering book.
In software development, productivity is all about getting in the Zone. When You are in the Zone, you are one with the code and writing software is easy as typing. When you are not, a whole day can pass without doing much work because thinking is just so hard.
One of the things I do to get myself into the zone are little “warm up” sessions before I start to code features that are hard for me to approach. I choose small problems that I particularly enjoy as warmups. Little treats, you might say. For example, I may start programming a feature by refactoring some remotely relevant code, commenting on legacy code around it or focusing on a small part of the feature that seems interesting.
To the outside viewer (a.k.a my boss when I was a developer) it may appear as though I’m wasting time on things that are not the core of my work – “We have no time to invest in code refactoring right now, we should ship this feature”, but I argue that this time is not spent but invested in making the development faster, and that the time it takes to develop the feature after investing it is much shorter.
Think about it – in many other areas of our life, the concept of warm up is very prevalent. Athletes warm up before an exercise to make it more effective and less dangerous. Singers warm up their vocal chords and musicians warm up their fingers before a show, and when I took an animation course, we were taught to start every day with a several minutes quicksketching session to get our creative juices flowing.
Why should programming be different?
Concentration and focus is a problem of acceleration and when you try to move from 0 to 100 kmph you should take the car that gives you the largest boost at the shortest time, and this is what programming warm up is all about.
I think that all the programmers I know want to get better at what they do. In fact, I think that every professional who takes pride in her work, not just a programmer, wants to get better at what she does. Sadly, I figured long ago that just by doing my work and following my daily routine, I will never be able to advance in a way that satisfies me.
This is why I’ve resolved to taking active steps towards my professional development.
Surrounding myself with bright people
I think that being surrounded by smart people with whom we communicate and work well is crucial for our development. I’ve learned so much from the people I work with, and I’m not talking only about technical knowledge and methods – by comparing myself to the people around me and finding our similarities and differences, I’ve been able to find out what my strengths and weaknesses are, and highlight my strengths while working on the things that need improving.
Working on my BSc in Math and Computer Science
It is a known fact that in the Israeli IT market, if you have the right kind of military experience, you don’t need a BSc in CS in order to get a job and advance to many positions. However, I feel that the broad formal education you get in the university often proves useful in unexpected situations.
Further than that, I hope that later my education will enable me join a research position in the field.
I make a point of always reading a book or a magazine that may broaden my horizons: it can be a technical book, a book about project management, general management (I’m currently working my way through Harvard Business Review‘s essays bundles, they are quite fascinating), or any other type of book that seem like it can open my mind to new ideas, or spark my creativity.
Working on pet projects
This is something that I learned from the guy that is sitting next to me. I always say that programming is a job that leaves you with a lot of free time. This is why I always keep an IDE open in the background with some pet projects, which I use to explore concepts that I find interesting, or features that may contribute to our product but I am not “formally allowed” to code.
Following technical blogs
I try to find interesting people whose opinion I value, and follow them online. I consider this an extension of the “surround yourself with bright people” principle to smart people who live oversea and have no clue that I exist.
Writing a blog!
Having to communicate your ideas often makes them clearer in your head. Writing a blog is a way to deal with subjects you may not normally talk about with your peers. In addition, when I worked on some of the (unpublished) technical articles for this blog, I faced the fact that I had some gaps in my knowledge, which I had to fill in order to complete my writing.
As an added bonus, I am also forced to slowly but surely improve my English skills.
Similar to writing, teaching forces you to communicate with your students. Teaching also pushes you to always learn a bit more than what you already know, because no matter how knowledgeable you are, your students will always find a way to surprise you with questions about this extra bit of information you’ve neglected.
I haven’t taught for a long time, and I really miss this experience.
What about you? How do you get fit and keep in professional shape?
Consider the following real-life problem: you are assigned a task to write a program that keeps a collection of objects, sorted according to some criteria, and at any given time you should be able to provide a list of the top N objects in that collection. Your program will receive events that modify the objects (and therefor trigger re-ordering of the list), and the processing of these events is time-critical. How would you implement it? What algorithms and data structures would you use?
My instinct, and I think that most programmers share this tendency with me, is to start thinking in Computer Science terms when we hear this question. We iterate over all the data structures we know, mentally compare their performance, try to think about sorting algorithms, weigh the options and…
Wait! Is this the right approach for this problem?
I’d argue that it certainly isn’t. In this case, all of the facts we know about our data structures and algorithms, are true in certain conditions. Take sorting performance, for instance. Everyone knows that insertion sort has horrible performance (O(n^2)), so we shouldn’t use it, right? But if our array size is small enough, and the data is already sorted, it is superior to other algorithms, so maybe for this problem it is better than any other option? What about data structures? Different implementation of the same data structure differ significantly in performance. And how does your preferred solution behaves on the production machine?
This is why I think that the best way to go about this problem is to write a small benchmark application, that compares several approaches with typical data and sample sizes, using different data structures implementations and algorithms, and run it on the machine that would eventually host the final product, if possible.
Programmers (and especially those of us who work in the field of performance measurement) tend to think that they know where the performance issue in the application will be, and that they can prepare for them in advance.
Well, they are wrong.
I’ve had the pleasure of doing performance testing and improvement several times in my career, and quite ironically, I’ve achieved the biggest improvements by undoing the damage that other programmers did when they thought they were writing some really clever, lightning fast, code.
Now, don’t get me wrong – I don’t say that knowing your stuff isn’t important. It is. But real-life application behavior is just too complicated to be evaluated on a whiteboard, and your performance issues will always be where you least expect them to be.
Stay humble, and measure measure measure.
 Seriously, people? Writing your own (incorrect) versions of data structures? Re-implementing String.equals, which is one of the most optimized pieces of code in the JVM? What were you thinking?!
Don’t even think about releasing a piece of code, if you haven’t stepped through every line at least 50 times with a debugger.
What? Are you serious? But I have written so many unit tests!
It is true, unit tests are an important aspect of long-term code quality, but they are just not enough. When you write a unit test, it is too easy to become optimistic and be absolutely sure that certain parts of your code work. It is easy to forget the internal workings of your code, and skip some edge cases, and unless you write and execute school like test suits, it is too easy to leave things out.
Is there a correct way to do it?
When you step through your code, stop before every line you execute, and try to think what you expect it to do. Execute the line and compare your result with the expected result. Work in several abstraction levels. Debug every line of the method you’ve written. When you think it is working fine, treat it as a black box and debug the methods that call it without stepping into it. Sometimes code that seem correct in one abstraction level, will turn out to be faulty when you examine it from another.
Hila, you are so smart! I’ve found a bug!
Why, thank you! *brushes off an imaginary hair from face and beams graciously*
Now turn it into a unit test. Why? Because the next thing you will fix will probably break your code again. Run your test, make sure it fails. Fix the bug, make sure the unit test passes.
Ok, my code looks like it is working now. Can I stop debugging?
Nope. Go ahead, run it again. You will find another bug.
Arrgh! This is so much work!
Too bad, writing quality code is what you are paid to do. If you don’t like it, I heard Walmart are recruiting now.
Isn’t it better to spend the time implementing cool new features and having my QA test the code?
No, from several reasons. They cannot do it as well as you can. Not because they are stupid, but because they don’t know your code as well as you do. In fact, even the future you cannot do it as well as you can. If you move to another task and postpone cleaning up after yourself until you get your inputs back from QA, you will definitely not remember all the little details of your implementation, and these bugs will be a lot harder and a lot more costly to solve. And finally – it is not the QA’s job to find these bugs, they have more important things to do, like making sure the whole system is functioning from the user’s perspective and testing the overall design and integration points. If they have to deal with the bugs you were too lazy to fix all day long, when will they have time to do the real work?
Trust me, step through your code (and wear sunscreen). Your QAs will thank you. Your future you will thank you. Your manager will thank you. Your users will thank you. I will personally thank you. Your neighbor’s cat will…
Hila, can I ask you something?
Yes, yes, I am implementing a new subsystem now and I’m finding trillions of funky bugs by stepping through my code.
Now go away! I’ve just hit a breakpoint!