Software, Team and Strategy

Mike Borozdin - Kubernetes @ Google. Previously: Dir of Eng @ DocuSign, Lead @ Microsoft. I help companies focus and engineers grow.

Monday, December 01, 2014

Three Pillars of Engineering Management

What’s it like to manage an engineering organization? “It’s an art and a science.” Well, at least that’s a common cliché response.

I’ve been managing teams for close to 15 years now -- long enough to reverse engineer at least some of the “science”. This post is about the big picture of engineering management; the pillars of a good engineering leader.

As a great Engineering VP, CTO, Director, Lead, or Manager, you need to be a top performer in three categories: product, team, and engineering excellence. Building and running a top-notch engineering organization requires that you consistently excel in all three.

#1 Product
Your team’s primary output to the world is a great product. Your customers depend on it, your company depends on it, and, ultimately, your job depends on it. No matter how well you do as an engineering leader in any category, delivering your product on time, on budget, and with high quality cannot be overlooked or substituted. Regardless of your project management approach, your toolkit, or your legacy code, you need to ship the right products at the right times to your customers. If you repeatedly miss deadlines or ship low quality products, you will quickly run out of excuses and your head will be on a chopping block. When you ship well and make your customers happy, your product line will grow -- and so too will your team.

#2 Team
With a solid team, you should have the budget and headcount to execute on a mission that’s bigger than what you can accomplish single-handedly. You know you have a strong and motivated team when they deliver products on schedule, overcome obstacles creatively, and adjust to market changes rapidly.

As a manager it’s your primary job to hire the right people, train them, keep them focused and motivated and also sometimes letting the bad ones go.  Assembling, growing and retaining a good team is hard, but rewarding.

A great engineer will inform you of exciting new tasks that were achieved on top of the agreed-upon deliverables and will contribute innovative ideas moving forward. A bad engineer won’t get things done well enough or on time, and will instead offer a hundred and one excuses for why things suck. Keep the team members who innovate, care about the customer and “underpromise, overdeliver”. Invest in them, so they feel their best and perform their best.

#3 Engineering Excellence
“The quality of a person’s life is in direct proportion to their commitment to excellence, regardless of their chosen field of endeavor.” – Vince Lombardi

Great engineering organizations are like great sports teams; they don’t only get things done, they also employ techniques that maximize resilience and minimize technical debt. Engineering excellence expands beyond just the tools, and into training and discipline with your processes. Utilizing unit testing, code reviews, developer documentation, automatic build systems, deployment automation, test automation, and all the other best practices will make sure you’re building for the future along the way.

At DocuSign, for example, we have continuous education classes at least a couple times a month to keep engineers current with the best practices. The best engineers are excited about being on teams that emphasize professional development and engineering excellence, while the worst engineers think it’s excessive or bogus. Keeping the bar high helps the latter group self-select out.

While I can’t say I have mastered all three pillars of engineering management -- product, team, and engineering excellence -- I can say that they’re all essential to starting and sustaining a successful engineering organization. Over the years, I’ve been fortunate to participate in teams that executed well on all three fronts, making for some magical moments

-mb

If you liked this article you might also enjoy:
SDET / QA Engineering Checklist  and Emotional Intelligence on Software Teams

Labels: , , , , ,

Friday, November 07, 2014

Simplify your life & business with DocuSign for Google

If you are using Google Drive and GMail check out what my team has built.  It's a great productivity hack for you!



Wednesday, November 05, 2014

Give Parse.com dialogs a modern look

I’ve been playing around with Parse.com, which is an excellent “mobile backend” framework.  It gives you an easy way to use database, user management, and some UI to get you started on all the major mobile devices.  As with all the frameworks that do a lot, it gets tricky when you need things to look or act differently than what you get “out of the box.”  I am going to share some customizations I have made to introduce a flat UI look (Fig 1) instead of the dark brushed metal look (Fig 2).


1. Before we begin,  follow the iOS guide to get the basic setup: https://parse.com/docs/ios_guide .
2. In order to do major customizations the UI for Login or Signup dialog you need to subclass the standard Parse.com classes.  Parse.com has a tutorial on how to do that here: https://parse.com/tutorials/login-and-signup-views .
3. If your app requires login in the viewDidLoad method of the first view you will need to see if there is an active user and display the login dialog if there isn’t.  An interesting fact about Parse is that it will keep the session between app launches which is very nice.  In the code below you can see that I am instantiating both the GCLoginViewController and the GCSignUpViewController.  They are both subclasses of the Parse framework classes.
    if( ! [PFUser currentUser]) {
        logInViewController = [[GCLoginViewController alloc] init];
        [logInViewController setDelegate:self];
        logInViewController.fields = PFLogInFieldsUsernameAndPassword
                                    | PFLogInFieldsLogInButton
                                    | PFLogInFieldsSignUpButton
                                    | PFLogInFieldsPasswordForgotten
                                    | PFLogInFieldsFacebook;
        
        GCSignUpViewController* signUpViewController = [[GCSignUpViewController alloc] init];
        [signUpViewController setDelegate:self];
        [logInViewController setSignUpController:signUpViewController];
        
        
        [self presentViewController:logInViewController animated:YES completion:nil];
    }
