Presentation for Code Camp ‘08

I will be giving a presentation at Code Camp in about one month. The title of my presentation is “The Evolution of a Scrappy Startup to a Successful Web Service”. In the following posts I will attempt to flush out some of the ideas I plan on presenting. Please feel free to comment on my ideas and provide feedback.

Part I: Prototyping

I remember Mint’s alpha launch as if it were yesterday even though it was almost two years. The main purpose of our launch was to get a prototype out for our friends, family, and investors to try out. We had pinned down our mission statement: “Mint: do more with your money.” We wanted to convey this message in our prototype. Thus, the feature set we chose was deliberately limited. Our main feature set consisted of showing users their transactions, and aggregating the balances of their checking and savings accounts, that was it! Nothing more nothing less. Why? Because the basic definition of a prototype in software development, is a rudimentary working model of a product or information system, build for demonstration purpose or as part of the development process. We planned on developing more features, but we wanted to demonstrate what we were going to do as a product. Starting out with a small feature set and growing it from there was the best way to go.

1. How did we arrive at this feature set? We started out by flushing out what was going to differentiate our product from the rest. Account aggregation, showing people their checking and savings accounts and categorized transactions on one web site.

2. What doesn’t belong in prototyping? Everyone wastes time trying to spec out a complete feature set, and all the bells and whistles they’d like to have in their product. We tried to limit that process. Once we had pinned down our feature set we went from there. The first step to prototyping is to figure out what the critical problems are that we are trying to solve and will encounter in trying to solve them. Since we were a financial web-app we had to handle security, and some concurrency amongst our 100+ users. We also had a few algorithms that we were implementing that drove our business differentiation, but none of these were completely flushed out. We coded up the bare-bones implementation for each of these. We also set up a simple unit test framework, but nothing too fancy and no system tests, because the focus was to get the product out there and have real users test it with real data!

3. So what did we it look like? Our prototype consisted of several Java modules but no real architecture, because we only had a couple hundred users and less than a handful of engineers to build it. So we made due with what we had. But we had good separation amongst our modules in terms of separating the core business logic from the data processing engines, and the UI from the server side logic.

Post to Twitter Tweet This Post

Territorial Women

When I was a senior at Duke I was determined to be my own woman. In my mind I thought it would be the last year of my life that I would be living my life on my own terms and not have anyone to answer to; I had the freedom to set my own goals, and work towards my own success.

At the time I thought I was making the right decision. Having my own life and my own territory was the only one thing that mattered to me, no one was going to trespass. I was reminded by this recently when I was watching an episode of LipStick Jungle. Mary Tyler Moore who plays Brooke Shields, Wendy’s mom, berates her for helping her daughter with her homework, and making the family dinner instead of working long hours at her company. Wendy’s mom is trying to help Wendy realize that someday Wendy may not be the president of her company, she won’t be the leader or own her career. Wendy’s mom lost ownership of her career years ago when she made the decision to build a family. Now she’s trying desperately to re-start the career she left, but she’s over 60, and no one believes she has the drive of a younger woman. Wendy’s mom and I both believe that building one’s career is about carving out a space for yourself. Its how we measure our success and our happiness, because its the only area in your life that you can control, and make decisions in. And when you’re younger you have more freedom because you’re only responsible for yourself. Losing one’s career is tantamount to losing one’s purpose, and having purpose is what keeps us productive and makes us happy.

To some Wendy’s mom’s situation might seem bleak, but I don’t think thats the point. Freedom is about making choices, and yes sometimes those choices mean giving up certain values like a career. And while it might take years to rebuild what you once gave up that doesn’t mean it isn’t worth the effort. In the words of Dido, “If my life is for rent and I don’t learn to buy, the I deserve nothing more than I get, cause nothing I have is truly mine.”

Post to Twitter Tweet This Post

Dukie Femgineers

I recently gave a talk to SWE (Society of Women Engineers) at my alma mater Duke University. The purpose of the talk was to give young women engineers insight into how college, specifically Duke did and didn’t prepare me to work as an engineer for a startup like Mint.com.

I thought the talk was well received and the girls asked a lot of good thoughful questions regarding startups, funding, marketing, and what employers were looking for in potential candidates.

Here is the gist of the talk I gave:

Hi, I’m Poornima Vijayashanker. I graduated from Duke as an ECE and CS major in ‘04. I left Duke to move to the Bay Area and work as a software engineer. For the past two years I’ve been working at Mint.com. Mint.com came about after the founder and CEO Aaron Patzer was frustrated with existing financial software. As a young and active individual he didn’t want to spend hours budgeting and tracking his finances. He found Mint.com as a way to help people save time and do more with their money. I knew about Mint.com since its inception. I came up with the name, and I’ve helped Aaron build his engineering team over the next two years.

