Scope Like Goldilocks

How to control scope and navigate the spectrum of engineering excellence versus business needs

Image for post

Photo by Toa Heftiba Şinca from Pexels

There is no single right answer to any non-trivial problem in software engineering. So, if multiple correct solutions exist, how do you decide which is best? It’s difficult to determine which is best because “best” is highly subjective and deeply personal — your opinion is formed from your individual collection of experiences, strengths & weaknesses, and values on related aspects like simplicity, maintainability, & scalability.

It’s these internal values that make all of this so tricky. Imagine a spectrum with engineering excellence at one end and business needs at the other. Both elements are required for a project to be successful, and operating at either extreme can be detrimental to the other. As an example, making too many quick-twitch fixes to address urgent business needs can have significant long-term impact on the quality of the code base or system maintainability; conversely, focusing too deeply on engineering excellence can lead to over-investment in areas or competitive disadvantages from being slow to market.

Image for post

Understanding this spectrum — and having awareness of where you and your colleagues lie on it — can help your team to be more pragmatic.

Awareness of this spectrum alone isn’t going to do you any favors in resolving conflict from perceived disconnects between you and co-workers, though. I’ve found myself in design/requirements stalemates many times, and I’ve used the spectrum as a way to visualize my frustration.

“You see, I live over here on one end of the spectrum,” I’d say, “and my colleague operates here, at the other end. We can’t agree on scope, and we aren’t getting started or making any progress as a result.”

The problem with the visualization as a tool for conflict resolution is those pesky personal values. Neither of us thinks we’re advocating for a solution that would be in the unhealthy extremes of the spectrum. The person in the engineering excellence camp just believes that business value is generated by following all the best engineering principles and creating scalable, high-performing, resilient applications whereas business needs nation wants quick delivery and maximum responsiveness to meet the ever-changing needs of its customers.

So, how do you find compromise when the source of conflict is so visceral?


Let’s see if we can steal a page from the Goldilocks playbook. She’s got a knack for identifying the undesirable ends of a spectrum before settling into a satisfying sweet spot. If you and your team or colleague(s) can’t agree on the scope of a solution, can you agree on what it shouldn’t be?

What’s a reasonable solution that everybody agrees is over-engineered, and what’s the fastest, but perhaps short-sighted, thing you could do? What’s the effort required for each approach, and what are the risks or consequences?

Just to be clear, I’m not suggesting to simply compare different proposals by plotting them on the spectrum— that probably won’t get you anywhere. Instead, work collaboratively to come up with bad solutions that lean too far in both directions. Find agreement by identifying undesirable characteristics of these options in the unhealthy parts of the spectrum.

Still not able to find compromise? It’s probably time to bring in a 3rd party, preferably a stakeholder. Show them your spectrum and explain the tradeoffs that exist at the opposite ends, then present the “real” options that are on the table and allow the stakeholder to decide.

The whole activity is an exercise in pragmatism. How can two parties with equal but conflicting opinions find common ground? The key is to calibrate and remove as much subjectivity as you can. By acknowledging the necessity of both aspects — engineering excellence and needs of the business — and agreeing on the “bounds” of the spectrum, you create a framework for identifying the region for compromise. That’s your sweet spot. That’s likely where your “best” solution should be.


Originally published at The Startup on September 21, 2020.

What RPGs Have Taught Me About Effective Software Development Teams

Image for post
Photo by Jason Leung on Unsplash

I grew up as a computer kid in the 80s and 90s and, consequently, spent a lot of time in video games. Now I manage two software engineering teams, and it’s time to prove to Mom that all those hours spent in Final Fantasy were actually valuable career development.

I’m primarily thinking about two video game genres: party-based RPGs and MMORPGs. The formula for these is pretty simple. You have a cast of characters with various capabilities, and they work together to accomplish amazing things. In order to succeed, you must be aware of your characters’ strengths & weaknesses, understand what skills are required to complete a challenge, and combine characters in a way that allows them to achieve the goal.

Well, that doesn’t sound so different from a software development team, does it? You’ve got a group of people with different abilities and aptitudes; you have a backlog of stories to complete; and the team must collaborate to achieve goals and accomplish amazing things. It’s, like, the same thing!

Given these undeniable parallels, what lessons from RPGs can be applied to software development teams?

It’s Dangerous To Go Alone

When you adventure alone in a video game, bad things don’t happen most of the time — but there’s risk. The same is true in software development, especially if individuals on your team are all working on separate things. The primary risks of soloing a software development project are consistency, quality, and knowledge-sharing.