4. The real styling is happening in the viewDidLoad function of the subclasses.  Here is my GCLoginViewController method.  You can see that button styling happens often enough that I actually created a class to style buttons with images and buttons without images.

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.logInView setLogo:[[UIImageView alloc] 
initWithImage:[UIImage imageNamed:@"MainIcon-small"]]];
    self.view.backgroundColor = [UIColor whiteColor];
    
    // Remove text shadow
    CALayer *layer = self.logInView.usernameField.layer;
    layer.shadowOpacity = 0.0f;
    layer = self.logInView.passwordField.layer;
    layer.shadowOpacity = 0.0f;
    layer = self.logInView.externalLogInLabel.layer;
    layer.shadowOpacity = 0.0f;
    layer = self.logInView.signUpLabel.layer;
    layer.shadowOpacity = 0.0f;
    
    [self.logInView.usernameField setTextColor:[UIColor blackColor]];
    [self.logInView.passwordField setTextColor:[UIColor blackColor]];
    [self.logInView.externalLogInLabel setTextColor:[UIColor blackColor]];
    [self.logInView.signUpLabel setTextColor:[UIColor blackColor]];
    
    // login button
    UIColor* gold = [UIColor colorWithRed:177.0f/255.0f green:117.0f/255.0f blue:0.0f alpha:1.0f];
    UIColor* facebookBlue = [UIColor colorWithRed:59.0f/255.0f green:89.0f/255.0f blue:152.0f/255.0f alpha:1.0f];

    [GCButtonStyles colorButton:self.logInView.logInButton 
background:gold textColor:[UIColor whiteColor]];
    [GCButtonStyles colorButton:self.logInView.facebookButton 
background:facebookBlue textColor:[UIColor whiteColor]];
    [GCButtonStyles colorButton:self.logInView.signUpButton 
background:[UIColor lightGrayColor] textColor:[UIColor whiteColor]];
    [GCButtonStyles colorButton:self.logInView.passwordForgottenButton 
background:[UIColor lightGrayColor] textColor:[UIColor whiteColor]];
    [GCButtonStyles colorButtonWithImage:self.logInView.passwordForgottenButton 
background:[UIColor lightGrayColor] textColor:[UIColor whiteColor]
      image:[UIImage imageNamed:@"forgot-image"]];
}

5. The GCSignUpViewController is using the same functions

- (void)viewDidLoad {
    [super viewDidLoad];
 
    [super viewDidLoad];
    [self.signUpView setLogo:[[UIImageView alloc]
initWithImage:[UIImage imageNamed:@"MainIcon-small"]]];
    self.view.backgroundColor = [UIColor whiteColor];
 
    // Remove text shadow
    CALayer *layer = self.signUpView.usernameField.layer;
    layer.shadowOpacity = 0.0f;
    layer = self.signUpView.passwordField.layer;
    layer.shadowOpacity = 0.0f;
    layer = self.signUpView.emailField .layer;
    layer.shadowOpacity = 0.0f;
 
    [self.signUpView.usernameField setTextColor:[UIColor blackColor]];
    [self.signUpView.passwordField setTextColor:[UIColor blackColor]];
    [self.signUpView.emailField setTextColor:[UIColor blackColor]];

    // login button
    UIColor* gold = [UIColor colorWithRed:177.0f/255.0f green:117.0f/255.0f blue:0.0f alpha:1.0f];
 
    [GCButtonStyles colorButton:self.signUpView.signUpButton background:gold
textColor:[UIColor whiteColor]];
}

6. The actual styling functions have a bunch of code because Apple exposes a bunch of elements that you can customize.  Parse puts the background and foreground images and colors so in order to completely reset the styles I am setting all those properties.
@interface GCButtonStyles : NSObject
+(void) colorButton:(UIButton*) button background:(UIColor*)
background textColor:(UIColor*) textColor;
+(void) colorButtonWithImage:(UIButton*) button background:(UIColor*)
background textColor:(UIColor*) textColor image:(UIImage*)image;
@end


#import "GCButtonStyles.h"

@implementation GCButtonStyles

