16 Jan 2017
What would you say if I told you that the secret to coding was LSD? When you stopped having a conversation with the floor lamp and finished freaking out about the pink spiders in your hair, you would probably tell me that I was mistaken. However, I don't mean d-lysergic acid diethylamide, aka "acid". I mean a slightly different meaning for this initialism.
Instead, I mean LSD in the following context:
Let's explore each one of these in detail.
This is the hard part. This is what people fret about when it comes to programming. Are the instructions you are giving the computer going to achieve a successful result? Is that result repeatable, given the same data? Will different data achieve a successful result? Have you flowed from each step in a logical progression?
These are all challenging questions, and are what provide the daunting obstacle to most people embracing coding. Bugs happen, though. They are arguably unavoidable. That should be a reason for you not to enjoy the process of communicating a solution to a problem to a computer.
Logic is also where we do the vast majority of our debugging. Questioning assumptions is part of being a developer. However, the logic of how we process data doesn't change from one programming language to another. The step-by-step process of getting the computer to work through your solution is relatively constant. Some languages may have a more streamlined process, some may require more declarative or more imperative programming steps, depending on the idiom. But the logic still doesn't change. Ultimately, even if you are building OO applications or using functional programming, your solution contains the same steps. How you have constructed the program flow of those steps can vary.
Have you used the right methods to enact your logic? Did you remember all of your commas, parentheses, curly braces, semicolons, or other syntactic characters that communicate meaning and functionality? When checking syntax, this is when it is always important to remember issues of capitalization, pluralization, hyphens versus underscores, and (if you're in Python) whitespace.
Fortunately, syntax is usually the easiest problem to solve. Most parsers/compilers will throw an error when they encounter an invalid syntax. Typos are usually easy to spot thanks to syntax highlighting in editors and method lookups in IDEs.
Unfortunately, syntax can't help faulty logic. Make sure you know what a method's return values and expected parameters are. Understanding synchronous versus asynchronous methods means you are sure that your logic is running in the order in which you intended it.
Last, but arguably most important, is data. Data is product. Do you have access to the data you need? And, is it in the format you need and/or expect? If the answer to either of these questions is no, then it doesn't matter what your logic or syntax are doing.
Ultimately, products that you build are designed to either consume, manipulate, manage, or produce data. It is imperative that you are comfortable with the data set that your code is using, and make your logical decisions based on that knowledge.
The initialism LSD is great, because it evokes a chuckle. The truth is, it should probably be in the order DLS, because as a programmer you're going to start with your data. The knowledge of the data you either have, or need, is going to inform your logical flow of steps to go from problem to solution. So, you will always progress from Data to Logic. Then, and only then, will you implement Syntax to apply the logic.
Additionally, data is usually provided, whether in the form of user input, access to a database, or from an external API. Logic is where the programmer will do most of their work, and the innovation happens. The logic, as discussed above, doesn't change regardless of which programming language you are using. That means that everything else is syntax, which is easily research-able (Google-able, in most cases). This becomes a strategy for rapidly becoming productive in new languages and frameworks.
As a debugging method, as a workflow for approaching the development of a new feature, or even as a teaching tool, the LSD principle of programming is incredibly useful. Try it out the next time you have a problem and let me know how well it works for helping you to solve your bugs.
If you have any comments or questions about this post, please feel free to shoot me an e-mail at don (at) donburks (dot) com. I would love to hear from you and continue the conversation.
09 Jan 2017
Many developers are still in the process of embracing all of the advances of ES6, CSS3, and HTML5. One of the under-utilized tools, in my ever-so-humble opinion, is the
<template> tag. Today's post is going to explore what this tag is, some of the inner workings of it, and also demo how you can use it in your every day workflow to improve your web applications.
What it is
<template> tag creates a non-rendered document fragment on your page. There's a lot of jargon in that sentence, so let's deconstruct it a bit and de-mystify what that sentence says we are getting with a
Also known as an 'inert' document fragment, this is HTML that is reviewed by the browser to ensure that it is valid HTML, but is not added to the overall parent document (DOM).
A document fragment is a minimal document object, like a DOM, but it has no parent. It is designed to hold well-formed markup. Document fragments are also intended to allow developers to clone and/or transfer the children of the fragment into the main document.
What does it all mean?
Putting these terms together means that when we define a
<template> tag on our page, we are embedding a mini-document into our DOM which the browser is not going to render until the contents of the
<template> are moved or copied into the main document itself.
So what does this look like in practice? Let's consider the following document:
<title>Playing with Templates</title>
<p>This is some rendered content.</p>
When this page is loaded, the strings 'One' and 'Two' in the
<li> tags are not rendered on the page. In fact, none of the content of the
<template> tag is rendered on the page. This can be confirmed with
document.querySelector('ul'); which returns
null. From the perspective of the DOM, there is no
<ul> tag currently on the page. The DOM did not build nodes for that and add it to the overall tree. The template tag, however, is part of the DOM.
Now, the real question becomes, how do we take advantage of this embedded markup and make it relevant for our page. Well, that is going to take some scripting. The first thing to understand is that the document fragment is stored in the
content property of the template. It is important that this
<template> has an ID on it. Theoretically, you could (would) have multiple templates on a page, so there is a need to be able to access each template individually.
In this case, since the template has the ID of
list_template we can access it a variety of ways. Here are a few:
list_template (This works because ID's create global variables in JS)
Once we have a reference to the template, we can start to work with it. Let's assume the following code:
const t = document.querySelector("#list_template");
const template = t.content.cloneNode(true);
With this code, we have references to both the template and the document fragment. Of importance is noting that we have cloned the document fragment. This allows us to re-use the template. Otherwise, we would be moving the nodes out of the document fragment and moving them into the DOM, thereby emptying the template for any future use. That would kind of defeat the purpose. By cloning the fragment, we have new nodes that we can modify and use the way we want.
Let's make this useful to us by adding some real data into the mix. Consider the following code:
const list = ["rubber ducks", "real ducks"];
const t = document.querySelector("#list_template");
const template = t.content.cloneNode(true);
const items = template.querySelectorAll("li");
items.forEach((li, index) => li.textContent = list[index]);
(Editor's note: Code does not work in IE11. If you're using IE11, you can't use template tags anyway. Please upgrade your browser.)
Walking through this, we have a list of some hardcoded data, though of course you could get data from a server for this. We then get a reference to the template itself, we recursively clone the contents of the template into a new variable. Doing a
querySelector on the contents, we get an array of the
<li> tags which we iterate through and update the
textContent property of each
<li> with the corresponding element of the data array. Our final step is to append the compiled template to the
parentNode of the template tag itself.
As with every web technology, there are some common gotchas. For example, according to the spec for the template tag, it should only be inside of
<colgroup> without a span attribute. You wouldn't want to next
<template> tags inside of
<div> tags or deep within the DOM of your document. Keep
<template> tags as a top-level tag.
<script> tags inside of
<template> tags is interesting. When the page is loaded, the
<script> tag will NOT be processed by the browser. This is due to the inert nature of the document fragment. However, the script will be evaluated as soon as it is added to the DOM, as you would expect.
As templates are essentially Web Components, it is going to work best if there is one outer tag which contains all of the HTML markup which you are wanting to include. Similar to how a React component would be built, this means that by cloning the document fragment recursively, you get one outer node and all the enclosed children of it. Please note that recursive cloning is the key here. That is what the
true param to the
cloneNode function is accomplishing.
Don't put an ID attribute on an element in a template unless you are sure that you will ONLY ever be accessing that template and adding it to the DOM once. The ID is not registered as part of the DOM until the template has been cloned and appended to the parent node.
Template tags are non-rendered document fragments which you can access via scripting to be able to populate with any data you wish. Cloning them is the best practice, so that you can re-use them later. By making them top-level tags (children of the body) and assigning an ID to each template, you can embed many page fragments which are effective for being able to populate your page after the initial load.
Please feel free to reach out at don (at) donburks.com with any comments you may have on this post.
29 Sep 2015
In all of my years of being a developer, it's only been in the past few years that I have really had to sit back and think about the philosophical side of what I do. Prior to that, there was always dealing with crushing deadlines, unreasonable specs, the thrill of a working implementation, and all of the assorted parts of a developer's life. However, as I have moved into more of a teaching role than a coding role, I am spending a fair bit of my time making sure that I can communicate to my students the very important why questions that surround our industry. One of the most important of these questions is the general concept 'What Is Programming?'
Programming is Expression
Historically, humans have used language to solve a problem. Pictograms on the walls of caves would depict the hunting of food. This was a language. As speaking and writing evolved, language became a way to communicate a solution to a problem to another human. What berries to eat, the best way to skin a freshly slain bison, how many shells you would take in exchange for a blanket, where to hide your treasures...these are all tasks that one might go to another for a solution. If that solution could not be communicated, it was fruitless. Knowledge could be shared, if only there was a way to codify it. Hence, language. When we think of programming, we think of syntax and math and logic usually. However, programming is an expression.
Programming is a way of expressing one's own interpretation of the best solution to a problem. It is a way to be eloquent, or terse, depending on the nature of the problem. And the language would express, most importantly, a repeatable solution. If I give you directions from your front door to the nearest ice cream store, the result of following those instructions would be repeatable. The same is true for a computer program. If I give it my starting balance in my checking account and a list of all the transactions, it will always be able to analyze the numbers and tell me how much money I don't have, as well as telling me that I shouldn't have gone to the ice cream store. And this outcome will be repeatable.
Programming is Progress
Many times, the reason or motivation behind creating a program to do a task and provide a solution is to convert an analog process to a digital one. A perfect case is an organization that I helped recently had an attendance process where staff at a remote event would have a paper sign up form that attendees would fill out. That form was then photographed with a smartphone, emailed to the head office where a local staff member would have to bring up the photo from e-mail and physically transcribe the information into a spreadsheet. That spreadsheet was then saved as a CSV and imported into another tool. I'm tired just from writing that out, much less having to do that process several hundred times every year.
By getting a tool built for them that would allow staff members to digitally input the data and have it post to an API backend which would record the data and allow reporting to be done in real-time, this organization was able to save hundreds of hours of work each year. Literal months of their staff members' lives was now returned to the organization simply by transforming an analog process into a fully-digital one. Programming is about progress, bringing tasks that have been done manually for long periods of time into the modern era by digitizing the workflow. Thanks to the 'repeatable solution' philosophy I discussed above, programming is enabled to provide real-world solutions.
Programming is Disassembly
One of the maxims which I often preach to students is that everything in programming comes down to the acronym LSD. Not the hallucinogenic, but instead LSD stands for Logic, Syntax, and Data. If you think about it, every bugfix is tracking down which one of these three things has failed in the execution of the program. Sometimes, that bugfix is one that stops the program and generates a stacktrace. However other times, it is an unintended behaviour that you have to trace the logic of to understand how to change it to a better set of steps. Programming is breaking a solution down into steps so small and finite that even a computer can do them. Of course, because computers are dumb we have to be very precise in the way we present the solution to our problem. That process of deconstructing the problem is a core aspect of programming.
Quite often, one of the best ways to approach a problem in programming is to start at the solution and work backwards. The process of figuring out what each prior step would be in order to get to the solution you envision is a critical piece of planning out a feature. Sometimes this can even go back to the analog and be done with pencil and paper, or whiteboarded, for the purposes of visualizing what the structure of the code will be. It will also generate a set of pseudocoded descriptions which can even be converted into TDD or BDD specifications that can help to guide the development for the developers.
Programming is Synthetic
Each of those technologies will have its own API and idiosyncrasies that will have to be implemented. The developer, by trade, is skilled in not only being able to understand the logical flow of information and execution which defines the solution they are building, but implicitly they are skilled in synthesizing these disparate technologies and skill sets into a single, unified effort to build a multi-tiered architecture which can accomplish their programmatic goals. The closest analogy is the role of a chef, whose knowledge of food, chemistry, knife techniques, cookware, presentation and seasonings can combine to produce a meal you may never forget, the developer synthesizes all of their knowledge into the code they write.
Programming is Fun
It cannot be stressed enough that programming is enjoyable. As a developer, there is an opportunity to create something new out of apparently nothing. A blank editor window is not an obstacle, it is a challenge. A developer's ability to identify an analog problem that can be resolved through the application of technology, deconstruct the solution into a repeatable path of steps, synthesize their knowledge of languages, frameworks, hardware, and networks, and ultimately strive to deliver an effective, expressive and eloquent solution to the problem is a tremendous thrill. There is a gratification, a deep personal reward in seeing the fruit of your labor appear on the screen, fully-formed and ready to be used.
When you see others using it, it validates every effort, every difficulty you had in creating it. In the words of Nikola Tesla:
“I do not think there is any thrill that can go through the human heart like that felt by the inventor as he sees some creation of the brain unfolding to success... Such emotions make a man forget food, sleep, friends, love, everything.”
Tesla had it right. Knowing that others are using your app and finding it useful is one of the greatest feelings there is. Being able to understand, quantify, codify, and verbalize the process of getting to that solution means that we go into every challenge with an even greater insight into why we do what we do.
27 Dec 2014
As an example, see this code:
As you can see if you run this code, what ends up happening is that our Garfield instance gets the swish() method we add to Cat, even though it wasn’t part of the original inheritance.
So, I started working on an implementation of some of the principles that Elliott covered in his talk, without having to implement something the size and weight of StampIt(his library for building instance safe objects). It wasn’t that I thought StampIt was a bad idea. In fact, it’s great. But what intrigued me was the idea of mixin-based object creation, where you could throw a few methods and properties in a mortar and pestle, grind for thirty seconds, and out pops an object.
So, I have created mkobj, a simple implementation which allows you to register callbacks and properties which you would like to use in object construction. You can see it and an example here. Please note the minified version of the code weighs in at a VERY minimal 267 bytes!
The library itself is rather simple. There are two methods:
This method will register a function or property that you would like to use as a mixin later for the construction of an object. The name must be unique, else it will overwrite a previously-saved mixin. If you pass null instead of a function or property, then it will unregister that particular named mixin. You can register as many as you would like, and they will be namespaced inside the mkobj library itself.
.construct([name1, name2, name3, …, nameN])
This will return an object with all of the properties passed in the array on it as keys, provided that they were previously registered using .register() (see above). If you didn’t .register() it, then it won’t be set on the object. All objects created by .construct() are instance-safe.
As well, you could take an object created by .construct() and make an instance-safe copy of it using Object.create();.
Have fun, play around with this. Perhaps if I get especially motivated next week before I head back to work, I will do the whole ‘module-compatibility’ thing, so that it’s RequireJS/CommonJS/Bower/Browserify/whatever-compatible. This technique would work well for Node as well. (Which is how I tested it all, anyway).
15 Nov 2014
Some of the most common myths about developers involve social awkwardness, poor fashion sense, and a general image of their minds being a warren of circuitry and math. There are many people who will assure you that the mind of a developer is a scary place, fraught with obscure lingo, random characters such as curly braces and parentheses, and an understanding of technology that surpasses that of mere mortals. However, one of the most pervasive myths about developers is that those who have certain mental illnesses are somehow more skilled and more suitable for the profession than others.
Myths are made to be disproven, and this particular myth is no exception. Topping the list of mental illnesses that supposedly contribute to the skills of a developer are dyslexia, OCD (Obsessive-Compulsive Disorder), and ASD (Autism Spectrum Disorder). However, while each of these is an illness that affects the way that the brain processes data and does impact problem-solving, they are no gift to a developer.
Dyslexia is often characterized by difficulties with accurate word recognition, decoding, and spelling. Most people think of dyslexia as letters being flipped and reversed, or the brain jumbling the order of the letters of a word when it tries to process it. These are two variants of dyslexia, but are by no means the entirety of the condition. However, the dyslexic developer myth says that someone who has learned to overcome dyslexia and “function” is therefore able to be more focused and attentive to the small details. Theoretically, this would make them a better programmer.
However, just because you learn to function with dyslexia doesn’t mean you are cured. Your brain never stops misinterpreting words and numbers, you just learn to re-interpret the input you’re getting. Dyslexia is a life-long struggle with expressing yourself through writing clearly, interpreting the written languages around you, and embracing complex grammatical structures. Unfortunately for dyslexic developers, writing code is a form of written expression, involving complex syntax having to read and accurately interpret code written by others.
There are at least ten times as many myths about OCD as there are myths about obsessive-compulsive developers, and the vast majority of them in both categories are misconceptions. Obsession is a word that we use very casually in everyday conversation, devaluing the definition of the word. People discuss being obsessed with a show, a food, or pumpkin-spice lattes. Compulsion is something we generally only face when in school or the military. An activity or class will be compulsory.
Many people use OCD as an adjective when they intend to say that they are choosy or particular about how something is done, without understanding how distinct it is from a condition that causes you physical discomfort and anxiety when reality is not following an arbitrary pattern upon which your mind has become fixated. The myth that developers with OCD have to have things just a certain way, orderly and methodically building their code, is completely false. Even if the process of coding is the pattern with which someone with OCD has become fixated, they are still just as likely to suffer anxiety when something isn’t correct. Having OCD doesn’t make you a good coder; it makes you an anxious one.
Anyone who has seen Rain Man has a certain impression of ASD, more commonly known as autism. Autistic people, the myth says, are automatically good at math, bad at dressing themselves, and don’t know the value of money. Many would agree that this is the very definition of a developer, however they are discounting the mental chaos and dysfunction that comes from being somewhere on the autism spectrum. Recent scientific progress has spurred a reclassification of the condition as a spectrum of disorders, including Asperger’s and savantism.
The misconception focuses on how all those who suffer with autism demonstrate savantism, or abnormally proficient skill in one area or another. Many have seen a movie of the week profiling Leslie Lemke, Kim Peek, Stephen Wiltshire, or Daniel Tammet. Therefore, it is an easy (though illogical) leap to go from those cases of autism to a developer with Asperger’s being expected to code at an abnormally proficient level. As the core areas affected by autism include the ability to express yourself and the ability solve problems, this makes the process of coding particularly challenging. Even with famous savants like Lemke and Wiltshire, they are only able to reproduce things they hear or see. Coding requires you to be able to innovate and invent.
Overall, the myths surrounding these mental illnesses being a benefit to developers are more detrimental than anything else. It puts an unfair pressure on these developers to perform at an impossible standard, and only adds to their anxiety when this arbitrary excellence isn’t achieved to someone’s Hollywood-fuelled expectations. A good developer is someone who studies, practices, and devotes themselves to building their skills. That is a set of characteristics that is independent of any other condition, and ultimately common to any profession. Good developers are good because they work hard, not because they suffer from mental illness.