Bug Hunt: Part 1

Debugging is one of those skills that is commonly not taught as a skill, but described as one. Schools don’t (necessarily) offer a course in debugging and it’s not taught as a unit in a curriculum. It’s sprinkled in between learning several basic skills, sometimes included as a single exercise when learning an operation syntax, where the student is given some code written incorrectly and told to find where the problem is and fix it. This isn’t a bad thing exactly. Debugging is a necessary skill but also a frame of mind that involves patience, curiosity, and an ability to accept things not working.

Debugging can involve removing errors but also doesn’t have to. Sometimes it involves restructuring the program because it doesn’t behave the way you intended it to and the way you thought it would, until you ran into a problem. It’s the practice of making your code behave the way you intended it to, and that can cover quite a number of bases.

The briefest of them are syntax and output errors. Syntax errors are easy to fix, but can be hard to spot. In hundreds, thousands of lines of code across many different files, where did you miss out the semi-colon, the backslash, the parentheses? The error doesn’t always tell you.

The easiest way to track it down is to save and test early, test often. This is where version control comes in; a lot can be said of version control but for the purposes of this discussion version control means we can work on one small part of our application at a time, and that narrows down the potential errors from thousands of lines of code to hundreds. And once you’ve narrowed the scope of what you’re working on, you can introduce some test code.

An example of test code in JavaScript

This block of test code, which I have liberally sprinkled in my Project SEEDs application in development, tests two things. It should show the phrase “Mr. Hammond, the phones are working.” on whatever component or page I have loaded, and it should log the same phrase to the console whenever a component including this function is loaded. If I see it, I know that the component loaded correctly even if the output is null or is otherwise not what I expected. If I don’t, I know the component isn’t loading.

That gives me two possibilities for where the error is located: either in the section of code that calls the component, or the component section itself is giving me the wrong output. Hopefully both of these sections of code are short enough that I can look through them and take it line by line, testing each, first noting down how it should work in comments and then if it doesn’t work as expected, noting down how it does behave. I also try to note the input given/output expected while I’m debugging, to keep it straight and to remind myself if I need to take a break.

An example of a piece of JavaScript that adds a button to a div

Recently I was adding a button to the div (podCard) that the above code writes to. I created the variable and element, gave it some inner HTML, added the click event listener and wrote out the function it called, and appended it to the div. It appeared on the div, but it didn’t perform the function when clicked. Nor, when I tested it as above, did it log anything to the console. By doing this I knew that the problem was most likely in the function call, for whatever reason, especially as when I put the whole function into the event listener it worked properly. And I could have left it like that, but the code was cleaner when abstracted out. So what was going wrong with the function call? We won’t discuss how long it took me to realize that I’d forgotten to append the parentheses that make it a function call. (About twenty minutes.)

A simple syntax error, but all told it took me a good thirty minutes to track down, including those twenty minutes it took me just to realize that I hadn’t typed the function call correctly. And yet because the whole thing worked as directed, i.e. the event listener listened and obeyed the commands when clicked and the component loaded correctly, I didn’t have an error message to point me to line 113 and say “this is not a correct function call.” Sometimes you have to narrow it down by trial and observation.

An example of a piece of JavaScript that creates a button to render a number of items

Output errors, when your code isn’t returning the result you expected and needed for it to work, often happen because of syntax errors but not always. In the example code above, I put in the event listener what I thought was the correct function call to render all the seedling pods. I clicked the Render All Pods button, and it rendered nothing. With some trial and observation as I’ve described, I realized that the renderPods function takes an argument: the fetch data. The fetch function, on the other hand, automatically calls the render function with the fetch data at the end of the chain on the fetch request. I put in the fetchPods function instead, and it worked … well, mostly properly. Again, we have an example of the code doing exactly what you told it to do, even though it might not be quite what you wanted. This time I knew why, though, and I left myself a note for another day’s work.

Trial and error, more broadly described as trial and observation, is one of the two main underpinnings of debugging code. Whether you use a debugger or endless print statements, you’ll need to repeat your operation several times to figure out where it’s going wrong and in what way, and how best to fix it. And because of this you will also need a generous helping of patience and a healthy sense of self-awareness. Sometimes the problem isn’t only with the code, it’s the fact that you’ve been working on the application for six hours straight and you need a break, a drink of water, a meal, a nap, or some combination of those.

When I began turning towards web development as a career rather than a hobby, my mother reminded me at the outset to remember to step away from the keyboard every so often. Get a snack, go outside for a walk, take a few deep breaths. Regardless of what tools or procedures you use to debug your code, it always helps to first clear the bugs out of your biological systems and approach your work with a clear and well-fueled mind.

Wires and Lights

Over sixty years ago a man began a speech with “This just might do nobody any good.” and in a way he was right.