+(void) colorButton:(UIButton*) button background:(UIColor*) background textColor:(UIColor*) textColor {
    [button setBackgroundImage:nil forState:UIControlStateNormal];
    [button setBackgroundImage:nil forState:UIControlStateHighlighted];
    [button setBackgroundImage:nil forState:UIControlStateSelected];
    [button setTitleColor:textColor forState:UIControlStateNormal];
    [button setTitleColor:textColor forState:UIControlStateHighlighted];
    [button setTitleColor:textColor forState:UIControlStateSelected];
    [button setTitleShadowColor:
[UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.0f] forState:UIControlStateNormal];
    [button setTitleShadowColor:
[UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.0f] forState:UIControlStateHighlighted];
    [button setTitleShadowColor:
[UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.0f] forState:UIControlStateSelected];
    [button setBackgroundColor:background];
}

+(void) colorButtonWithImage:(UIButton*) button background:(UIColor*) background textColor:(UIColor*) textColor image:(UIImage*)image
{
    [self colorButton:button background:background textColor:textColor];
    [button setImage:image forState:UIControlStateNormal];
    [button setImage:image forState:UIControlStateHighlighted];
    [button setImage:image forState:UIControlStateSelected];
}


@end

These functions can be used on almost any buttons that you get in UI elements regardless of whether they came from Parse or another framework.  In this particular situation the resetting of the styles and backgrounds gives the user interface a more modern, flat look.   Enjoy!

PS: If you liked this post you might also like other hands on blog posts like the TestFlight one: http://www.mikebz.com/2014/08/testflight-and-importance-of-private.html or the 4 Page Guide to Core Data: http://www.mikebz.com/2014/06/4-page-guide-to-core-data.html

Thursday, September 25, 2014

Win a Prize at Your Next Hackathon

Simple Invoice App on the AppStoreA couple of weeks ago I decided to participate in the TechCrunch Disrupt Hackathon. My app, Simple Invoice (www.sendsimpleinvoice.com), ended up winning a prize.  I think if I hadn’t already learned about the vendors’ APIs and come up with some ideas before the Hackathon I would never have had a chance.  Here are a few tips for you to win your next Hackathon!

Think ahead. First and foremost, take a look at the Hackathon website and learn about the sponsors ahead of time.  If the first time you learn about the sponsor APIs is during the event, you are probably behind.  That’s the big reason why popular APIs like DropBox, Twilio, and Twitter always get a lot of hacks – people already know them and might even have some code stashed somewhere.

IoT > Mobile > Web. The second tip is to use hardware if you can help it.  In terms of the things that are most likely to win prizes, I have noticed that wearable technology is perceived more advanced than mobile apps, which in turn generally beat pure web apps.  If you have a choice between building then keep in mind that IoT > Mobile > Web.

Involve technical evangelists. Next tip: always involve the evangelists from the API companies.  They can help you; they can debug their own code and they can guide you in the right direction.  Don’t forget that they want you to be successful because a great app using their platform gets them on stage and in the news!

I worked closely with Evo Snap team and they helped me quite a bit.  They have several different APIs and one was easier to call from iOS than another.  They were also able to give me internal error codes when I couldn’t figure out why my parameters didn’t work.  Without their involvement I wouldn’t have been able to complete my app in time.

Practice your pitch. Practice your presentation and make sure that you can deliver it in less than the allotted time.  It’s always good to have a few extra seconds to add a joke in if you think of something funny.  At TechCrunch Disrupt, we had 60 seconds per presentation.  Here is a link to my pitch – I tried to waste zero time:
http://techcrunch.com/video/simple-invoice-presents-at-techcrunch-disrupt-hackathon/518403996/

A good app with a bad presentation is unlikely to win.  The judges do not have time to go through all of the apps, so they will likely only pay attention to the ones that caught their attention during the first round of presentations.

Establish a web presence. The last thing is to hire a designer and direct part of his/her time into putting together a one page website.  I grabbed a template and put together quick information on a one page website: www.sendsimpleinvoice.com.  The template cost me $13 and I just filled out all the info.  Between registering a domain and launching the site on Digital Ocean, I only spent a couple of hours on the whole thing.

Good luck in your next Hackathon! They are fun, they are winnable, and they offer a great opportunity to learn about new technologies.

PS:  you can download my app here https://itunes.apple.com/us/app/send-simple-invoice/id917501386
PPS: If you liked this post you might want to check out the post about using Test Flight and about Starting a Mobile App Business.

Labels: , , , , , ,

Wednesday, August 27, 2014

TestFlight and the Importance of a Private Beta


The most important thing about the product is making sure it addresses the customer need.  I wanted to share my experience with one tool that made it easy to distribute and get feedback for an iOS app.  You should use this or similar tools for your application or you will run a risk of shipping a dud.

