Strategies for Successful Development

Process and technology for small teams building real software

Archive for the ‘Dev Leads’ Category

Swallows, logs, throws, and ignores (exceptions)

Posted by S4SD (Seth Morris) on 2011/05/10

This post is in response to Logging is the New Exception Swallowing by Martin Jarvis.

I am always glad to see someone pointing out that exception handling is horribly handled!

First, a disclaimer. I’m a bit old school. I think exceptions are generally bad things that have led to worse code and worse error handling. I recognize that I am in the minority and that the ship has sailed, though.

Mr. Jarvis is raising a point which goes to the heart of the problem. We write code that swallows (or logs unimportant exceptions because we get yelled at for swallowing exceptions) because our libraries use exceptions poorly and because our development culture uses exceptions even more poorly. Exceptions, no matter what academic purists and book authors claim, are used in to mean any of several conditions in the real world, and they’re used with the same syntax despite the semantics.

In the wild (including in the .NET library), an exception could mean any combination of:

  • The function couldn’t perform its contract (the classic definition of an exception).
  • The function is informing you of a side effect (“Hi. I’ve consumed all your disk space. Have a nice day.”). This may not even be an error.
  • Some internal object threw an exception. I hope the library correctly listed every exception that type it can throw AND the functions it calls can throw. And that they correctly listed this.
  • There is an informational message you should log, but you can continue.
  • We’re done with a loop. The exception indicates the end of some condition (reading a file, network access, etc.)

And we may want to respond wildly differently:

  • The system state is inconsistent, exit the app ASAP. This is often the correct answer in client apps.
  • Try a different function.
  • Move on. For example, some type conversion failed and the original value is as good as it gets.

We get in this situation because we use exceptions poorly, but the response can’t be “Use exceptions better.” We have to deal with libraries that we can’t change, we have to deal with legacy code that we shouldn’t change, our team members have–and will continue to hire–people of varying skill, and writing exception handling isn’t the reason we’re writing software. We’re writing software to meet some business need (or some general need, if you aren’t comfortable with the word “business”). Exceptions take up too much of our time (as does anything that isn’t about making our users and customers happier and more successful).

For a fabulous example of the current situation, consider the joys of int.Parse() and the need for int.TryParse(), which has a horrible legacy syntax and obfuscates the logic of the code.

So we’re left with a mix of reasonable responses to exceptions:

  • Catch the exceptions we can do something useful with, even if that is crashing, and let some unknown error handler above us catch the others. This is the most common suggested solution.
  • Catch the exceptions we have some alternate response to and swallow others with some default action.
  • Swallow everything because failing what we’re doing is not critical. Some comment to this effect makes code reviewers happy (and is generally good for other reasons!), but the same boilerplate comment in many places actually decreases readability. Differentiate Decision from Idiom.
  • Log the exception so we don’t get dinged in a code review for ignoring exceptions. Off-site code reviews by outside consultants love to make long lists of correctly swallowed exceptions and present them managers who are less-technical or who don’t have a familiarity with the code or platform and can’t identify which are well-considered and which are just lazy1.

This post calls out a good response that is often left implicit, because it also gets dinged in code reviews and it is a little scary:

  • Let any unknown upstream called catch exceptions, if they can, and hope they can handle it

Here’s what I’d like to add: It’s a good response when a few conditions are met. In other conditions, other responses make sense (of course). Code should express its intent and assumptions to other programmers who will have to maintain it for years to come; it needs to be readable as to which conditions the programmer assumes are present.

  • All exceptions are handled here. When the libraries change, this code needs to be re-evaluated for exception handling.
  • Known exceptions are handled, but bailing out to upstream handlers is acceptable. Finally blocks are used correctly, for example.
  • Exceptions are informational, but shouldn’t stop execution.
  • Downstream code throws exceptions when this code doesn’t care and downstream functions use the “pass exceptions along and hope they’re handled” philosophy. We just want them to go away.