Not that pointing out the things Edward R Murrow pointed out in his speech, now famously known as the ‘Wires and Lights Speech’, did anyone harm. He pointed out a great many things about the then-new industry of television that needed addressing. He drew attention to several things that were wrong, that needed review, that would be better if done in a different way or that could be cause for consternation. He explained why he was concerned, and what direction he thought the television industry was taking, as opposed to what direction he felt it should take, and why that should be as well. Murrow was long dead by the time I was even born, let alone had heard of this speech or its importance, but it is still important today. (And it seems I’m not the only one who thinks so.)

I’ve been thinking about this speech a lot lately. Primarily because I’m looking for my first job in web development, I’m directing my career in the field, and I get to have my first shot at what that means. What goals do I want to achieve, other than of course the goal of paying my bills with a little extra for fun? I feel like I barely thought about it at all when I was first asked the question: I want to do environmental work, I want to work in ed-tech, I want to work in accessibility and make the internet safer and better and available to all. I was just old enough that I had some years of living in a world without internet before the World Wide Web came into being even in its first, very limited incarnation. So it seemed miraculous to me when we were able to reach across the world and learn new things, communicate with people we would have a hard time reaching before, or even knowing of their existence in more than an abstract fashion. Obviously Ireland or Russia or Brazil has universities and professors who teach at them, but with the World Wide Web a girl could find that university’s site and email those professors and ask, what do we know about ancient kings? This language? That traditional dress?

I still feel that way about the internet, even though it’s gotten quite a bit more dangerous in the years since. In many ways and along many axes (emotional, mental, even physical) the dangers on the internet have multiplied exponentially. But as we develop new technology and new software to pair with it the benefits of the internet have also grown. And along with both, the weight of our responsibility as those who are the architects of the modern web.

I’m still fumbling around the edges of what I think my responsibility is, as someone who can code. To make my web pages as accessible as possible, definitely, and I’m expanding on the knowledge of the code for that every day. Other aspects of accessibility, lean coding and designing cleanly but without unnecessary animation or components, I already have ingrained in me from the era of 28.8k modems. It can be difficult, I think, when one knows how to code and bend portions of the internet in the general direction of one’s will, to remember that not everyone has a fiber connection and a fast computer. Not everyone has a computer at home, or an internet connection. And if I’m going to code something that I want to reach even people with limited or no computer ability, if I can imagine someone might have to go to a library to use my website, I have to keep that in mind. And what else is my responsibility? To be careful with my language? To put nothing out there that doesn’t have some use? What defines ‘use’? Should the internet move towards being primarily functional and educational, and how much room do we reserve for frivolity? Who defines frivolity? Who decides what is worthy of a strong presence on the internet, and what can be left to bitrot?

I don’t have any of these answers. I know they are questions with increasing urgency, especially with the advance of blockchain technology and cryptocurrency. There are deep environmental and ethical concerns around this field, and arguments have been made that while blockchain technology and the so-called Web3 may have uses they have not yet proven that these uses cannot be better and more safely served with other, existing tech. And this is a debate that I feel we will have again and again, as innovations iterate and grow our idea of the web as it stands now into something new. It’s not done growing. It may have only reached its angry adolescence.

“This just might do nobody any good,” I mutter, typing these words into a blog entry. This is a debate we will have again and again, those of us who care and want to be intentional in our actions building the modern web. Many more of us will shrug and walk away, because we don’t care. We’re in this to move fast and break things, to develop, to find out what we can do next. And there’s something to be said for being unrestrained in one’s curiosity. But for me, personally, it must always be tempered by an effort to do no harm. I want to bring the wonderful feeling of having the boundaries of one’s world suddenly expanded beyond belief to everyone. And it’s up to them whether or not to use it; I just want everyone to have the opportunity, in safety.

React: Code Challenge Practice

It will come as a shock to absolutely no one that I struggle with live coding challenges. Many people struggle with doing work when they are being watched, and there are a number of scientific theories and descriptors as to why. It took me a couple of live coding challenges to realize what was going on but once I did the answer was mercifully simple: practice. Practice until I achieve a level of reflexive fluency.

With human languages, spoken languages such as Japanese or Italian, I would have a chapter in a textbook to study. I would have phrases and vocabulary to memorize and use in sentences, and I might find an environment where I could listen and repeat them in a conversational manner. I might even seek out a partner to practice with. Computer languages aren’t taught in the same established textbook format as spoken languages, but there is still a vocabulary of built-in methods one can learn, and a syntax, and a set of basic sentences beginning with a “Hello World!” function. So when I had trouble with my React code challenge, I set up my practice environment where I could repeat the basic React phrases, and I started repeating.

A class “ClickyButton” and its constructor method

One of the first things I had trouble with in the React live-code challenge was remembering that state exists. So, creating components that used and altered state was the first thing I needed to do. In this case, making a button that shows how many clicks I’ve made. Overall I wrote between 10 and 15 little React files that used and altered state, but ClickyButton was the first one.

An event handler function called handleClick including an if/then/else block.

After setting state, I had to make an event handler. This was more familiar from older attempts at learning and using JavaScript, but using an event handler to modify state was new, so I needed to practice it. Memorize it, as one might memorize a “Nice to meet you” or a “Where is the restaurant” in a basic dialogue exercise for a human language. For the first step, I created the incrementor and then used setState to update the state.

