Sunday, 28 July 2024

D3 and HighCharts: Pros, Cons and Comparisons (Part 2/2)

We have examined D3; now let's take a look at HighCharts.

HighCharts

HighCharts is a commercial Data Visualization tool that produces all (or most) known manner of charts. What's required is a HTML placeholder, a remote link to the library, and your dataset. You declare a HighCharts object and fill in all the properties required, and presto, you have a chart. If your data already comes in a format easily readable by HighCharts, there's very little coding necessary beyond that.


HighCharts takes care of the rest. The end result is your chart of choice, rendered beautifully with whatever color schemes you chose. Mouseovers, tooltips and animations are all built-in. The default settings are great - you don't have to lift a finger.

Which can sometimes be a problem in itself - HighCharts takes care of everything so you won't have to. But if you do want to customize, your options are limited to a plethora of color palettes, custom CSS stylings and other visual stuff. Anything truly out of the box is, unfortunately, also out of the question.
Thus you have a staggeringly huge number of known options, and hopefully your end goal fits into one of these pre-designed templates. As time goes by, HighCharts adds more and more different chart types to their repertoire, in the form of additional libraries. However, again, they are still pre-defined options, so getting something truly custom with HighCharts isn't going to be possible.

When it comes to hammering out a standard good-looking solution quickly with minimal fuss, HighCharts can't be beat. At least, not by D3.

HighCharts is gonna cost you.

HighCharts is free by default, though if you're using it for commercial purposes, there's a license you have to pay for. It's like SGD 200 a year if I'm not mistaken. A single license, with no frills and not inclusive of other add-ons, which also incur a cost. In other words, HighCharts is either free or hideously expensive, depending on what you're using it for.

Conclusion

HighCharts is the optimal choice if you're aiming for a quick and decent solution for a simple well-documented use case, and don't mind paying. If you require a lot of customization and don't mind starting from a painfully low level, D3 is your go-to. D3 is incredibly flexible, but that flexibility comes with a certain amount of complexity which you have to be comfortable dealing with.

My way or the high(charts) way!
T___T

Friday, 26 July 2024

D3 and HighCharts: Pros, Cons and Comparisons (Part 1/2)

As far as Data Visualization goes, I have had the privilege of working primarily with JavaScript libraries D3 and HighCharts. And while to the untrained eye, they are, well, just JavaScript libraries with different names. However, as I'm about to show you today, there are marked differences between the two. Which one you choose will ultimately boil down to your needs, and understanding of their differences will play a huge part in your decision.

Data Driven Documents (D3)

D3 is a Data Visualization library with functions that enable you to step through a series of data in an array, and insert graphical elements (usually SVG - HTML is possible too, but not nearly as versatile) depending on the visualization required. One could chose rectangles or extremely thick lines for bar charts, lines and circles for line charts and paths for pie charts. The measurements of those graphical elements would, of course, depend on the data. Other parts of the chart such as scales, axes and legends, are also handled using inserted SVG lines and text.


Due to the very nature of the way it's designed to be used, a certain amount of math in the usage of D3 is inevitable. You'll need to measure what needs to be subtracted from what, proportionality of this element to that element, and so on. You will need to position everything just so.

The good news is, you'll be able to do it. D3 offers developers a staggering amount of control over the final product. What the library does is give the developer an easy way to traverse the data, along with some useful aggregation functions that can be in turn be nested to produce complex calculations. There's plenty of sweat and toil involved if you want to add bells and whistles (hover effects, fancy positioning, and very custom stuff), but it can absolutely be done simply because the developer is still largely in control.

A lot of control.

Thus, if the design of your intended visualization is unconventional, D3 is the preferred choice.

However, with the amount of complexity and control D3 offers, inevitably more code is involved, and subsequently maintenance can be a chore, if not a nightmare. No one but the most masochistic dev wants to deal with more code, especially if the end goal is something more or less standard.

Finally, D3 is free. It's an open-source project. for something that's free, D3 offers a whole lot of value.

Next

A look at HighCharts.

Sunday, 21 July 2024

Web Tutorial: Python Matplotlib Pie Chart

Howdy, folks!