Also, note that there is a significant different between handling exceptions around one statement, such as int.Parse(), and a statement block which may throw exceptions from any of several calls.

I augment coding standards with something less draconian: a “stop” list (https://s4sd.wordpress.com/2008/09/17/development-red-lights/). This is a list of statement, idioms, and techniques which require stopping, stepping back, and explaining to another (senior) developer. If a second set of eyes agrees that it’s reasonable in this context, you go forward (and say who agreed in the checkin comment!). Swallowing exceptions is a good Stop item.

Make a considered and deliberate choice in how to handle exceptions. Then make it clear. Code that swallows (or logs) any exception indiscriminately won’t go away. It’s impossible to handle exceptions better than your downstream calls throw them and real, reasonable conditions arise where exceptions in downstream code just don’t matter. As an obvious example, an exception from an error logging call (say, network or disk unavailability is preventing logging) shouldn’t be logged.

Just for fun, here’s a cute way to document swallowing errors. “Cute trick” is usually a code phrase for “bad for maintenance,” but maybe this one is reasonable.

   1: using System;

   2:  

   3: namespace ExceptionSwallowing

   4: {

   5:     class Program

   6:     {

   7:         delegate void statementblock();

   8:         static void SWALLOW_EXCEPTIONS(statementblock fn) {try{fn();}catch(Exception){;}}

   9:  

  10:         static void Main(string[] args)

  11:         {

  12:             SWALLOW_EXCEPTIONS(()=>

  13:             {

  14:                 Console.WriteLine("Example of executing a Statement Block");

  15:             });

  16:             Console.WriteLine();

  17:  

  18:             try

  19:             {

  20:                 Console.WriteLine("Throwing an exception that should be swallowed");

  21:                 SWALLOW_EXCEPTIONS(() =>

  22:                 {

  23:                     Console.WriteLine("Throwing an exception that should be swallowed");

  24:                     throw (new Exception("ExceptionToBeIgnored"));

  25:                 });

  26:                 Console.WriteLine("  Success: the exception was correctly ignored");

  27:             }

  28:             catch (Exception e)

  29:             {

  30:                 Console.WriteLine(  "Error: the exception was caught but should have been swallowed: " + e.Message);

  31:             }

  32:         

  33:             Console.WriteLine();

  34:             Console.WriteLine("Press any key to exit");

  35:             Console.ReadKey();

  36:         }

  37:     }

  38: }



Listening to: Lou Reed – New York – Romeo Had Juliette

1) In software, about half the time “Lazy Programmer” is used as a code phrase for “pressured to meet deadlines,” “not given sufficient training,” or “no longer working here and easy to blame.”

Advertisements

Posted in Dev Leads, Tips, Tools, and Tricks | Tagged: , , , | Leave a Comment »

Development “Red Lights”

Posted by S4SD (Seth Morris) on 2008/09/17

Development Red Lights are those things which should stop a programmer in his or her tracks for a second—and maybe a third—look. When you see one, pull another developer over and prove that it’s the right thing to do.

None are wrong and all have uses. They aren’t in the "never do this" category. They are tricks, odd work-around, obscure language and platform features, or even sometimes-correct decisions that won’t break anything, but have some undesirable implication. Many are nightmares waiting to happen to some poor maintenance engineer.

I encourage you to make your own list for your team. Post it. Carry a copy into code reviews and ask the developer to explain why anything on the list is still in the code. There are often good reasons, but at least put a comment on every one.

The list doesn’t need to be long. And ideally you’ll never see anyone try to use something on the list. But it’s well worth having it around.

Here are some of the items that start on my list. After these I add domain- and project-specific items. Include red lights specific to technologies you’re using and any specific to the project’s existing code. This isn’t the place for a list of code suggestions or gotchas; keep it to unreasonable-but-happens code and design that might be necessary sometimes.