And then, to make it a little more complex and decorative, I added an if/then/else block. This was both to add a bit of complexity to the component and to remind myself of the format of an if/then/else block in JavaScript. I haven’t done as much JavaScript over the years as I have done CSS and HTML, and I took better to Ruby in bootcamp, so a little reminder couldn’t hurt.

A function using the State hooks

I didn’t learn about hooks in bootcamp, but I did learn about them in CodeAcademy, so I did some practice with those too. And it would help me practice thinking of React as using state. For this exercise I had a single useState hook to change the color of a div and several buttons that, when clicked, would call that setColor function. (I also, as you see, left myself comments to explain how it would work because I knew it would take me a few minutes when I went back and looked to remember how it all hangs together.)

A return block displaying a div, a p tag, and four buttons each calling setColor to a different color.

And then the second part of hook practice: using the setColor function. Each button changes the color in the div according to the divStyle assignment in the previous graphic, as explained above.

The constructor method for a react component called Oracle.

Another thing I definitely wanted to practice and make instinctive was props. Similar to state, it was a concept that hadn’t yet taken hold in the back of my mind, so I made a few components that used props. In this case, I would hard-code the props into the main app component because the point (at this time) wasn’t to learn how to pass around the props, but how to pass down the props and use them in the component.

I also wanted to practice binding methods to their specific instances. I prefer using arrow functions, but it’s always good to have a few methods in your tool-belt for doing different things; in this case I used the bind for the handleClick method.

For the handler method I used a switch/case statement, because I wanted to have multiple options depending on what the props were. I declared the variable for the result at the top, and then set it to different strings for each case. Because this was a bit complex involving some modification to the main app component, I included a console-log to track my progress.

This is not, by any means, a complete list of all the aspects of React I practiced. I mixed and matched all of these code fragments to create small, simple apps that changed text, changed colors, responded to clicks. As with practicing for dialogue challenges in the various human languages I’ve studied, it helps me to keep a space, a git repository, to practice the basic “phrases” of React and increase my fluency in the framework so that when my next code challenge appears, it comes instinctively and without more than an initial moment of freeze.

The Art of the Comment

At one point during my Flatiron Boot Camp journey I realized my code commenting habits were getting a little idiosyncratic, to put it diplomatically. I expressed some mild concern about this to a number of friends, since I do have a number of friends who are programmers or project managers. I received, for my concerns, a Wayback Machine copy of a set of github statistics on profanity in commits. Nice to see I’m not the only one leaving bleepy notes in my code! Variable hilarity of saying the f-word in your comments aside, it made me think about my code commenting and commit habits.

I’ve been programming for so long that many of my foundational habits were formed in the dark recesses of childhood from which memory is dubiously retrievable at best. I do know that my habit of giving each section of code an all-caps label describing what goes in these ten lines of code (or fifteen, or five, whatever constitutes a section) comes from the early days of designing HTML. There were fewer tags to differentiate the purpose of this or that section then, so comments describing the purpose of each section of script with an index at the top was helpful for Ctrl-F purposes. And I did write a lot of code that involved a header, a menu bar, a pile of text, a footer menu bar. Sometimes a disclaimer stating that I didn’t own these characters, please don’t sue me Chris Carter.

An example of my comments on a plain, static HTML document.

Getting deeper into boot camp meant learning new programming languages for the first time in years, beginning to functional program end. Although the underlying logic of the languages remained computer logic, some of the syntax and a few of the commands were very new. So in addition to my section comments I began to add instructional comments after every two to three lines of code, so when I went back over older labs I understood why this command was formatted this way, what this other command meant and what it referred to, what the expected output at this point in the code was, what return value I was getting and what return value I was looking for. It’s harder to remember to do this now that I feel more fluent in Ruby and JavaScript, but I try to keep in mind that five years in the future I might not have touched Ruby or JavaScript in all that time, and I might want to remember what’s going on here.

A basic block of code in my Research Repository project, with comments so that when I go back and look I remember what is going on.

Commenting code is not a skill I learned in Flatiron School. I think it should be. The internet and technology in general being what it is today, no one programmer can be expected to maintain a system or a program over the course of their lifetime and, when they retire, to train just one person to follow them. Everything is interconnected and everything builds off of someone else’s work. To be a polite, kind programmer we should all learn how to write clear, concise notes in our code so the devs following us can understand what we were doing and where we were going with this code. Maybe line-by-line and command-by-command is a bit much if you’re not actively learning that language, but where data is being taken from and what return values or type of return values you’re expecting should be a part of that commentary. Explain why these files are imported and exported, what data or functionality they’re providing, and if the file is large enough add in a note once you reach that point of intersection where the file was imported from again, to minimize scrolling up and down. 

In addition to the commenting I start every app with two markdown files: project notes and a dev log. The dev log is a day-by-working-day log of everything I’ve done, including sometimes notes on what version of a gem I installed or what packages I installed in what order, mainly to keep track of what I’ve done but also when necessary to indicate that some steps should be done in a specific order if I or anyone else wants to duplicate the app to a certain point.

