Friday, November 10, 2017

Coffee, and more Coffee

So last week in the Front End Web Dev class I am TA'in, we launched The Big Kahuna Concept: we started the JS portion of the course.

While Tom stood at the front leading everyone through basic concepts and syntax, I put together a simple web page that would have a JS-driven clock and time-appropriate, coffee-themed greeting.

You can see the code here: https://github.com/mgienow/Coffee_Clock


I am humbled by how long it took me to get this going.

The initial page came together in less than 20 minutes.  Which is maybe 10 more than it ought to be, since it;s basically three divs in the markup, plus basic CSS styling and a background image.

But my grasp of tying JS in to HTML has always been shaky, mainly because I've barely ever done it.

Today was the day.

The first time, I had to work from an example in my Duckett text.

That gave the structure for the "It's Coffee O'Clock" greeting:
const java = document.getElementById('java');
let msg= `It's Coffee O'Clock!`
java.textContent = msg;

From there, I could start to figure out how to get the other parts I needed. Which also required either brushing up on, or learning from new, some JS concepts like the Date() object and Math.random(). 

The clock was pretty easy...
const hourNow = today.getHours();
const minNow = today.getMinutes();
const clock = document.getElementById('clock');
clock.innerHTML = `${hourNow}:${minutes}`;

...until I realized that the built-in getMinutes() function returns literally only the minute number. So at 3:10 you're cool, it returns '10' -- but if it's 3:01, you only get '1'.  So my clock would say "15:1" instead of "15:01".  So I had to puzzle out a function to put that zero in whenever the minute value was <10:
let minutes = minsAddZero(minNow);  
function minsAddZero(i){
  if(i<10){i='0' + i};
  return i;
}
which got things looking right.

Finally, the biggest challenge. Or smallest, since in a way I was totally ready for this based on all the code challenges I've done. Conceptually, I had it right away:
function sendSalutations() {  let coffeeBreak  if (hourNow>16){    coffeeBreak = `Good evening!<br>                    Like some decaf?`  } else if (hourNow>11){  coffeeBreak = `Good afternoon.<br>                How about an energizing<br>                espresso?`  }else if (hourNow>5){    coffeeBreak = `Good morning!<br>                    Ahhh, nothing like that first cup...`  } else {    coffeeBreak = `How do you take YOURS?`  }  const salutations = document.getElementById('salutations')  salutations.innerHTML = coffeeBreak}sendSalutations();

Take a look at the hour, and use for/else to pass in the proper humorous greeting for that time of day.

Anyway, it's all there, abundantly commented on GH.  The big thing for me was that I did it two more times, refining it each time. The first re-do, I needed to peek a couple times at my original code. The second one I did blindfolded. Figuratively speaking.

IMportant lesson learned: one of the things I was puzzled about was how the new ES6 template literal for strings is supposed to take away the need to use newline escaped characters (\n) to indicate line breaks. But it wasn't showing up that way in my HTML.  They were right in console, but not on the page. It took what is an embarrassingly long time for me to realize that HTML doesn't speak ES6...so I had to switch from .textContent (which only passes the straight string) to .innerHTML (which allows HTML tags for styling).

 

Monday, November 6, 2017

Workin' My Way Back to RegEx...

Ok, so in the past week, my coding activities have included the following:

  1. Working on "Intro to JS" materials to help co-teach the Front End Web Development course my JavaScript mentor Tom teaches at Betamore Academy;
  2. As a direct outcome of item 1, realizing that even 15 months in to learning JS, there are serious potholes in the roadway of my self-taught JS journey;
  3. Working through pothole-filling material in my favorite JS book, "JavaScript and jQuery: Interactive Front-End Development," by Jon Duckett;
  4. Getting my ass kicked -- repeatedly -- on a level 7 Codewars Kata (see item 2 about holes, above).

Today, let's talk about the kata.  It is the "compare strings by sum of chars" challenge, wherein you are given two strings and asked to determine whether or not they are equal by dint of their ASCII values. If the arg strings are null, empty or contain anything other than a letter (i.e., numbers or punctuation or, say, the turd emoji) the string's value is zero.

I decided to approach the challenge in pure JS, no regex. I then wrote out the code logic in plain words. I will skip boring you with this because it is in the final code, in the form of comments.

