melreams.com

Nerrrrd

Context!

a railway bridge supported by brick arches surrounded by lush green jungle
Unrelated image from pexels.com to make this post look nicer in social media shares.

So I was browsing workplace.stackexchange.com questions late one night, as you do, and came across an interesting one: How to explain business priorities to a programmer.

That one didn’t go at all the way I thought from the title. It turns out the business priorities actually did make sense (the business had this wild idea that queries, even especially complicated ones, should take less than 4 hours to run) and the programmer was being unreasonably rigid in following “best practices”.

But weirdly, one of the answers said that both parties were wrong – that the programmer shouldn’t have been so attached to having nice looking code and the manager shouldn’t have insisted on using an anti-pattern. What? The anti-pattern (using raw SQL instead of the ORM) improved performance by multiple orders of magnitude! If performance matters at all, you cannot possibly tell me that massively improving performance was the wrong thing to do.

Okay, there is some nuance there :) If your ORM performs that badly it’s likely not configured right for your situation, so it might be better in the long term to fix your config than to keep writing custom SQL for every query that’s the least bit complicated. On the other hand, if you don’t have an expert handy who can tune your ORM config, it might be easier to ditch it, at least for the more complicated queries, and just write some SQL. Or hey, how about a compromise? Use a stored procedure, that’s what they’re for! If it’s a query you run a lot, it might even make sense to make a view for it.

No matter what you end up doing, it’s still not wrong to use a supposed “anti-pattern” if you have a good reason to do it. It’s the context that makes something a bad idea, even the best idea can turn bad if you use it the wrong way. The only way to know whether your “anti-pattern” is actually a bad idea for your particular situation is…. to look at your particular situation! You can’t just say something is an anti-pattern without knowing what the person using that anti-pattern is trying to accomplish.

Let’s look at another datebasey example. It’s generally considered a bad idea to denormalize your database, every database design course will tell you so. Normalizing your database ensures all of your data is always right by isolating everything that can change independently. Since you don’t usually bother to keep data at all if you don’t care if it’s all accurate, you almost always want your data nicely normalized.

But sometimes correctness isn’t the absolute most important thing. Let’s take browser or mobile games, for instance. If your game takes too long to load, your players will just go do something else and they might not ever come back. It’s much more important to be fast than it is to be perfect if you want to make money on a game like that. And if something does go wrong and a player gets mad because their data didn’t get saved correctly, you can just give them game currency until they’re happy again.

In a situation where performance is more important than correctness, normalization is the anti-pattern. Like I said, it’s all about context!

To be clear, there are some things that are just a terrible idea no matter what you’re doing. I don’t care how clever you think you are, your variable names need to make sense. And no matter how well it performs, if your system is so confusing than no one can make updates, then it’s a bad system. But for the most part whether or not something is an anti-pattern is about what you’re trying to accomplish more than it’s about the “anti-pattern” itself.

Everybody likes code that makes sense to them, and everybody likes to feel like they’re doing things the right way, but rigidly following “best practices” just isn’t good enough. If it doesn’t help you achieve your greater goals for your application (ie not just gold-plating your code, but providing value to your users or customers), it’s just not a good idea no matter how many experts call it a best practice.

And yes, that means you can’t know if your code is good or bad without knowing exactly what you’re trying to do. Welcome to professional programming!

Be a better programmer while still having a life: part 12

a waxing moon a little over half full against a deep blue sky
Unrelated image from pexels.com to make this post look nicer in social media shares.

Keep it simple!

It sounds obvious, but I have wasted so much time debugging problems that turned out to be something ridiculously simple like my browser cache being outdated, having forgotten to deploy my code, having made my updates in my local database instead of the staging database, etc, etc. Better developers are more productive, and you know what instantly makes a person more productive? Wasting less time!

Double checking extremely simple obvious things can save you massive amounts of time. Like I said earlier, a little self-doubt is good for you. If you can’t ever doubt yourself at all, you’re going to waste a lot of time on silly mistakes you could have just double-checked.