An excerpt from the DevLog for my project Audrey Three.

The project notes file is mainly just a neat one-stop shop to keep my to-do list, my bug list, and my base project architecture. And since it started with writing apps for the Flatiron School boot camp, it includes sections for requirements (although now requirements might be more accurately ‘initial design goals’) and stretch goals. The to-do list includes brief notes on bugs I may find, notes about reframing that needs to happen, style details to clean up, and other small fixes to make. As I clear it out, I migrate the stretch goals to the to-do list one by one.

An excerpt from the Project Notes file for my project Audrey Three

I don’t know that having a dev log on every app would be helpful to everyone following in that programmer’s footsteps, but I find them useful. And as I said earlier, I like taking apart programs to find out how they fit together.

The project notes, on the other hand, should also be taught as a basic one- or two-reading insert in coding boot camps. I wish I had a set of instructions and a few samples to show me how to make a clear, useful Readme document! Writing is a skill often referred to as a “soft” skill, and equally often overlooked in career tracks and educational courses of all kinds, not just tech. However, communication is a vital skill in any workplace. That extends to writing an email that’s both polite and includes all relevant information, writing an instructional pamphlet for a device or piece of software, or writing commentary and commit messages in computer code. The profanity can be fun and reassuring to know you’re not the only one struggling with this particular piece of software, but it doesn’t help if you finish reading through the code and you’re still as confused as you were when you started.

Keep it concise, but make no assumptions as to what your reader knows. It may help to talk through your code as if you’re rubber-ducking it. State your intentions, but also state what your tested results are at each step, so a person following you can tell when the results they’re getting are indicative of broken code and narrow down the source. And don’t sweat the f-bombs, but do follow up every ‘what the ffffff’ with an explanation of what the problem is so, if nothing else, when you go back to debug it you’ll have a clear idea of what the problem is and you won’t be repeating discoveries you made already.

On Language

One of the odder, the more quintessentially me aspects of my life as a web developer, as a computer programmer in general, is that I find very little difference in learning a computer language and learning a human language. This is a difficult topic to describe, and sort of a difficult topic to live through because I haven’t found anyone else who looks at it quite the same way (if you’re out there give a shout!), but it goes to the heart of how I think about programming and learning new computer languages. I don’t find them intimidating by and large; they’re another pile of things for me to learn, but I understand how they work.

To me, computer languages and human languages work in fundamentally the same way. There are sets of specific parts arranged to convey meaning and intent, shaping and acting upon the context in which they exist. All human languages have roughly the same core parts, and computer languages also have a mutually intelligible kind of logic. Both types of language share vocabulary, the parts themselves, and syntax, the order in which you put the parts to finish off the meaning you want to convey. Some languages have less rigid syntax, some have more. Some languages have a smaller vocabulary and some bigger, but as a general statement once you understand the purposes of the parts you’re arranging, learning the syntax and vocabulary becomes much easier.

For, again, a very broad generalization made over literally thousands of languages both human and computer, if you want to accomplish something in a computer language you’ll use a binary structure. By inference, computer languages will have an if-then-else structure. If X is true, do Y. If X is false, do Z. It looks different in BASIC, in JavaScript, in Java, in Python, in Ruby, but the function of the structure is the same and when you understand how an if-then-else block works and can apply that logic to your program goals, it becomes easier to simply write lines of code. Human languages are more complex than if-then-else, but they still contain the same parts: nouns, verbs, adjectives. And they still have one of a very limited set of syntaxes, primarily Subject-Verb-Object (English, Russian, Mandarin) and Subject-Object-Verb (Japanese, Hindi); although more types than those exist those make up the overwhelming majority of language syntaxes.

For a more concrete example: the first computer language I learned was BASIC. BASIC’s if-then-else structure looks like this:

IF [statement]

THEN [action, usually involving a GOTO to reference other blocks of code]

{ELSE} and so on.

JavaScript’s if-then-else statements on the other hand look like:

if (statement) then {

block of code goes here } else {

block of code goes here };

Largely, the same idea and almost identical words. I don’t quite want to say “if you’ve seen one if-then-else statement you’ve seen ’em all” because obviously there’s questions of using brackets or curly braces or parentheses, and how you address the condition to be read true or false, and so on. But knowing that if-then logic exists is a fundamental concept of computer science that, if you’re down to taking it for granted, can help you conceptualize a program before you start writing a single line of code.

I could and have gone on for an hour on the subject of linguistic similarities, especially in otherwise seemingly disparate languages. My go-to is usually the one about Russian and Irish being similar in certain ways, and how I blame the Vikings. But for a less verbose example, I was raised speaking English and Spanish both. In high school, rather than continue on an advanced Spanish literature program, I opted to learn French instead. Because I already spoke another language, and a Latinate one at that (sharing the same Latin roots as Spanish), I was already comfortable with the concept of gendered nouns, a more verbose possessive noun system, even some of the vocabulary sharing root words with Spanish. Nobody is ever prepared for French counting systems, but you get the idea. My existing skill with languages built a strong foundation to learn more languages, and has continued to do so. Similarly, my existing foundation with computer code and programming languages helps me learn new languages.

