The 7 Habits of Highly Ineffective Software Engineers

In this article (which has no relation to Covey’s famous book, The 7 Habits of Highly Effective People, except maybe the number seven), we will take a different approach in our discussion of good habits by first pointing out the bad ones.  By going from ineffective to effective, we will essentially discover what really separates good engineers from the exceptional.

#1: Don’t ever try to re-balance the time-scope-quality triangle.

you can have it pick two; cheap, fast , goodIf you do, be sure to never articulate this tradeoff to the customer.  More importantly, be sure to ignore  Murphy’s three laws:

  1. Everything takes longer than you think,
  2. nothing is as easy as it looks, and
  3. if something can go wrong, it will.

By doing this, you’ll ensure that a product will be delivered late, have way too many features than originally agreed upon, and be full of bugs (not to mention way over budget).  In addition, the customer (who fortunately has a great sense of humor) will have a good laugh and you’ll both be on your merry way to the next project.

But seriously.  Although this triangle sometimes autocorrects by force, far too many engineers think that this triangle is the PM’s problem (project or product manager).  Honestly, it should be both your problems.  You as a developer are closer to the product’s internals than anyone else, and it is your responsibility to regularly communicate the current state of the triangle to your managers and recommend re-balancing strategies.

Certainly, the biggest problem with analyzing this triangle is that managers tend to use the wrong data to assess progress.  That is, they only use timeline and budget as their indicators of progress, when they ought to be incorporating user stories and user acceptance tests as a better indicator.  To summarize, people in charge tend to view the time-scope-quality triangle as more of a time-scope-resources triangle, when resources != quality.  In reality, not all resources are created equal, and so often times it’s four variables you should take into account, not three:
post2A
great article on a shirky.com web blog talked about why healthcare.gov failed and applied it to I.T. projects in general.  A quote from it that I really liked, “If I had to design a litmus test…[for managing I.T. projects, and we’ll talk about litmus tests more in habit 4]…I would look for just one signal: Can anyone with authority over a new project articulate the tradeoff between features, quality, and time?”

“When a project cannot meet all three goals—a situation Healthcare.gov was clearly in—something will give. If you want certain features at a certain level of quality, you’d better be able to move the deadline. If you want overall quality by a certain deadline, you’d better be able to simplify, delay, or drop features. And if you have a fixed feature list and deadline, quality will suffer.”

The most common scenario in my experience is scope creep with decreasing time–therefore quality has to suffer, or you have to suffer putting in crazy hours to meet a deadline.  It doesn’t have to be this way. Sometimes we have to learn to say “no” even if something is feasible, even reasonable.  Other times, we have to stretch ourselves and say “yes” even if we know it may take some effort.

Question for discussion: What are some strategies or tactics you’ve employed to keep this triangle balanced and happy?

#2: Only choose battles you will lose.

but seriously bro, through another one tiger memeTime isn’t precious, and so if you know you’re going up against “the man”, or a brick wall of politics, or stubborn customers, keep fighting until you finally lose.  Always try to be the martyr, because nothing feels better than telling someone “I told you so!  I warned you about this!” afterward.  Speaking of battles…why even start one?  Just code a bunch of stuff that affects a bunch of other stuff and do not tell anyone.

But seriously.  Don’t get me wrong on this, you are a consultant and should be actively involved in the decision-making process, and as such should voice your opinion in a professional way.  However, you should always choose your battles wisely–only ones that are within your sphere of influence.

Doug Turnure has a great Pluralsight course about how to have a better career in software.  In it he talks about the need to avoid being a diva by always taking glamorous stands on things.  Don’t ever be that guy in a meeting where everybody rolls their eyes as you go off on soapbox after soapbox about things.  Worse yet, how would you feel if at the next meeting, you’re not invited because people think you impede progress by arguing and being confrontational on just about every issue?  You’re allowed to disagree on issues, but choose your battles wisely, and accept compromise where it makes sense, even if you don’t agree with the outcome.

Every company has politics.  Do not become too immersed in it, because it almost never ends well.  Never mix politics with software development.  

When we talk about battles, we’re really talking about two kinds:

  1. stakeholders vs. developers.  This is usually a battle between the “customer is always right” mentality and the “I as the developer know what’s best for you” mentality.
  2. developer vs. developer.  Often times, devs will disagree heavily on architecture decisions, resulting in implementation battles. Or worse, a developer will insist that everyone conform to doing things their way.  Software engineers are very opinionated individuals, and some just love a good intellectual battle over ideas on how to solve problems.  This is good in some situations.  Other times it can mark the slow, painful death of a project.

Questions for discussion: How can we help resolve the “customer is always right” versus the “I as the developer know what’s best for you” battle?  How do we resolve implementation battles between developers? How should we balance “rough consensus and working code” with “always doing it someone else’s way?

#3: Only strive for 2 out of 3 on the Golden Trifecta for a Model Employee