Where I got stuck: 
  • First, on null string test cases. Because, for what I now realize was an embarrassingly long time, my code proceeded upon the assumption that null had length of zero -- when of course you can't determine length of something that does not exist. It finally occurred to me to look at MDN  to see why my code kept returning an error -- that told me, in plain English, "TypeError: Cannot read property 'length' of null". I was extremely sure that I was right and JS simply wrong. Sigh. This is actually weird for me, because I typically assume the opposite -- last week I had some freaky browser thing going on where console.log(whatever) was not displaying, and I was sure it was me. As in, I had somehow messed up in applying one of the most fundamental JS tools in the box.  Turns out there is a toggle in console that I had accidentally flipped, turning off display of anything NOT an error. Gosh, thanks, Chrome!
  • Next, I was also SUPER sure of another thing that also turned to be ahem wrong wrong wrong. My test case for whether string elements were alpha only characters involved converting .toUpperCase() -- the instructions specified treating all letters as capitals even if passed as lower case -- and then checking if the ASCII value was greater than or equal to 65 (the value of capital "A") and less than or equal to 90 (the value of cap "Z").  Unfortunately, I was confident that you could do this:
                  if(65 <= str1Val <=90){do some stuff}


         When it turns out, no you can't.  it's got to be:

                         if(str1Val>=65 && str1Val<=90){do that stuff}

    Dude, I was just trying to make my code a little sleeker. Though I guess i               could drop two equal signs and achieve the same thing with 

                         if(str1Val>64 && str1Val<91){do that stuff}

My thought with using 65 and 90 with the greater/lesser equals operators was to make my code more readable -- i.e., make it plain that these numbers represented A and Z. Like, more readable  for all the ASCII savants who will ever stumble across my Codewars solution and instantly convert this in their heads and be impressed.

 function compare(s1, s2) {  
 //establish counter variables to hold the ASCII code values of the strings  
 let s1Sum=0;  
 let s2Sum=0;  
 //if s1 is null OR empty (has a length of zero) return s1Sum=0:  
 if(s1 == null || s1.length==0) {  
  s1Sum=0;  
 } else {  
 //else, convert s1 to upper case and loop over each character in the string,   
 //assigning the ASCII value (obtained with `charCodeAt()` for each position)  
 //to a newly inititalized variablie, s1Val:  
 s1=s1.toUpperCase();  
 for(var i=0; i<s1.length; i++){  
  let s1Val = s1.charCodeAt(i);  
  //IF the value is between 65 and 90 (the capital alphabet ASCII values),  
  //add s1Val to s1Sum:  
   if(s1Val>=65 && s1Val <= 90){  
    s1Sum += s1Val;  
   }   
  //if it's not between 65 and 90, then it is a number or other symbol, so return   
  //s1Sum = 0:  
   else {  
    s1Sum=0;  
    }  
   }  
  }  
  //Now repeat same logic for the second passed arg, s2:  
  if(s2==null || s2.length==0) {  
  s2Sum = 0;  
  }else {  
   s2=s2.toUpperCase();  
   for(var i=0; i<s2.length; i++) {  
   var s2Val = s2.charCodeAt(i);  
   if(s2Val>=65 && s2Val <= 90){  
   s2Sum += s2Val;  
   } else {  
    s2Sum=0;  
    }  
   }  
  }  
  //Finally, compare the two counter variables, s1Sum and s2Sum, returning   
  //true if equal and false if not equal  
 if(s1Sum === s2Sum) {  
   return true;  
  } else {  
   return false;  
  }  
 }

So!  That got things working. Notice, however, that a few lets aside, I am still thinking in ES5. Tomorrow's challenge: refactor into more modern JS, if that is possible. And then a side quest: repeat the challenge, this time using regex.

Sunday, October 29, 2017

Day 3: Fat arrows, backticks, let and const



I spent my Saturday getting a grip, finally, on the fundamentals of ES6.  JavaScript has been around since 1996, in various forms, with next-number versions every couple of years introducing new features and functionalities. JS was kind of stuck on ES5 (version 5) for a long time, though -- after it was introduced in 2009, the entity in charge of updating the JS standard did not give us ES6 until 2015. Most JS devs learned ES5, and it seems like many if not most of the online academies are even now, in 2017, still teaching the previous version of the language. I've not made a huge point of fact checking this, but the main "learn ES6!" online resources I've looked at, while figuring out the best way to finally learn it myself, are aimed at teaching people who already know JS the new features of ES6.

And now I am finally one of them.  I focused on four ES6 entities:


  • Template literal syntax, which is pretty sweet. Basically, you surround a string with backticks instead of quote marks (single or double both work, but JS convention leaned toward single). Using backticks means not having to escape special characters or use newline breaks for multiline strings. Thus, 
var ironButterfly = 'Innagadadavida, honey\n\don\’\t you know that know that I\’\m lovin you?’;  becomes
var ironButterfly = `Innagadadavida, honey, Don’t you know that I’m lovin you?`


  • Arrow functions, aka the fat arrow => which replaces the 'function' keyword and lexically binds the function's 'this' to the specific block where it appears (designated by two curly braces {}). In ES5, this can mutate whenever you create a closure, which can lead to unforeseen code behavior and much cursing. ES6 brings us the fat arrow function syntax -- => -- where ‘this’ will always retain function context. SO much typing saved! SO much callback hell avoided! No moar need for ‘that=this’ or .bind(this) or other such tedious yet necessary statements!  We go from:



