Category: Software

Gainslog now makes daily backups to Google Drive

Thanks to this great tutorial on how to extend Laravel’s storage to Google Drive, Gainslog now pushes daily updates to Google Drive.

Following the tutorial, one issue people run into is a File not found error when running the backup command.

You can get around it by setting the backup folder name to an empty string – but that will place all the backup zip files directly into the storage/app folder.

One way to make sure all backups go into a single folder is to setup a new local disk in filesystem.php and update the backup.php config to use that one instead.


// config/filesystems.php
'local' => [
    'driver' => 'local',
    'root' => storage_path('app'),
],

'local-backups' => [
    'driver' => 'local',
    'root' => storage_path('app/backups'),
],

// config/backup.php
'destination' => [

    /*
     * The filename prefix used for the backup zip file.
     */
    'filename_prefix' => 'backup-',

    /*
     * The disk names on which the backups will be stored.
     */
    'disks' => [
        'local-backups',
        'google'
    ],
],

Interfering in the way users are used to doing things is a no-no

Gainslog is a simple calorie tracker I made with only a handful of users.

If you ever tracked your macros before, you know reaching your daily protein intake goal is the most difficult to attain from all three macronutrients (proteins, carbs, and fats). Once you hit your proteins target, the other ones come around easy.

Because protein is the hardest macro to fill, I made it look like a priority throughout the app – making sure that everywhere macros appear they are ordered based on how hard is to get them in one’s diet. So it’s “proteins, carbs, and fats”.

Leaving aside the fact that for some people (with high calorie needs), carbs are harder to get, a new user pointed out that on a regular food label, the macros order is different – it’s fats, carbs, proteins – and that I should correct the site to reflect that.

Gainslog’s “add food” form

It makes sense, at least for the form used to add new food items. When you’re copying stuff from one place to another, it’s easier if the order in which you enter the information is the same. Being a good maintainer and carrying about people’s wishes, I’ve corrected the order everywhere through the site.

As soon as the update hit production, all hell broke loose – all users instantly went “why you changed that?” on me.

What is funny is that they didn’t notice the labels changing everywhere, but only on the daily status area. They, like me, were used to focus on the first number (since protein intake was the hardest to achieve).

Gainslog’s daily status – order was changed to fats, carbs, proteins from proteins, carbs, fats

Long story short, I reverted the order for the daily status and kept the others reflecting the food labels – which made it super easier to enter new items, but of course, few people actually noticed it.

Books told me that “taking a feature away will irritate users”, but I never thought such a small change will be taxed this hard. Nevertheless, I interfered in the way people were used to doing things, and that pissed them off. Lesson learned.

The fact they didn’t notice the order changing in other places concerns me – it means there’s something I can clean up more. If the information is not worth noticing, why keep it?

Amsterdam is card-only

I recently visited Amsterdam, and besides the never-ending smell of weed and thousands and thousands of bikes, another weird thing stood out. Most shops, bars, and restaurants are card-only. They do not accept cash at all.

While I understand and support the reasoning behind that – it’s much safer for both parties, eliminates human error, and it’s less expensive than dealing with cash, what bothers me is they don’t let you know in advance. Not even a poster or a note, nothing.

I regret not finding out what happens if you say you don’t have a card at all. Free meal?

Sorting algorithms

Photo by Charles Deluvio 🇵🇭🇨🇦 on Unsplash

Whenever I read about interviewing at a large company the author talks about how you need to know your algorithms on the spot and to the letter. It’s the same old story everywhere: “I got some basic questions about this, this, and that, and then we moved on to algorithms”.

I always felt bad for not knowing algorithms but let it slide thinking one day I’ll need to learn them in order to do my job. Funny enough, after many years of programming, I’m yet to stumble upon a situation in which I need to do a Bucket sort, or a tree sort, or whatever other sort exists. You might argue that I don’t do them because I don’t know them, but I can easily counter that with “most of the time I just need to pull records out from the database and order them by x column”.

Anyway, today I thought I should give algorithms a try. Not because I feel bad for not knowing them, but because I’m sure there is plenty to learn from figuring out how they work.

I hope it will be fun 🙂

First screencasts: building dashcopy

Building dashcopy

A few days ago I wrote about doing something I never did before, something I’m not particularly good at. As expected, the initial result was poor, but I kept on improving the obvious mistakes and it got better. It’s true what they say: first drafts always suck.

Sharing your progress through screencasts, podcasts, and blog posts is a common practice, so I thought I should give it a go and started a video series on youtube. It’s a great way to keep myself accountable and practice expressing my thoughts and my rusty East-European English.

I knew it will be hard. Talking by yourself, and especially hearing your voice, is super awkward, even more so if your pronunciation is poor, or you’re just bad at talking in general.

But oddly enough, it wasn’t that hard as I thought it will be. The end result is a million miles away compared to your standard Jeffrey Way screencast, but it’s way better than I hoped for. My pace is irregular and I sound like I’m talking from a hole, but overall the videos are bearable.

Although sometimes I got into too much detail, or wasted time running tests knowing they will fail (beating that TDD dead horse), my intent is to move away from the tutorial-like material and turn it into real, unplanned coding sessions where I try to figure out the best approach in doing things. Ideally, I would love to reach a point in which I am able to code and speak my mind at the same time, but I am aware it will take me a long time o master that skill.