Image for post
Source

Working alone on projects offers short-term risk due to the fact that quality and completion time are largely dependent on who does the work. Someone who’s very experienced and understands the subject area well will probably get by fine, but a developer with less familiarity will take longer and be more likely to make mistakes that require re-work. Peer code reviews are slower and less effective because reviewers need to context-switch and focus deeply to understand decision-making and what’s been done. Individual stories are completed less efficiently because everyone has their own assignments and agenda, and other people’s work becomes a secondary objective.

Knowledge-sharing and information silos are the long-term threat. It’s easy for people to become specialized as certain types of work gravitate toward them. If an individual is the only one that worked on a specific project, guess who gets tapped when it needs attention later? Future work can also be bottlenecked when the person with all the knowledge isn’t available, and the situation gets worse when that same person is the bottleneck for multiple workstreams or when personnel changes occur.

In the video game world, the risks and consequences of soloing are typically limited to just you. People choose to solo because it’s convenient — they don’t want to wait or look for other players — or because they enjoy the challenge. Sometimes it feels easier to go it alone in software, too. However, software development is a team game, and you’re not typically looking for extra challenge just for the fun of it.

Ensuring you have multiple people working on a project mitigates the risk. One person doesn’t go down a bad path by themselves, and at least two people should know how things work and why decisions were made. Pair or group programming is inherently review-as-you-go which leads to better initial code quality, and that in-turn helps with completing stories efficiently due to less feedback cycles and re-work.

You don’t want everybody acting alone, but it’s equally important to make sure you don’t have too many resources focusing on a task. In other words…

Bring the Right Group

Image for post
Source

Quests in RPGs require a certain set of skills to complete. Easy quests are achievable by smaller, less experienced groups, but hard ones require more people, specific skills, or other special assistance. In games, it may seem more efficient to clear easier, low-level content with powerful, advanced characters, but if the strongest characters are focused on easy things, it means they aren’t working on more challenging, higher-reward objectives.

Software development is an exercise in efficiency. You have a backlog filled with user stories. Some are easy and some are difficult. You want to complete them all, though, and the faster you can do it, the better. The trick is for the team to determine the optimal way to complete as much as it can as possible as quickly as possible.

How would you do that in a game? First, you’d decide which quests are most important and what skills they require. Next, you’d look at which characters are available and what skills they possess. Then you can optimize who can do what. Perhaps one small group could tackle three easy quests while another group works on a single complicated one.

This same strategy can be applied to sprint planning. You’ve got stories in a prioritized backlog and a team of people to complete them. Which people have specific skills or knowledge required to complete the highest-value stories? Assign those folks first. Who’s left, and what’s the best way to utilize them? Make sure everybody is assigned, and balance the groups.

You may find that you don’t have enough people with the right skills to succeed with all the most important things. Luckily, RPGs give us a solution for that, too!

Level-up All You Characters

Image for post
Source

Characters in RPGs progress by completing tasks that reward experience. Once you’ve accumulated enough experience, you level-up and become stronger or gain powerful new abilities. In order to have a well-balanced team, you must use all your characters so they all gain experience. If you have a weaker, low-level character, you can grow them most quickly by leaning on them as heavily as possible in content that’s within their reach. Sometimes that can be painful, if you need to return to a low-level area and perform low-value activities, but the investment pays off with time. Once those characters “catch up” they provide valuable versatility to the team.

On a software team, this means ensuring that everybody’s getting reps with the most important skills. People won’t suddenly gain project management skills by not managing projects. Instead, acknowledge it: “I want you to manage this project so you can develop these skills.” You want someone to be a better decision-maker? Ask them to make decisions. Similarly, just because someone can do a thing in 15 minutes doesn’t mean they should do it simply because it would take someone else 2 hours. Instead, invest that 2 hours. The experience is as valuable as the time saved, and it contributes to both the growth of the individual and the strength of the team.

To be a successful team, there are multiple roles that need to be filled. As employees gain experience, they typically focus on a single role. For example, “I’m a developer, and this is what I do as a developer.” Often times, that’s enough to do a good job, but a great team member understands all the roles within the team and has the ability to recognize and step in when a role isn’t being fulfilled.

How do you develop that level of situational awareness?

Learn the Mechanics

Image for post
Source

Often times, games have encounters with mechanics that need to executed in order to succeed. You can win by knowing enough to go through the motions, but the best players don’t just know what to do — the know why they’re doing it. That also means understanding the consequence for not doing a particular mechanic and being able to adjust on the fly when things start to go sideways.