As a final note, I want to say this is also useful for more than just being a giant nerd. Having recently completed a boot camp and frozen on numerous technical challenges and live coding exercises, I got even more nervous at the thought of doing one of these for a job interview. And then I thought back to my Japanese class where, invariably, unlike the class studies and the homework, I couldn’t just breeze through. I froze, forgetting all my vocabulary except the words for “for example” and “okay.” This always happened, unless I’d spent several hours rehearsing and rehearsing my phrases and grammar on my own or in conversation with other students, to the point where  it felt more instinctive than reaching back for a memory of a lesson. As exhausting as the prospect is, knowing this gives me confidence that I will eventually be able to pass technical challenges and live-coding exercises– if I do the prep work ahead of time. I can do this. I have ample proof that I can. I just have to put in the work.

Developer’s Log, Stardate I Can’t Believe I Spent That Much Time On That.

For the umpteenth time, one of the extra fun parts of having three intermittent decades of experience in computer programming, both web development related and not, is that you have a near-instinctive idea of how computer logic works. You start out the tech boot camp knowing that you need to make sure the conditions are true, that you haven’t left a loop running, that you aren’t sending the compiler or engine looking for a variable that doesn’t exist. That solves a lot of problems before they can come up. Unfortunately, it’s still not proof against the really–

— I don’t want to call them ‘stupid’ problems, because they’re not. I’ll call them Sub-Optimal Coding Conditions problems. I shouldn’t have tried this on five hours of broken sleep. —

the Sub-Optimal Coding Conditions problems. The SOCC problems. The ones you make when you’re tired, or you forgot to eat lunch (and breakfast), or you’ve been looking at the same code for two and a half hours without a break. I will continually bang this drum, and occasionally have it bounced off my head: you will write your best code when you’re hydrated, fed, and rested. And have recently thought about something that is not code.

Today I was working on a project for boot camp, never mind what it does for now but the setup to the joke is I had two objects, Item and Source. They were tied through the join table ItemSources. I had a form for new Items and a part of that form was you could pick a Source for that item from a list of checkboxes, or pick multiple Sources, or you could create a new Source by name. So let’s go through the code piece by piece, shall we? Can you figure out where the SOCC problem arose before I could? Because it took me a good hour or so.

c

Everything looks good, right? We’ve got validations, relationships. An Item belongs to a List, and then the aforementioned relationship to Sources. We also had the sources-attributes writer method, where we take the attributes fed in through the form and create a new Source object if we can’t find one by that name already. I went through a couple variations on this code trying to figure out where I’d gone wrong, but this is probably the cleanest version.

So here we’ve got the Item form, and again, everything looks good, right? Well, not entirely, it took me a couple rounds of coding in here to remember that a fields_for method exists, but I did get there eventually and thought, hah, that solves my problem! It did not. I went back and I dug out of an earlier lab the notes where I’d coded this in bare HTML rather than erb language, hoping that would help for some reason. It did not.

Was it in the controller? I didn’t see how it could be, the controller code was already pretty clean and I knew what each part did, I didn’t see a place that I’d missed a step, but I went over it anyway. Twice. Didn’t help. At this point I was getting irritated and nervous, and this is definitely when I started thinking I should have put a pause on the code till tomorrow, but no. Because sometimes I know better, and I push anyway.

I used the tried and true method of taking each step of the code as slowly as I could make it. I put in a byebug interrupt to pause it after the user, that is to say me, had fed data into the form to see what I was working with. I went over each step of the program in the Rails console carrying it through to the next step manually, line by line. By now I was in the Item model code, going through the source_attributes writer method and discovered that it wasn’t actually writing the new Source object. Okay. But why wasn’t it writing the new Source object?

This is the part where, if I’m being honest, it was only luck that made me think of the actual problem instead of going in circles for another hour and then shamefacedly taking myself to someone else to look over it. I didn’t type anything, I went over in my head the steps of creating a new Source object. What were the necessary and relevant items needed to create a Source object? Well, it needed a name, the rest of it could be added in edits, and I went over to the Source model to see what else was going on in here.

And there it was staring me in the face. validates :name, :location, presence: true. The only problem here is that the fields_for method only took in an argument for a name, no location. So the params fed into creating the new Source object would fail validation, the new object wouldn’t be created, and thus my problem. I spent an entire hour figuring out that it was nine freaking characters ruining my whole process and driving me up a wall and back down again. This is why we don’t code tired, friends. It doesn’t entirely eliminate these kinds of errors to make sure you’re working rested, fed, and watered, but it does help cut down on them.

Eventually I’ll have enough practice in Rails to put that validation back in, but for now taking it out was the easier solution to get the project finished and turned in. I did add it to the stretch goals in the project notes, as well as a brief reminder to myself in the dev log to check your validations if you’re wondering why an object won’t write. It’s useful, I find, to have a mental or physical list of first things to check and make sure you haven’t forgotten or miswritten. Double checking to make sure I included a save method where it should go has saved me a lot of grief, I tell you what. And now I can add checking my validations to the list.