If you’re a lead, it’s important that you create your own list and customizing it to your team. I’ve kept my samples short.

Design

  • Classes with "Controller," "Manager," or similar suffixes

These classes often indicate that procedural code has been shoehorned into an object design without any refactoring. They can be appropriate, but check each one and make sure it isn’t actually just wrapping procedural design.

If you want procedural code, go ahead and use it, but make it clear. Don’t try to disguise it as objects.

  • Loose coupling

If you have loosely coupled events (best identified as events where there is no visible relationship between the caller and the callee until run-time), stop and demonstrate that you will use the coupling in a way that makes sense. It’s easy to loosely couple events "on principle" and lose the ability to trace the logic forward. Loose coupling is often appropriate, but it comes at a high cost in maintainability as a system evolves. It is also easier to put loose coupling in than to take it out. Err on the side of the simplest and most easily corrected.

C++

  • Non-public Inheritance

Virtual inheritance is almost always undesirable. It either indicates an inadvertent diamond inheritance or a has-a relationship (composition) modeled as an is-a (inheritance). Consider composition or creating an interface.

Private inheritance means the class is inheriting implementation instead of interface. This is usually undesirable. Again, consider whether composition is a better alternative.

Protected inheritance is just plain wrong. It makes peoples’ heads hurt. Don’t do it.

  • Uncommon Operators

Avoid strange operators and casts, particularly the pointer-to-member operators, >* and .*. These raise the bar for maintenance considerably and can generally be designed-away.

Also be suspicious of overloading the function call operator, operator(). These often indicate gold-plating or overdesign.

In general, operator overloading (other than assignment and maybe comparison) should be limited to classes that behave like data types rather than functional classes. As a rubric, if you have operators as well as functional members (methods) re-evaluate the design and make sure you really mean it.

  • Implicit Casts

Be very careful creating implicit casts. Any c’tor with one parameter creates an implicit cast the compiler will call to coerce a type; this can lead to unexpected behavior that hides a code mistake. Treat c’tors with the same respect you would a cast and consider an explicit cast instead, both in the interface and in the usage.

If a class creates a implicit cast, consider using an OutputDebugString() in debug mode to track it. You can’t search for implicit casting, that’s why it’s implicit 🙂

Not every one-argument c’tor is a warning sign. Watch for conversions from a type that is conceptually similar to the class implementing the c’tor. You want to flag the Red Light when the c’tor may catch a developer using a different class in place of this one.

  • Empty statement blocks

Check that these aren’t a too-clever way to combine logic into a loop test.

Similarly, check that any artificial scope has a reason to exist and is clearly documented.

C#

I don’t yet have a good starter list for C#, VB.NET, or the .NET framework.

Any suggestions?

I have a few items I use for JavaScript code, but they’re pretty obscure. I don’t know if I’ll post them.


Listening to: The Bonhoffs – Manhattan Sleeps – Shiraz

 

Posted in Dev Leads | 1 Comment »

Dev Leads pt 1: What is a Lead?

Posted by S4SD (Seth Morris) on 2008/09/17

This is part one in a series on the role and practice of the Technical Lead, Lead Engineer, or whatever your company calls them.

What is a lead?

The software industry doesn’t have any standardization of titles, responsibility, team structure, or levels of experience and skill; the industry as a whole is certainly too young and too dynamic for all that. But at many— maybe most— companies, teams have technical people who perform both technical and non-technical leadership. Many companies mark these people out as development leads; at others they may be called technical managers, managers of technology, or even some untitled subset of senior engineers.

These people are in roles with duties they have not been trained for; they are often neither appreciated nor compensated for the role; and they often have no explicit authority to perform many of the day-to-day tasks required of them. The dev lead’s job usually falls to them for non-technical reasons: the respect of their peers, their ability to communicate and mediate within the team, and their appreciation of the entire project context and business needs, as opposed to just technical skill.

At many companies, the people in lead roles are never told exactly what is expected of them as the lead, where it can go as a career within the company, or how their performance as a lead will be evaluated. And very, very few companies provide any real training in being a lead.

To make matters worse, most leads are also expected to continue owning crucial sections of code, but the work of the lead requires an interrupt-driven and meeting-heavy day showing a level of confidence that is in direct opposition to the requirements of deep coding: uninterrupted time, introspection, and repeated failure. Many leads work much of the regular workday as a lead, doing procedural things, answering questions, and firefighting; then they work into the evening or night writing their code. 

 

Working Styles

 

Lead

Contributor

Work day

interrupt-driven

scheduled

Attention direction

external

internal

Focus on

many things

one thing at a time

Primary context

the project

one piece of the project

Scope

big picture

details

Validation

external (see/hear evidence that the project is running well)

internal (individual work known to be good by internal judgement)

Temporal structure

perceives time from outside for comparison and planning

varies, but generally contains a strong component of immersion in the moment of work (c.f. "Flow")

Motivation direction

often identifying risk or problems and motivating away from them

often motivating towards a planned course of action (function contract, workflow, test plan, etc.)

Responsible for

everyone

self

If leads are to get the support they require—if you, as a lead, are to get the support you need—we need to identify what a lead is, what a lead does, and why almost every company comes to a similar recognition of a special technical-cum-leadership role but we as an industry still fail to articulate and support it.

Who is a lead?

The role of development lead isn’t always spelled out to the team. Who is a lead? At different companies, different job titles may have the de facto lead role. Sometimes, several titles at the same company are leads, depending on the team or individuals. Sometimes, the lead isn’t recognized by any title or even acknowledged by management. Some leads are self-selected and lead by personal authority.

Commonly, development leads can be found with these titles:

· Dev Lead

· Technical Lead

· Technical Manager

· Senior Software Engineer (although not all Sr Engineers act as leads, of course)

· Manager of Technology

A lead is recognized by the role s/he performs, however poorly that role may be articulated; the title is secondary. As an industry, software is averse to titles, established levels of skill, defined strata of experience, or other standardizations common in some industries.

What isn’t a lead?

A lead isn’t a manager. Some managers are also leads, and some leads are acting or de facto managers, but the role of being a lead is about the project and the technology, not managing the people.

People go to a manager as a liaison with the company: other departments ask to know who is assigned to do what, team members get their priorities and deadlines, or team members ask use the manager as their primary interface to company policies and HR. The manager role operates in a framework of company needs and company policy. Who has sick time available? How is the new hire doing in his or her first 90 days? The scope of the management role includes the project, but is focused more generally on the company and its rules. Managers may insulate team members from too-rapid change outside the team or from maneuvering and posturing that would just distract the team, but the manager role doesn’t have to have to have anything to do with the details of the project.

The Role(s) of the Lead

Leads, on the other hand, are the interface to the project. The lead represents the team to people who don’t interact with the project daily—and the lead interprets and translates the rest of the company back to the team. On a technical front, the lead maintains the state of the project: what is complete, what is at risk, what piece is necessary for what other piece and provides guidance on the implementation as a whole, maintaining consistency, training less-experienced developers, and keeping the broad view of what-impacts-what so other developers can focus on individual pieces.

(Click for full-size image)

Leads perform many roles within a team: designer, communicator, negotiator, mentor, taskmaster, and more. Not every lead has the same responsibilities and every company has a slightly different mix of tasks a lead spends time on. Often these tasks have conflicting needs: uninterrupted time versus interrupt-driven behavior, alone versus interactive, short-term versus long-term. Balancing these tasks is the art of being a good lead, and it varies from company to company and from project to project.

Why does the role vary so much? Because a lead fills in gaps that the organization has institutionalized.

Larger view, split attention

The common themes of the lead’s roles are larger view and split attention. The lead must take a larger view than just one section of the code, or even just the code, and the lead’s attention is split between the project and its goals, the team members and their activities, the lead’s own development, and the business situation and business purpose of the project.

The lead has to communicate the business purpose of the project to the developers and moderate between the project’s business needs and the team’s technical desires. The lead also balances the technical activities and needs of individual team members.

It is the lead’s job to bring this larger view and understanding of the whole situation—technical and non-technical—to technical discussions with the team and planning and status discussions with management.

Technical decisions

The most obvious responsibility of a dev lead—and the one that usually gets mentioned first by their managers—is to mediate and lead technical decisions. This requires knowing the technology and its capabilities, knowing the abilities and experience of the team members, and knowing the requirements and specifications of the product. It also requires an understanding of any sales and marketing limitations on technology, assessing schedule impact, predicting risk, and navigating interpersonal politics on the team.

In addition, the lead must often make quick, confident decisions an present them convincingly to the team.

Owns shipping

On most teams, the lead is the one looked to by management to see that the team’s piece ship. This involves knowing what’s working, what isn’t, and what’s risky. The lead needs to raise problems with management quickly, predict technical problems before they happen, and keep the team focused on shipping the product.

Managing up

The dev lead is the voice of the team to management on anything technical. The lead is responsible for bringing technical problems, hardware, software, or facilities needs, ideas for new approaches, or anything else requiring the company’s assistance to management. Even if the lead is not also to titular manager, personnel issues will often become apparent to the lead first or manifest as technical issues; the lead is often the only way management is informed about what’s actually going on with the team.

It is the job of the lead to "manage up" for the team: to reduce the amount of overhead management requires, to filter management’s activities to only those relevant to the team, and to convince management to listen to the team’s concerns and needs.

Interpret management

As the flip side of being the voice of the team, the lead interprets management’s directives and business needs into technical needs. This includes developing development plans, validating technical specifications, and making technical decisions. This puts the lead in a position of influencing how the team reacts to management’s decisions and communications.

Oversee design

The lead oversees design. This can lead to a tension with team members depending on how much autonomy the team members have to do their own design. It can also lead to conflict with team members over the design decisions. The lead needs strong technical decision-making skills, but also needs good skills to communicate the reasons for decisions and the requirements decisions are made on, as well as good communication, rapport, and influencing skills.

As a corollary to this, the lead determines the criteria used to make technical decisions. Internal conflict can be reduced by making these criteria explicit at the outset. (But that’s the subject of another post.)

Mentor juniors

The lead is the person junior engineers look to for technical growth, evaluation, and inspiration. The lead is in a position to shape their expectations, their work ethic, their interaction with their peers and with management, and their career path.

How the lead interacts with juniors can be especially important when there are other senior, non-lead developers who do or do not want to mentor juniors.

Model engineer

The lead is the model engineer for the team. He or she is the example of what is expected. The lead’s code and design must be of acceptable quality, the lead’s communication must be acceptably clear and helpful, and the lead’s focus sets the tone for the team and tells them what is important. Leads are in between developers and managers. Even if they are also managers, when they are acting as a lead they are a developer as well. Leads must be familiar with the complete design and much of the code the teams produces.

As a developer, different leads have different levels of code-producing involvement. Some leads take critical pieces of code and keep them to themselves; others refuse to take code on the critical path. This usually depends on the amount of time and attention other tasks are requiring of the lead.

The lead’s code has to be of acceptable quality, but it doesn’t have to be the best on the team. There may be brilliant developers who aren’t leads for many reasons. As the holder of the project state, the lead needs to acknowledge that someone else’s code is a better model for junior developers to learn from.

Implement technical process

The lead implements the technical, team-facing portion of the development process. The lead sets the pace, tone, and structure for code reviews, design walk-throughs, and technical documentation. How the process is reified comes from the lead.


Listening to: Dusty Springfield – Dusty in Memphis – The Windmills of Your Mind

 

Posted in Dev Leads | Leave a Comment »