Software teams have a process designed to help the team succeed or — more pessimistically — prevent it from failing. Individual contributors can be successful by adhering to the rules and following the process. Great teammates will understand the underlying reasons for the process, though, and be able to make decisions around when it’s time to deviate.

Much like in games, a great way to become more familiar with the intricacies of your process is to learn it one role at a time from people who are already proficient. How does your team gather requirements and translate them into actionable work? What’s the best way to do a peer code review? What tests need to be run to verify there are no regressions? With better understanding, you can help improve these processes. Don’t just learn how to do things; learn why to do them.

Image for post
Photo by Jackson Simmer on Unsplash

These lessons from RPGs aren’t necessarily special or specific to software development; they’re just general best practices for teamwork and growth.

Recognize the strengths and weaknesses of individuals on the team, and utilize them in a way that makes sense — just like you wouldn’t have your squishy wizards standing in front of heavily-armored knights in a game.

Use the right number of people based on the task. There are both short and long term risks associated with using too few people but possibility for reduced efficiency & throughput with too many. It’s also important that the group have the right set of skills to accomplish the goal. Don’t poke the dragon alone, don’t bring the entire village to feed the horses, and don’t send a small group of adventurers into the dark cave without a torch.

Build your team by ensuring that people have the opportunity to grow. Acknowledge that having somebody less skilled perform a task pays dividends as they gain competency. If you don’t give people the chance to improve, they won’t. Having more people at level cap lets you tackle a wider array of challenges or accomplish more things at once.

Invest in helping team members understand the big pictures. What’s the greater purpose behind your team? Why do your processes exist? Encourage people to learn new roles and step outside the bounds of their specific job. The increased awareness and versatility differentiates good teammates from great ones. In an epic RPG boss fight, you can still win if somebody knows how to kite when the tank dies.

Know the team, grow the team. Use the right skills to get the kills, and collect that sweet, sweet loot.

Image for post
Source

Originally published at https://adamprescott.medium.com on October 5, 2020.

Transitioning from Developer to Manager

Image for post
Photo by Fabrizio Verrecchia on Unsplash

It’s not uncommon for successful software developers to find themselves in leadership positions. There are many possible leadership trajectories, one of which is management. Moving into management was scary for me, and over the years I’ve talked to a number of people at that point in their careers experiencing a similar dilemma. This is the story of my experience, why I made the decision I did, what I’ve learned along the way, and how it’s turned out.

The pre-management era

Let’s start with a little about my background, eh? I started my career as a junior developer and worked my way into a senior role, eventually becoming an architect. As an architect, I served as the technical lead for my team and worked closely with managers to make various leadership decisions. I wore many hats in order to best address whatever I felt my team needed most at the time.

After nearly 10 years with my first company, I left to join a former co-worker at a startup. At the time, this new company was small enough that we didn’t have much of an organizational hierarchy. We were a group of senior developers that all had decision-making authority with freedom to work on what we felt was most important. We still collaborated, of course, but we weren’t all chipping away at a common product backlog.

The loose structure worked great for us as a small team, but it doesn’t scale. As we added more people to the team and new products to our catalog, we needed more structure. We divided into product-specific teams with narrower focus and dedicated backlogs. That was our no/low-management tipping point, and that’s where my journey into management begins.

My boss was suffering the consequences of our very flat organization, and they needed people willing to take on some of these managerial responsibilities. I felt like I was being forced to commit: did I want to be a manager or not? I wasn’t given an ultimatum; in fact, my boss was very clear that there was no wrong choice, and my career would continue to grow regardless. That was comforting, but I still had the decision to make.

The management path was scary for a variety of reasons. I had a proven track record as a developer. I was good at coding and troubleshooting. I knew how to solve software problems. Managers take on an entirely different set of problems that require a different skills — skills I wasn’t sure I’d have. Managing a team when things are going well didn’t seem so bad, but it’s the whole “dealing with people” thing that had me worried. Did I really want to give up coding — the thing I enjoyed and had built a successful career doing — to be a manager and have to deal with people?

Making the decision

I ended up lingering at this juncture for a while. Depending on the day, I might’ve leaned one way or the other, but for the most part I remained undecided and non-committal. In my free moments, I’d research what made a good manager and read stories like this one to understand other people’s experiences. There were a few nuggets of wisdom that helped me make my choice.