My interest in working for Mint.com grew from my desire to be more than just an engineer. I wanted to have the freedom to create a product that would change people’s lives, and I also wanted to experience the evolution of a company and a product.

Duke prepared me for the startup environment. For starts, Duke’s curriculum is very challenging. The CS courses teach students good software fundamentals, and coding skills which apply directly to industry. Duke’s engineering school teaches the princples of problems solving that can be continually applied to any business or engineering problem.

When I first came to Duke I thought I was accepted by mistake. I was certainly not the smartest person there, and found the first two years very difficult. But then I started to see how my peers solved problems, and I began to think about engineering problems differently. Collaborating on projects and working as a TA exposed me to different methods of writing code. I became smarter just by being surrounded by smart kids

Finally, Duke’s professors are very supportive of their students, which is exhibited by the countless teaching awards they win year after year. My own engineering Professor Lisa Huettel is an endless source of inspiration to me both as a female and as a engineer. Her patience year after year, and boundless enthusiasm for engineering keep me motivated.

However, I think there are a few areas for improvement.

At Duke, every year is sort of the same. Sure each class is slightly different; there are those that are based on projects, others that have problem sets and tests, and some that you write papers for. And each year gets more and more challenging, but overall you have a very similar routine once you understand the system.

But at a startup you are constantly dealing with change. In the two years I’ve been at Mint I’ve seen the company grow from 3 people to 27, which meant that I played a pivotal role in the growth of it, including hiring my own boss, and explaining the architecture of the system to new employees. I wasn’t just coding everyday. I’ve also had to learn how to support a growing user base. During all these changes I had to learn to adapt, and accommodate them in order to be successful.

Duke didn’t teach me how to make tradeoffs, which is a highly valuable skill required in business and engineering because of time and resource constraints. In every class you are assigned a set of problems or a project, which you have to complete fully. Whereas in industry you might be given three features, but may only have time to implement one or two of them, and then you spend the remaining release cycle unit testing them, because you want to deliever a quality solution to customers, whose satisfaction and approval are your final grade.

Also, when writing a piece of code its not enough for it to be correct, it has to be scalable (handle multiple incoming and outgoing requests),
not generate too much load on the database, and be robust enough to avoid security breaches. Thinking in these terms comes with time and experience, but it could be incorporated into the existing curriculum by giving students more freedom when it comes to software or hardware design.

There was a lot that Duke did for me, but I would say the one thing it did best was teach me how to have fun. Not many people can say they’ve experienced an NCAA basketball championship, or been tenting with classmates in K-ville. Duke does an especially good job of keeping its students happy and instilling an element of work/life balance in them that I havent seen at many other institutions. I think this transcends everything else, because ultimately in working for a startup you want to be ethusiastic and passionate about the company and the product, and having fun every step of the way is the only way to ensure a happy and successful engineer.

In closing, I enjoy working at Mint.com, and the thousands of positive testimonals represent how successful it has been. I would like to thank Duke for playing a part in its and my own success.

Post to Twitter Tweet This Post

Performance: Part II Address Scalability Before Its Too Late

As your product and user base grows you want to ensure that your customers both old and new have a good user experience. You want their experience to improve and not stagnate or diminish over time; scalability is another key element to address to ensure the success of your website. Scalability is defined as the capacity to keep pace with changes and growth. 

Maintaining a scalable website requires thinking from a business perspective. You want to understand how rapidly your site is growing, and what the frequency of usage is. These two factors serve as metrics for predicting how to allocate resources. You can also use historical usage as an indicator of how much activity you expect in the future. Press releases and media events increase the user base over the course of a few days or even a week by unexpected amounts. Ideally, the number of users is increasing at steady predictable rate week over week. Depending on the type of site you’re running you can figure out what the peak hours for use are, or if user activity increases during certain seasons of the year. Also, knowing the frequency or peak hours of usage helps to schedule maintenance, new feature release, and cron jobs, which won’t interfere with the user’s experience.

Continuing to think in terms of business, you’re site is operating on a fixed budget, hence the amount of resources you have is directly proportional to your operating costs. Until you receive another round of funding or bring in revenue you have to make due with what you have. Therefore, you must understand the limits of your resources in terms of response time, throughput, and concurrency in order to allocate resources efficiently but still guarantee quality. Load testing* is the best way to predict the limits of each of these. 

Now lets switch back to thinking like an software engineer. From a code base perspective, web applications should be tier based. Here is a simple tiered approach:

UI -> Business Logic -> Persisted Object -> DB

You might also have another tiered data model that runs in parallel, which could be used to process or retrieve data that is not in immediate use by the user. Usually a messaging protocol such as JMS or RMI is used as a means of communication between these parallel data model tiers. The benefit of having a tier-based is that you can cache data that doesn’t change frequently across tiers, thereby limiting the number of expensive DB calls made. Moreover, as the number of concurrent users increases securing data across users becomes pivotal. With a tier based approach only certain tiers can manipulate and persist data. 

I’m sure we’ve all learned from our intro computer architecture class that CPU bound processes are the fastest and can be parallelized, whereas I/O processes are the bottleneck. In the case of a website, accessing the DB is the slowest I/O process. However, you can speed up access to data by sharding the database. Sharding breaks up a large database into smaller pieces that contains redundant information or a parent db can map data to separate dbs.

The last and priciest technique is having multiple servers. Configuring a load balancer to handle requests and the send them to each server is one way improving throughput and response times for user.

Improving the scalability of your website is a good problem to have, because it means your site is growing! But you don’t want to wait until a server crashes or a db thrashes. A little forethought will continue to grow your user base and keep them coming back for more!

* Future article on load testing.

Post to Twitter Tweet This Post

Performance: Part I Develop a Monitoring Scheme

Two years ago Aaron Patzer was frustrated with Quicken and Money, because setting up the service alone took over an hour. His painful experience led him to ditch both these products, and create his own product Mint.com, in hopes of delivering a faster and more useful personal financial service. Unfortunately, not everyone is a programmer, who can automate a tedious task, and not all tasks can be automated through software. Hence bad products continue to perpetuate the marketplace, and users are left waiting: in a line, for a site to download, or for a better service to come along. But sometimes their prayers are answered and a better service does come along. However, its only a matter of time till this service becomes plagued by inefficiencies. So how do we keep a web service performant? In the realm of software I believe there are three basic principles to keep a site up and running with crowd pleasing response times:

1. Develop a monitoring scheme
2. Address scalability before its too late
3. Re-write code

The first computer I ever had was a 486. While I initially believed that the thrill of just having a computer was enough, I was soon annoyed with the machine when I installed my first modem, and the damn thing would take minutes to connect. Fortunately, my dad’s frustration for it grew as well, and we soon replaced it with a Pentium I, II, III, and so on. So being a very green software engineer, I believed that a fast CPU makes life faster. However, I learned a very valuable lesson in my graduate computer architecture class at Stanford, what “Intel giveth, Gates Taketh away.” Throwing hardware to improve the performance of your machine is easy, but its expensive and only a temporary solution. And even if your company can buy a faster server it doesn’t mean that the consumer can afford to do the same!

So how does a web service stay efficient overtime? Monitoring! Specifically, monitoring features in the context of data flow. Any given feature fits into one of two categories: it either has data that will be displayed to the user, or as the user uses the feature, they generate data that must be stored. Here are the two simple flows:

a. server -> data -> user 
b. server-> user -> data -> server

In flow a its important to get the data from the server to the user asap. In flow b its important to get the data from the user back to the server to process it, store it, and in some cases return the processed data back to the user. Now that we know the areas where the data will be exchanged those are the places we need to monitor. 

For flow a, we need to figure out how large of a data set we are dealing with, and how long it will take to retrieve the data set from the server. Once we have the data set we need to figure out how long it takes until the user sees the complete data set. 

For flow b, we might need to return data to the user once its processed which is similar to flow a, but the harder part is taking in the data from the user, and processing it quickly, and then responding to the user with the new data. Unfortunately, the round trip associated with this flow is an unavoidable evil. But, there are ways to optimize it …

Post to Twitter Tweet This Post

Trade-offs in Unit Testing – Part III Stub Objects

I understand that no one likes to write test cases. For most developers its tied with debugging as their least favorite activity, because they just want to focus on algorithms, and writing code; thats the fun stuff. But I don’t think developers understand the importance of writing test cases. The more test cases you write the more time you have to develop! I know it sounds counter-intuitive. But the reasoning is the more test cases you write, the fewer bugs you have to fix, which also means less time spent debugging as well! Writing quality code frees up time to work on more new and exciting projects. 

Recently at Mint I noticed I was getting bombarded with bugs everyday I walked into the office. And they were all for features that I had written over 6 months ago! But I hadn’t bothered to test them out, because I was being assigned new feature requests everyday, and writing code for new features was much more glamorous to writing test cases for old features. So one evening I decided enough is enough! I was tired of sitting in my cube every week and devoting more than half a day to fixing and debugging bugs! What was my solution? Unit-testing using stubs. I took each key feature that I was responsible for a created a test suite for them. For each suite I outlined the basic unit test cases, corner cases, and test cases for bugs I had experienced. My next dilemma was how to write the unit test cases without needing a Spring Application Context, and without needing to generate test data or use a database… enter Stubs.