diagram on delivering qualtiy results, having a team player, and delivering on timeThe bottom line is that 2 out of 3 ain’t bad! In other words:

  1. If you’re really smart and able to deliver good results on time, then you’re allowed to be a jerk.
  2. If you’re a super nice guy and able to make people laugh, and you deliver good results, then don’t worry about deadlines because doggonit – people like you and will give you all the time you need.
  3. If you’re a super nice guy and people just adore your personality, and you’re able to code 60 WPM so you get things done quickly, then don’t worry if your deliverables are half-as(s|k)ed or not adding value.

Don’t worry about being a team player that goes against the grain. “This is how I do it, and so should you – it’s my way or the highway” attitude should prevail.  It’s better to be a liability than an asset, because adding value to a project is overrated.  There is no “I” in team!

And finally, when it comes to results, you’re not about solving the problem quickly and effectively.  Take your time, since after all, you’re a two-thirds kind of a guy because at least you’re nice.

But seriously.  Neil Gaiman in a famous address to the University of Arts Class of 2012 talked about what I’m calling the “Golden Trifecta for a Model Employee”, that is that you delivery high quality work, on time, and are a good team player (i.e. easy to get along with).  Almost everything you look for in a good employee boils down to these three components.  Most good employees are two out of the three.  Great employees strive for all three.

Regarding being a team player, always remember that negativity breeds more negativity.  As Turnure put it, “You tend to see only what you’re looking for.  If you actively look for negative things, you’ll find them.”

Question for discussion:  What is a great way to find out if a prospective employee will meet all three demands of the trifecta?

#4: Don’t ever adapt as technology changes – stick to what you know!

charles darwin quote

You should never have to learn or relearn something.  You should never have to unlearn something.  And once you’re considered senior, you should never have to learn something new–it’s all about the comfort zone!  Be a jack-of-all-trades and a master of none.  When it comes to all technologies, it’s best to apply a litmus test (i.e. accept/reject it based off a single factor).  And above all, always be partial to or show spite for a particular language, tool, or technology.

But seriously.  A senior developer once told me something that always stuck with me: “The biggest impediment to software engineers is being set in their ways.”  Often times, it’s up to you to determine how to implement a solution and what technologies to use; however, more often than not, usually a client has an established technology stack that you have to adapt to.

Doug Turnure in his Pluralsight course about having a better career in software defined three things related to this that hurts people in their careers when it comes to their expertise, and they are: 1) picking a fringe technology, 2) clinging to a fading technology, and 3) holding an emotional attachment to a technology.  “The essence of marketability is to be good at what other people are using.”  Good way to know what’s in demand?  One suggestion is to look at conference topics, or see what search terms are popular on job boards.  Consulting companies are also experts at knowing what’s in demand, since they work with multiple clients in multiple industries.

Avoid only liking what you use and not liking what you don’t use.  The reverse is also true.

In addition, software engineers can be very opinionated people, and will fight to the death (religiously at times) for their favorite language, tool, or technology, rather than taking the time and effort to carefully weigh the advantages/disadvantages of each technology and making informed decisions.

In the end, if you want a successful career in technology, you have to define a continual learning plan in order to adapt and progress, especially since technology changes so rapidly.  This includes setting SMART goals (specific, measurable, attainable, realistic, timeline), which may include items such as participation in code challenges, brown bags at work, certification exams, conference attendance, books, and other training resources.

Question for discussion:  How do you adapt to changing technologies, both personally and as an organization?

#5: Be as unapproachable as possible to devs [who know less than you about stuff]

cartoon about being unapproachable Patience is least important, so stop trying to explain a concept if they don’t understand it the first time.  And there’s certainly no need to be teachable.  You’re always right, because most people know less than you about stuff.  At the very least be condescending so that the developer knows that they’re not worthy of your time and expertise.

But seriously.  As a software engineer, you are guaranteed to have to be a mentor at some point in your career, and the greatest software engineers are also the greatest mentors.  Although knowledge acquisition can take months or years depending on the complexity of the technology, sometimes teaching what you’ve learned to someone else can save both of you a lot of headache down the road, rather than forcing everyone to take your same learning path.

It’s tempting to just want to do everything yourself, or just take over someone’s keyboard when they have a coding question.  Most often, junior developers just need a few nudges in the right direction, and then they can start to teach themselves.  Others may need a bit more hand-holding at first then others.  In general, it depends on the person, and you’ll have to take a different, more balanced approach in each situation for each person.  If someone just never seems to be progressing regardless of how many ways you try to help, then this could be a sign of deeper issues.  In general, the 30-minute rule is a good starting point, which is that if a developer is still struggling for 30 minutes or more after researching to try and find a solution to a problem, then offer to help.

In a previous client, I had worked under a senior dev that had trained all of us junior devs so well to be self-sufficient that “he almost wasn’t needed anymore”.  But is this ever the case?  Do senior developers worry that by training others to do everything they do that they’re somehow progressing toward not being needed anymore?  This is a myth in the industry when it comes to job security.  The bottom line is, if you can get a team under you working well enough, your ROI will be so high that it will create a win-win situation.  You add a ton of value to the company, your burden gets lighter, and then others can recommend you without reservation for higher-stake roles in the future.