This can be really really hard to remember as a dev, so don’t feel bad if you mess it up sometimes. My best guess is that’s a side effect of working with complicated problems all the time, so we assume the problem has to be more complicated than just having deployed the wrong code like a dope.

Another great way to keep things simple is to build the simplest possible solution for your problem. This is such a common problem that we have an acronym for it already: YAGNI (you ain’t gonna need it). Before you write more code ask yourself “Do I actually need this?” Protip: if you actually need the thing it will be obvious. If you don’t actually need it, don’t build it. Yes, things should be somewhat flexible, but there’s a limit.

Names are a great clue to whether you’ve built something so flexible that all it’s really doing is adding complexity. If you can’t guess what your object/function/module is for by looking at its name, it’s probably too vague. Using Java reflection is also a bad sign :P

Another way to check whether you’re building something too flexible is to try to explain it to someone else. If they can’t follow what on earth you’re doing, it’s definitely too vague. Even if they can follow your explanation, another person who isn’t attached to the terribly clever idea you came up with may be a lot more willing to say “No, we don’t actually need this, this, or this. That part is really cool, though.”

You can also try asking yourself if there’s anything you could possibly take out of your design. If you were doing the thing manually (just imagine your database lookups are done in a filing cabinet or giant binder instead), what would be different? Would there be fewer steps? Fewer people/processes/forms/approvals involved? This can be a tough one for programmers because for many of us, super complicated “solutions” make us feel smart and we love to feel smart.

I’m not going to pretend I’m any sort of UI expert, but this definitely applies to UI too. Do you really need a setting for everything? No! Make a decision already, if you’re going to leave everything up to the user, what are you even for? At least provide a sensible default setting and hide the fiddly stuff no one cares about under an “advanced” tab or something.

You know who failed at keeping it simple? Yep, it’s Google bro. Hey, if he didn’t want to be used as a terrible example over and over he should have been a better engineer. Given the choice between ignoring all of the existing science about gender differences in humans and making up a ridiculous and complicated fairy tale about how even though sexism obviously exists that couldn’t possibly be the reason there are fewer women than men in tech (let’s just ignore the fact that programming started out as a job for women while the men physically built the computers), no it must be some bizarre feature of our silly ladybrains, and the simple and obvious explanation that sexism exists, dude went with the most complicated possible explanation.

The more complicated your idea, solution, or design is, the more chances it has to fail. That’s still true even if your argument wasn’t built on sand in the first place. Simplicity, on the other hand, tends to work a lot better. The fewer moving parts you have, the fewer things you have to worry about holding in your head while you build it. As a bit of an aside, if you’re ever wondered why even extremely expensive software produced by armies of highly paid contractors is so often terrible and buggy, it’s because there are too many moving parts for our poor fleshy brains to keep track of.

Simplicity is incredible timesaver, for both you and your team. Simplicity in your code reduces the number of bugs you create, and avoiding creating bugs is orders of magnitude faster than fixing them. It also makes it easier to fix your bugs when you do run into them. Simplicity in your design can be the difference between a project that actually goes into production and does something useful, and something that just never quite gets launched. Simplicity in your problem solving helps you catch silly mistakes that waste hours of your time, so keep it simple!

Be a better programmer while still having a life: part 9

brown wooden wheel on an old cart with fallen leaves around it on the ground.
Vaguely related image from pexels.com to make this post look nicer in social media shares.

Don’t reinvent the wheel! I’ve touched on this before, but it definitely merits its own post.

A huge part of becoming a better developer is understanding when you don’t need to write new code to solve a problem. The more code you write, the more code you have to maintain, the more chances you have to screw it up, and the more time it takes to write it. So before you write new code, see if there’s a library, a plugin, a product, a design pattern, or a best practice that solves your problem. At least see if anyone wrote an article or blog post about a similar problem and learn from what they did.

To be fair, sometimes what you need really isn’t well served by an existing trustworthy product or library and you do need to write your own custom code, but that needs to be an informed choice, not a reflex.

What I think makes a product trustworthy is active development and a large userbase. The main advantages of using a library instead of writing your own code is that you don’t have to update it and that most of the bugs have been worked out already because so many people use it. By all means use a small library that isn’t maintained if it’s convenient and not a core part of your project, but for the love of god don’t depend on a framework/database/core part of your project that isn’t actively maintained and/or doesn’t have any users. That will just end in tears.

