Recent Updates Toggle Comment Threads | Keyboard Shortcuts

  • Joel 10:39 PM on December 2, 2016 Permalink | Reply  

    Bad Developer No Twinkie Part 7: Assuming data is good 

    Bad data happens.  Sometimes it happens accidentally.  Sometimes it happens intentionally.  There’s one thing that is for certain though – it will happen.

    This week we got hit by a particularly nasty bug.  It happened entirely because the way a particular piece of code was running – it made the assumption that an incoming piece of data was ordered by a given attribute.  In 99%+ of the cases, it was ordered, but no where in the specifications did it say that it would be ordered.  In the cases where data came in out of order, we were doing things incorrectly, and we generated bad results.

    I find this particularly true when working with Python and JSON data: never trust the format of data (especially the contents of Python dictionaries or JSON data).  For example, in python, you would do something like:

    someVal = someDictionary["level1"]["level2"]
    

    If someDictionary was loaded from a piece of JSON from a web request, how do you know that “level1” is there?  You don’t.  In such a case, the above line will explode.

    I am quite fond of the new C# way of handling things with the null conditional operator:

    var someVal = someObject?.someProperty1?.someProperty2;
    

    In the above code, someVal will only take on the value of someProperty2 if someObject is not null and someProperty1 is not null.  One nice clean line.  You still have to check the result of someVal, as it could still be null, but it is a nice, clean way of doing things.

     
  • Joel 11:15 PM on November 29, 2016 Permalink | Reply  

    The problem with HTTP status codes 

    HTTP status codes are pretty useful.  They can tell you when things have gone wrong, and tell you roughly what went wrong.  There are, however, cases which don’t seem to be covered by them.

    In my job, I work with web services – both writing them and consuming them.  Our team, in particular, has a number of projects that provide a web API endpoint to the UI team, and we in-turn, rely on other web services.  Some of these web services are written by us, and some are not.

    When the user makes a request from the UI, it hits an endpoint somewhere in the bulk of our application.  From there, it may go on to call one of these other external services.  In general, if the user makes a bad request, we immediately return with an HTTP 400 (bad request), and we try to indicate that the user did something wrong.  If something terrible happens (like an unhandled exception), we kick back with an HTTP 500 (internal server error).  But what do we do if one of the external services that we rely on fails?

    It isn’t necessarily the user’s fault, as the user didn’t do anything wrong.  It also isn’t necessarily an internal server error, as it wasn’t our service that failed.  Not only that, but all the contents of internal server errors are replaced with a generic message, so as to not leak things like stack traces, which would make reverse-engineering things much easier.  So if we return an HTTP 400, it makes it look like the user did something wrong (which isn’t the case).  If we return an HTTP 500, we can’t tell exactly what went wrong.  In cases like this, we’ve been doing one of two things:

    • Return an HTTP 400 error anyway, so we can at least tell what is going on.  This is less than ideal, but at least allows us to see what went wrong, and the UI properly displays something to the user.

    – Return an HTTP 500, but with a specific content.  Rather than having the body of the request replaced with something generic, we fill it out with detail on what went wrong, and hope that the UI knows how to display this properly.

    Both still seem a bit less than ideal, but there doesn’t seem to be an HTTP status code for “Hey, something went wrong with an external service, even though you did everything correctly.”

     
  • Joel 10:39 PM on November 24, 2016 Permalink | Reply  

    Bad Developer No Twinkie Part 6: Don’t lie to your users 

    No one likes being lied to, even from software.

    Take the following screenshot for example:

    wp_ss_20161101_0001

    Do you think I’ve got no browsing history?  If you did, you are wrong.  See the little blue dots at the top of the image?  That means it’s still loading.  One part of the screen was telling me that had no browsing history, while the other part of the screen was telling me that it was still loading.  (And for whatever reason, loading a browsing history in Windows Phone 8.1 takes forever).  So basically, part of the app is lying to me.  Wouldn’t it make so much more sense if it said “Loading…” instead of “Now browsing history”?

    Don’t lie to your users.  If you don’t know something, indicate that you don’t know it.

    I’ve had Outlook do this same thing.  One part of Outlook was saying that I had an unread RSS feed, yet actually looking at the RSS feed items, there was nothing unread.

    Remember the wise words of Thumper (from Bambi) when it comes to UI:

    If you haven’t got anything truthful to display to your users, don’t display anything at all. falsified data.

     
  • Joel 6:57 PM on November 18, 2016 Permalink | Reply  

    Bad Developer No Twinkie Part 5: Assuming people know things 

    As a software developer, you have to work with people.  It’s part of your job.  Sometimes those people are other developers, sometimes they are your clients.  Despite what it looks like, software development is rarely, if ever, a solitary effort.

    As such, you should never assume that whoever it is you are working with knows everything.  I had two rather frustrating instances this week with two different parties, simply because they made the assumption that I knew things – things which were not obviously stated.  It essentially made me feel like an idiot.  No one likes feeling like an idiot.

    Let’s look at a few examples of this:

      • Don’t assume your clients know technical details.  Maybe you are lucky, and you have a tech-savvy client who actually knows a bit about software development.  That doesn’t mean they know all the ins and outs of whatever it is you’ve built for them.  Don’t treat them like an idiot, but also don’t assume that they know everything about the software you’ve built for them.
      • Don’t assume new developers know the technical details.  Building software is often a complicated affair.  Every piece of software is different.  So is almost every development shop.  New developers won’t know all the details of the stuff you’ve built.  Take the time to coach them properly.  Time invested now is more time saved later.
      • Don’t assume developers have all the domain knowledge they need.  Developers don’t know everything.  I’ve worked on software for at least two major different industries.  In both cases, it took a fair bit of reading and discussing with other developers on the team to gain the necessary domain knowledge to fully understand the problems we were trying to solve.  Even after working in a particular industry for a few years, there’s still a lot that I don’t know.

    Don’t take this to the extreme though.  Treating your customers like they don’t know anything has a similar effect.  Essentially, if you are doing your job right, you should be in frequent communication with your clients anyway, and should have an understanding of where their knowledge level is at.

     
  • Joel 8:53 PM on November 8, 2016 Permalink | Reply  

    Whiteboard interview alternatives? 

    One of the things that seems to be taking a lot of flak lately in the tech industry is the concept of a whiteboard interview. The interviewer asks the interviewee some sort of coding question, and asks him/her to write a solution on a whiteboard, as opposed to writing out the solution on the computer.  The idea behind this is to see the candidate’s train of thought, and see how they approach a problem that they would potentially be unfamiliar with.  In the real world, no one writes code on a whiteboard, and no reasonable employer is going to deny an employee internet access to search for solutions.

    (The only situation where I can see someone being disallowed internet access is when working on classified materials, which is by far, the minority of the real jobs out there).

    So rightfully so, the classic “whiteboard interview” is getting a bit of a bad rap.  But I still haven’t seen many alternatives proposed.  Some of the ones I have heard of:

    • Give the person a laptop and have him/her code on it.
    • Online sites that allow a candidate to code in a browser (handy for remote interviews).
    • Look at the person’s public git repositories for examples of code they have done.
    • Not asking coding questions.

    As far as each of these go, there are pros/cons.  For example, if a person only has done private work, they’d have no public examples of their code that they could show.  Not asking coding questions doesn’t help filter out the candidates that can’t actually code.  Out of the above options, the least unfriendly seem to be actually giving the candidate some sort of IDE and letting them actually code something, but even this isn’t failure proof.  I know I don’t code as well on an unfamiliar keyboard layout, and I’d potentially be slower if I were working in an unfamiliar IDE.

    Either way, I still think as an industry, we’ve got a lot of room to improve here.  But how do we do it?  In that regard, the tech industry is a bit different.  I’ve never heard of a doctor being asked to perform a “practice” surgery on someone before getting a job at a different hospital.  But a doctor also goes through a lot more rigorous process to becoming a doctor.  Almost anyone can pick up a compiler and learn to code.

    I’m curious to know what you other folks have encountered during tech interviews (or even interviews in other industries).

     
  • Joel 8:48 PM on November 2, 2016 Permalink | Reply  

    Bad Developer No Twinkie Part 4: Gigantor functions 

    I think at one point or another, we’ve all done this.  We started off with a nice small function, but kept adding functionality to it.  Just a few lines here and there, and before you know it, you’ve created a 1100 line long gigantic function that everyone refers to as “Gigantor”.  It does multiple things, the logic is complex, and the code is a rats nest.  Everyone fears touching it, because no one wants to break it.

    It’s easy to say “Don’t do this”, but harder to not do in practice.

    My recommendations for avoiding this situation:

    • As you write it, refactor it. When you see an opportunity to clean something up, do it.
    • Make sure a given function does one small thing. If you find a function doing more than one thing, split it
    • Don’t write similar code more than once. If you find you are seeing similar structures within the same function, that should fail the smell test – it’s ripe for refactoring.

    It’s better and easier to keep on top of things, rather than one day waking up and having to fight Gigantor. No one likes fighting Gigantor.

     
  • Joel 9:32 PM on October 28, 2016 Permalink | Reply  

    Bad Developer No Twinkie Part 3: Ignoring documentation 

    I can’t count the number of times that I’ve seen someone refer to a particular project (whether it be a JavaScript library or a 3D physics engine), only to check it out and find a complete lack of documentation.  I’m not talking about code comments or internal documentation, but end-user documentation.

    Don’t ignore documentation if you are producing a product that ‘other’ people are going to have to use.

    Yes, maintaining documentation can be a pain in the butt, but it’s part of the job.  If you actually want people to use the thing you are working on, you’ll likely need to instruct them in one form or another – be it a simple README file or a series of video tutorials.  (Although kudos to you if you have created a product that requires minimal effort to understand and use).

     
  • Joel 8:28 PM on October 28, 2016 Permalink | Reply  

    Code won’t tell you everything 

    This thought crossed my mind the other day: in order to understand what is happening with a particular program, looking at the code won’t always tell you everything you need to know.  It’s a good start, but without examining the environment that the code is running in, you may be missing some critical details.

    When I say the environment the code is running in, I mean things like:

    • External library version numbers
    • Environment variables
    • The current system time (and time zone)
    • Network conditions (latency, packet loss, bandwidth)
    • Existing data

    In my software development experience, there’s been multiple occasions when the code has looked correct, but things were still running incorrectly as a result of something other than the code.

    Remember: if the code looks correct, but results aren’t: check your environment.

     
  • Joel 6:49 PM on October 21, 2016 Permalink | Reply  

    Bad Developer No Twinkie Part 2: Improper use of null values 

    Null values are okay in certain circumstances.

    You may have heard null values called the “billion dollar mistake”  because the amount of problems that they can potentially cause. This is true – using null variables where you shouldn’t be is a bad idea. In general, I avoid them, but there are some cases where they can be handy, and can actually save headaches later on.

    Let’s take an example. Suppose that you are writing some sort of application that tracks your personal contacts. For each person, you are tracking a name. email address, phone number, and a birth date. Now suppose you don’t know the birth date for a new contact. If the birth date field is not nullable, you end up having to enter some sort of default value – like January 1, 1900. Later on, you add a feature that reminds you when people’s birthdays are, and you are suddenly inundated with reminds about tons of birthdays on January 1st.

    In a case like this, it makes perfect sense to make the birth date field nullable. A null value basically means “I don’t know what this is right now, but I might know later on”.  This does mean that you will have to do proper null checks – especially when displaying things on a UI, but at least now you have an easy way of telling if you actually have the birth date for a given person rather than relying on some magical date which may or may not actually mean what it is.  This sort of thing – using magical default values to mean something that you really don’t know – leads to anger.  And as we all know, anger leads to suffering, which leads to hate, which leads to suffering, and before you know it, you’ve crossed over into the dark side.

    To use a more personal example, one project I recently touched had something like this. In a particular piece of data, they were using the value of 0.01 to indicate that they didn’t actually know what the real value was. (In this particular domain, valid values could have ranged from, say, 20 to 200, so seeing a value below 20 is already a bit suspicious, but still).  So why not use a null value?  I have no idea why they didn’t.  But shame on them.

    My recommendation for null values is this: start with making everything not-null, then allow nulls as required by business needs.

     
  • Joel 10:00 PM on September 30, 2016 Permalink | Reply  

    Bad Developer, No Twinkie Part 1: Unclear error messages 

    In the spirit of Ernest Adam’s “Bad Game Designer, No Twinkie!” series, I’m tempted to write a series of blog posts about bad things I’ve seen in general programming.

    The first one up to the bat: unclear error messages.

    This one bit my team this morning.  We have a nightly job that runs, and tries to associate data between two different systems.  Each time this cron job runs, it sends me an email and tells me if any part of the data isn’t successfully matched between systems.  This morning we finally had the time to look into some potentially bad data, and came across a particular error message.

    Let’s say our data has 5 parts that all need to be in place for the import to work.  In our case, it wasn’t that part A was bad, or that part B was bad, it was actually part C that was bad.  Unfortunately our error message looked something like:

    Bad data in Part B.

    A bit of a red herring, no?  It wasn’t an outright incorrect error message, but it led us down a debugging path that we didn’t need to go down.  We ended up spending longer debugging the process because the message being generated wasn’t the real cause of the fault.

    The lesson: Make sure your error messages actually reflect the cause of the problem.  Include as much information as possible as to what actually failed.  It’ll make your life (or the next developer’s life) easier in the long run.

    Don’t do this:

    Awesome.png

     
c
Compose new post
j
Next post/Next comment
k
Previous post/Previous comment
r
Reply
e
Edit
o
Show/Hide comments
t
Go to top
l
Go to login
h
Show/Hide help
shift + esc
Cancel