Ceci n’est pas une gallerie

The joke here is that I am in fact a ginormous nerd across several axes, including the arts. For those not familiar, there is a famous work of art called “The Treachery of Images” that is a picture of a fairly generic smoking pipe, underneath which is written “ceci n’est pas une pipe.” From the French, this means “this is not a pipe.” Of course it isn’t, it’s a picture of a pipe, but that’s not how most people would think of it; most people would look at it and say well, yes, of course it’s a pipe, what do you mean it’s not a pipe? And when it’s explained, the logic is clear, but it’s still not the common first reaction unless you’ve had the whole Surrealism movement lecture in art history and, of course, you’re a giant nerd.

Anyway.

Ceci n’est pas une gallerie, because this is not a gallery of images. Could I have encoded a gallery  into which a person could upload images? Probably, but I was a bit crunched for time and also not entirely sure I wanted to do that, regardless. The goal of this project is not and has never been to display the images; there are numerous other services for that. Rather, the goal of this project was to serve as sort of a card catalog for images with fields for the style, the medium, the number of hours it took to make it, and the subject of the artwork. Eventually, with more practice, I plan to introduce a user model so that the gallery project can serve as a sort of skill list, and a user’s profile page can display hours spent working in each medium they prefer. Other stretch goals include a randomizer function where anyone can click a button and get a randomly generated set of prompts for medium, style, or subject. The whole project came out of a desire to code that randomizer, specifically, because I was practicing with my art supplies and wanted prompts. You see what I mean by scope shift?

The project requirements involved a Rails back-end and a React/Redux front-end, and in the beginning I made the full thing in Rails because I wanted to see if I could get the method to show a user’s time spent in a particular medium functioning. I didn’t have to build the full Rails front-end, I suppose, but I did anyway and in a separate repository, plus I decided I could use the practice in Rails. Having gotten the method working, I created the primary working repository and built up the Rails back-end, then started working on the React/Redux front end. That proved to be… more complicated.

Among the things I learned working on this project: did you know the FastJSONAPI serializer won’t play nicely with React/Redux? I do now! I used the ActiveModelSerializer instead, as advised by a project walkthrough kindly provided by the school. Being absolutely candid: I hate JavaScript and all its frameworks. I find it clunky and prone to bloat and have for years if not decades, but building out the project did help me become familiar with its workings, as I presume was the goal. 

In coding the various components and containers I became familiar with a stateless component as opposed to a component with state. Stateless components are more likely to be display components, action components, anything that doesn’t need to maintain a state set at construction (and rendering, eventually). Conversely, if it needs to maintain a state, such as any containers in which anything is rendered (not the display styling itself, but the container that feeds the data to the display) or any input form, obviously that becomes a Class component with a state in the constructor method. The constructor method need not be explicitly stated in the code, but the state does need to be there.

I also got considerable practice in passing through props, finding those props in the Redux dev tools or by logging them to the console, figuring out which components needed which props, and how to access them and when and why. One particular sticking point was the usage of ‘props’ vs ‘this.props’: props are passed to all components but if it is a functional component, there’s no need to use ‘this’, referring to that specific instance of a class component. It took me an appallingly long time to figure that out. I also got some practice in using mapStateToProps (feeding information from the state of store to the component at hand via props) and mapDispatchToProps (dispatching action functions to the store so they can be used to manipulate the data, to change the state).

And I made a lot of mistakes. The usage of the wrong serializer gem was probably the biggest one, but there were still a number of mistakes made, many of them involving naming functions. Many of those involved thinking I knew what I was doing, building out shells of many files, and then getting confused which one was which when I had endless number of ‘Gallery’ and ‘Galleries’ files floating around. Nothing smacks down careless arrogance like having to delete half your files because you’ve lost track of which was which and start over, with proper build-test-build more form.

And still, there’s been a considerable amount of scope creep and scope shift. I’m going to have to consider what I want out of this, although I still think a more informational file-cabinet type app is what I want, rather than a display app of the artwork itself. I left out the URL field of the at-this-point final product deliberately, not wanting to come up with a number of fake URLs for demonstration purposes and since the artwork described comes from my own artwork, most of which I haven’t uploaded anywhere. I could, in future versions, change the URL field to a location field and include either a URL or a description of whether the artwork is in a gallery, in a portfolio folder somewhere, on a parent’s fridge door. I’ve considered adding a field for Have/No Longer Have, because some of my artwork I’ve sent off to friends or family, and in the case of more professional artists they might have sold a piece. All things to consider for future versions, but for now this is a simple, working non-gallery app, and I’m pleased with how it’s made and how much I’ve learned by making it.

Go and Fetch

When I first started coding in HTML, HTML itself was a baby. This was about a year before Java, JavaScript, Ruby. All I could really do with it was play around, and my friends and I played around quite a bit in our lunch hour at school in the computer lab. As web 1.0 took shape, we coded up fan pages for the television shows and books we enjoyed, informational pages about obscure Welsh towns with really long names, individual pages for ourselves mostly, I think, for college applications. I remember coding and archive of a group story written via listserv, using small awkwardly rendered images to show who had written what and having a very neat but very ugly menu on one side of the page. It was a simpler time.