var _this = this$('.btn').click(function(event){  _this.sendData()})
To the more economical -- and lexically stable --

$('.btn').click((event) =>{
 this.sendData()})
  • Const and Let: Like var, these are used for variable assignment, but let and const both come bearing functional semantic significance. They both are lexically binding, meaning that they are bound to the context of the code block where they are declared. (And, conversely, are thus not subject to variable hoisting). Const creates a read-only reference to a value, meaning that a const cannot be assigned to a new value. Let is re-assignable.
That, friends, is the quick run-down. I wrote a tutorial for The New Stack, complete with code samples, and will link to it as soon as it is up.

Friday, October 27, 2017

Day 2: Refactoring for fun and smartness

So last night I went to the closing party for the alternative newsweekly where I worked for two decades, the Baltimore City Paper. Many if not most of my colleagues were there, and there was much catching up. Some of us are yet staying the course upon the uneasy waters of professional journalism, but at least half the people I spoke with have moved on to new careers. Many of them, when asked the inevitable "So hey what are you doing now?", responded with downcast eyes and a description on some variation of a PR or marketing job.

It was pretty great, when on the receiving end of that question, to be able to say, "I'm a web developer."

So now to live up to it.


 function ìsZeroBalanced(n){  
  return (n.length === 0) ? false : true;  
  let x = n.reduce((a,b) => a+b, 0);  
 return (x===0 && n.every(y=>n.includes(-y))) ? true: false;  
 };  