Skills can be learned. It feels obvious to say, but hearing this was reassuring because I always considered “learning new skills” to be one of my strengths. It gave me confidence to know that I could supplement applicable existing skills with new, learned skills. For example, I know how to troubleshoot an application by stepping through code until I find a problem, then come up with a solution and implement it to fix the issue. The same critical thinking can be used to identify problems with a team, but I may need to do research on agile processes or collaboration techniques to come up with the solution.

You can nerd out on management. As a developer, there are always new things to learn and play with: languages and language features, tools, technologies, and techniques. I remember learning about something like Microsoft Azure for the first time and being so excited to have a reason to use it. The same kinds of continuous innovation exist for managers, too, but you need some awareness of manager & team problems in order for the solutions to make sense — just like you need context for those new things in software development. How can you automate team processes to reduce toil? What things cause the most friction or prevent work from getting done? How can you make 1:1s more effective? How can you maximize the team’s impact on company goals? How can you improve individual accountability? These are all super valuable areas to focus on, and they’re ripe for fresh ideas and innovation.

There is no “point of no return.” I was worried I’d go from awesome dev to mediocre manager, be unhappy, lose my edge, and feel trapped. It was reassuring to hear that I could go back and that my development skills wouldn’t disappear after being less active for a bit. I’m less involved in daily development tasks now and there are a lot of pull requests doing thing that I don’t understand, but when I do get back into the code, it all comes back.

As you may have guessed, I decided that moving into a manager role was the right move for me, and I’ve been at it for a few years now. It hasn’t always been fun or easy, but the more I do it, the more proficient I become. This has a cyclical effect, too, because increased proficiency leads to more engagement which brings more enjoyment and satisfaction.

Learning to manage

The most difficult thing about becoming a manager for me was the self doubt. (See imposter syndrome.) I felt like I was less valuable to the team “managing” than if I was a developer focused on getting things done. I wasn’t sure if I was spending my time on the right things, and the things I was spending my time on were different than that of my peers/other managers. I was failing to adequately help team members that weren’t meeting expectations. I was doing the best I could, and my boss was supporting and encouraging me — but I didn’t feel like I was doing a good job. It was tough.

Looking back, I think there were two key mistakes I made as a new manager. The first was not being direct with people. I was trying to focus on positive behaviors and encouragement and not being explicit about areas that needed improvement. The second mistake was that I didn’t think about the strengths and weaknesses of individuals on the team and strategize how to use them most effectively. (More on that, here!) You can imagine how these two mistakes can create problems: praise for strengths versus less feedback & higher expectations for weaknesses. It’s no surprise that situations didn’t improve!

The single most important advice I have for new managers is to lead with empathy. Get to know your team, and treat them like people. Give them positive and negative feedback. You’d want your boss to tell you if did something wrong, right? But, it would start to feel bad if they only talked to you about the things you did poorly, too. Learn details about their lives outside of work. It would get annoying if you had to re-explain every week why you had to be late to the same meeting for same reason. The better you can understand your team — professionally and personally — the more effectively you can manage.

The best way to get to know your team is through one-on-ones. One-on-ones are a pretty common “most important thing” for new managers, but the thing it took me a while to learn was how to prepare for one-on-ones. This is very hand-in-hand with leading with empathy. Being prepared for these intimate meetings is the best way to demonstrate that you care. Come up with questions and topics that are specific to the person you’re talking to. What do they like or not like about their job? What are their goals, and are there things you can do to help ensure they’re progressing toward them? What are things they did well or poorly? What do they think they did well or poorly? It’s also a chance to solicit feedback from them about you. Be sure to take notes! They’ll help ensure you don’t miss important follow-ups and make preparing for the next meeting easier.

The next steps

Managing with empathy and preparing for & conducting one-on-ones are things you can implement immediately regardless of experience. The next steps take some time and depend on your team. The most important things will be to establish behaviors that will maximize effectiveness and define a clear vision and purpose. These are no easy feats, though. They require thoughtfulness, focus, strategy, and persistence & dedication. You must monitor progress and be wary of regression, and advocate for the right amount of change to keep things trending positively. And, you need to do all this in addition to whatever your team needs to keep things going operationally!

This is a good summary of what my day-to-day looks like now. I’ve got meetings and operational concerns, and then extra time goes into reflection and solutioning for these bigger, longer-term items. There are still ups & downs; still days where I feel like I’m doing a bad job; and still days where I wish I could just write some code. It’s been a rewarding experience, though. It’s been amazing to watch the team adapt & succeed and to help people grow. I love when we can take on an ambitious goal and achieve it.