When you have a code base as large as Mint’s you are bound to run into some interdependencies even when unit testing. But the principle of unit testing is to focus on one or a limited number of classes or key functionality. The best way to do this is to use a stub. A stub acts as a substitute for another class. The easiest way to implement it is to extend a parent class or implement an interface, and then provide a basic implementation of the class by specifying simple return values for the methods (i.e. there is hardly any logic in the methods). You then replace the class-under-test’s dependency with a stub class. 

For example, all my Alert classes had a dependence to an AlertDao class (the AlertDao class is the class that stores data base objects). Since I didn’t want to my unit test cases to depend on a data base I abstracted away the AlertDao Class using an AlertDaoStub. The AlertDaoStub contained the same methods as the AlertDao, but they methods had very simple return values. In place of using an AlertDao I used the AlertDaoStub; this change was transparent to the Alert class.

e.g. Implementation of the Stub class

// class-under-test
AlertManager am = new AlertManager();
// stub class that extends a parent class
AlertDao ad = new AlertDaoStub();
// replace AlertDao with AlertDaoStub
am.setAlertDao(ad);

public class AlertManager {
    private AlertDao _myAlertDao;

    public void setAlertDao(AlertDao ad) {
        this._myAlertDao = ad;
    }
}

// This can either be a public class or a private inner class depending on how much it needs to

// be re-used

public class AlertDaoStub extends AlertDao {

    public Set<Alert> getAlerts(User u) {
        return new HashSet<Alert>();
    } 

    public void setAlerts(User u, Set<Alert> alerts) {
        user.setAlerts(alerts); 
    }
}

While this technique required some refactoring, and one long night of coding, I believe in the long run I will have contributed to the quality of the Mint code base, and saved myself countless hours of debugging.

Post to Twitter Tweet This Post

Part II – Trade-off to using Mock Objects

I spent a week testing the security framework at Mint.  I chose Mock objects as the methodology for testing because I wanted to test that when a user logs in a certain set of methods is called (i.e. there was clearly an expected behavior I was aiming to test).  Being very familiar with the architecture of the code base I knew the levels of hierarchy that needed to be traversed for a user to successfully log in, and thus my test case consisted of verifying the correct behavior at each of those levels.  While I was able to successfully use Mocks to create the test suite I wanted, I came across several key trade-offs of behavioral testing using Mocks.

1. You must have a decent understand of the use case you are testing; you must know which methods and classes are pivotal to the test case, and which can be abstracted away using expectations.

2. Using expectations can be a time-saver because unlike stubs you can just specify what the return value of the method should be, how many times it should be called, and what if any parameters are expected.  This limits the amount of test code you need to write.  However, the class methods need to be fairly deterministic, meaning they must always return the same result given a certain set of inputs.  

3. Mocks are perfect when it comes to testing classes with limited functionality or that are isolated from other classes.  Interdependencies between classes makes using Mocks a nuisance.  If the given class you are testing has a lot of dependencies amongst other classes then it requires you to create Mocks for those classes as well.  This can bloat your test code, and take a longer time to test, because now you must program for the dependent classes and setup their expected behavior as well.

Post to Twitter Tweet This Post

Code loving girl meets design loving boy

Once upon time there was a girl who sat in her cube, and coded all day and night. She loved it, nothing brought her more joy and happiness. Then one day a boy came and sat in the cube across from her, he loved to design, but also liked to tease the coding loving girl. The girl thought the boy was goofy and distracted her from her passion.

One summer day the girl came in, and coded away for a few hours. Suddenly she realized that the boy wasn’t there. The girl thought, “Hmm I wonder where he is…alas I shall finally get some coding done.” But in her heart the girl felt strange. She couldn’t explain what it was. Coding wasn’t enough to brighten her day. A few hours later the boy appeared, smiling, happy, and goofy as ever. Instantly, a smile appeared across the girl’s face.

Post to Twitter Tweet This Post

Demystifying Debugging

Part I: Principles of Debugging