True to my resolution, I was at my desk by 8:15 this morning (even though a bit bleary-eyed, it was a late night and many drinks were bought. It was a wake. Can't toast without a beverage). And the refactoring was pretty easy. The main return statement I didn't even need to look up the syntax on MDN. The first conditional I'm not thrilled with -- currently it too is a ternary, but used inappropriately. There is never a scenario in that evaluation statement where you want a return of true.  However,
return (n.length ===0) ? false;
doesn't work. I don't even  know what this is called in order to try to google and figure out a better way.  So for now the mystery is, which is less bad, the inappropriate ternary, or

if(n.length === 0) return false;
which gets at the problem of figuring this stuff out on your own. I try not to waste my mentor's time with very small questions like this. And I showed it to Asa, who said he doesn't know and currently doesn't feel like he could even do this JS challenge successfully. So it sounds like what I could use is a bigger pool of people to bother with my semi-n00b JS queries...

Speaking of which, I've got this morning free to work on JS before having to do an interview right after lunch. Time to go learn me some JavaScript.

Thursday, October 26, 2017

Day One: Zero-Balanced Arrays drive me to bake corn muffins

So this morning my JavaScript mentor, Tom Kraak, messaged me to say that he is meeting with his manager today -- and that he wanted my permission to mention me as a candidate for the JS dev hires his company is making. Holy shit. The imposter syndrome was strong. I feel like I am nowhere near ready. I said this. Tom replied that I am ready. There was some more "no I'm not, yes you are" back and forth, but the upshot is he told me it's time to jump off the cliff and I told him to go ahead and throw my name into the ring. (I am nothing if not a mistress of the mixed-up metaphors).

Aaaaand then I proceeded to have a panic attack over how I  have literally zero anything to show a prospective boss. None of my projects are finished. Four websites all about 80% done. A couple JS projects -- a pomodoro clock, your classic todo list "app" -- both lingering in the twilight zone limbo of almost but not quite finished.  OK! So! Clearly it's time to dust off my hands and get to work finishing...so of course first I decide to do a quick code challenge


Codewars, level 7 kyu (out of 8 levels, 8 being the easiest), "zero-balanced sum" challenge. Seemed like it would not present too much trouble:



"An array is called zero-balanced if its elements sum to 0 and for each positive element n, there exists another element that is the negative of n. Write a function named ìsZeroBalanced that returns true if its argument is zero-b"alanced array, else return false. Note that an empty array will not sum to zero."

I was determined to tackle this in Grown Up JS -- no for loops or if/else statements.  And quickly settled on my approach:

1. Check for empty array. If empty, return false.
2. Use reduce() to sum array's contents to a single value.
3. (here's the tricky part) Iterate over the array to match positive and negative values. In a true zero balanced array, each positive integer item will have a corresponding negative integer item. A scroll thru MDN turned up Array.prototype.includes() and Array.prototype.every() combined should do the trick.

SO, I ended up with

which should work, right?

Only it didn't.  And I spent four hours, including an appeal to Stack Overflow, trying to figure out why.

I haaaaate asking Stack Overflow for help. Those people are like my ex -- ignoring the question I'm asking in order to criticize, nitpick and start a fight over HOW I'm asking it.

And they were useless, anyway.  Two hours later, after a lot of cursing at the screen and a break to bake some corn muffins, because at least I know how to bake corn muffins without actually FUCKING IT ALL TO HELL, I finally tried:



And IT WORKED.

Can you see the subtle difference?

It was all in the variable names in the every() callback function.  I used n because apparently I am an idiot.  I was so worried to bits about getting the syntax right that when things refused to work I refused to believe the problem was anything BUT my syntax. It didn't help that the error that was getting thrown in console was


"Uncaught TypeError: n.every is not a function"

Y not?

Oh ho ho hohooooo. You laugh, or you cry. When it comes to learning JavaScript, sometimes you do both at the same time.

Tomorrow I am going to take a crack at refactoring the answer to remove the if/else statement into a ternary. But for now I'm just so very very very happy that it works, I fear to touch one single thing.
There are ten thousands reasons NOT to attempt a mid-life career change from journalist to JavaScript developer. And I am totally tempted to list every single one of them right here, because then that would keep me from going back to the piece of code I have been beating my head against for the past three hours and 50 minutes.

I'm pretty much scared witless by this, my failure to solve what should have been a straightforward low-level code challenge. Because by now I should be better than this.

It has been 15 months since I graduated front-end web developer bootcamp (at Betamore Academy, here in Baltimore) and I have not yet landed a job as a coder. To be honest, I have not really been looking -- because I know my skills are not where they need to be in order to get the job I want. The opportunities that came my way, immediately post bootcamp, were basically formatting HTML and CSS marketing emails -- which so did not interest me. I was newly hooked on JavaScript and wanted to get a real coding job.


Sounds good, right? Spend a few more months studying JS, level up to being a serious contender for a serious dev job. But: there is always a but, and this is a big one: It's a long, long way from JS n00b to someone who can actually build useful things.  Like so many other recent bootcamp grads, I've stumbled across the gaping chasm that exists between the end of the course and the distant, much-desired horizon of being a skilled, experienced (and, yes please, paid) professional programmer. There are no bridges across this chasm, at least none that I've been able to find. There is no map. Somehow, you're just supposed to magically just get there. The path is made by walking.


And so the past year has been a comedy of errors, of me trying to self-study JavaScript and build a portfolio, between paying the rent and raising the kids (did I mention I'm a single parent?) and just the regular life stuff we've all got. Progress has been agonizingly slow. Mainly because studying is the first thing to fall off my daily to-do list when something comes up, like one of my kids is home sick from school or I have a writing deadline (tech journalism is how I'm currently earning that aforementioned rent) or fill-in-the-blank-with-today's-disaster. 


So this is me re-arranging my priorities. It's time to get serious about JS, put it at the front of the queue instead of the end. I hereby commit to spending minimum one hour each day doing something to roll that rock an eentsy bit forward: code challenges. Reading Kyle Simpson's YDKJS books. Working through WatchAndCode.com lessons. Or even my own small JS projects.


My commitment: no later than 9am each morning, weekends included, my butt is going to be in my desk chair.  I am going to write at least a short account of what I did, posted here. And also push things to GitHub, to show this work to the world. My GH dance card is distressingly blank because I have not been putting up the small things I do. I guess I feel like they're too inconsequential. (Also I have a bit of a GH avoidance issue, so this will help me get over that ridiculous, self-imposed blockage as well).

I started today. Next post is about what I did. But before then, a final word about this blog's title. I have a coding pal, Asa, who is in pretty much the same situation I am when it comes to trying, and failing, to advance as autodidacts. We both start, we both stop -- get distracted or pulled away -- and above all we commiserate over how crazy-making the whole process can be.  A recent sample Slack exchange:

asasmith [12:13 PM] 
I'll go on a js kick, and then get pulled away from it work on other stuff, then I feel like I'm back at square one when I come to it
michellegee [12:13 PM]
YES 
asasmith [12:14 PM]
patience is not a skill of mine
I want to know all of the things now 
michellegee [12:17 PM]
learning takes place in stages, just because of how our brains are wired.  first comes exposure, the initial interaction with new skill/knowledge.  second comes integration — which, interestingly, happens while we are sleeping.  the brain organizes and stores that information at that time.
there is a term called “savings” that refers to how, every time you work on this new skill, the length of time required to retrieve and use your newly learned information gets shorter and shorter.  but this is an inevitable middle step towards true fluency: we all have this gap where we have to struggle to implement what we've learned. there is no short-cutting the process, but the more you do it the easier it gets. obviously.
the smarter we are, the more impatient we are with our own learning curves.  we think that somehow we should be able to skip that long, difficult slog from first exposure to true assimilation.  but nobody can.

not even einstein.

So now I'm putting my money where my mouth is. It's assimilation time, fellow travelers. Let's put the pedal to the JS metal and find out how to get there from here.