Making the transition to manager was a scary decision. I had to learn new skills to solve new types of problems, and I had to battle through some self-doubt. I don’t regret my choice, though. I’m not perfect, I make mistakes & bad decisions, and I’m still learning as I go. But, I love my teams, and I love the problem space that I get to live in.

Have you made this transition yourself? What things have helped you succeed? Are you faced with the decision now — what worries you? I’d love to hear from you!


Originally published at The Innovation on November 7, 2020.

How to Not Suck at Exception Handling

Yesterday a co-worker sent me an email about an error that was reported to them. “Have you seen this error before? If you have, can you tell me what it means?” This is a huge pet peeve of mine. Too many developers view exception handling as nothing more than an anti-crash mechanism. When an exception occurs, it gets logged and ignored. If the application’s not working, somebody might look at the log and see a repeated error message in the form of an exception.ToString(). That exception gets reported and travels electronically through the ranks until it makes its way back to the developer: “Oh, that exception?” the developer replies, “That just means the certificate is missing.”

Oh, that’s it? Thanks for the info, but I’ve got news for you: you failed. If you can say “That exception means…” then that’s what the application should’ve reported to begin with. Further, an explanation like this should only be forgivable if it’s followed by “I’ll update the application to say that.” Accepting “<insert exception here> means <actual problem>” as a solution should be unacceptable to all parties involved.

The good news for developers is that this isn’t a hard problem to solve: you just have to not suck at exception handling. The even-better news is that it’s not hard to be a good exception handler, you just have to think about what you’re doing and follow a few easy steps.

Reduce exception handling

My smelly-sense definitely goes off when I see code that has exception handling in every single function. This obviously depends on the code–maybe it’s necessary–but you should try to only include exception handling where it’s needed. If you can’t think of anything that can go wrong, don’t cover it up when the unthinkable occurs.

Of course, if you can think of things that might cause exceptions…

Catch specific exception types

This is where you look at your code and think of everything that might go wrong. If you’re writing a file, what happens if you don’t have permissions or the directory is missing? If you’re calling a web service, what happens if the service isn’t available? What happens if you access that database with invalid credentials? Each of these problems produces a specific exception type that can be caught and handled in its own special way. If you know where an exception could occur but don’t know the specific exception type, test to find out.

It would be rude in all of these scenarios to simply pretend that everything is okay and move on. Instead, do the courteous thing…

Provide meaningful messages

Don’t just tell people what happened, tell them what it means or what they can do about it! Should they restart the application? Do they need to contact an administrator? Is it connection problem? Is this going to resolve itself?

I mean, don’t get me wrong: System.ServiceModel.Security.SecurityNegotiationException “SOAP security negotiation with http://localhost/someservice.svc for target http://localhost/someservice.svc failed. See inner exception for more details” is a terrific error, but you’re not doing anybody any favors by showing it in a message box or writing it to a log. Doing something like that is just begging to be bothered for interpretation later. Instead, provide a meaningful message: “A security negotiation exception occurred. Verify that the certificate exists and has appropriate permissions.”

Remember that updating these messages is an important maintenance step. If a new cause for an exception is identified, be sure to add relevant information to your messages to make them as helpful as possible!

Don’t eat exceptions

One of the worst things you can do is to “eat” exceptions. I’m talking about adding try { … } catch (Exception) { } around all your code where the catch logic does nothing or quietly logs some details without indicating any problems to the rest of the application. I’m not suggesting that you let any and all unaccounted for errors crash your application, but allowing exceptions to fail as loudly as possible will lead to a more robust end product. The squeaky wheel gets the oil, you know? If you follow the guidance above, a new exception that was previously unaccounted for will result in code that specifically handles the newly identified scenario and provide meaningful information. The next time the exception occurs, there should be no mystery around what caused it or what should be done as a result.

Test everything*

*Everything that you can think of. The end goal of most applications is (or should be) to create a positive user experience. To that end, when you’re adding exception handling for specific scenarios and providing meaningful messages, you should verify how it will present to the user. If it’s something the user needs to address, make sure they receive clear information about what they should do. If the user needs to contact somebody, such as an administrator, make sure they know what to tell them. If something happened that the user doesn’t need to worry about, maybe you want to make sure that they can’t tell it even happened. Whatever it is that you’re trying to do, test it and make sure it works how a user should expect it to.

Extra McNugget Sauce, Scope Control, and Expectations Management

One of the biggest challenges that my team faces when working with customers on a software development project is controlling scope. These projects begin with a contract followed by a formal requirements document that must be signed by the customer prior to beginning development work. We’re realistic about this process; we don’t expect that every requirement will be correctly identified upfront, and we’re willing to work with the customer throughout the development process to ensure that their needs are met.