You also don’t want to import a library for every little thing, the more libraries you import the more bloated your project becomes and the more chances you have to run into a bug in one of them (and let’s not forget the left-pad debacle), but for stuff that would take more than a few hours to write, see if somebody else already wrote it.

For example, writing your own regex to validate email addresses is almost certainly a waste of time. Are you really going to write a better validator than the Apache Commons EmailValidator? No, you’re not. And do you want to have to maintain it forever even if you do write a great validator? No, you don’t. So use the library and move on with your day.

Yes, writing code is way more fun than integrating a library, but when you’re at work your job is to get results. If writing your own code gets the best result, do that, but if integrating a library gets the best result, do that instead. Of course, to understand what gets the best results, be it a library, a whole product, an API, a design pattern or whatever else, that means you have to understand what’s out there.

As a bit of an aside, that’s why the Google bro is an incompetent engineer – his ridiculous screed shows he either didn’t read or didn’t understand any of the existing research about personality differences between men and women (spoiler: there aren’t any statistically significant ones). While junior engineers get a pass on not searching for or not understanding existing libraries, senior engineers do not. If you can’t Google (see what I did there :D) existing research or existing libraries, you simply are not operating at a senior engineer level.

Sometimes it is useful to reinvent the wheel – modern wheels with inner tubes and shock absorbers make riding in a modern car a lot more comfortable than riding in the first cars with their solid wheels (Google bro’s wheel, on the other hand, is square and the axel is off center, which is just embarrassing). If you can’t do better than existing wheels, just use what’s already out there and save yourself some time.

Ironically, admitting that you aren’t the greatest developer who ever lived makes you a better developer. Accepting that actively maintained, well-used libraries are often better than what you would write on your own not only saves you a lot of time, but also makes your final product better.

Link of the day

Jessica Kerr has a really interesting blog post about how code reuse is often overrated. Back in college I learned all about how important code reuse was and how duplicated code was the worst, but we never (probably because we had a lot of material to cover in a limited time) talked about how code reuse can cause problems. Jessica gives a great explanation of how bad code reuse can paint you into a corner, you should check it out.

 

 

What’s a code smell, anyway?

a rugged metal tower, possibly a lighthouse, seen at low tide on a rocky beach with puddles all around
Unrelated image from pexels.com to make this post look nicer in social media shares.

Design is one of my favourite parts of programming, but I constantly run into the problem of how to tell whether my design is any good.

Before we go any further, I think we should define what makes a good design is. My definition is that if you can change it in the future without cursing your past self, it must have been good design. You may have noticed that using that definition makes it difficult to figure out whether a design is any good until potentially months after the fact when you need to change it. It would be nice to know ahead of time whether your design is going to lead to a lot of swearing in the future, and that’s where I have trouble.

To be fair, if I could definitively answer the question of whether a design was good without having to try to change it, I’d be a millionaire and I’d be writing this post from my own private island :) Whether a design that seems good now is going to continue to be helpful in the future is just a hard problem and there’s no getting around that.

That said, I think code smells can help a lot there. A code smell is, in the words of Martin Fowler, a surface indication that usually corresponds to a deeper problem in the system. The term was coined by Kent Beck while he helped Martin Fowler with his book Refactoring.

This whole concept would probably make more sense with an example. An especially designy code smell is a class that does too much. Ideally a class should have one responsibility – if it’s concerned with more than one thing that’s a strong sign it should be broken up into separate classes. The specific problem with a class that does too much is that it’s likely to lead to long, messy methods that do too many things and don’t make sense because of it, and it generally makes it hard to reason about your system. The more one class does, the more state it’s likely to need to keep track of, and the more state one class keeps track of, the more chances you have to completely mess it up. You may have gotten a hint here that software design is about accepting that humans are bad at it and trying to work around that basic fact :p