Now it’s a somewhat intimidating number of years later, and the web is very different. I’m writing this on the web, for example. I’m writing this in a word processor in a web browser via a dictation program that also interacts with the web browser. The dictation program existed back then, it was called Dragon Dictate, but the browser I’m writing on did not exist and the company that maintains it didn’t even exist for the first couple of years I was tooling around on the web. It’s an interesting world to look at having been poking around at the edges of it at the beginning, and now finally expanding my knowledge of it into things like asynchronous procedure and creating webpages that have a front-and a back-end.

Fetch (and Go)

AJAX stands for Asynchronous JavaScript And XML. It encompasses the asynchronous procedure that allows pages to load with the perception of simultaneity from the user point of view. Typically the first things that render are the styling elements involving HTML and CSS. The HTML might render the static elements either for general background information purposes or for simple styling, and as it states in the name the CSS is the styling of the page. After these initial simple elements that do not require any interaction or resolution to display, the fetch() protocol can begin.

The first part of the fetch() protocol is the request. A fetch request is a global method that acts on the window object and returns a promise object. A promise object exists in one of three states, much like a token in a Go game. Instead of alive, dead, or unsettled the promise object exists in a state of fulfilled, rejected, or pending. Once the promise object is successfully returned, rather than in the state of pending, the functions attached to it can then be performed. For the purposes of this explanation I also use the Go analogy because when a promise object is in either a fulfilled or a rejected state, it is said to be “settled”. It may also be termed “resolved”.

In the game of Go, a stone or group of stones is said to be alive if the player can connected to other friendly stones around the board. A stone or group of stones is said to be dead if it can be immediately captured. In the same way if the promise object is returned in a state of fulfilled, certain functions can subsequently be called and the intended course of the website can continue. If the promise object is returned in the state of rejected, other functions are called and usually the intended course of the website is halted so that the errors can be corrected. The functions are chained to the fetch request by a series of commands using .then. Because these functions are chained, each function can only be called and begin operation when the previous function has three settled to a state of alive, or fulfilled. Otherwise the function must be settled into a state of dead, or rejected, and errors must be fixed (or the board wiped clean) before the function chain can continue.

Like a chain of stones, each successive element is connected to the previous one. So in the typical example

A fetch made of Go.

the initial fetch() refers to a URL, which encompasses some data. The data reappears in the first .then call, assuming that first promise object is returned alive/fulfilled, and can be named pretty much anything although in this case and in standard format is usually called something like “response” or “res”. The function within the first .then call returns the response data converted into json data. The next .then call in the chain contains another function which manipulates the json data in some way, and if we needed to manipulate the returned result of that function (or set of functions), we could add another .then call, and so on. By usual practice, at the end of all of these comes the .catch call, which handles any dead/rejected promise objects. Since the rejected promise objects are now captured and can no longer be connected around the board, they must be resolved within the catch call. Having done that, as I understand it, other stones can then move around the board meeting that other functions can be called after the .catch call. But at the moment that’s a bit more advanced than my current experience has me comfortable with.

Project SEEDs

Every year since we moved to the house we currently live in I’ve had some sort of a garden. In the last couple of years, what with everything that’s happened, my garden has expanded quite a bit. So when it came to the JavaScript project it seemed like a good place to create a tracker for germination rates of every plant I tried to grow from seed.

I didn’t need a complex set of associations for this. I had Plant models, representing the general details of each type of plant I was trying to grow, and I had Pod models, representing the details of each seed or set of seeds that I planted. A pod doesn’t necessarily have to be an individual seed planted, a pod is any block of seeds that is planted in the same unit with the same conditions. I use this word because when I started growing things from seed I used little peat pods and the specially formed Styrofoam tray that came with them. Currently I use recycled plastic six packs in the same sort of tray, and since each pack is subject to the same conditions I call each pack a pod. Each of these models comes with several different attributes, as there are many conditions that can affect the growing of a plant from seed.

As far as the functions went, I knew that I would want a read function, a write function, and an update function. Read and write functions obviously to create new pods, but also an update function so I could update each pod with the germination rate. If I planted six Coyote Tomato seeds, and only four germinated, I would want to update the record with that number. It’s a simple application, but with only three A J A X calls I can keep track of the conditions in which I plant my seeds, how many of them germinate under each set of conditions, and I can see whether a plant germinates more readily on a seedling rack under artificial light or in natural sunlight.