Occasionally, we’ll find ourselves working with customers that keep pushing scope, little by little, until the project has been stretched so far beyond the original requirements that we’re not sure how we got there. Kudos to that customer for getting some serious bang for their buck, but at some point we, the development team, need to draw the line. The problem in a lot of these scenarios is that we’ve given and given and given with little or no resistance. We’ve set the expectation that if they ask for something, we’ll give it to them. We can find ourselves with a customer that’s unhappy about being cut off despite delivering a lot more than was originally bargained for.

This scenario has two major flaws. There’s obviously the issue of scope control, but expectations management for the customer is equally problematic.

I like to use a McNugget sauce analogy here. If you go to McDonald’s five times and get an extra sauce with your McNuggets for free, you’re happy. But then, on the sixth visit, maybe you get charged for the extra sauce because it’s the restaurant’s policy. This would upset a lot of people. “This is an outrage! I come here every Tuesday, and every time I get an extra sauce. I have never been charged for it before.” Rather than being happy about getting the extra sauce for free the first five times, they’re upset about not getting it for free the sixth time. However, if the McDonald’s employee were to let you know, “Hey, we’re supposed to charge for extra sauce, but I’ll let you have it for free this time,” then you’re less likely to feel like you’re being unjustly charged when you’re eventually asked to pay.

The same philosophy can be applied to our software development projects. When the customer makes that first seemingly innocuous, out-of-scope request, let them know that you’re doing them a little favor. “This request is out of scope, but I can see where it would be valuable. I’ll discuss this with the team to see if we can fit it in.” If you decide to do it, be sure to let them know that you’re making an exception this time. Finally, document that you gave them some “extra sauce” so that when/if you need to push back on a request, you can show them everything they’ve already gotten for “free.”

Getting back to the McNugget sauce analogy, some folks would still probably be upset about being made to pay even when they’ve been notified that they should be charged for the sauce they’re getting for free. “I know it’s not supposed to be free, but this is the first time I’ve ever been asked to pay. Get me the manager!” In response to that, I’d say an equally valid takeaway from this article is, “Do not give away [too much|any] extra sauce for free.”

Finding Time to Innovate

Innovation is the backbone of any software development effort. If you aren’t doing something new, what’s the point? Without new ideas, you’ll never be first, you’ll never have something that your competitors don’t, and you will never be the best.

I think most people would agree with these statements when talking about a software company or product, but I’m actually talking about developers. You–the developer–need to constantly explore new ideas and learn new skills. Doing things you’ve always done the way you’ve always done them will likely never result in anything more than marginally better than what you have now. (Hey, more = better, right?) In other words, you will need to do new things in new ways in order to produce something significantly better than what you have now.

This is where things get a little less straightforward. How do you learn to do things you haven’t done in ways you haven’t done them before? In my opinion, it’s all about exploration and experimentation. When I read an article about a new tool or language feature, I’ll spend some time playing around with it. I don’t necessarily have a use in mind; I just want to see what it’s about. The result over time is that I have a whole host of things I’ve messed around with that are implementation-detail candidates on future projects. Additionally, when discussing new projects, I can say things like, “This is useful, but it would be really cool if we added X. Here’s how we can do that.”

We can all agree that innovation is essential, and it’s important for developers to spend time learning and exploring to help with the innovating. There are only so many hours in the day, though, and you’ve probably got other, more important things to work on. You’d love to spend time trying new things, but your boss isn’t going let you have free time to do that. After all, there’s money to be made! So what can you do?

I work for a somewhat old-school software company. The senior management overseeing development isn’t likely to institute 20% time any time soon. They aren’t going to designate a percentage of hours as play time, but that doesn’t mean that creativity is forbidden or frowned upon. It just means you have to find the time yourself. I’d venture to say that most software developers are salaried employees obligated to 40 hours per week but expected to work more. What if you spend just one hour each day learning something new? You’ll probably still be giving 40+ hours of effort to the “actual work,” but you’ll also be learning new things that interest you. Fast math shows us that 5 hours represents 11% of a 45-hour week so, by taking 1 hour each day you effectively create “10% time” for yourself.  If one hour is too much time for you, take 30 minutes, or do it every other day. Take the time and stick it on the end of your lunch hour if you need a bigger block.