Now that we're on a roll with the Python matplotlib bar and line charts, we should absolutely go ahead and make a pie chart. This one is going to be simple because most of the work - data gathering and massaging - has already been done with the bar chart. And with matplotlib, the tough calculations are taken care of! Therefore, this web tutorial will not be a two-parter.

Just take the code for the bar chart here, and begin by clearing out the contents of the barChart() function. Then rename the function to pieChart(). Also, we won't be using numpy, so remove the line that imports that library.
#import numpy as np
import matplotlib.pyplot as plt

def pieChart(labels, vals, season, stat):


Also, change the call to the function. With these small changes done, we're all set to create a pie chart!
stats = [];
for v in values:
  stats.append(v[stat])

pieChart(players, stats, season, stat)


We begin by using the figure() method to set the size of the chart. For this, I recommend a square value, meaning the width is the same as the height.
def pieChart(labels, vals, season, stat):
  plt.figure(figsize = (8, 8))


We then use the pie() method. In it, we pass vals, then pass labels as the labels argument.
def pieChart(labels, vals, season, stat):
  plt.figure(figsize = (8, 8))
  
  plt.pie(vals, labels=labels)


We then use the title() method to display the stat type and season. You'll notice that we still use the custom function seasonName() that we created for the bar chart.
def pieChart(labels, vals, season, stat):
  plt.figure(figsize = (8, 8))
  
  plt.pie(vals, labels=labels)

  plt.title("Liverpool FC Player " + stat + " for " + seasonName(season))


Finally, of course, we use the show() method to display the chart.
def pieChart(labels, vals, season, stat):
  plt.figure(figsize = (8, 8))
  
  plt.pie(vals, labels=labels)

  plt.title("Liverpool FC Player " + stat + " for " + seasonName(season))
  plt.show()


Now we run the program. I select the 2021/2022 season and select appearances as the stat type. We get a colorful pie chart!


Here's something potentially useful - a legend!
def pieChart(labels, vals, season, stat):
  plt.figure(figsize = (8, 8))
  
  #customcolors = [];
  #customexplode = [];

  plt.pie(vals, labels=labels)
  plt.legend()

  plt.title("Liverpool FC Player " + stat + " for " + seasonName(season))
  plt.show()


This is for when you have a lot of colors, and you want an easy way to refer without having to squint at the labels.


However, we're not going to use it because I have something else entirely in mind. So, remove this line.
def pieChart(labels, vals, season, stat):
  plt.figure(figsize = (8, 8))

  plt.pie(vals, labels=labels)
  #plt.legend()

  plt.title("Liverpool FC Player " + stat + " for " + seasonName(season))
  plt.show()


Let's put percentages into the wedges. The autopct argument is how we format the string to display percentage labels.
plt.pie(vals, labels=labels, autopct="%1.1f%%")


Neat!


Next up, let me show you why I didn't want the legend earlier. That's because, this being a Liverpool FC chart, I want it in shades of red. And if everything's a shade of red, the legend is going to be next to useless. Start by declaring the list, customcolors. Follow up with a For loop that iterates through vals. Since we want the index value, use enumerate() on vals.
def pieChart(labels, vals, season, stat):
  plt.figure(figsize = (8, 8))
  
  customcolors = [];

  for index, value in enumerate(vals):
      
  plt.pie(vals, labels=labels, autopct="%1.1f%%")

  plt.title("Liverpool FC Player " + stat + " for " + seasonName(season))
  plt.show()


For each element, append stuff in customcolors. We want a Hex string that represents the a shade of the color red. So the string is going to be "#" followed by 6 characters. The last 4 are always "0000".
def pieChart(labels, vals, season, stat):
  plt.figure(figsize = (8, 8))
  
  customcolors = [];

  for index, value in enumerate(vals):
    customcolors.append("#" + + "0000")
      
  plt.pie(vals, labels=labels, autopct="%1.1f%%")

  plt.title("Liverpool FC Player " + stat + " for " + seasonName(season))
  plt.show()