The thing with a code smell is that it’s not a hard and fast rule, it’s just a hint that something could be wrong. Sometimes it can be reasonable for a class to do “too much,” it depends on the exact thing you’re trying to accomplish and the context (i.e. the rest of your application) that your class is part of. Having a good design is more about the thing you’re trying to accomplish than it is about following all the rules whether or not they make sense in your particular situation.

The great thing about code smells and design patterns and all that is that they let you take advantage of other people’s experience. Can you imagine how long it would take to get good at software design if you had to make all the mistakes yourself? I love hearing what other people have messed up so I can maybe avoid that particular problem. And from the other side, I’d love it if anything I’ve told another dev helped them avoid a problem. It’s all well and good if I solve a problem for myself, but if I can help a couple of people avoid the problem in the first place and if those people help a couple other people avoid that problem, then I’ve done much more good than if I quietly fixed my own code and moved on.

Stay tuned for more posts about code smells, there are plenty of them to get through :)

Let the computer do it for you

Loosely related image from pexels.com to make this post look nicer in social media shares.

Many years ago when I was in college, a friend taught me something that’s been really useful for my whole career. That lesson was to let the computer do it for you. Unless there’s a compelling reason to do things the hard way, just let the computer make things easier for you.

Learning lisp? Get a plugin for your text editor or a simple IDE like Dr Racket that matches your parens for you.

Working with fixed width files? Get Record Editor, it’ll save you so much time!

Fighting with javascript? Get WebStorm! Seriously, it’s freaking amazing.

If you have to do something tedious and fiddly, get the computer to help you. That’s what it’s good at. There is a tool out there that will make your life easier, you just have to go and look for it. The hard part is remembering to go look for it :)

It’s normal to think that if there was a tool you could use your teacher or your boss or someone on your team would have told you about it, but thinking to look for tools like that is surprisingly unusual. And to be fair, it can be a real timesink to try tool after tool just to find out none of them are better than what you’re already using.

That said, if someone on your team hasn’t already told you that they’ve tried everything they could find (and searched for tools recently), it’s worth doing at least a little Googling and seeing if there’s already a tool that would make your life easier. Other people use lisp, you can safely assume there are tools out there for it. Other people use fixed width files, you can safely assume there are tools for those too. And tons of other people use javascript, tools for that are getting better all the time.

If there isn’t already a tool, you might be able to build one. That’s exactly what bash or powershell scripting is for – fiddly things that humans are bad at and tedious but simple things that humans just don’t wanna do. If you’ve ever run a build script, you’ve used a custom tool that someone wrote to automate building your application so it gets done the exact same way every single time. No matter what OS you’re running, there will be other scripts out on the internet that you can take apart to build your own custom tools.

Whether you find tools or build your own, remember that boring stuff is the computer’s job!

Link of the day

Julia Evans has a great guide to asking good questions, you should read it :) Asking good questions is such a useful skill, I wish programming education spent more time on it.

Getting really good at asking questions is also a great hack for looking like a better developer (it’ll also help you actually become better, but in the short term it’s a good hack). When you ask a bad question, like “My code isn’t working, can you help me?” people have to wonder what you’ve tried already or if you tried at all before giving up and asking someone else. If you ask the exact same question with more detail, especially about what you tried already, like “I’m trying to send an email but I’m getting an error message I don’t understand. I tried googling it but I got a bunch of different answers and I don’t know which one applies to my problem. Can you help me sort through them?” then it’s obvious that not only did you not immediately give up, but you also respect your answerer’s time enough to make it as easy as possible for them to help you. Telling them what you’ve tried already means they can skip suggesting things you already did, and asking a specific question means they don’t have to do the work of figuring out what the question actually is before they can even start thinking about how to answer it.

People love it when you make things easier for them, and when you show them you’ve put some effort into doing so, they’ll think you’re a better programmer than the person who makes getting the real question out of them like pulling teeth even if both of you are around the same skill level. That’s the hack part :) The becoming a better programmer part is that stating a question really clearly (yay rubber ducks!) and listing everything you’ve tried already may trigger that flash of insight about what you haven’t tried but should or what assumption you made that could be wrong. If you get into the habit of reflecting on what you’re doing, you’ll learn a lot faster than someome who sits around and waits for help.

Be a better programmer while still having a life: part 5

Unrelated image from pexels.com to make this post look nicer in social media shares.

Today’s tip for becoming a better programmer while still having a life isn’t just good for you, it’s good for your whole team. That tip is documentation.

I know, nobody actually likes doing documentation. Fortunately, I’m not talking about dry design docs or endless specifications, I’m talking about a simple wiki (or whatever works for you), written by you and your team for you and your team. It doesn’t have to be polished, it doesn’t have to be formal, it doesn’t even have to be spelled perfectly. All it needs to be is correct and understandable. The idea is to explain things just like you would to another dev on your team, not to waste hours proofreading.

Great, but what should you document? In short, anything you’re going to want to know later. Especially useful things to write down are why architectural decisions were made, how parts of the system work at a high level, guides to testing certain features (great for complicated payment provider integrations, not that I’ve been fighting with those), and especially guides to setting up your development environment, whatever that thing is that you forget every time and have to look up again or ask someone about.

Just saving yourself time relearning parts of your codebase will help you get things done faster, which is basically being a better programmer, but explaining things (even if you’re writing to yourself) helps you understand them better. Explaining something forces you to think about every little detail, and putting something in your own words helps it stick in your brain – it’s the same principle that helps you remember things better when you take notes on them, whether or not you ever look at those notes. The better you understand your codebase, the better decisions you can make about how to add new features or fix bugs.

As a bonus, reflecting on why you made certain decisions and being able to go back later and see if the reason you did things the way you did holds up over time also makes you a better developer. You don’t even need to make a special effort to do this, if code gets used it gets changed. All you need to do is wait, eventually you will have to revisit the code you documented and by the time you do that, you will probably have forgotten the details and will need to go look it up in that handy wiki you created :)

Writing things down also helps you get that answer again without interrupting anyone, and the less you can interrupt teammates the better considering how expensive interruptions are for programmers. I couldn’t find a hard number, but I feel comfortable saying that it takes at least ten minutes to get back into a complex task like programming once you’ve been interrupted. It can be even worse if you get interrupted at just the wrong time. I have a terrible time getting into a task when I know I’ll have to stop soon for a meeting or appointment or whatever, which means an unfortunately timed interruption can kill a solid half hour of productivity even if it only took a couple of minutes to deal with the interruption itself.

All the benefits you get from making knowledge about your code available and searchable also apply to your teammates. If you just document how to set up your development environment, that can save hours every time someone has to set up their environment whether it’s a new employee starting or a long time employee getting a shiny new computer to replace an old one. It’s even better for everyone around you if the whole writing things down idea catches on – then they also get the benefits of explaining things and documenting the particular things they forget and need to look up as well.

And best of all, this is another work thing you can do at work that has no effect on your personal time.

Be a better programmer while still having a life: part 4

Unrelated image from pexels.com to make this post look nicer in social media shares and because red pandas are adorable.

As much as we would all like to believe that programming is about logic, not feelings, being able to deal with your emotions is incredibly important if you want to be a better programmer. For example, one of the best things you can possibly do for you career is to learn to take criticism. Logically everyone should be thrilled to get feedback on their work but you know what gets in the way? Yep, it’s emotions.

It can suck to hear all about what’s wrong with your code, especially if you worked really hard on it and thought that this time you finally got it right. Hearing about what you need to improve is incredibly helpful (who has time to make every possible mistake on their own? that would take forever!), but that doesn’t mean it never hurts your feelings. And when people’s feelings are hurt, it’s really hard for them to listen. Sometimes emotions get in the way of your improvement as a developer.

So how do you learn to take feedback even when it hurts?

First of all, you’ve got to accept that it’s normal to have feelings about being told that your code isn’t good enough. There’s no fixing a problem that you can’t admit is happening, after all. That absolutely does not mean you should be ashamed of having feelings – not only is it just plain wrong to shame anyone, including yourself, for being human, but it’s a huge waste of time. All it means is that if your feelings are keeping you from being able to take feedback, you’ve got to get a handle on them. You would debug a program that couldn’t handle certain inputs, right? Sometimes your mind needs debugging too.

One way to do that is to remind yourself that feelings aren’t facts. Just because you feel attacked or like everything you do is stupid and terrible and you’re never going to be any good at this and should just crawl into a hole doesn’t make it true. That’s just your brain freaking out, if you give it a minute it will calm down. Yes, it sucks in the moment to hear that your code needs work, but you’re going to feel fine tomorrow. With practice, you’ll get used to hearing what you can improve and start skipping the boring angsting step to go directly to fixing things.

A common thing programmers do that makes that way harder is to get really really really attached to their code. You should absolutely care about whether you’re doing a good job but you’ve got to remember that your code is not you. The quality of your code has nothing to do with your worth as a human being and any one piece of code doesn’t even mean much of anything about your skills as a programmer. Everyone has off days, making a mistake does not mean you’re a bad programmer, will always be a bad programmer and should just go find a hole to crawl into. Everybody makes mistakes, you’re not that special ;)

Quick side note: code reviews are never supposed to be mean. Aside from being a tremendous dick move and thoroughly unprofessional, it’s a waste of time to be a jerk when you’re giving feedback. If people hate doing code reviews they will find ways to not do them and the quality of code on your project will suffer. If you can’t be nice because it’s right, be nice because it’s effective. And if your team lead/senior dev/whoever does your reviews can’t at least be civil, find a new job. Life is too short to put up with dicks.

Something else you can remind yourself about when you’re having feelings about a code review is that nobody gives advice to people they don’t believe can do better. If you believe someone can’t learn you don’t bother giving them a code review, you quietly fix what you can while they’re not looking and hope they eventually get fired. Bothering to give someone feedback is a statement that they’re worth the effort.

The most important piece of advice I can give you, though, is that you need to be able to take a step back both from your feelings. Meditation is great for this, by the way. I’m going to steal Headspace’s traffic metaphor here because it’s really good: training your mind isn’t about forcibly clearing it, it’s about learning to watch your thoughts and feelings go by like cars on the road and not needing to run out into the street and direct traffic. Having a feeling doesn’t mean you have to do something about it right then, you can wait a bit and see if it’s still important.

That stepping back thing is useful for more than just code reviews, too. Professional software development can be really frustrating for reasons that have nothing to do with writing code. Features get changed or cut, projects get dropped, companies change direction, sometimes things never make it into production no matter how much you believe in them or how hard you try. If you can’t step back from your attachment to a project and accept that things don’t always go the way you wish they would or even the way they logically ought to, you’re going to have a bad time in this field (or any other for that matter).

While you’re at it, literally step away from the computer now and then and do something else. Not only can you become a better programmer and still have a life, but having a life will make you a better programmer. Nerds tend to hyperfocus, which is great when you have a concrete task to get done but not quite as great when you lose all sense of perspective because you do nothing but code all day. Having other things you’re good at and other things to look forward to really helps put that one bad code review into perspective.

Be a better programmer while still having a life: part 3

Unrelated image from pexels.com to make this post look nicer in social media shares.

More stuff you can do to be a better programmer while still having a life!

The core of programming is really problem solving, but we’re kind of expected to pick it up as we go while we’re learning specific skills like programming in java. I have a strong suspicion that’s why so many new developers feel totally lost when they try to build something on their own: we’ve collectively done a bad job of teaching them how to break down problems and solve them.

Problem solving is a gigantic topic so I’m not pretending this blog post is going to be comprehensive, I’m just aiming to share a few tips to get you started.

First of all, don’t just start coding. It really helps to have some sort of plan for what you’re going to do. If you dive in and just start coding without any sort of plan you’ll often end up lost in the weeds because figuring out how to solve a problem and how to code that solution at the same time is so much harder than doing those things one at a time.

Ironically, it’s also hard not to do those things at the same time. It’s really common to feel like you’re wasting time planning and making lists when you should be writing code, or that planning is boring and no plan is ever perfect so why bother? It’s also not at all unusual for programmers to start coding without a plan because they’re worried about whether they can solve the problem, so they just start writing code and hope the complete solution will come to them.

Having a plan actually speeds things up because it cuts down on the feeling your way around in the dark that you end up doing when you don’t know where you’re going or how to get there. If you really can’t stand the planning part, programming may just not be for you – solving problems is the real job, code is just the tool we use to solve them. Making a plan may force you to admit that you just don’t know how to solve a certain problem which sucks, I’m not going to lie, but isn’t it better to figure that out right away instead of potentially spending days or weeks coding only to find out that your partial solution is never going to work? Trust me, that sucks way more.

So that’s all great, but how exactly do you break down a problem and make a plan to solve it?

One example is laid out in 5 Steps to Solving Programming Problems by Adrian Prieto. The step I want to concentrate on is “2. Solve the problem manually.” Seriously, write it down exactly the way you would do it if you had to do it manually. If part of the problem involves looking things up in the database, just pretend you have a gigantic binder or that you can call another department for the data you need. The imaginary manual procedure might sound really awful and tedious but that’s fine, computers are great at boring and tedious.

Example time! A common programming challenge question is to write a palindrome checker – you give it a string, it tells you whether or not it’s the same backwards and forwards. It’s really easy to look at a short palindrome like racecar and see that it’s obviously the same backwards and forwards, so let’s imagine we have a much longer string. Now how do we tell whether or not it’s a palindrome? One way is to look at the first character and see if it’s the same as the last character, then the second character and the second last one, and keep doing that until we get to the middle of the string (let’s assume for now that we don’t have to worry about spaces or punctuation). If we make it to the middle of the string it must be a palindrome, so we can return true. If any of the pairs of characters don’t match then it’s definitely not a palindrome, so we can stop checking right there and return false.

Now that we have a manual process, we can start adapting it for a computer to run. The thing you have to remember is that computers are really dumb. If you tell a person “stop when you get to the middle of the string” they’ll know what you mean and what to do if the string has an odd number of characters so there’s only one in the middle. Computers, on the other hand, don’t know what a “middle” is unless you tell them and don’t know what to do with a string with an odd number of characters either. For that matter, they don’t know how to tell they’ve gotten to the middle of the string.

In the interests of not making this post 5000 words long I’ll skip the specifics of telling a computer how to find the middle of a string, the important thing to know is that once you have an overall process you can dive into subproblems like “how can the computer tell when it has checked enough characters?” without losing sight of why that problem even matters and how it fits into the rest of your solution.

It really doesn’t matter how bad your first try at a process is. Writing down how you would do it manually is always good enough for a first try, and once you have a basic process you can start improving it or even trying totally different algorithms. The great thing about a simple set of point form instructions or even pseudocode is that it’s much quicker and easier to change than actual code, so you can mess with it to your heart’s content.

That works great for straightforward problems, but what do you do with an overwhelmingly large problem where it’s not obvious where to start? Let’s say you want to build a todo list app. Should you start by designing the UI? Or by figuring out what your data model should look like? How do you decide which features your app should have?

The question about what features you should have is one of the simpler ones: build the tiniest thing that could possibly work. You can always add more features later. In the case of a todo list app, I would start with being able to add new todos and being able to cross off existing ones. Don’t worry about subtasks, don’t worry about due dates or recurring tasks or anything else, just start with the simplest thing that could possibly be considered a todo list.

As for where to start, if I knew the right way to approach every problem I’d be a millionaire :) I personally like to start with the UI so that once I get down to the data model I already have a list of all the visible information that I definitely need to store. On the other hand, if you’re especially comfortable with data modelling it can be easier to start there. That can also save you from building a database that’s perfect for one screen and kind of terrible for everything else. It really doesn’t matter where you start as long as you remember to look at your overall design from different angles and see if it still makes sense.

At the “boxes and lines” diagram stage just like the point form description of a manual process stage you lose hardly any time at all if you sketch out a solution, figure out it doesn’t handle something well, then throw it out and start over. The important thing is to learn more about the problem, not to come up with a perfect design on the first try.

Like communication, practising problem solving doesn’t have to take up a single hour of your time outside of work. You can get all the practice you need on work problems while you’re at work and still have a life outside of work :)