By allocating “you time” and spending it, you’re going to grow professionally, and that benefits both you and your employer. You’ll be better equipped to tackle complex problems in the future, and you’ll have fresh ideas for how to solve old problems. You’ll also have increased job satisfaction because you get to work on things that interest you in addition to your regular assignments. I believe it’s a true win-win scenario. So stop worrying about the hours you’re “given,” and go learn something!

Unit Testing Stored Procedure Calls with Rhino Mocks

Database stored procedure calls are one of the trickiest things to unit test, and there are many different approaches that can be taken. My team has run the gamut: test DBs that rollback with each run, no testing for direct data access functions (!), virtual functions w/ partial mocks (see here).

The latest approach that I’ve been using is much more straightforward and feels like a more natural use of Rhino Mocks. Let’s look at some examples of how to test some common database stored procedure tasks. (Note that these examples assume use of the Microsoft Enterprise Library.)

Create a mockable Database

The primary challenge that I’ve found with testing database code is that Microsoft.Practices.EnterpriseLibrary.Data.Database isn’t mock-friendly. However, the other “pieces” such as DbCommand and DbCommandParameterCollection are very easy to work with. So, we can solve the Database problem by creating a simple wrapper (Important! Note that the methods have the virtual keyword, which will allow them to be overridden.):

public class DatabaseWrapper
{
    private Database _database;
    private Database Database
    {
        get { return _database = _database ?? DatabaseFactory.CreateDatabase(); }
        set { _database = value; }
    }

    public virtual DbCommand GetStoredProcCommand(string storedProcedureName)
    {
        return Database.GetStoredProcCommand(storedProcedureName);
    }

    public virtual void DiscoverParameters(DbCommand command)
    {
        Database.DiscoverParameters(command);
    }
}

Executing a stored procedure

Now that we are able to mock the database object, we can write some useful tests. Let’s say you want to execute a stored procedure named “MyStoredProcedure,” and you want to write a test to verify that your code handles an exception thrown when it’s executed. That’s very easy!

Here’s my class with the function I want to test:

public class MyDataAccess
{
    public DatabaseWrapper Database { get; set; }
    public Thingy GetThingy()
    {
        Thingy thingy = null;
        try
        {
            var dbCommand = Database.GetStoredProcCommand("MyStoredProcedure");
            Database.DiscoverParameters(dbCommand);
            var result = dbCommand.ExecuteNonQuery();
            // populate thingy
        }
        catch (Exception ex)
        {
            // handle exception
        }
        return thingy;
    }
}

And here’s my test that will throw an exception when the stored procedure is executed. I create my DatabaseWrapper as a PartialMock, allowing me to override its methods.

[TestMethod]
public void GetThingyHandlesException()
{
    // Arrange
    var target = new MyDataAccess();
    var mockDatabase = MockRepository.GeneratePartialMock<DatabaseWrapper>();
    target.Database = mockDatabase;

    // mock Database
    const string storedProc = "MyStoredProcedure";
    var mockDbCommand = MockRepository.GenerateMock<DbCommand>();
    mockDatabase.Expect(x => x.GetStoredProcCommand(storedProc))
        .Return(mockDbCommand);
    mockDatabase.Expect(x => x.DiscoverParameters(mockDbCommand));
    
    // mock DbCommand
    var ex = new Exception("Oh noes!");
    mockDbCommand.Expect(x => x.ExecuteNonQuery())
        .Throw(ex);

    // Act
    var actual = target.GetThingy();

    // Assert
    mockDatabase.VerifyAllExpectations();
    mockDbCommand.VerifyAllExpectations();
    Assert.IsNull(actual);
}

Setting input parameters

Need to set some input parameters? No problem!

dbCommand.Parameters["@id"].Value = id;

And, in your test, you add this:

var mockParams = MockRepository.GenerateMock<DbParameterCollection>();
var mockParam = MockRepository.GenerateMock<DbParameter>();

mockDbCommand.Expect(x => x.Parameters).Return(mockParams);

mockParams.Expect(x => x["@id"]).Return(mockParam);

const int id = 123;
mockParam.Expect(x => x.Value = id);

mockParams.VerifyAllExpectations();
mockParam.VerifyAllExpectations();

Reading output parameters

How about output parameters?

thingy.Value = dbCommand.Parameters["@Value"].Value as string;

Add the additional mocks and assertions:

var mockOutParam = MockRepository.GenerateMock<DbParameter>();

mockParams.Expect(x => x["@Value"]).Return(mockOutParam);

const string value = "MyValue";
mockOutParam.Expect(x => x.Value).Return(value);