And as for the missing 2 characters, we want them to be any Hex value from "96" up to "FF". So, use index with a formula that gets progressively bigger with each iteration. The lowest possible number is 150 (which is 96 in Hexadecimal). To ensure that it's always a two-character Hex value, run the result in the format() function, passing in "02x" as the second argument.
def pieChart(labels, vals, season, stat):
  plt.figure(figsize = (8, 8))
  
  customcolors = [];

  for index, value in enumerate(vals):
    customcolors.append("#" + format(index * 20 + 150, "02x") + "0000")
      
  plt.pie(vals, labels=labels, autopct="%1.1f%%")

  plt.title("Liverpool FC Player " + stat + " for " + seasonName(season))
  plt.show()


At the end of this, customcolors should be a list full of Hex values of the color red! Add it to the pie() function as the argument colors.
plt.pie(vals, labels=labels, colors=customcolors, autopct="%1.1f%%")


I've deliberately selected a season with a lot of values to let you see what it looks like. The colors are disparate enough that they look distinct when right next to each other, but again, useless as part of a legend. Also, be warned, this is not going to work if you have more than a handful of values!


The next thing you might want to do is cut out a wedge of that pie. Let's say we want the biggest contributor to the pie to stand out further. What do we do? Why, we pass in a list with float values that will tell Python how much we want each wedge to be separated from the rest - not at all (a 0) or a little (any value greater than 0 but less than 1). To do that, we need another list, customexplode.
def pieChart(labels, vals, season, stat):
  plt.figure(figsize = (8, 8))
  
  customcolors = [];
  customexplode = [];

  for index, value in enumerate(vals):
    customcolors.append("#" + format(index * 20 + 150, "02x") + "0000")
      
  plt.pie(vals, labels=labels, colors=customcolors, autopct="%1.1f%%")

  plt.title("Liverpool FC Player " + stat + " for " + seasonName(season))
  plt.show()


In the For loop, check if value is equal to the highest possible value in vals. If so, add 0.1 to the list. If not, add 0 to the list.
for index, value in enumerate(vals):
  customcolors.append("#" + format(index * 20 + 150, "02x") + "0000")
  
  if (value == max(vals)):
    customexplode.append(0.1)
  else:
    customexplode.append(0)


Then put customexplode into the pie() function as the argument explode.
for index, value in enumerate(vals):
  customcolors.append("#" + format(index * 20 + 150, "02x") + "0000")
  
  if (value == max(vals)):
    customexplode.append(0.1)
  else:
    customexplode.append(0)
    
