Categories
code development programming

Event Horizon : When sharpening the code means missing bug zero.

A great programmer sees software as a craft, honing a perfect solution from a sea of binary logic. Good software is beautiful outside and in, and even on a large scale is simple enough that there are no obvious bugs. They produce software that is precise and clean down to the last detail, continually improving quality. 

But it’s easy to fall into the trap where quality beats everything. The software cannot ship until every bug is fixed, every scenario is covered, even the heat death of the universe. And the software still hasn’t left your machine.

Until your code is in front of your users it’s an untested hypothesis about what they want and what they can use. And hypotheses, no matter how precise, have a habit of not surviving contact with reality.

Test early, test often 

So start with a smaller hypothesis. Remember that for most of what we do, Newton’s laws of motion are good enough, and simple enough. Unless you’re building something that depends on very precise timings and/or very high speeds, you don’t need to handle relativity.

So ship it.

Build it. Test it. Ship it.

Prove your hypothesis meets the real world, and use it. Define your MVP. Cut it to the bone. And ship it.

Make sure you’re building the right thing: ship it.

Bug Zero 

Every project has a bug zero: no-one can use something that doesn’t exist, and isn’t live.

Fix that bug first, because every other bug depends on it. Either the bug is important enough for them to complain and tell you want they want. Or it’s never used, so remove the functionality.

 

Advertisement
Categories
development leadership lifehacks

The importance of language: acknowledgements 

There’s a few little things that sneak in to conversations and emails that you probably don’t realise you’re doing, until someone points them out to you.

No problem VS You’re welcome

Darlene Price has a great list of phrases you should never say at work. One that really stuck with me was replying to “thanks”, with “no problem”. It was something I did reflexively, either because I thought I was Australian, or because I wanted to minimise the work I’d done. As the article above explains however, it also implies that it would be a problem in other circumstances. Whilst that may be true, there’s an implicit “it’s OK, this time” vibe that, once I spotted it, started to come across to me like a passive aggressive threat. I don’t think that’s how it was perceived, but once I saw that, I couldn’t unsee it, so stopped using “no problem” almost immediately after reading that article.

You’re smart VS You worked hard

This is a parenting basic tip, but it’s a useful thought in general. If you’re smart, then you’re #1, so why try harder. If you worked hard, then you can see the effoer for your reward, and hard work is not a barrier to future success. If you’re smart and you fail, then you’re just not smart enough. If you worked hard and fail, then you either keep working, or seek help. It’s OK to ask for help if you’ve put effort in and need support. It’s not OK if you’re not smart enough, your ego will get in the way.

Categories
development leadership

Dealing with stressful relations

happy sliced bread
“…until everybody does what they’re always going to have to do from the very beginning — sit down and talk!”

Sometimes, there are customers, and users, that frustrate us. They tell us we’re idiots because we built what they asked for (not what they needed), or because they changed their minds. Sometimes they change the hardware, without telling us, into the DMZ, and then get us to figure out why the intranet site no longer works with single sign-on. Sometimes they ask us to draw red triangles with a blue pen.

Most discussions with the customer are straightforward, and you each understand the others strengths, but when things like this happen, especially when there’s a lack of honesty, or a common understanding, it’s easy to quickly reach an impasse and finding yourself getting angry.

I used to work in a call centre for an ISP, where much of the stress was already in play before the customer phoned. I had to learn to deal with people calmly, even when they were clearly upset at not getting the internet service they’d requested. My induction trainer said he took it as a personal challenge to have a customer like that smiling by the end of the call. We had limited tools at our disposal. We had engineers we could call, and we had certain discretionary payments that could be made to compensate for lack of service (although I note that my mobile provider pays these automatically, which is a far better customer experience).

Recently, in the news, there was a story about a wedding venue whose manager was annoyed by a particular bride and decided to challenge her on a forum about it, despite the bride not mentioning the venue, therefore dragging herself into a mess, especially once the other brides in the forum got involved, and she started posting contract details publicly.

It was not a good way to deal with customers.

I have seen it before. It’s an attitude I see when an incumbent supplier loses a renewal to a rival company, and tries to frustrate them, to make it look like the new team are incompetent, without grasping why they lost the contract in the first place. I see it with certain managers who have trouble relinquishing control. I’ve seen it with the customer who said “if you could only write bug free code, we wouldn’t need to test”. I can see where their thinking is coming from, but each example breaks down the trust between the customer and the supplier, and causes barriers to go up, which inevitably make deadlines trickier to meet, increase procedural safeguards, and kill any hope of agility.

I’m not always a people person, but I understand the importance of trust in maintaining these relationships. If you find yourself getting frustrated, don’t take it out on the customer, however much you may feel they deserve it. The customer isn’t always right, but they always deserve respect, if you want the relationship to last.

  • Take time to reflect, and calm down.
  • Sound out the conversation you want to have with an understanding colleague, or a rubber duck, so you can get to the meat of what you want to resolve.
  • If you need to sit down and negotiate a peace, set some groundrules.
  • Always challenge yourself to make the other person happy.
  • Be honest.

And it’s not just your customers, I’ve had to deal with big disagreements in the team as well. Sometimes you need to shepherd the team, and sometimes you need to manage them. Just don’t become part of the problem.

Categories
code development leadership lifehacks programming

Something or Nothing

image

“We must do something
“How about we paint this elephant pink and let it rampage through the nursery?”
“Well, it’s better than nothing, I suppose”

No, no, no, no

There’s a limit to what you can do. If you don’t know your next step, step away from the keyboard, grab a coffee, or a whiteboard, or a book. If you’re still not sure, write some tests to experiment, and throw them away so you can think about the full impact before you wrote the final version.

A man of action forced into a state of thought is unhappy until he can get out of it. – Franz Kafka

Movement isn’t always progress

Just because you’re doing something doesn’t mean it’s productive, if it’s poorly conceived and planned, if it’s reactive rather than proactive, it’s just as likely to be actively harmful. Bad code isn’t technical debt, it’s a trapdoor, or a cancer if it starts to spread.

Adding code without requirements is a clear way to hokey-cokey code or creeping complexity. If you can’t say that your change will improve the code for other developers, the customer, or the users, stop and think.

Bigger picture

It’s not just changes that cause problems. Unthought architecture can be even more dangerous. Obviously statically typed code is better than dynamic, because the compiler does something to protect you. Except static typing doesn’t protect you from null references, it doesn’t protect you from yourself.

It’s obviously better to have some logging than no logging. Unless you log everything and can’t find anything. Unless you log user and database passwords in the clear on your web server.

Every line of code you write is a breeding ground for bugs and security holes. If you remove complexity, and embrace simplicity, nothing is the most secure, most reliable way to implement something, and you need to justify the risks that come from changing that by giving the change a reason to happen.

It’s not just code

Is it better to have a project plan for a different project with different deadlines than no project plan? And even if it has the name of your project at the top and estimates you wrote, is it still a realistic plan for your project?

And are they your use cases?

Be Zen

Strive for quality via simplicity (and go read Zen And The Art Of Motorcycle Maintenance: 40th Anniversary Edition to truly understand that). You Aren’t Going To Need It. So don’t write it, until you do. Embrace nothing when the right something is unclear.

It’s not always easy, especially when we want to look busy, but sometimes your most productive hour is the one you spent watching that presentation on your todo list, rather than writing that $6bn dollar error.

Categories
development leadership

Handling disagreements as a team

Following my code review post, I added some more thoughts regarding code reviews, but there was one comment that I wanted to come back to later:

“Social aspect: How do we handle disagreements? As a team.” – peitor

There are a number of aspects to successfully dealing with disagreements, some of which are about mitigation and avoiding the problem in advance, and others about how you deal with the problem once the disagreement has started to grow, after all, it’s hard to avoid the vim vs emacs, “that’s not RESTful”, brace placement, or other developer arguments.

Collective Ownership

The first key to avoiding unnecessary disagreements is to leave your ego at the door, because teams full of egos will fight each other to be seen. As Peopleware: Productive Projects and Teams so elegantly describes, any situation that asks developers to compete against each other, whether under performance review,or by dividing functional teams geographically, will inevitably lead to conflict and a blame culture. If you are all on the same team, with the same goal, it’s in everyone’s interest to resolve disagreements before they become conflicts.

Constructive Criticism

One of my colleagues has been writing a series on becoming a technical lead, it’s all worth a read, but his latest post, about constructive criticism, is particularly relevant to this discussion.

Constructive Criticism is a reality of doing code reviews, it’s arguably the whole point of doing them, but make sure that you are able to articulate clearly what you expected in a friendly manner, a Blame Culture is bad.

This doesn’t just apply to code reviews, but that’s an important example of where code is judged. Firstly, constructive criticism should be about the behaviour or the outcome, rather than the person (although even at that level, it’s wise to avoid abusive language if you want to avoid alienating your team, just ask Linux Torvalds), and secondly it should offer practical, achievable improvements, so that the person receiving them can use them as an opportunity to improve.

Lone Wolf

There are 2 main categories for individuals who have a detrimental effect on the team. One is the black hole who needs additional support or encouragement and sucks time away from the rest of the team, and any work they produce is marginal. They might be just a poor team player, or a square peg in a round hole (maybe they’d be great in another job on the team or in the company), but they breed resentment in the rest of the team having to compensate.

As a leader, you either need to find a way to help the person to improve and fit into the role they are doing, via mentoring, training or other means; or you need to find a role they are better suited to, by looking at other tasks that need doing.

If you can’t do either of these things, you will need to make the tough decision to get that person off your team so that the rest of the team become more productive and do not degenerate into dysfunction.

Rockstar

The other key individual threat to team coherence is the rockstar developer. The one who plays by their own rules, and always knows best. Unlike the black hole, they get the job done, but they often do so at the expense of the team.

Key traits of Rockstar code is code that doesn’t fit the rest of the team, code that is too clever for its own good, and therefore much harder to test and debug.

Everyone knows that debugging is twice as hard as writing a program in the first place. So if you’re as clever as you can be when you write it, how will you ever debug it?

Just like the black hole, the rockstar developer causes addition work for the rest of the team, but often leaves behind code that the rest of the team don’t understand in order to be able to refactor it. This resentment can be seen by the rockstar developer as jealousy, as their non-stick ego prevents them from taking responsibility for dysfunctions in the team, and it is clear, particularly to those outside the team, that the individual is achieving results (indeed, the rockstar often makes it very clear).

A rockstar does have many of the qualities needed to be a good developer, so long as they can be convinced to simplify and work with the team rather than steamrolling past. Unlike black holes, they are probably doing the right tasks, but need help to understand their impact on the rest of the team and any problems that result from their code, as they may have trouble accepting it.

Duelling banjos

Sometimes, there are individuals that work well with the rest of the team but not each other. Sometimes this can be caused by jealousy or resentment, particularly if one was recently promoted or given extra responsibility when they were previously equal, or one of them is more likely to have their ideas accepted by the team.

The slighted individual in this scenario needs support from the other individual and the rest of the team to accept the situation, and build resilience so they can move on, and, where appropriate, a clear explanation for why the differential occurs.

Hopefully these disagreements are on the ideas rather than the individuals, because when things get personal, it gets a lot harder for people to back away from a disagreement. However, the technology world is notorious for bug fights over little things.

Which text editor do you use? (whichever one you like, so long as you can set the format to the project coding standards)

Where do you put the opening braces? (for Javascript, always use K&R style, on the same line, for everything else, whatever the project says)

If you’re fighting over something that doesn’t really matter, ask yourself why, and if you can just agree to disagree, and accept that you’re not going to convert everyone to Dvorak.

If you see others on your team fighting, look out for Logical Fallacies that can drag the argument down into personal attacks, or unproductive sniping rather than a stimulating argument on improving the code. Be prepared to step in and separate the individuals. Give them a chance to cool down and reset, or space to think, talk and reflect.

Red eyed monster

The tired, stressed team are far more likely to argue and those arguments are more likely to get personal. Don’t overwork. Find your work-life balance.

You

You are a member of the team. Exhibit the behaviour you want to see.

Categories
code development programming

Up to speed with Git with recommended tools and books

On my current project, I introduced Git to a team used to Subversion (apart from the odd few), so I’ve had to research a few good resources for the team. I wanted to share these with you, for those of you new to Git, or wanted to get your team up to speed.

The best resource I found to start with was Version Control by Example by Eric Sink, which walks through a typical workflow in Subversion, Git and a couple of other version control systems. It’s great for picking up the basics for those coming from another version control system, or none.

I recently read Pro Git, by Scott Chacon and Ben Straub, which has given me a much better understanding of what’s going on under the hood, and has been a great resource to help me understand some of the problems the team have had with Git, and the patterns and principles required to fix them. It’s also got some great information for administering servers and repos, including setting up hooks, transport protocols, and various other details. I’m not sure I’d recommend it to a novice, but if you really want to get under the skin of the key-value datastore and directory structure underneath Git and want to know how and why it does what it does, it’s a great resource.

Pro Git recommends HTTPS as the transport layer, and that’s probably the easiest to set up for corporate networks with tough firewalls, but I have had problems with Github’s 2-factor authentication, and I tend to switch between a number of tools on the desktop, primarily SourceTree and Visual Studio 2013’s Git Flow Extension by Jakob Ehn for the Git Flow process, TortoiseGit for the merge UI, and the command line for everything else, which means the credential cache is often out of date, whereas SSH keys are much easier to keep in sync via Pageant, as installed by Tortoise. If you want to set up SSH keys yourself in Windows, one of my colleagues wrote this post.

For the members of the team less comfortable with curly braces, I’ve pointed them towards GitHub Desktop for the easiest way to stay in sync.

What are your favourite Git tools and reading?

Categories
code development programming

Dynamic language and semantics

Given the opportunity to revisit my Genetic Algorithms library, I wanted to revisit my open letter to Jon Skeet, about semantics and dynamic languages, and compare how the code looks in C++ vs Python. I accept that C++ is an overly verbose language but the problem I want to discuss is similar in C# and Java. I’m just going to pick a few examples, but feel free to explore the code yourself, either as C++ templates or as Python examples. These examples all expect a certain knowledge of Genetic Algorithms, so I’d recommend reviewing my previous post first if you are unfamiliar with the concepts.

If you’re trying to compare them directly from the repositories, please note that I have removed some comments and logging, and changed the formatting in this post for reasons of clarity, and have yet to apply those changes back to the repository. I have also added some functionality to the python code that doesn’t currently exist in the repository to ensure the examples are comparable.

Fitness

In C++

  /***********************************************************************
   *            SAMPLE FITNESS FUNCTIONS                                 *
   ***********************************************************************/

  template<class _Ctype, int _Csize>
  struct fitness_base {
    virtual double operator()(_Ctype chrom[_Csize]) = 0;
  } ;

  template<class _Ctype, int _Csize>
  struct maxones : public fitness_base<_Ctype,_Csize>{
    double operator()(_Ctype chrom[_Csize]) {
      return std::count(chrom, chrom+_Csize, 1);    
    };
  } ;

The fitness function for a chromosome returns a number that is used to rank the chromosome such that fitter solutions are more likely to survive and breed. For the example below, note that by default, the chromosome is an array of type _Ctype (default: bool), of length _CSize (default: 32)

The fitness function must be passed as a parameter to the constructor so that different problems can be explored using the same representation. This requires a type for fitness functions fitness_base which is defined as virtual to ensure it can be overridden, and contains an () operator so it can be called. In C#, this would be a delegate type, and we would be able to use the function/action types from the library as the base class for maxones. The fitness function shown simply counts the number of ones in the chromosome.

In Python

    def fitness(self):
        return sum(self.genome) 

Functions are first-class objects in Python, so we don’t need anything special to pass them as arguments, or require overloading the () operator. However, Python also allows patching classes post-initialisation, so we can overwrite the fitness function, or we can use Python’s multiple inheritance mechanism to subclass 2 different versions of chromosome, one of which overrides the fitness function, and the other overriding the crossover function.

Note that the fitness function is different between the two fitness functions is simple, but I now prefer the cleanliness of sum to a conditional count, but the overall character of the code will not be altered by the 2-character difference.

Run one generation

In C++

    void run_once_replace() { // one generation = psize crossovers
      pop_t newpop;
      newpop.reserve(_population_size);

      for(int i = 0; i < _population_size; ++i) {
          chrom_t child = select_chromosome() + select_chromosome();
          newpop.push_back(child);
      }

      copy(newpop.begin(),newpop.end(),_population.begin());

    };

In Python

    def run_once(self):
        "Run one iteration of the genetic algorithm"
        # Use replacement algorithm
        new_pop = []
        for i in range(len(self.pop)):
            a, b = self.select_two_members()
            new_pop.append(a + b)
        self.pop = new_pop

In these examples, apart from some small syntactic sugar that allows us to return 2 values from a function, the C++ and Python code are just as clear as each other.

Conclusion

In contrast to my letter, there isn’t as big a difference as I believed when I originally wrote the letter, at least in terms of the resultant code, although I remember the pain trying to get the types lining up properly in the first place. Semantics still matter, and types definitely got in the way designing the chromosomes, but actually, outside some specific cases, with well structured code, static and dynamic languages can both make semantic meaning clear.

Categories
development programming

Software is not a fixed point in time

That’s why business struggles with agile. It wants to freeze software and treat it like a building rather than a support tool for a process.

It’s also why business has to spend a long time “evaluating” new operating systems, browsers, devices,… because change is not built in to how many businesses do business.

Businesses don’t trust change, for very good reasons. Change is expensive, it involves retraining, replacing, and dealing with sunk costs. Change means managing communications, managing staff and making the infrastructure to support old and new. It’s painful and no-one wants to go through it again. So it gets put off, and it’s even more painful next time.

It’s frustrating watching customers who adjust their process to work around the software rather than fixing the software, and freeing staff up for all the nice to have things they moan about. If they’re working around your software, it’s likely they don’t know what it does, and it’s magic, or they know what it does and they don’t like it (which makes it tricky to enforce ethics by software alone).

You look at software and see the Palace of Versailles, we look at it and see the Winchester Mystery House. We see dead ends, unsafe structures, secret passages, and we want to fix it, to make it easier for you. So take a look at your workarounds and the creaky floorboards, knock down a wall or two, build an extension, and invest in something that will make it a pleasure to live with everyday rather than just living with the pain.

Categories
code development leadership programming

More about code reviews

Many thanks to @peitor for engaging with the last code review post, particularly his comments there, which I recommend reading, and his tweet:

I want to explore a few of his thoughts a bit further, particularly around what code reviews are for.

“team building”

You need to build your reviews carefully to allow team building. As a technical lead, I always get a member of the team, or a peer (if there’s no team yet), to review my code. This can be intimidating for people who believe that there is a hierarchy of knowledge in the team, where the lead knows all, and imparts knowledge. How can such an Oracle be challenged? If I can’t be challenged, I’ve built the wrong team. No-one should release code without review, especially the technical lead, who’s likely to be doing the least coding.

In a properly functioning team however, delegation means that the lead doesn’t have to know everything. They can rely on the developer doing the work to understand the process better than anyone else on the team, and use the review as a learning process to share that knowledge. A functioning code review process not only promotes quality, but it promotes communications within the team.

“finding alternative solutions.”

This is a great use of the review-as-pairing model where the code review is started before the code is complete, allowing for a discussion of options, and the wider context, to ensure the most suitable solution is found.

Maybe you just think of this as a chat between developers, but it’s a great time to review the code and the ideas that generate that code, whilst they’re easier to change. Much easier to change a thought than a test suite.

“What tool can we leverage to make the review more automated?”

I would argue, as @michaelbolton so eloquently does when discussing automated testing with John Sonmez, that the things worth reviewing are the things you can’t automate. Click through and see his replies and the blogs he links to. It’s a gentle but powerful argument.

Tools are great. I love compilers, static code checkers, I love the Roslyn examples I’ve seen, but all that comes before the code review. If it doesn’t compile, or it doesn’t meet the style guide, or the tests don’t pass, it’s not ready.

That’s not to say it can’t be reviewed. There may be questions that need reviewed and answered before all the automated stuff passes, but the sign off review requires that the change has passed the automated steps before it can be reviewed.

Also, be wary of following style guidelines. There’s a reason compilers don’t complain about these things. Unless you know why a guideline exists, don’t follow it blindly. Review your automation as much as your code.

“Review not only code in your team. What about the build process? Deployment scripts? Configuration setup?”

Definitely. This might need to involve the whole team, but everything should be open to review and reflect, and where possible, version it so you can review, share and rollback changes. Don’t trust change, but understand it and use it to help you improve.

“Does it stand on its own?”

“What do you mean by stands on its own?As in, the code under review is a complete new feature, or that it is self-consistent (code and tests match, etc.)

Does the change need a lot of explanation via voice? Or is everything there, so that a future reader can follow everything aka the Why? What?”

Does the code leave behind enough context? We all know the scenario where we’re trying to track down some obscure bug, and then we see that 18 months ago, someone used a > rather than a >= and you’re not sure why. The code review is a good chance to document those decisions. If you want to make sure everyone knows you meant “tomorrow or after” instead of “today or after”, make sure it’s explicit, so that when someone calls your code in 12 months time, they don’t get surprised.

Is there anything else I’ve missed?

I love reading your comments, so please let me know

Categories
development leadership

On respect

image

Firstly, an apology to my regular readers on the delay to this post.  I’ve had a very busy couple of weeks personally, squeezing out the time I have available to blog. Hopefully things will be back to normal next week.

As a coda to my 3 Dear… Blog posts, I wanted to discuss respect.

All of these talk about respect, but I realise that respect isn’t always understood. Respect doesn’t mean to tolerate, it doesn’t mean to accept someone’s position blindly, it doesn’t mean opinion is as valid as fact.

It means that I will try to tailor my message to talk about things meaningful to you, I will be technical with developers, I will talk deadlines and finances with managers, and I will talk to users about their business, not our architecture.

I will disagree with you, but I will be open to the possibility that I am wrong, if you can show me why.

If we can’t agree on something, we must respect each other and the team enough to come to a way forward that recognises without necessarily resolving that disagreement.

I will not respect your opinion. But I will respect your right to hold it. I will respect a hypothesis based on that opinion that can be tested and reasoned about. And I will respect the result of that test, if the methodology is sound. I expect that your first hypothesis will not be your last.

I will not respect you because of the title you hold, your seniority or your ability to bulldoze dissent. I will respect you if your actions demonstrate respect, if your words respect your actions, and your attitude respects your words. Power is not worthy of respect. You will be judged by how you wield that power. I will try and wield my power responsibly.

I am open to change, but not for the sake of change.

Respect yourself and the respect for others will follow.