mockParams.VerifyAllExpectations();
mockOutParam.VerifyAllExpectations();
Assert.AreEqual(value, actual.Value);

Working with sets of parameters

When you have more than a few parameters to work with, the unit test code can get quite lengthy. I like to keep it clean by extracting the duplicated logic into a separate function, like so:

var paramsToVerify = new List<DbParameter>();
mockParams.Expect(x => x["@whammyparammy"])
    .Return(MockParameter<int>(paramsToVerify));

My function allows you to specify and verify the type of each parameter, but you could easily modify it to expect a specific value.

private static DbParameter MockParameter<T>(List<DbParameter> paramsCollection)
{
    // set Expect with Arg<T>.Is.TypeOf to force the specific type
    var mockParam = MockRepository.GenerateMock<DbParameter>();
    mockParam.Expect(x => x.Value = Arg<T>.Is.TypeOf);

    if (paramsCollection != null)
        paramsCollection.Add(mockParam);

    return mockParam;
}

I keep the parameters in a list so I can verify them during my assertions.

paramsToVerify.ForEach(x => x.VerifyAllExpectations());

Eight Qualities of Remarkable Emloyees

Inc.com is running a great article by Jeff Haden titled Eight Qualities of Remarkable Employees. The article discusses eight non-tangible behaviors exhibited by the best of the best. These qualities all transcend industry, but there were a few that I felt were particularly true for software development.

They ignore job descriptions

There are many external factors that can influence a software project, and any one of them can roadblock the whole thing. New requirements, unexpected challenges, verification, and deployment issues all have the ability to derail your timeline, and it will often be someone else’s official responsibility to deal with the problem. Waiting for somebody else costs you valuable time and can ultimately lead to missed deadlines or failure. Cut out the middle-men, do what needs to be done, and enjoy success.

(This seems obvious, but I’m going to say it anyway: be aware of the politics of your actions. Preventing a distraction: good; doing someone else’s job: bad.)

They like to prove others wrong

If you’ve got a great idea that others don’t believe in, there are two options: let them go down what you believe to be an incorrect or inferior path, or prove them wrong. When you set out to prove them wrong, you may find that you were actually wrong. (*gasp* I know–not likely, right?) That’s still a win, though, because you (hopefully!) learned from it. If you’re right, you’ll help steer a project toward an optimal solution and gain credibility with your team.

I think healthy competition also falls into this category. If you have individuals competing with each other to find an optimal solution, you’re more likely to find it than if you have a single person trying to accomplish the same thing. Each person is likely to come up with a solution that they feel is the best, and the way to “win” is to prove its the best to their peers.

They’re always fiddling

Tinkering is SO important to software developers. It’s how you practice and hone your craft. It’s how your learn new things. Evolving your skillset and tools allows you to be more creative and innovative with your solutions, which further energizes the team.

Make Your Job Obsolete

A long time ago, I read a book by Chad Fowler titled The Passionate Programmer: Creating a Remarkable Career in Software Development. This is a great book that I’d recommend to anybody getting started in software development. It’s full of great tips and ideas like trying to be the worst on your team (surround yourself by greatness), the importance of practice, and striving to be a little better every single day.

One of the concepts that really resonated with me is making it a goal to make whatever position you’re currently in obsolete. With a larger software company, it’s easy to get your hands into a lot of different projects. It’s also easy to become the person with specialized knowledge on specific topics. There’s a feeling of security that comes along with that–they can’t get rid of me; nobody else knows this–but it also makes it harder for you to move forward. I fell into this trap myself a few years ago. There was nobody on the bench to replace me so that I could move on to new and different challenges, and it took some time to get myself out of that position.

Keeping the goal of obsoleting your job in mind day-to-day helps you accomplish two major things: your tasks get easier and you stay available for whatever’s next. And, one of the amazing things about being a software developer is that you have the power to do this through software! The key is identifying processes that can be automated and then mustering up the motivation to follow through and execute.

So what processes can/should be automated? This will be different for everybody and largely depends on your typical tasks. Here are some examples I’ve encountered:

  • Anything that involves cutting and pasting
  • Things that are run on an interval (e.g., daily/hourly/weekly reports)
  • Complex data entry tasks (i.e., create an application to simplify the process)
  • Abused spreadsheets (spreadsheets that are modified and emailed each day can be replaced with web portals with databases that have entry and reporting)
  • Utility-type or out-of-application SQL scripts

Your imagination is the limit. Dream it, create it, and share it. If you do a great job, your managers and co-workers will thank you!

%d bloggers like this: