We all know the feeling. You've got a new task to do, and you can't think of how to implement it. Or; you've got an idea for something, and you can't decide where to start. No matter what it is, you have a problem to solve, but no ideas yet on how to solve it. No, you're not alone, and no you are NOT a bad developer.
I had this problem for a very long time, long through my development career, and it wasn't until recently that I found a trick to overcoming it. Please note, your mileage may vary. What works for me may not work for you, and it's no silver bullet, but I would recommend giving this a good try :)
First, lets use our imagination. Think about a situation where you are asked to build some sort of API layer on top of something. When I say an API, I just mean a series of functions or methods that perform certain related tasks. Let’s say, for example, that we needed to build a helper library in JS that generates media query strings. I built just such a tool for my Shades library (shameless plug, sorry).
The way I approached that task was to work backwards. Hang on, what? Let me show you. We know the end result, since it’s described for us already: we want to generate media query strings. This wrapper library needs to be able to generate any valid media query. So, first step, take a look at a few medium-sized media query examples, ones that combine a broad set of media query features, and at the same time lets work out what all the different individual types of value that can go into a media query.
Some examples taken from the MDN docs are as follows:
@media screen, print
@media (max-width: 1245px)
@media screen and (min-width: 30em) and (orientation: landscape)
@media screen, print and (min-width: 30em) and (max-width: 100em) and (orientation: landscape) and (color)
After looking at these and looking through the rest of the MDN docs on the subject, we find that media queries support the following things:
- Media “Types”, of which there are only 4 possible values:
speech, and one can have anywhere from 0 to all of these in a single query.
- Media “Features”, most of which can accept a value of their own (such as
heightwhich accept pixel numbers), some which allow only one of a set of possible values (such as
orientation, which can only be either
landscape), and others which are implicitly set to true if you include then without specifying a value (such as
- Logical Operators (such as
Now we understand all the different possible values that can go in a query (or at least we know the different kinds!) and we have varying examples of what media queries can look like. They can be as small as just one value, of either a media “type”, or media “feature”. Alternatively, they can be as large as you want to go, including literally every possible “feature” and every valid “type”, including various logical operators and combinators. So, that’s quite daunting, but we don’t need to start by implementing each of these one by one! Not at all!
Let’s just start by imagining we had the perfect library already built, that we could use right now. If we needed to write a media query using this library, what would that look like? Imagine it as being the best JS library in the world for this task, without worrying about the implementation or complexity or anything yet. Pretend it’s all done for you. Let’s have a go at writing a media query with our amazing, magical pretend library. What I ended up writing at the very beginning as my “ideal api” looked something like this:
Which would translate into something like this:
@media screen and (orientation:portrait) and (width:950px) and (hover:hover)
Now we have an idea of what we really want to build! The end result may vary a little bit, but the general goal is very clear. We can now start writing our first test cases too! In the end, the actual API I built looks more like:
Only slight changes, but changes are still ok. Just because we designed our API first doesn't mean it's set in stone. At least we now have a target to aim for.
I hope this method helps you just as much as it has helped me. Until next time!