Here’s a link to the channel. If you watch programming screencasts regularly, I would love to get your opinion.

Also, if writing is something you wish to get better at, join the list and be the first to know when dashcopy is ready.

The build cycle of a Laravel application feature

I wrote about having a crossword approach to writing software, but I haven’t given any real-world examples. I only said it’s better because it doesn’t let you wander around and dip your fingers into everything. It keeps you focused on what’s needed now.

Let’s say you’re building a content management system using Laravel. Here are the steps I’d take to build it:

1. Write the code to display the posts in some kind of list. You can get this done by just having a seeder in place and a simple query on the index method. Don’t worry about filtering or anything like that.

2. Write the code to show, store, update, and delete posts. Completely ignore any validation and authorization for now.

3. Notice I haven’t said anything about writing views. No html&css should be written so far. Views can wait.

4. Go back to the create and update methods and add some validation rules.

5. Sprinkle some authorization too. Don’t forget about the delete method.

6. If you need to filter the posts in any way, now is probably a good time to do it. Don’t forget to write tests that cover every filter.

7. Now that all the logic is in place and thoroughly tested, we can start focusing on the views. Style the index and the show views.

8. Add the create and edit post endpoints and style their views too.

9. Sprinkle some javascript where’s needed. Don’t over do it.

10. Pick the next feature. Make sure it touches as few things as possible.

Rinse and repeat.

Better, not perfect

I just finished something I’ve been working on for the past week and I am quite dissatisfied with the result. I’m not sad, nor annoyed. It’s something I never did before, so poor results were to be expected anyway.

What brings me satisfaction is that, one week in, and I already found more than a few ways to make it better. They are not ifs or maybes. They are obvious improvements that directly impact the end result.

Don’t waste time, don’t put much thought on it, “Just ship it” they say.

The reason behind “just ship it” is to get as much feedback as possible to help you gradually improve whatever you shipped. The faster you get the feedback the better.

But how do we know when it’s “ship-ready”? It will never be perfect, but when it will be good enough? You can’t just deliver some crappy version of your idea and expect people to like it enough to guide you in the right direction.

It’s good enough when you’re done improving the obvious.

Eloquent trick #1: Replace conditionals with “when”

It happens very often that we want to apply certain eloquent query conditions based on what a request sends in. Sometimes it’s a “search by name” thing, other times we just need to filter the records based on a status column.

Usually it looks like this:

public function index(Request $request) 
{
    $posts = Post::newQuery();

    if ($request->term) {
        $posts->where('name', 'LIKE', "%{$request->term}%");
    }

    if ($request->status) {
        $posts->where('status', $request->status);
    }

    return view('posts.index', ['posts' => $posts->paginate()])
}

I recently discovered there’s an alternative to using conditionals. The “when” method executes a callback (second parameter) when the first parameter evaluates to true.

public function index(Request $request) 
{
    $posts = Post::when($request->term, function($q, $term) {
        $q->where('name', 'LIKE', "%{$term}%");
    })->when($request->status, function($q, $status) {
        $q->where('status', $status);
    });

    return view('posts.index', ['posts' => $posts->paginate()])
}

It’s not all that better if you ask me. Yes, it hides the conditionals, but it also makes the code harder to read. Especially if you have more conditions to add.

I’d use this “when” approach for single conditions only.

public function index(Request $request) 
{
    $posts = Post::when($request->term, function($q, $term) {
        $q->where('name', 'LIKE', "%{$term}%");
    });

    return view('posts.index', ['posts' => $posts->paginate()])
}

Thank you, apple, for letting us know we’re not alone

Feel bad for messing up something at work lately? You’re not alone :). Apple messed up big time.

The bug lets you call anyone with FaceTime, and immediately hear the audio coming from their phone — before the person on the other end has accepted or rejected the incoming call.

Read more here.

A crossword approach to writing software

One of our jobs as programmers is to think ahead so that we build the right things in the right order and at the right time.

“Ok, I’m gonna build this to do that, and then I’m going to add X so I can do the other thing that will do Y and everything should fit together.”

Our everyday thought process

The problem is sometimes we’re overthinking it. Sometimes we don’t need that extra class or that extra parameter. And that method we think we’ll use later might never be called at all.

Everything we write has a cost. Every extra class, variable, method, or parameter we add makes our code harder and harder to understand and support.

The reason why we fall into this trap is that we often don’t have enough information about what we’re building. We know the bulk of it, but details always seem to be slipping through the cracks. Building extra stuff is our way of trying to catch those hidden details. We call it speculative generality.

One way to avoid speculative generality is by taking a crossword approach.

The most effective way of solving a crossword puzzle is by filling in the easiest words first. Find and complete them, and you get more information about those other hard words you don’t really know what they are and how to solve.

The same principle can be applied when writing software. Instead of building a component from the inside out, do the opposite and start from the outside in.

Stop trying to figure out the hardest parts and go for the easy ones first. This way, while you move towards the core of your component, you’ll uncover more and more details about it.

Start by picking the smallest possible feature.