You can have the best architecture, you can have the sleekest styles and the coolest user interface, but if you can’t get the users to use your app – it’s not worth much.  To minimize the risk of shipping a dud because of wrong features or system incompatibility I highly recommend that you conduct a private beta using a tool like TestFlight.  If you are building an iOS app, TestFlight allows you to upload a build of your app and then invite your beta testers to try the app out.



  1. The first thing to do is to sign up for a TestFlight account.  Once you have set up an account you can start inviting members of your team.
  2. When your team joins you can gather their device identifiers (UDID).  You need the device identifiers because your private build is only going to be allowed to run on a few devices. 
  3. The testers then get a notification and sign up for TestFlight, upon joining they can connect their device and supply their UDID.
  4. After your beta testers have uploaded their UDIDs you will need to go back to the Apple developer portal and upload the new UDIDs so that you can create a profile that includes the new devices.
  5. In XCode -> Preference -> Accounts -> View Details you will need to referesh the profile so that you have a provisioning profile with the latest UDIDs.
  6. Next time you build and export an IPA it should be installable on the testers devices.  Upload the IPA file to TestFlight and notify beta testers about the new build. 
  7. Testers then follow the link from the e-mail or from the TestFlight website to get the latest build and it downloads directly to their phone.



You can see that the process is a little bit involved, but I believe that’s the best you can do with the current iOS distribution architecture.  There are a few things that will happen as a result of the private beta: some people will not install your app, some people will install it and encounter problems, some people will install it and ask for features, some people will install it and want to know when they can get the final version.

All of those events are useful:

  • If no one goes through the trouble of installing your app, you are probably not addressing an existing business need – it’s time to get back to talking to customers and learning more about their problem space.
  • When customers encounter problems it means that your testing needs to expand and you might need to add coverage on systems and devices you haven’t tried before.
  • Feature requests are good too, it means that people were interested enough to try it out but need something else for a complete solution.
  • If your customers ask you when they can get the final version you’ve hit the jackpot – your app will actually help someone.


Do not skip the private beta.  You do not want to spend marketing dollars or time before you got some feedback on your app.  When you finally launch with good feedback you will have customer testimonials and the right feature set.  You can market your successes and your users will help you.

-mb

PS: if you have feedback I'd love to hear from  you on Twitter @mikebz
PPS: If you like this post you might also enjoy: "Don't hate on Startup Code" and "So you want to start a mobile app business"

Saturday, August 16, 2014

SDET / QA Engineer Interview Checklist

After interviewing and hiring hundreds of engineers over the past 12+  years I have come up with a few checklists.  I wanted to share one of those with you so you could conduct comprehensive interviews of QA Engineers for your team.

I use this checklist when I review incoming resumes and during the interview.  It keeps me from missing areas that ensure a good team and technology fit.  I hope you make good use of them.  If you think there are good questions or topics that I have missed - get in touch with me!



If you like this checklist you might want to check out these posts:
Emotional Intelligence in Software Teams  and Good-bye manual tester, hello crowdsourcing!

Saturday, July 26, 2014

The #1 mistake in Agile Project Management

It’s been over 12 years since I read the life-changing Agile Software Development with Scrum by Ken Schwaber and Mike Beedle. I’ve been a big proponent of Agile in every organization I’ve worked with since, including Microsoft and DocuSign. Now, in the position of directing 4 engineering teams that execute Scrum in parallel, I continuously see one mistake that almost all agile practitioners make: they think that taking the Agile approach means they don’t need a plan.

Engineers who use Scrum or Kanban often hesitate when it comes to long-term roadmaps. The most common rebuttal: “this is not agile! We’re going to plan one sprint, adjust our backlog, then re-evaluate in two weeks.” Of course this see-what-happens style of project management appeals to engineers, but it doesn’t work very well for big projects that require marketing, partnerships, customer rollouts, or other external coordination. This a frequent predicament.

Then the question arises: how do you reconcile Agile development with planning a marketing blitz or roadshow 6 months in advance? An engineer can’t just tell the marketing team, “we don’t know what features we will have in the product... we don’t know when they’re going to be done... we’re just going to go sprint by sprint and we’ll let you know what we’ve created by then.”

The answer for synchronizing Agile with planning is to shift the perception of what Agile means. Contrary to common assumption, being Agile is not based on an inherent lack of planning. Rather, Agile is about getting feedback as quickly as possible and adjusting plans accordingly.

Early in my Agile career, someone gave me a useful analogy. It goes like this:
Just like with driving, software development is full of surprises. There are virtual detours, stop lights, crazy drivers, and flat tires.  And just like with driving, a virtual detour doesn’t mean you’re not going to arrive at your destination. It does mean, though, that you might need to drive a little faster to make up for lost time or let your friends know that you’ll be a few hours late.  
The beauty of Agile is that it encourages engineers to identify surprises as early as possible and adjust plans accordingly. That way, software teams don’t leave their colleagues hanging at the last minute or waste months pursuing the wrong goals.

Labels: , , , ,