Monday, 29 July 2019

Factors In Tech Career Progression (Part 2/2)

Make no mistake, I've had a rocky career. Some of it was due to poor choices, some of it wanderlust. After the first six years spent in desktop support, I swore never again to allow my comfort zone to hold me back. The result was several one-year stints (sometimes shorter) in various firms. This also resulted in me picking up new skillsets and applying previously acquired skills.

The following table is comprised of this information...

Job. This is comprised of job title, company type and what I was doing.

Skills Transferred. This describes the skills I had picked up in my previous jobs that I got to use in the current one (those in bold denote most recent skills).

Learned. The skills I picked up during the stint in the company, whether at work, at school or on my own.

Remuneration. How much my pay went up (or down) from my previous job.

YEAR JOB SKILLS REMUNERATION
2008 Technical Officer in a small non-tech firm, creating dynamic web portals. Transferred: Classic ASP, HTML/CSS/JavaScript
Learned: MySQL, CPanel
-8%
2010 Web Developer in a small tech firm, creating dynamic web portals. Transferred: MySQL, CPanel
Learned: PHP, AJAX, WordPress
4%
Mid 2011 Web Developer in a small tech firm, creating CMS-driven web portals and e-commerce sites. Transferred: WordPress, AJAX
Learned: Requirements gathering, customer relations, Joomla!
3%
Late 2011 Web Developer in a small tech firm, creating dynamic web portals, e-commerce sites and web applications. Transferred: Requirements gathering, customer relations
Learned: Stored Procedures, SQL Server, ASP.NET (C#), Visual Studio, TFS, ColdFusion,
3%
Late 2012 Web Developer in a medium non-tech firm, creating dyamic web portals and e-commerce sites. Transferred: Stored Procedures, SQL Server
Learned: Bootstrap, SQL views, Mailchimp and Google APIs
17%
2014 Web Developer in a medium non-tech firm, creating dyamic web portals. Transferred: Bootstrap
Learned: Java, Android Studio, Eclipse, jQuery, jQuery Mobile, AngularJS, Responsive Design
15%
2016 Web Developer in a small tech firm, creating web and mobile application. Transferred: jQuery, Responsive Design
Learned: MeteorJS, Semantic UI, LESS, ECMAScript
5%
2017 Web Developer in a large tech firm, maintaining large-scale web application, public-facing APIs and automated DevOps. Transferred: ECMAScript
Learned: Ruby, ReactJS, DevOps
25%

Editor's Note: I've been informed by a reader that I left out Java, which I picked up sometime in 2015. My mistake. While I have yet to use Java in any significant fashion, much of my current habit of almost exclusively using Object-Oriented Programming can be traced back to the time I learned Java. Still, it's a blip on the scale, and the data doesn't suffer significantly from its omission.

Let's interpret this data!

Data's useless if we're not going to interpret it, so here goes...

Here's a chart...


To make things simpler, here's a cumulative-value line graph plotted from the table. The red line represents the new skills I picked up, the light blue line represents the skills I transferred from job to job, and the yellow line represents cumulative salary growth.

In the table, you'll notice that throughout the years, my title has remained predominantly "Web Developer". There's been no mention of Management. Yet, my pay has gone steadily up, despite a slight blip at the beginning due to my career change. Sure, a 10% pay rise could be due to inflation. But towards the tail end of that table, the increase goes above 10% and up to a whopping 25%.

One could claim that where I work is a contributing factor, and that's undeniable. Smaller firms do tend to deal in lower-value work (take note; this will be relevant a few paragraphs later), and thus can't afford to pay much. But, without the experience and skills acquired at the smaller firms, I might not have been hired by the latter firms today.

Also, the amount of skills I leveraged off in each new place of employment is relevant. In fact, I've almost never failed to use stuff I've learned from my last place of employment. And near the end of the table, as time went by, it seems that the list of skills I'm leveraging on from past workplaces, is growing longer. You'll see the blue line trending upwards steadily in the graph. Of course, picking up new skills does help. The salary growth spikes each time the red line does. But it still isn't enough to explain why my pay went up over time.

Now, take a close look at what I was doing in each of these companies. At first, I was making dynamic data-driven websites. Then I graduated to CMS-driven web portals, followed by e-commerce sites. And finally, I began making and maintaining large-scale web applications. Am I still making dynamic data-driven websites? Haven't done that in years. With the rise of sitebuilders such as WiX, Weebly, SquareSpace et al, the value of the work needed to be done on such websites has drastically fallen. Increasingly fewer people are willing to pay others to do something that can easily be done themselves. Now such sitebuilders are capable of creating CMS-driven e-commerce websites just like that. There's no doubt in my mind that if I were still making websites as my main hustle, my career would be in a tailspin.

But web applications of sufficient complexity still require developer expertise. I've graduated to doing more valuable work using the same technical skills I've acquired over the years. That is the main cause of the rise in remuneration - higher-value work. My value is measured by the value of what I do, not by some grand-sounding title. It's not even because I'm particularly good at what I do. It's because what I do is in demand. And people are willing to pay for it.

Track your career progress!

If nothing else, it will give you a greater appreciation for how far you've come.

Stop moaning over not being a Senior this-or-that, or envying those in Management. For all you know, you could be shit at that level and dodged a bullet by focusing on what you're good at. Though, if you really suck at this level, you might want to try getting promoted to Management. It seems to have worked for plenty of people.

That's not to say that only crap programmers become Managers (else I would have been promoted long ago), but the best Managers I've had weren't necessarily the more technically experienced ones, though this doesn't hurt, as you might imagine. No, those were the ones who knew what orders they were qualified to give and what they weren't, and were willing to shut up, stand aside, and let you work.

Where I'm going

As mentioned earlier, having a wide skillset was advantageous early in my career. It allowed me to be easily employable. I may have mentioned this before here, but once, I stole the jobs of three people  because I could do all their jobs - not because I was better at them at those jobs, but simply because the work did not require the level of expertise they had that the company was paying for. I was basically cheap labor doing three jobs (and the scary thing was, I've had worse. This was, in comparison, practically a vacation for me).

Years later, things have changed. Technology has changed. The tech landscape has shifted.

At this point in my career, I'm going to have to stop being, in military parlance, all-over-the-shop and try to specialize in something. Because with what I'm getting paid now, I'm rapidly going the way of the people I so blithely replaced years ago.

Onward and upward!
T___T

Friday, 26 July 2019

Factors In Tech Career Progression (Part 1/2)

In a departure from code and workforce politics, let's examine the subject of career progression in tech.

Career progress, to most laypeople, has a formula: start as a peon, work your way up, get a Senior title (and a pay raise), get into Management (with another pay raise). I've lost count of the number of people that have repeatedly advised me to get into Management, because, to them, that is career progress.

With due respect, these people are talking out of their asses exhibiting a significant (but understandable) amount of ignorance. That's not how the tech industry works.

Sure, that might be how some tech firms work. But bear in mind that the tech scene in Singapore is hardly at maturation point and many companies still adopt the traditional structures that older companies have used over the decades. While that's how it currently works now at some places, that's not how it's supposed to work.

How people tend to measure career progress

There are some metrics that are often used outside of the tech industry. And while to some industries they may be a decent gauge of how far you've come, tech hirers generally know better. And here's why.

Titles. Fancy titles don't mean anything. And any organization that thinks they mean something, or tries to force them to mean something, has a lot of catching up to do. If someone wanted a fancy title, all they have to do is register a company (which will cost all of what? Fifty bucks?) and declare themselves CEO or something.

Here's a nice title...


What does a title mean, really? A title is just a one (or two, or three) word phrase that describes what your job is as accurately as possible.

Engineer.

System Architect.

Technical Officer.

Web Application Developer.

Adding "Chief" or "Senior" to the title looks nice on a business card and even better on a resume. Sure, I get that. But what does it actually say about what you do? A bit fat nothing - because "Senior" or even "Manager" means different things in different firms and different contexts. If you were doing a basic job and the title got a bit too fancy, a few pertinent questions would get you found out in a hurry. Long story short, no interviewing Manager who knows anything is going to use that as a gauge for determining your worth to his company.

And speaking of "Manager"...

Management. Let's assume the word "Manager" on your resume is honestly earned. You are a Manager. You have at least one or two people taking orders from you, and you perform organizational delegation. But bear in mind that where you are a Manager at, is also pertinent. Being a Manager in some kuching kurap operation is worlds apart from being a Manager in a legit tech firm of a reasonable size. Also, what were you managing? If you were a Database System Manager, that doesn't instantly qualify you to be a Web Operations Team Manager... unless you're some kind of genius that thinks that anything under "Information Technology" is automatically related.

There's more to be said for aspiring to Management. In many factory settings, if you do one job long enough, you get enough experience in it to be able to supervise and train others. Ergo, you get promoted. You're now a Manager, or at least higher up the pecking order. Trying to apply this approach wholesale to the tech industry is incredibly naive. Management in tech is more about people skills and organizational savvy than technical skills. In fact, the longer you've been in Management, the more you can expect your tech skills to degrade because you don't exercise them often enough. And there is no guarantee you would be a better Manager than developer - you could become a walking, breathing example of The Peter Principle. There are plenty of very talented engineers and developers who won't survive in a Management capacity simply because people skills aren't their thing. Should this talent not be promoted? Well, if being in Management was the only way for their careers to progress, many tech workers would be screwed. Because, as much as I detest the stereotype that techies are antisocial geeks, there's an uncomfortable amount of truth in it.

Less space at the top.

The thing is, being promoted to Manager carries a certain amount of risk - most of which have to do with job security. Once you get to that level, there is no going back. There are always openings for developers - but a lot less for Managers. Why's that? Simple. Corporate structure can be represented as a triangle. The further up the pecking order you are, the less space there is to move. If you are a Manager and you ever lose your job, you can expect to take a lot longer than the average grunt finding another one. Because Managers generally don't obligingly vacate their positions for you unless there's space further up the pecking order for them.

Pay. Now we're getting warmer. Pay is a pretty good benchmark for determining how far your career has progressed. Generally, the longer you've been doing this job, the better your chances of getting a decent salary. That said, there's a ceiling. Grunt work developers are always in demand, but that's because they generally come cheap. If an employer is willing to pay more, that usually means they expect a certain amount of expertise to be in your resume. So, in that sense, you're not just a grunt.

Has your salary grown?

Pay is a decent benchmark, but it's almost useless unless you couple it with other metrics. In fact, I would even say that other metrics are more indicative of career progress, and pay is simply a by-product of that progress. However, pay is very relevant in the sense that everybody, to some degree or other, does it for the money. There are people who don't care about titles, or rank. I confess to being one of them. But there's exceedingly few people who don't care about money at all. Of course, it takes all sorts to make a world and sometimes you may encounter people who don't mind getting less money if they have a nice senior title... all in the name of career progress. I find this patently absurd, but to each his own.

What really determines career progress in the tech industry

Having taken a look at some of the things people use to measure career progress, I think it's safe to say I've adequately explained why those metrics don't work that well in the tech industry.

How about skillsets then? Surely acquired skills determines career progress? Well... not so much.

We're talking about an industry where things get outdated quickly and change happens at a breakneck pace. Thus, the ability to learn, unlearn and relearn is vital. Sure, some things are timeless and even industry-agnostic - properly structured programming, cleanliness of code and ability to work with others are just a few things to come to mind - but tools change, and they change frequently.

So knowing the latest tools, or even a wide repertoire of tools, is nice. It's certainly kept me employable. But it's not wholly responsible for any sort of progress I may have enjoyed. No, we're measured by what value we bring to the table. The greater the value, the higher the remuneration. Being in Management is one type of value, but it's not the only type of value.

Not convinced? Allow me to illustrate...

Next

Let's look at my career trajectory and see what we can learn from this. In particular, I want to look at the skills I've had to pick up over the years, and how they were picked up from one job and transferred over to subsequent jobs, and even more importantly, what I did in those jobs.

Saturday, 20 July 2019

Web Tutorial: ReactJS British Insult Generator

Today's web tutorial uses ReactJS again, so if you missed the last one, you might want to go take a gander!

I got this meme on Social Media, and it was touted as a basic formula for British insults. That was pretty cool, all things considered, and I really wanted to use that formula... in conjunction with some program code, of course.


Since we made a random text display program using ReactJS, I figure we can do the same thing here, except using multiple arrays instead of just one. But with a major difference - the script has to run as soon as the page is loaded, and not on the click of a button.

Here's some HTML...

We begin with a very bare-bones ReactJS setup, almost identical to the last one. The only difference right now, is, the div we render content in has an id of insultContainer.
<!DOCTYPE html>
<html>
    <head>
        <title>Insult Generator</title>

        <style>

        </style>

        <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
        <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
        <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
    </head>
    <body>
        <div id="insultContainer"></div>

        <script type="text/babel">

        </script>
    </body>
</html>


Let's write the class, Insult. A constructor (with state included) has been added, along with a render() method.
<!DOCTYPE html>
<html>
    <head>
        <title>Insult Generator</title>
        <style>

        </style>

        <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
        <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
        <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
    </head>
    <body>
        <div id="insultContainer"></div>

        <script type="text/babel">
            class Insult extends React.Component
            {
                constructor(props)
                {
                      super(props);
                      this.state =
                      {

                      };
                  }

                render()
                {
                    return (

                    );               
                }
            }

            ReactDOM.render(<Insult />, document.getElementById("insultContainer"));
        </script>
    </body>
</html>


Now, the render() method needs to return something. So let's give it something to return. Let's start with four arrays - action, adjective, curse and noun - in accordance to the formula. Each of these arrays will contain the appropriate words. It goes without saying that you should feel free to provide your own lists of words.
            render()
            {
                this.action =
                [
                    "Get out of here",
                    "Go to hell",
                    "Eat shit",
                    "Fall over and die",
                    "Get a life",
                    "Go kill yourself",
                    "Shut your mouth",
                    "Get bent",
                    "Sod off",
                    "Go jump off a bridge"
                ];

                this.adjective =
                [
                    "incomprehensible",
                    "obnoxious",
                    "repugnant",
                    "repulsive",
                    "ignorant",
                    "misshapen",
                    "noisy",
                    "glorious",
                    "defective",
                    "absolute",
                    "vigorous"
                ];

                this.curse =
                [
                    "bitch",
                    "shit",
                    "piss",
                    "dick",
                    "twat",
                    "ass",
                    "cum",
                    "jizz",
                    "fuck"
                ];

                this.noun =
                [
                    "monkey",
                    "dwarf",
                    "box",
                    "house",
                    "garden",
                    "train",
                    "camel",
                    "hamster",
                    "trumpet",
                    "bubble",
                    "waffle",
                    "spoon",
                    "stick",
                    "sandwich",
                    "cruiser",
                    "carriage",
                    "ticket",
                    "collection",
                    "cable",
                    "bagel",
                    "sack",
                    "puppet",
                    "lamp"
                ];

                return (

                );               
            }


Inside the return block, render a paragraph tag with an id of insultContent and the template string for the displayed curse. For now, let's just set the content to the first element of each array.
                    return (
                            <p id="insultContent">
                            {this.action[0]}, you {this.adjective[0]} {this.curse[0]} {this.noun[0]}
                            </p>
                    );


Refresh. You'll see this. Now we need to make the screen change this every few seconds.


For this to happen, we need to add some properties to state. actionIndex will be the integer that points to the current element of the action array. And so on, and so forth, for the other properties. All will default to 0.
                constructor(props)
                {
                      super(props);
                      this.state =
                      {
                          "actionIndex": 0,
                          "adjectiveIndex": 0,
                          "curseIndex": 0,
                          "nounIndex": 0
                      };
                  }


Then we bind the changeInsult() method to the constructor.
                constructor(props)
                {
                      super(props);
                      this.state =
                      {
                          "actionIndex": 0,
                          "adjectiveIndex": 0,
                          "curseIndex": 0,
                          "nounIndex": 0
                      };
                      this.changeInsult = this.changeInsult.bind(this);
                  }


Of course, we'll need to define the changeInsult() method.
                constructor(props)
                {
                      super(props);
                      this.state =
                      {
                          "actionIndex": 0,
                          "adjectiveIndex": 0,
                          "curseIndex": 0,
                          "nounIndex": 0,
                      };
                      this.changeInsult = this.changeInsult.bind(this);
                  }

                changeInsult()
                {

                }


Every, say, three seconds, we call the setState() method
                changeInsult()
                {
                    this.interval = setInterval
                    (
                        () =>
                        {
                            this.setState
                            (
                                {

                                }
                            );
                        },
                        3000
                    );
                }


actionIndex, adjectiveIndex, curseIndex and nounIndex will be set to a random number between 0 and the upper limit of their respective arrays.
                            this.setState
                            (
                                {
                                    "actionIndex": Math.floor((Math.random() * (this.action.length))),
                                    "adjectiveIndex": Math.floor((Math.random() * (this.adjective.length))),
                                    "curseIndex": Math.floor((Math.random() * (this.curse.length))),
                                    "nounIndex": Math.floor((Math.random() * (this.noun.length)))
                                }
                            );


But what's the trigger for this? changeInsult() needs to be run. We use the componentDidMount() method which is roughly the ReactJS equivalent of the onLoad property. Thus, the changeInsult() method will be called when the Insult component is loaded.
                changeInsult()
                {
                    this.interval = setInterval
                    (
                        () =>
                        {
                            this.setState
                            (
                                {
                                    "actionIndex": Math.floor((Math.random() * (this.action.length))),
                                    "adjectiveIndex": Math.floor((Math.random() * (this.adjective.length))),
                                    "curseIndex": Math.floor((Math.random() * (this.curse.length))),
                                    "nounIndex": Math.floor((Math.random() * (this.noun.length)))
                                }
                            );
                        },
                        3000
                    );
                }

                componentDidMount()
                {
                    this.changeInsult();
                }


More on the componentDidMount() method here!

And one last thing... yep, we now need to have proper indexes.
                    return (
                            <p id="insultContent">
                            {this.action[this.state.actionIndex]}, you {this.adjective[this.state.adjectiveIndex]} {this.curse[this.state.curseIndex]} {this.noun[this.state.nounIndex]}
                            </p>
                    ); 


And there you see, your insult changes every three seconds!


That's nice, but...

OK, I get it. The transition is pretty abrupt, huh? Let's pretty it up. Other than having an orange background with white text, the rest you should feel comfortable playing with.
        <style>
            #insultContent
            {
                border-radius: 20px;
                font-size: 20px;
                background-color: rgba(255, 200, 0, 1);
                color: #FFFFFF;
                font-family: verdana;
                font-weight: bold;
                padding: 2em;
                width: 20em;
                margin: 10% auto 0 auto;
                text-align: center;
            }
        </style>


There you go, so far so good!


Now let's let it transition nicely from insult to insult. First, change the style. Set the initial background color to zero opacity. I know, this will make it effectively invisible since the text is white, but bear with me, you'll see where this is going. Also, set the transition property to half of three seconds, which is 1.5.
        <style>
            #insultContent
            {
                border-radius: 20px;
                font-size: 20px;
                background-color: rgba(255, 200, 0, 0);
                color: #FFFFFF;
                font-family: verdana;
                font-weight: bold;
                padding: 2em;
                width: 20em;
                margin: 10% auto 0 auto;
                text-align: center;
                -webkit-transition: 1.5s all;
                transition: 1.5s all;
            }
        </style>


In the changeInsult() method, start off by setting the background color of the insultContent paragraph tag to full opacity.
                changeInsult()
                {
                    this.interval = setInterval
                    (
                        () =>
                        {
                            document.getElementById("insultContent").style.backgroundColor = "rgba(255, 200, 0, 1)";
                            this.setState
                            (
                                {
                                    "actionIndex": Math.floor((Math.random() * (this.action.length))),
                                    "adjectiveIndex": Math.floor((Math.random() * (this.adjective.length))),
                                    "curseIndex": Math.floor((Math.random() * (this.curse.length))),
                                    "nounIndex": Math.floor((Math.random() * (this.noun.length))),
                                }
                            );
                        },
                        3000
                    );
                }


Then, within the first setInterval() function, use a setTimeout() function to set the background color back to zero opacity. The interval for this should be 1.5 seconds. Refresh and try again!
                changeInsult()
                {
                    this.interval = setInterval
                    (
                        () =>
                        {
                            document.getElementById("insultContent").style.backgroundColor = "rgba(255, 200, 0, 1)";
                            this.setState
                            (
                                {
                                    "actionIndex": Math.floor((Math.random() * (this.action.length))),
                                    "adjectiveIndex": Math.floor((Math.random() * (this.adjective.length))),
                                    "curseIndex": Math.floor((Math.random() * (this.curse.length))),
                                    "nounIndex": Math.floor((Math.random() * (this.noun.length))),
                                }
                            );

                            setTimeout
                            (
                                () =>
                                {
                                    document.getElementById("insultContent").style.backgroundColor = "rgba(255, 200, 0, 0)";   
                                },
                                1500
                            );
                        },
                        3000
                    );
                }

A note about the fat arrow notation...

I know usually we use a function declaration for the callback in setInterval() and setTimeout() functions. But since this is ReactJS and we're trying to do things the ECMAScript way, that's what we're going to use.

More about the fat arrow notation.

Adieu for now, you unrepentant wank biscuits!
T___T

Tuesday, 16 July 2019

Film Review: Child's Play (2019)

"Hi, I'm Chucky! Wanna play?"

Anyone having childhood memories of this has gotta be old as dirt, and that unfortunately describes me. I was eleven when Child's Play came out, and while I can't say I've watched all of the sequels, I did managed to catch Bride of Chucky ten years later. Fast forward more than twenty years, and a reboot of Child's Play just appeared in cinemas.


Was I excited to watch this murderous psycho doll at work again? You betcha!

Warning - spoilers ahead (duh), not for the weak of stomach!

As would be expected of any Chucky movie, this flick is full of gleeful violence and campy humor. But I'm not going to try that hard to avoid spoilers. Fuck that shit. If you're watching a Chucky movie, plot twists are probably not all that high on your list of priorities.

Also, I got the pictures below of the dolls, from the Internet. It's just to illustrate a point and I'm not trying to profit off this, so please don't sue (or eviscerate) me.

The Premise

Andy is a shy boy with a hearing disability. One day, his mother gives him a present - a doll named Chucky which has an AI chip. The doll is capable of connecting to the internet and learning all the things it sees. Unfortunately, it learns all the wrong things, and without any inhibitions against violence or understanding of boundaries, it soon becomes possessive of Andy and this snowballs into a bloody homicidal spree. Along the way, Chucky even picks up the ability to control other toys via the Internet of Things, and as you may expect, it's total mayhem from there.

Unlike the original Child's Play which was a supernatural thriller about a serial killer whose soul got transferred to a doll, this movie is a tech horror thriller about the Internet of Things and wayward machines. Nothing new there; that theme has been pretty much done to death (pun intended) since Skynet in the era of The Terminator. Still, we're here to watch Chucky stab some hearts and slit some throats, and trust me brother, that little bastard delivers just the same.

The Characters

Mark Hamill voices Chucky, the friendly toy turned slasher robot. And just in case you think Hamill is too much of a good guy to voice Chucky, remember that he was the voice behind The Joker in the JLA Animated Series.

Gabriel Bateman puts in a strong performance as Andy Barclay. Bateman plays the shy antisocial Andy well, isolated as much by his hearing disability as by his awkward social skills, and later on his increasing paranoia. He reacts superbly to the growing horrors that Chucky introduces to him.

Aubrey Plaza is Karen Barclay, single mother to Andy. Plaza brings a certain sardonic wit to her character, and shares good chemistry with her onscreen son. She also provides a fair amount of fanservice later on when a voyeur peeks at her in the shower.

Brian Tyree Henry as Detective Mike Norris, the good-guy cop who befriends Andy and acts as a potential love interest for Karen at the end. Equal parts badass and jolly everyman. I last saw him in Widows as a very different character, and I think it was a good casting choice here.

Carlease Burke as Mike's mother Doreen. Burke is a hoot. Her Doreen is a nagging mother and sassy black woman all in one. I was sorry to see her die. She gets easily the best pre-death line in the entire movie.

Ty Consiglio as Pugg, the crass teenager who ends up befriending and helping Andy. Fun to watch, hope to see more of him in the inevitable sequel.

Beatrice Kitsos as Falyn. She personifies Girl Power here, and is a reassuring voice of reason.

Marlon Kazadi as Omar, a bratty teen who also winds up becoming Andy's friend.

David Lewis plays Karen's cheating boyfriend Shane with as much unlikeability as possible, and his eventual death is both horrifying and satisfying. I actually groaned aloud at the scene where he broke both legs. It was so good.

Trent Redekop as Gabe, a creepy voyeuristic basement-dweller who happens to be very good at electronics.

Tim Matheson as Kaslan CEO, Henry Kaslan. He had this prim, proper signified air about him and I was hoping he would make an appearance beyond onscreen advertisements. Alas...

The Mood

It starts off with a storm, and we're introduced to the factory where these dolls are made. After a cringey starting sequence I honestly could have done without, it's pretty much sunshine and daisies, and gradually gets more unsettling as Chucky is introduced. There are plenty of laughs here, and even later on when Chucky starts embracing his inner psychopath.

At the end, things go way over the top with the violence, but it's all rip-roaring hilarity.

What I liked

The tech-themed update on this old-school horror flick was great. I loved it, not just as a tech; but as a person living in the now, it appealed to me. It made things relatable. Chucky is now a WiFi-enabled gadget that can be accessed via a mobile app. Neat!

The Child's Play franchise is famed for its unflinching delivery of the good old blood and guts, and this movie did not disappoint.

Aside from Shane and Gabe who were supposed to be detestable, the other characters were likeable and this contributed to me, as the viewer, being emotionally invested in seeing them survive. The actors really seemed to be enjoying themselves. Pugg, Falyn and even Omar warmed my heart when they stuck with Andy to put Chucky down. Mike and his mother were a lovable bickering mother-son pair. Karen and Andy had a great dynamic going, too. Damn, I even felt sorry for Chucky! All the pint-sized maniac ever wanted was a friend!

The theme song was deliciously cheesy. It keeps running through my head now!

Cheeky references to The Texas Chainsaw Massacre and Robocop!

What I didn't

The factory sequence was pretty lame and illogical. It was set in Vietnam, and the suicidal worker was seen programming Chucky to remove his violence inhibitors. In Vietnam, if you are this skilled, you probably don't need to be in a factory taking shit from supervisors.

The updated 2019 look for Chucky is not an improvement over the original. One of the reasons why Chucky was so frightening was because the doll was really cute and innocent-looking before it began its rampage of carnage. The doll in 2019 looks creepy from the outset (resembling a midget Steve Buscemi from Con Air), and when it starts exhibiting malevolent behavior, somehow this takes away from the menace.

From this...

...to this? Seriously?!

Chucky is seen needing to stand on a chair to get to knives on a table. How is it at the end, he can leap at Andy? Makes no goddamn sense. Totally inconsistent.

Conclusion

The reboot of Child's Play isn't for everyone. You might be a huge fan of the original and hate this one on principle. But honestly, as a techie, I loved this version. It gave me all the in-your-face bloodshed I've come to expect, along with dark humor and sinister vibes.

All in all, if you don't take your movies too seriously, it's a real scream. I know I had a ridiculous amount of fun.

My Rating

7 / 10

This movie absolutely kills it!
T___T

Monday, 8 July 2019

Fake news? No, fake nudes!

Deepfake technology has been up and coming for the past few years. From facial synthesis to cloned voices to video manipulation, the possibilities for abuse are terrifying. For instance, there may come a day when audio and video evidence can no longer be submitted in court because fake media is indistinguishable from the real thing.

Terrifying, undoubtedly. But also fascinating.

From a technical point of view, this application of technology is interesting. It's art and science in one heady package. The myriad of possibilities for actual practical use ranging from the mundane (test profile photos for Social Media simulations) to the awesome (fully computer-generated action movies where actors aren't at risk of getting injured).

But sometimes people go too far. And a couple weeks ago, the development team behind the now-defunct app DeepNude found out the hard way.

DeepNude is an app that creates simulated nudity. It purports to digitally remove the clothing from any picture of a woman, and display her naked. When this app was released, the outrage went viral, and while I'm not a big fan of online outrage in general, it's hard to say this was wholly undeserved. Women, in particular, were horrified at the implications regarding enabling perverted fantasies and revenge porn.

The tech, in layman's terms

Of course, DeepNude doesn't exactly digitally remove clothes to reveal the actual person's naked body beneath. Unless they had actual footage of that person's naked body (certain celebrities in the adult entertainment industry, for example), that would be impossible. That person might have tattoos, birthmarks, or sporting a third nipple. There's no way to tell.

What this app actually does is refer to its database of body parts and replace the clothed body in the photo with a computer-generated nude one. Kind of like what people have been doing to celebrity photos (painstakingly using Photoshop or something), but now automated via software.

Apology and shutdown

The creators of DeepNude issued an apology, after shutting down their operation when it crashed due to overwhelming traffic.

Here is the brief history, and the end of DeepNude. We created this project for users' entertainment a few months ago. We thought we were selling a few sales a month in a very controlled manner. Honestly, the app is not that great, it only works with particular photos. We never thought it would become viral and we would not be able to control the traffic. We greatly underestimated the request.

Despite the safety measures adopted (watermarks) if 500,000 people use it,  the probability that people will misuse it is too high. We don't want to make mney this way. Surely some copies of DeepNude will be shared on the web, but we dn't want to be the ones who sell it. Downloading the software from other sources or sharing it by any other means would be aganst the terms of our website. From now on, DeepNude will not release other versions and does not grant anyone its use. Not even the licenses to activate the Premium version.

People who have not yet upgraded will receive a refund.
The world is not yet ready for DeepNude.


If you ask me, this seems too little, too late.

This app is deeply sexist not because of misogyny. Not because it shows women nude. But because it doesn't do the same for men. If you feed the app a man's image, it's going to show a naked woman's body with a man's head.

This is only a simulated
example using my sick
Photoshop skillz!

So if this app only allows users to "strip" women (and deny the ladies a similar pleasure), what's this for other than cheap male thrills? The creators didn't think it would be abused? They don't want to make money this way? That's cute.

The world is not yet ready for DeepNude? Bitch, please. As mentioned earlier, people have been doing this for years. The app simply made it easier. The world's been more than ready for something like DeepNude for a while now. Guess it was really a matter of time.

An interesting question

I've seen people question why the "perverted geeks" like the creators would think this was a good idea in the first place. It seemed like a genuine question, so I thought I'd answer that.

You see, that's the thing about us developers. We don't think. Not much about the non-technical stuff, anyway.

Case in point - when I first heard about the app, you know what my first thought was? Not how horrifying and misogynistic it is, but how something like that is supposed to work.

Even after processing the entire spectacle, moral outrage is the last thing on my mind. (Not being a woman, any moral outrage I expressed would come off as disingenuous, at best) My predominant position is that Deepfake technology has tremendous potential, and the creators of DeepNude using it as wank material strikes me as a huge waste.

Generally, when a developer is presented with a problem, our first instinct is to solve it, not to moralize it. We spend more time thinking about whether or not it can be done, rather than whether or not it should be done. That's why we need business people to tell us what's actually useful and commercially viable (and in good taste). Because, on this evidence, left to our own devices, us geeks would just waste our time churning out technically brilliant but utterly useless junk.

We automate stuff. And in this case, the choice of stuff to automate was unfortunate.

And that's the naked truth!
T___T

Wednesday, 3 July 2019

An amusing but frustrating JavaScript episode

Writing JavaScript in a team can sometimes lead to interesting exchanges. I recall a day when I was going through some code left behind by a previous developer. It was a HTML string. It went something like this.

var templateString = "<div class='data-label'>Id</div><div class='data-value'>" + getUserCode(row.id) + "</div><div class='data-label'>Name</div><div class='data-value'>" + getFullUserName(row.title,row.name) + "</div><div class='data-label'>Designation</div><div class='data-value'>" + (row.userType==''?'user':row.userType) + "</div>";


Now, when faced with a long string like this, my first instinct is to break it up into something readable, and more importantly, maintainable. Also, keeping it in its original form would mean I had to scroll horizontally back and forth every time I wanted to examine it. So after I was done with it, it looked like this.

var rowString =
"<div class='data-label'>Id</div>" +
"<div class='data-value'>" + getUserCode(row.id) + "</div>" +
"<div class='data-label'>Name</div>" +
"<div class='data-value'>" + getFullUserName(row.title, row.name) + "</div>" +
"<div class='data-label'>Designation</div>" +
"<div class='data-value'>" + (row.userType == '' ? 'user' : row.userType) + "</div>";


This way, if I needed to add to the block or make adjustments, I could be reasonably sure my edits would not result in missing tags or poorly formed HTML. Sure, there was some unnecessary concatenation, but since they were split into different lines, I figured it should be harder to screw something up this way.

So far so good, right?

Well, something else came up and I had to hand this off to a colleague. When I came back to it and saw what he'd done, my jaw fell open. It now looked like this.

var rowString =
"<div class='data-label'>Id</div>" + "<div class='data-value'>" + getUserCode(row.id) + "</div>" + "<div class='data-label'>Name</div>" + "<div class='data-value'>" + getFullUserName(row.title, row.name) + "</div>" + "<div class='data-label'>Designation</div>" + "<div class='data-value'>" + (row.userType == '' ? 'user' : row.userType) + "</div>";


When I was done resisting the urge to strangle him, I asked him politely why he'd created this monstrosity. His reply?

"Oh, I just think it's more readable this way."

Seriously, what in the ever-loving fuck? This combined the worst of both worlds. It was long and cumbersome, concatenated strings where they didn't need to be concatenated (thus increasing the probability of introducing errors upon editing), and I would still have to scroll horizontally back and forth to read it!

No way in hell was that more readable!

That's the end of my story!

It was a brief one, all things considered.

No, the guy wasn't stupid. He was possibly an even better coder than me. But our minds work differently, and perhaps some coders are just less concerned about clarity.

That's the long and short of it...
T___T