And please, don’t be condescending. Nothing shatters a fragile developer more than when you belittle them or roll your eyes to others as soon as they leave, as if they aren’t even worthy of your time and expertise.

Question for discussion:  How do you best deal with other developers that are constantly asking for your help?

#6: Assume everything, especially when you think it’s common sense

to save time lets just assume i know everythingFor most assumptions, you don’t need to get a green light from customers beforehand.  For the assumptions that do require a green light beforehand, however, just do what you think is best rather than what the customer is actually asking for, because you know better.  It’s also important to always talk before you listen. Be opinionated!  Never seek to understand the customer’s needs.  Never engage in reflective listening.  And whatever you do, forget the Platinum Rule (treating others the way they want to be treated) – it’s overrated.

But seriously. This habit comes down to setting requirements that are well understood by all.  Always restate to the customer what you’re planning on in a language they can understand–getting buyoff earlier saves you a ton of heartache down the road.

So many customers hate being bogged down with the technical details of a requirement, and often will tune you out when you start talking about them.  Every implementation detail doesn’t necessarily need to be discussed, but the goals of the implementation do.  Explain the strategy to the customer, not the tactics.

Get your PM’s (both project and product) involved in what you’re trying to accomplish at each sprint, even if you have to by force at times.  Far too many managers use the “truck-order-delivery” mentality or some form of the waterfall approach when it comes to software deliverables, and this can lead to disastrous results.  In the blog article referenced above from shirky.com, it mentions that “…the vision of technology as something you can buy according to a plan, then have delivered as if it were coming off a truck, flatters and relieves managers who have no idea and no interest in how this stuff works….it’s also a breeding ground for disaster.”  While it’s important for the highest management levels to see the bigger picture and have more of a bird’s eye view of the product, this should never be the case for project and product managers.

Almost 99% of the time, you will be given incomplete requirements, or wishy-washy ones at best. A vision is not a plan, just as a high-fidelity screenshot with lots of pretty graphics is not a website.  Form follows function.  Often times you need to be the one to gather requirements, because either the customer doesn’t know exactly what they want, they don’t want to get bogged down with the details, or they simply don’t know the right questions to ask.  Requirements should be based off a consensus between you and the customer, not one-sided.  Embrace agile, embrace change without too much scope creep, and stop testing in production!  Get feedback as early as possible in the chain.

It’s also important to utilize different points of view when it comes to setting requirements.  Not only end-users, but especially BA’s (if you’re lucky enough to have one), other subject-matter experts, as well as product managers should be a part of the process.  Again–setting requirements should be a team effort.  Software engineers are creators just as much as they are builders.  Everyone needs to be involved in the decision-making process.

Question for discussion:  So many customers only want to evaluate things in a production-like environment.  How can we help to ensure early feedback in a more agile way?  How do you best establish requirements for a software project?

#7: Try to over-complicate everything, because purism is king, and you’re awesome

image008

Prematurely optimize your code to adhere purely to every SOLID principle 100% of the time.  Take a philosophical, over-idealistic approach, and always do stuff you just read in that really great academic book from a lifetime CS professor with no practical experience (no offense to CS professors).  Never give in to balancing principle and practice.

Make sure the next guy looking at your code (which will probably be you) will have to ask you for clarification on what the heck the code is supposed to be doing. This is because your code needs to make you look smart–so smart that if nobody can maintain it due to its complexity, you can smile knowing you’ve accomplished your goal.  Hooray for job security!  You’re the best now!

But seriously. This all comes back to the KISS principle.  Premature optimization is the root of all evil.  In addition, I’d rather copy and paste some logic twice then having to spend hours architecting a more dynamic solution just to handle two use-cases.  Give me a third use-case for a copy-paste, and only then will I seriously consider a more dynamic solution.

It’s important to remember that it’s not really about the code, it’s about the business, and understanding why you’re being paid.  You’re being paid to solve business problems, not just to write awesome code. Far too often I’ve seen grandiose ideas, plans, or visions that look great on paper, sound great in a team meeting or a lecture, but simply fail to live up to the hype in reality.  Large, enterprise-level application code bases will always have technical debt and are never perfect.  The reality is that every programmer comes to the codebase with a certain style of doing things, and with varying levels of experience.  Rough consensus and working code is important.

Don’t get me wrong, I’m all for SOLID principles and design patterns, but these should only be utilized where the objectives are clearly understood by all, and where it’s going to add the most value to the application.  The biggest cost factors with purism is complexity (and sometimes performance), not to mention another developer only being able to understand what’s going on in the code after a lengthy architecture presentation by a senior dev. Try to balance principle and practice.  Extremes to one end or the other are usually bad.

Question for discussion:  How do you best balance principle and practice when it comes to writing clean code?

Bringing it all together

In summary, the main thing that all of these habits have in common is ego–more specifically, learning to control your ego by checking it at the door.  They also have to do with managing your own personal brand and being a balanced person.  In managing your brand, as Turnure put it, it’s important to realize that you have a user interface.  If people don’t know what you can do or how well you do it, how will they know to hire you?  How are you marketable at that point?

So go out there and be passionate about your work, your brand, and above all, don’t be grumpy.