Although the project was fairly straightforward given the material I had learned already, it was a good exercise in programming for functionality, for usefulness towards a users end goal, and frankly it was a good exercise in patience while debugging. I went through several versions of the associations before I settled on the most simple turning out to be the most practical. Once I had the associations down I had to figure out the attributes, which I knew were going to be numerous to begin with because there are obviously a lot of growing conditions that can be either created or considered. Handling a lot of attributes was all right on the back end, but on the front end it required a lot of consideration as to how I wanted to format it, where the information came from, how I needed to format it so that it could be read properly, etc. And of course, this led to the exercise in patience in debugging. Several times, various errors kicked up because I had forgotten to include an attribute, or had forgotten to format the association correctly, or had forgotten that a particular attribute was based on the association and therefore needed to be formatted differently than a plain old attribute. For example, each pod does not have a specific name in and of itself. It takes its name from the plant with which it is associated. And I have considered changing this, so that each pod can have its own name and be distinguished more readily from other pods, such as being able to call one pod San Marzano Tomato Outside, and then calling another pod San Marzano Tomato – Seedlings Rack. This might be something that I change in a future version, but at the moment each pod still takes its name from the plant.

I also had a small bit of trouble when it came to creating the edit function. The way in which I was taught through videos and walk-throughs to create the edit function did not work for either the version I was using, or for some reason I haven’t yet figured out. This came into play when creating the render function: I could not simply write the HTML code and return it, rather I had to create it via JavaScript and append it to the appropriate parent element. Then, because I was doing this in a different way than the walk-through, I had to pay special attention to each element in the HTML and connect it to each element of the edit function in the JavaScript. There were a lot of times when I had to go back, either undo the last several commands I had written or look over the last several commands line by line, see where I had gone wrong, and whether or not the changes I had made were the cause of the application not functioning as I wanted it to (or at all) or if the changes were working but I had failed to do something or if I had done something else incorrectly. It was all very complicated and, again, a good lesson in patience in debugging.

This is the first application project I have created in this boot camp that I feel is pretty much ready as intended for deployment right when I have finished it. I do still have stretch goals, and I would like to implement them, but the overall goal of being able to track germination rates under certain conditions for planting from seed is achieved. The application works. As a programmer I’m very pleased with what I’ve created, and as a gardener too.

The Research Repository

The Research Repository is a continuation or a sister project to Tropiary, the previous project I wrote for Flatiron school. I designed it for written projects, novels and short stories or non-fiction projects such as research papers, but in its current form it could be used for any project that requires research along several different subjects. It’s not quite as intuitive as I’d like it to be, but that may be a future problem, or a problem to address with writing clear directions on each new form page.

Functionally, each user has a profile constructed by their choice of login. Via Github (and the Omniauth project requirement), the user has a username based on their email address but does not have a display name. If you create an account directly you can create a username and a password, but you have no display name until you’re logged in and then can edit your profile. User creation requires a valid format email address, a username, and a password.

Once the user creates an account they have an option of creating a project or a list. A list can exist independently of a project, as it might be just a list of material the user wants to examine in further detail. The List object has many Projects and the Project object has many lists both through Topics. If the user chooses to create a project the options are simple: a project title, a project description (i.e. novel, research paper, essay), and a project summary. Having created a project, the user is then shunted to the project page showing the information and inviting the user to create a topic. This is where things become a bit complicated, and as my skills improve I intend to streamline it a bit. Each topic should be written in the context (and an example is given on the page) as it relates to the project. So, for example, a novel might have topics for the Protagonist’s hometown, the Protagonist’s childhood, the Antagonist’s background, and so on.

That done, the user may want to create a list for the topic. The ‘Create a List’ link takes the user to a page where they can give a list a name and select the topics they want to associate with that list. My test code has, for example, a list for 1930s Greenwich Village and a list for FTL (Faster Than Light) Travel. 1930s Greenwich Village is associated with only one project, through the topic of Main Setting. FTL Travel has two projects associated with it, through the topic Trade and Communication Structure for the project Triumvirate and through the topic Galactic Armada for the project Grumpy Old Mercs. And a list can always be edited to link it to a project via a topic if, for example, a user discovers that there’s a great deal of interest in research about snails and wants to write an informative essay or a listicle with pictures about it.

Once you have a list, you can now begin to add items! There are many fields to the item list but only two are required in validations: name and material. If we want to access the material we have to know what type it is, is it a book? a DVD? an audio file? a PDF? The rest are helpful, but not necessary. We can also, at the bottom of the page, add a source. The source can be a website, a library, a bookstore, a university press, anywhere you can source the material you’re looking for. Once the source exists you can then edit it to add a location or to change whether or not it’s free (such as a library or a web archive), and to add hours and a short description. I have not made the latter two options available for creating a source because the user might not immediately know these things and want to get the source entered in the database so as to remember to look it up later. However, once the source exists, a user can click on the ‘view all’  and be shown a list of sources with links to the individual pages, where the edit button exists. All sources are public, meaning you don’t have to be logged in to view them, and you can choose whether to view free sources or paywalled sources or all sources.

Most wish lists available on the web are bound to a single source: a single bookstore, a library, an audio archive. And even though Amazon is extensive, it isn’t the be-all and end-all of doing research. The main purpose behind this project is to create a single page where users can share sources or lists for various topics (the public/private toggle for lists is next on my coding goals, but was not necessary for the project) and exchange information about any subject they choose.