As fate would have it I run into fellow developers all over the world. For example, I traveled all the way to Buenos Aires to study Spanish and get away from the tech-centric bay area and its ubiquitous engineers; ironically on the first day of my Spanish class I sat next to Rob, the software developer, from Chicago. When our teacher asked us what we did both of us remarked that we were developers, only Rob responded that he hated it, while I being the ode-to-code writing femgineer remarked with alacrity, “I love it!”. I later asked Rob why he was despised coding, and his only response was, “I hate debugging.” I wouldn’t say I hate debugging, its just part of the job description, and since I love being a software engineer I treat debugging as a necessary activity. 

However, I can empathize with Rob. I remember writing my code as a freshman, and absolutely abhorring debugging even 100 lines of code! I knew how to use GDB and DDD, but I still didn’t like that my program wouldn’t just work after I compiled it. My hatred for debugging reached its peak when I had my first job, and the software program was over a million lines of code. I couldn’t stand sitting in my cube, and being told to debug a bug that I hadn’t even written! Most of the time the authors had poorly commented the code, and had left the company years ago. But I would trudge through it, and try to figure out what was going on.

It wasn’t until I was at a startup that I began to learn how to debug properly. At a startup everything is top priority; bugs, features, scalability, performance, etc. There is no time to whine or solve a problem sloppily, because 99% of the time the bug will come back to haunt you, and there just isn’t anyone else around to fix the bug. So I had to roll-up my sleeves and learn the number one principle of being a good debugger: patience.

Stepping through code in a debugger can seem monotonous, but its one of the surest ways to figure out whats causing the bug. There are times when patience can run out, which in my experience is also the point when the debugger become futile. With a look of defeat and anguish on my face I would approach my boss. Instead of telling me to try harder, he taught me the second principle to being a good debugger: understand the problem or use case, and think about how other areas of the code or things might affect it. Basically, this means that the bug not exist in your code, and its probably being triggered by code in a different module, system, or process. To find the cause of the bug requires understanding the intricate details, and architecture of the system you are working on. This does not have to be a one man effort, because no one expects you to know everything about the code base, even if you wrote it all yourself! This leads to the third principle: communicate with others. But before doing this I would recommend going back to principle #2 and trying to hypothesize where you think the bug might have originated and formulate a hypothesis. Could it be in some other code, the framework you’re using, a language construct, or even the IDE? Narrowing the scope of the problem first, and talking about the methods you’ve used to debug will foster better communication. Keep in mind your colleague has to understand you in order to help you debug.

The final principle is intuition, intuition, intuition, which can only come from experience. So while debugging a really tough bug today might seem like druggery, you might see the same issue again tomorrow, six months from now, or even years down the road. While the same solution might be applicable often times it might not. However, recalling the old bug will do two things for you: one it will help you remember the context and the code space you dealt with before, so you won’t have to re-learn it. Two, spotting the pattern puts your mind into the frame of thinking that you used before to tackle the problem, which will save you time, and give you confidence when it comes to tackling the current bug.

Part II: Motivation

Part III: Time to solve the mystery

Post to Twitter Tweet This Post

Resolution for 2008

Every year I make one resolution; unlike most resolutions mine isn’t a concrete, its just a simple abstract statement of what I wish to accomplish or improve about myself through out the year. This year my resolution was to push my comfort zone, which involves putting myself in situations that I would normally back away from either due to shyness, fear, or apathy.

Now that over two months have passed I’d like to take stock of a few events in my life or situations I have encountered that have helped me to accomplish this resolution.

1. Yoga Competition (January 5, 2008): I stood in an auditorium of about 100+ people and performed 7 yoga asanas (postures) in under 3 minutes. The week before my competition I was a nervous wreck. Training was draining, and my passion for yoga became a hatred. I kept worrying about falling out, disappointing my friends, and in general failing to meet my own expectations. But the minute before my routine I was calm and collected. I just told myself to go out there, and “do it”, which is exactly what I did. While I was performing I didn’t think about anything. I simply went on stage and performed my routine as a I had rehearsed for nearly a month. I felt great afterwards. Probably the most confident I’d felt in years!! Part of me was actually sad when it was over, because I no longer had the competition to look forward to, but I knew there would be another one soon…

2. Trapeze (March 9, 2008): I can’t say that I’m afraid of heights, but I am always slightly nervous when it comes to trying out new things that might threaten my life, who isnt??  So I signed up, climbed up the thirty foot skinny ladder, and my palms started to sweat and my heart began to race a little. I didn’t have enough confidence in the person who was belaying me to just let go and swing out, but a familiar voice gave me confidence, when he said, “Don’t worry Poornima, Daryl is very strong, he’s got you.” That was enough for me to jump off and swing! It was simply a matter of trust, combined with confidence in myself, and understanding when and how to move my body.  After that first swing I was hooked!

3. Argentina (Coming soon!)

Post to Twitter Tweet This Post