plt.pie(vals, labels=labels, colors=customcolors, explode=customexplode, autopct="%1.1f%%"")


And this is what happens!



That was short and sweet...

As mentioned at the start, most of the work had already been done in previous web tutorials. The only thing left was really to use the data to render the pie chart.

Goodpie for now,
T___T

Thursday, 18 July 2024

The case against badmouthing your former employers publicly

Most Human Resource professionals will tell you that it is a supremely bad idea to badmouth your former employers in front of new prospective employers. And they're not wrong. There are no tangible benefits to doing so, no matter how emotionally satisfying it might be in the moment

Examples... (actual situations with fictional names)
"When I was employed by ProTouch, I was working for this guy who was a real kan-cheong spider."

"Last year, I was working in C Media Pte Ltd. The CEO was such a slimy piece of shit."

"In my last company, my CTO was Sebastian Lee, a temperamental jackass who had the emotional maturity of a teenager."

Even when I've had the occasion to say uncomplimentary things about companies I've worked for, even companies I've merely encountered during an interview, names are generally left out, unlike in the examples above. That's because my relating of the incident is meant as an exercise in retrospection, not as a means to discredit those parties in any way. Besides, I believe that such parties get found out eventually, with or without my help.

If it's already in the
news, it doesn't count.

When I say "badmouth", I should clarify that this does not extend to statements of fact that are a matter of public record. For example, if I worked for a company that got into trouble for failing to pay employee salaries, I would not be shy about discussing the subject if it ever came up. But if I had found out that my employer was having an affair with the receptionist, well, it's not my place to discuss the issue.

Usual reasons to refrain

It leaves a bad impression. That's about the sum of it. Any other reason I state in this section inevitably comes right back to this - it makes you look bad. And when you're in a position where you want to persuade someone that you're a good fit for their organization, the last thing you want to do is look bad.

Now, your lack of success at your last workplace could be attributed to a terrible boss or company. But part of being an adult professional is the ability to at least own your shit. That's not to say that any of it was your fault, but this is about optics. Being able to present it as you taking responsibility for a situation does portray you as being a big boy (or girl) who can take things in stride and learn lessons from adversity. Conversely, failure to do so paints an entirely different picture.

Reflects badly
on you.

And in cases where the unpleasantness happened months back, that's worse. Harping on issues that happened back then, even if they were a hundred percent true, does you no favors. All prospective employers are going to see is some bitter disgruntled former employee who just can't let it go.

Also, your ability to sell yourself is arguably the biggest test of any interview. If you can't sell yourself without tearing some other party down, that says a lot about you... none of it good.

But the biggest reason...

I, too, prefer not to name-and-shame my previous employees. Not that I couldn't, or that I'm afraid of legal repurcussions.

Anything negative I could say about my previous employers, I have on record somewhere. And if you think that sounds horribly cynical, do you for one moment believe that they don't have a record of your transgressions which they will break out the moment they find it necessary? You actually do? You dear, sweet summer child, you.

My point is, even if all the negative things I could say were indisputable facts which I can back up with documented proof with zero legal ramifications for divulging them, I still would not say anything bad about my former employers - on record, that is.

And that's because I shouldn't have to.

I'm a trained professional with more than a decade of software development experience, who works hard to keep himself current. My skills are in demand. I have options, dammit. There's a whole world of them waiting for me on the road ahead.

Eating my dust.

Why should I take the effort to lambast my former employers, regardless of what unpleasant experiences I've had with them? My former employers are history. Over and done with. Shrinking objects in the rear view mirror of my life. I have bigger fish to fry.

And that, dear readers, is the biggest reason. It's not about taking the high road. It's about taking the road where you don't look back. Whatever happens to them from this point forth is no longer your concern, schadenfreude be damned.

Conclusion

There's rarely a good reason to speak badly about your former employers, to a prospective employer. If you can't say something nice, either change the subject or say something really superficial. Your interviewer will get the message. What you don't say, speaks louder than what you do say.

My former employers were... really stylish!
T___T

Friday, 12 July 2024

Spot The Bug: Objectified but undefined

Just when you thought it was safe! For today's edition of Spot The Bug, we go back to JavaScript. This isn't that big of a surprise because vanilla JavaScript makes it really easy to introduce these bugs into your code.
Bugs are the
bane of my
existence!


For one of my little data experiments, I had some football data. It was a compilation of the 2023/2024 English Premier League Season's top goalscorers.

I loaded this object into my JavaScript and ran it. This seemed simple enough. I wanted to derive some numbers from the data.
{
  "Erling Haaland" : 27,
  "Cole Palmer" : 22,
  "Alexander Isak" : 21,
  "Ollie Watkins" : 19,
  "Dominic Solanke" : 19,
  "Phil Foden" : 19,
  "Mohamed Salah" : 18,
  "Heung-min Son" : 17,
  "Jarrod Bowen" : 16,
  "Bukayo Saka" : 16,
  "Jean-Philippe Mateta" : 16,
  "Nicolas Jackson" : 14,
  "Chris Wood" : 14,
  "Kai Havertz" : 13,
  "Leandro Trossard" : 12,
  "Hee-chan Hwang" : 12,
  "Matheus Cunha" : 12,
  "Yoane Wissa" : 12,
  "Darwin Nunez" : 11,
  "Richarlison" : 11,
  "Julian Alvarez" : 11,
  "Carlton Morris" : 11,
  "Anthony Gordon" : 11,
  "Eberechi Eze" : 11,
  "Leon Bailey" : 10,
  "Diogo Jota" : 10,
  "Bruno Fernandes" : 10,
  "Michael Olise" : 10,
  "Elijah Adebayo" : 10,
  "Rasmus Hojlund" : 10
}


This was the code.
<!DOCTYPE html>
<html>
    <head>
      <title>EPl Top Scorers</title>

      <script>
      var topscorers = 
      {
        "Erling Haaland" : 27,
        "Cole Palmer" : 22,
        "Alexander Isak" : 21,
        "Ollie Watkins" : 19,
        "Dominic Solanke" : 19,
        "Phil Foden" : 19,
        "Mohamed Salah" : 18,
        "Heung-min Son" : 17,
        "Jarrod Bowen" : 16,
        "Bukayo Saka" : 16,
        "Jean-Philippe Mateta" : 16,
        "Nicolas Jackson" : 14,
        "Chris Wood" : 14,
        "Kai Havertz" : 13,
        "Leandro Trossard" : 12,
        "Hee-chan Hwang" : 12,
        "Matheus Cunha" : 12,
        "Yoane Wissa" : 12,
        "Darwin Nunez" : 11,
        "Richarlison" : 11,
        "Julian Alvarez" : 11,
        "Carlton Morris" : 11,
        "Anthony Gordon" : 11,
        "Eberechi Eze" : 11,
        "Leon Bailey" : 10,
        "Diogo Jota" : 10,
        "Bruno Fernandes" : 10,
        "Michael Olise" : 10,
        "Elijah Adebayo" : 10,
        "Rasmus Hojlund" : 10
      }

      function fillStats()
      {
        var goals_10 = document.getElementById("goals_10");
        goals_10.innerHTML = "There are " + topscorers.length + " players who scored more than 10 goals for the season of 2023/2024";

        var goals = Object.values(topscorers);

        var div_goals = document.getElementById("goals_20");
        var arr_goals = goals.filter((x) => { return x >= 20; });
        div_goals.innerHTML = "There are " + arr_goals.length + " players who scored more than 20 goals for the season of 2023/2024";

        var div_goals = document.getElementById("goals_15");
        var arr_goals = goals.filter((x) => { return x >= 15 && x <= 19; });
        div_goals.innerHTML = "There are " + arr_goals.length + " players who scored 15 to 19 goals for the season of 2023/2024";

        var div_goals = document.getElementById("goals_12");
        var arr_goals = goals.filter((x) => { return x >= 12 && x <= 14; });
        div_goals.innerHTML = "There are " + arr_goals.length + " players who scored 12 to 14 goals for the season of 2023/2024";
       }
      </script>
    </head>

    <body onload="fillStats();">
      <div id="goals_10">
  
      </div>

      <div id="goals_20">
  
      </div>

      <div id="goals_15">
  
      </div>

      <div id="goals_12">
  
      </div>
    </body>
</html>


What Went Wrong

Simply put, right at the first line. "There are undefined players who scored more than 10 goals for the season of 2023/2024"? What the hell?


Why It Went Wrong

Notice that all the other string outputs were fine. It was just the first line - the number had been replaced by the word "undefined".

This was because I tried to obtain the length property of topscorers. It worked when I tried it on arr_goals because arr_goals was an array. But topscorers was not an array. It was an object. A-ha! What a gotcha!

Since topscorers consisted only of players who had scored 10 goals or more, I figured I didn't need a subset of the object like I did with the count for players who had scored a certain number of goals above 10; just needed to get a count of all the players in topscorers.

How I Fixed It

What I should have done was get an array of all values of topscorers like this...
goals_10.innerHTML = "There are " + Object.values(topscorers).length + " players who scored more than 10 goals for the season of 2023/2024";


Now it worked.


Moral of the Story

An array is a type of object. But an object isn't necessarily a type of array and may not have the properties or methods associated with arrays. It's easy to mistake one for the other.

As bugs go, it was a pretty simple one. But so sneaky because no error was ever reflected in the console.

Thanks for reading! I had a ball writing this!
T___T

Sunday, 7 July 2024

Great Expectations and how to manage them

Ever have this problem with expectations? Unreasonable, illogical expectations, to be exact.

It's almost inevitable if you are a developer working for non-tech people. Having little to no experience with the process of software development, they have no idea what constitutes a reasonable expectation, and let their imagination fill in the blanks. With amusing, and sometimes nightmarish, results. An (admittedly extreme) example would be the employer assuming you can fix the microwave simply because you know how to write software.

Fix this!

That's not to say experienced tech people don't have unreasonable expectations either. Their expectations tend to be a little less fanciful, but no less impractical when it comes right down to it. An example would be the employer expecting you, as an employee, to match his devotion to the company he created.

Then there are the in-betweeners. The ones who know a bit of programming, just enough to be problematic, but aren't exactly technical. Because they know how to code, they have expectations of how quickly code can be churned out. Unfortunately, they do not have experience with the less fun aspects of software development, such as best practices, testing and optimization. Therefore those expectations, too, can be divorced from reality.

People are like animals, in the sense that they need to be trained. Some might argue that humans have intelligence superior to animals. Well, that's great. That just makes it easier to train them. Make no mistake; where you are concerned, how people treat you is ultimately how you train them to treat you.

This kind of training tends to take two forms.

Don't give them what they want

And by that, I also mean stop being so obliging. When you satisfy an unreasonable request, it sets a new bar for expectations. And then it becomes the norm. This ultimately means that you're setting yourself up for increasing and unnecessary hardship.

If you get texts at night long after you're supposed to be off for the day, do not respond until the next day. Or at least, don't respond every single time. Or make them wait. Either way, make them expect that if they contact you at a certain time, they're not going to get a response right away, if at all.

If you're tasked to do something that is radically out of your job scope, make them expect you to fail. Sometimes spectacularly.

I've been known to work on weekends and public holidays. However, if my employers explicitly tell me that they expect me to use my weekends for work, I make damn sure I'll be doing something else during the weekend. It's the principle of the thing. It's not that I have a problem with working on weekends; I just have a problem with it being my employer's expectation. And, as an employee, I consider it my ethical responsibility to disabuse my employers, either in word or deed, of such expectations.

Gone fishing.

If the expectation is impossible, don't bust your ass trying to do it. Make sure you do the job that you're paid to do, and then maybe work on the impossible requirement. This sets the tone; you fulfil your professional obligations - no two ways about it, that's your first and foremost priority - and prevents expectations from getting too high. Once people see that they're not going to get what they asked for, but they are absolutely getting what they paid for, expectations get realigned. This, of course, assumes that you're dealing with reasonable people. In the corporate world, you don't always have that luxury. An alarming percentage of the time, you might end up looking for a new job.

Also, can't stress this enough, communication. Don't just say "yes" and then not do it - that's passive-aggressive bullshit and you should hold yourself to higher standards. Let them know it can't be done, why it can't be done, and what would have to give in order for you to carry it out.

Give them exactly what they want

Or what they say they want. People tend to tell you what they want without thinking it through. In order to be helpful, we should at least give them fair warning that what they want comes with a whole lot of caveats. And if that doesn't work, give them a preview of what fulfilling their wishes looks like.

And if that's still not enough, let them have it.

Now, just to be clear, I'm not advocating Malicious Compliance. It's one of the top fantasies of the average disgruntled employee (and understandably so!) but we're professionals. And as professionals, it is our duty to point out the pitfalls and advise accordingly. However, while we may be professionals, we're not superheroes. We can't save people from themselves. Thus, if an ill-advised route is insisted upon, short of it being illegal, give them what they want, and let the cards fall where they may.

They insist on not encrypting passwords and storing them in cleartext? Hey, go for it. But make sure the decision is reversible.

They insist on adding a new software feature that would compromise the functionality of existing features? Knock yourself out. Again, make sure you have a backup.

But if you go this route, document your objections. Obsessively. There may come a day when you need it. Also, plan your exit. People generally don't like being reminded of their failure, and your continued presence may be just such a reminder.

Here's a personal example. There was a time Mom had this unfortunate habit of calling me, and when I was otherwise occupied and didn't pick up, she would leave a string of missed calls on my phone. And then when I finally called her back, I would get an earful for not calling back right away. The kicker was, the body of her message was never anything that required immediate attention, such as an emergency. Like the house being on fire, or someone being sent to the hospital. No, the message would be something alone the lines of reminding me that Dad's birthday was next week, or asking if my refrigerator had any space for some extra apples she had picked up.

Missed calls.

Now, I love apples, but that's neither here nor there. I had to get her off this expectation that I had to be instantly responsive at all times regardless of the situation. The next time she called, I was walking alongside a busy road, and I had an idea. I picked up, and let her hear the blaring horns of irate road-users. She asked what the hell was going on there, and I innocently replied that I'd been in the process of crossing the road, and inquired what was the matter. In effect, I had given her a preview of just what could happen if she got what she wanted.

I wouldn't go so far as to say she never called me on my phone again, but each time she called, she had to weigh the contents of her message against the possibility of me getting run over by traffic just because I mindlessly picked up the phone as she demanded. The result was that she got into the habit of leaving messages on WhatsApp instead. You may think I'm a real asshole for scaring my own mother like that, but there was no lie in anything I did. There was a real possibility of something horrible happening if she got her way, and this was not a message that could be effectively delivered by me just telling her, since Asian parents, y'know, tend not to take their kids seriously.

On the flip side...

All this only works if you're competent at what you do, and you deliver what you're actually paid to do. It doesn't mean that just because you're bad at what you do, unreasonable requests become any less unreasonable. But being good at your actual job would help your case a lot more.

Expecting your response,
T___T

Tuesday, 2 July 2024

The time is now, or at least, soon

Procrastination can be a beautiful thing. It staves off burnout, promotes peace of mind, slows life down to a manageable pace. And yet, taken too far, it can lead to regrets. Unfulfilled aspirations. Because time marches on, and doesn't come back. Opportunities are like origami boats floating along the river.

Like origami boats
in the water.

One of the challenges in life, in or outside the workplace, is to identify what things can be reasonably put off for another time, and what things would better serve you being done now. As in, now, pronto. Or at least, given a concrete timeline to begin.

For example, if you want to make a lifestyle change (Diet? Exercise?) putting it off indefinitely is a poor choice. Putting it off to next Monday or even the start of next month, however, can be justified on the grounds that it makes progress easier to track.

On the other hand, such justifications don't always pan out because, again, time marches on, and opportunities are lost.

A couple years back, I received a pay raise. It wasn't much; I was left with just over a hundred dollars extra after deductibles. I had the idea of giving the extra to my mother; after all, my pay had been going up the past couple years and she hadn't really benefitted from it. Then I looked at the pitiful amount and felt embarassed. Wouldn't it make more sense to wait another year, and if my pay went up again, put it all together to give her a more hefty income boost?

Running out of
time.

No. No, it wouldn't. The thing is, I was in my mid-forties and Mom was almost seventy. What if I waited another year and she croaked in the meantime? Sure, that hundred bucks wasn't going to make much of a splash. But I had given her to understand that whatever I got, we would share it. And it was time to deliver. The time was now. Or possibly never.

Even further back, in the year 2019, I was doing my usual annual appraisal of my current work situation and seeing if there were other opportunities out there. Part of me wanted to kick back and extend my contract by another year, and the other part insisted on at least attending a few interviews to see what was what.

Then COVID-19 happened. People got laid off left and right - generally I mean, not the software industry specifically. I decided that terrible though the entire thing was, it was an excellent opportunity. If I accepted that new job offer and it didn't work out, no one was going to question me not having a job, when just about the entire island was facing pretty much the same problem (though for different reasons). But I had to make the decision now. Not next three days, not next week. Now.

When COVID-19 wrecked
the world.

Spoiler alert: the new job didn't work out, but the resultant scenario happened just as I thought it would. I attended job interviews, and no one batted an eyelash when they saw I had that gap in my resume. I had successfully identified an opportunity in the midst of a crisis and taken advantage of it.

There have been several examples of this throughout my life, where I had to go do something. Before, it was a matter of finding a reason to do it; but at some point, it became a matter of finding a reason not to.

Take this blog, for example. When I started it back in 2014, did I wait till I was older and wiser and more professionally experienced before airing my views on a tech blog, for fear of embarrassing myself? No, I got off my ass and did it, public opinion be damned. It's now the tenth year I've been doing this. Has this blog become a resounding success? Also no. But it's a heck of a lot more successful than the blogs that never got started. And I've learned so much from doing this.

Just went out
there and started
this blog.

The "Now or Never" philosphy has been the driving force behind every new programming language I've learned, every tech platform I've tried. Every post-graduate Diploma course I've signed up for. All because I knew there would come a day my body just couldn't handle the rigors of studying while working any more.

Next time? There might not be a next time. And if I want to put things off, I have to be OK with that possibility.

The Time Is Now!

Inaction is a choice like any other, but bear in mind that all choices have an associated cost.

There's no need to jump into anything, of course. However, before deciding to do nothing, you might want to consider what you're missing out on, and if it's really worth it.

No time like the present.
T___T