The Renegade Coder Code First. Ask Questions Later. Thu, 14 Nov 2019 20:23:13 -0500 en-US hourly 1 The Renegade Coder 32 32 127809749 Managing People Is Hard Mon, 11 Nov 2019 15:00:19 +0000

When it comes to teaching, sometimes you're stuck managing people as part of a team. Today, I'll share some of my frustrations.

The post Managing People Is Hard appeared first on The Renegade Coder.

To view this content, you must be a member of The Renegade Coder's Patreon at "For Glory!" or higher tier
Already a Patreon member? Refresh to access this post.

The post Managing People Is Hard appeared first on The Renegade Coder.

]]> 0 19612
The Controversy Behind The Walrus Operator in Python Fri, 08 Nov 2019 15:00:57 +0000

As of Python 3.8, there's a new operator in town: the walrus operator. Let's talk about some of the controversy around it.

The post The Controversy Behind The Walrus Operator in Python appeared first on The Renegade Coder.


If you haven’t heard, Python 3.8 features a rather controversial new operator called the walrus operator. In this article, I’ll share some of my first impressions as well as the views from all sides. Feel free to share some of your thoughts as well in the comments.

Table of Contents

Understanding the Walrus Operator

Recently, I was browsing, and I found a really cool article by Jason McDonald which covered a new feature in Python 3.8, the walrus operator. If you haven’t seen the operator, it looks like this: :=.

In this article, Jason states that the new operator “allows you to store and test a value in the same line.” In other words, we can compress this:

nums = [87, 71, 58]
max_range = max(nums) - min(nums)
if max_range > 30:
  # do something

Into this:

nums = [87, 71, 58]
if (max_range := max(nums) - min(nums)) > 30:
  # do something

In this example, we saved a line because we moved the assignment into the condition using the walrus operator. Specifically, the walrus operator performs assignment while also returning the stored value.

In this case, max_range will store 29, so we can use it later. For example, we might have a few additional conditions which leverage max_range:

nums = [87, 71, 58]
if (max_range := max(nums) - min(nums)) > 30:
  # do something
elif max_range < 20:
  # do something else

Of course, if you’re like me, you don’t really see the advantage. That’s why I decided to do some research.

First Impressions

When I first saw this syntax, I immediately thought “wow, this doesn’t seem like a syntax that meshes well with the Zen of Python.” In fact, after revisiting the Zen of Python, I think there are several bullet points this new syntax misses.

Beautiful Is Better Than Ugly

While beauty is in the eye of the beholder, you have to admit that an assignment statement in the middle of an expression is kind of ugly. In the example above, I had to add an extra set of parentheses to make the left expression more explicit. Unfortunately, extra parentheses reduce the beauty quite a bit.

Sparse Is Better than Dense

If the intent of the walrus operator is to compress two lines into one, then that directly contradicts “sparse is better than dense.” In the example I shared above, the first condition is fairly dense; there’s a lot to unpack. Wouldn’t it always make more sense to place the assignment on a separate line?

If you’re looking for a good example of a feature that compresses code, take a look at the list comprehension. Not only does it reduce nesting, but it also makes the process of generating a list much simpler. To be honest, I don’t get that vibe with the walrus operator. Assignment is already a pretty easy thing to do.

In the Face of Ambiguity, Refuse the Temptation to Guess.

In the example above, I introduced parentheses to make the condition more explicit. Had I left out the parentheses, it becomes a little more difficult to parse:

 if range := max(nums) - min(nums) > 30:

In this case, we have several operators on a single line, so it’s unclear which operators take precedence. As it turns out, the arithmetic comes first. After that, the resulting integer is compared to 30. Finally, the result of that comparison (False) is stored in range and returned. Would you have guessed that when looking at this line?

To make matters worse, the walrus operator makes assignment ambiguous. In short, the walrus operator looks like a statement, but it behaves like an expression with side effects. If you’re unsure why that might be an issue, check out my article on the difference between statements and expressions.

There Should Be One—and Preferably Only One—Obvious Way to Do It.

One of the interesting things about this operator is that it now introduces a completely new way to perform assignment. In other words, it directly violates the “there should be only way way to do it” rule.

That said, I’m a little bit on the fence with this one because the new operator is more explicit. In other words, it differentiates the intent behind := and =. In addition, it reduces potential bugs related to confusing = and == in conditions.

Likewise, as far as I can tell, you can’t just use the walrus operator in all the same places you would use assignment. In fact, they’re completely different operators. Unfortunately, nothing is really stopping you from doing something like this:

(x := 5)

I don’t know why you would ever do this, but it’s now very legal code. Luckily, PEP 572 prohibits it. Of course, that doesn’t stop code like this from appearing in the wild. In fact, the documentation lists a handful of ways the new syntax can be abused. That’s not a good sign!

If the Implementation Is Hard to Explain, It’s a Bad Idea

At this point, I sort of drew the line with this new feature. As I dug around to read others’ opinions on the subject, I found the following gold nugget:

This feels very Perl-y in the example given, in that it requires that you know what yet another operator means to read code that uses it. Since Python is supposed to be “executable pseudocode” (roughly), this kind of new operator might increase the amount of learning that a beginner has to do to read others’ code. I hope that this decision does not pave the way for more like it, because it would make Python code much less readable to someone who hasn’t studied the new operators yet.

snazz, 2019

That’s when I realized why I love Python so much. It’s just so damn easy to read. At this point, I really feel like the addition of this operator was a mistake.


As with anything, I hate to form an opinion without really digging into the topic, so I decided to hear from the folks who were excited about this feature. To my surprise, I found a lot of cool examples.

Loop Variable Updates Are Easy

By far, the strongest case for the new walrus operator is in while loops. Specifically, I liked the example by Dustin Ingram which leveraged the operator to remove duplicate lines of code. For example, we can convert this (source):

chunk =
while chunk:
  chunk =

Into this:

while chunk :=

By introducing the walrus operator, we remove a duplicate line of code. Now, every time the loop iterates, we automatically update chunk without having to initialize it or update it explicitly.

Seeing this example is enough for me to see the value in the walrus operator. In fact, I’m so impressed by this example that it made me wonder where else this could be used to improve existing code.

That said, I did dig around, and some folks still felt like this was a bad example. After all, shouldn’t file reading support an iterable? That way, we could use a for loop, and this wouldn’t be an issue at all. In other words, isn’t the walrus operator just covering up for bad library design? Perhaps.

List Comprehensions Get a New Tool

As an avid list comprehension enthusiast, I’ve found that the walrus operator can actually improve efficiency by allowing us to reuse calculations. For example, we might have a comprehension which looks like this:

[determinant(m) for m in matrices if determinant(m) > 0]

In this example, we build up a list of determinants from a list of matrices. Of course, we only want to include matrices whose determinants are greater than zero.

Unfortunately, the determinant calculation might be expensive. In addition, if we have a lot of matrices, calculating the determinant twice per matrix could be costly. Luckily, the walrus operator is here to help:

[d for m in matrices if (d := determinant(m)) > 0]

Now, we only calculate the determinant once for each matrix. How slick is that?


Beyond the two examples above, I’ve seen a few other examples including pattern matching, but I don’t really have an appreciation for it. Honestly, the other examples just seem kind of niche.

For instance, PEP 572 states that the walrus operator helps with saving expensive computations. Of course, the example they provide is with constructing a list:

[y := f(x), y**2, y**3]

Here, we have a list that looks like this:

[y, y**2, y**3]

In other words, what’s stopping us from declaring y on a separate line?

y = f(x)
[y, y**2, y**3]

In the list comprehension example above, I get it, but here I don’t. Perhaps there’s a more detailed example which explains why we’d need to embed an assignment statement in list creation. If you have one, feel free to share it in the comments.


Now that I’ve had a chance to look at the new walrus operator more or less objectively, I have to say that I think my first impressions still stand, but I’m willing to be persuaded otherwise.

After seeing a few solid examples, I was still really skeptical, so I decided to take a look at the rationale behind the operator in PEP 572. If you get a chance, take a look at that document because it’s enormous. Clearly, this decision was well thought out. My only fear is that the authors were persuaded to include the feature by shear sunk cost fallacy, but who knows.

If you read through PEP 572, you’ll see 79 code blocks across the entire page. To me, that’s just a ridiculous amount of examples. To make matters worse, a large portion of the examples show edge cases where the operator won’t work or wouldn’t be ideal rather than where it would provide an edge. For instance, take a look at some of these examples:

x = y = z = 0  # Equivalent: (z := (y := (x := 0)))
x = 1, 2  # Sets x to (1, 2)
(x := 1, 2)  # Sets x to 1
total += tax  # Equivalent: (total := total + tax)

That said, the authors did go as far as to provide some examples from their reworked standard library. Of course, these examples are much larger, so I won’t share them here. However, you’re welcome to take a peek.

Personally, I think the examples linked above illustrate the advantage of the walrus operator much better than some of the cases I shared in the counterpoint section. Specifically, any time the walrus operator removes duplicate or nested code, I’m happy with it. Otherwise, it seems to have very few obvious use cases.

My worry is that adding a new operator adds unnecessary complexity to the language, and I’m not convinced that the pros outweigh the cons. At any rate, I trust the decision of the team that put it together, and I’m excited to see how the community uses it!


With all that said, thanks again for showing your support and checking out my work. If you’re new here, I’d appreciate it if you hopped on my mailing list or even joined me on Patreon. If you do decide to lay down some cash, there’s a ton in it for you including having an article written about you, getting coupon codes to the store, and gaining access to premium articles.

Speaking of my store, you might find some value in my Python 3 Cheat Sheet which features two full pages of beginner-related language features like loops, conditionals, and comprehensions. If you head over there now, you can catch 10% off with the coupon code RENEGADE.

While you’re here, you might benefit from some additional Python resources courtesy of Amazon:

Alternatively, you’re welcome to stick around and check out some of my other Python articles:

As always, thanks for stopping by! See you back soon.

The post The Controversy Behind The Walrus Operator in Python appeared first on The Renegade Coder.

]]> 0 19514
How I Display Code in My Python Videos Mon, 04 Nov 2019 15:00:01 +0000

As a new YouTuber, I thought it would be fun to share a bit of behind the scenes for my patrons. Learn how I display code in my Python videos.

The post How I Display Code in My Python Videos appeared first on The Renegade Coder.

To view this content, you must be a member of The Renegade Coder's Patreon at "For Glory!" or higher tier
Already a Patreon member? Refresh to access this post.

The post How I Display Code in My Python Videos appeared first on The Renegade Coder.

]]> 0 19427
Reverse a String in Dart Fri, 01 Nov 2019 14:00:37 +0000

Today, we're featuring another article by someone in the Sample Programs community. Let's learn how to Reverse a String in Dart with Slashdoom.

The post Reverse a String in Dart appeared first on The Renegade Coder.


Welcome back to yet another edition of Reverse a String in Every Language—Jeremy here! This time around, we have a guest post from Slashdoom who has been adding quite a few Dart snippets to our Sample Programs repo. As a result, I figured I’d feature one of their articles on the blog.

How to Implement the Solution

Below is the completed Dart solution:

void main(List<String> args) {
    print( reverse(args[0]) );
String reverse(input) {
    return input.split('').reversed.join();

Much like C or Java, Dart uses the function name main as an entry point for the program. In this case, we don’t need main to return any data so the type void is used. Within the main function’s parameters, you’ll see List<String> args which will define args as a list of strings and fill this list with input from the command line in the form of arguments which in this case are simply strings separated by spaces.

For example:

dart reverse-string.dart "Hello World"

…would fill the args list as [Hello World].

dart reverse-string.dart "Hello" "World"

…would fill the args list as [Hello, World].

It should be noted that in this example program only the first argument passed to the program will be processed because we’re only passing the first string in the list to our reverse function’s input by adding the index position [0] to args in the print( reverse(args[0]) ); line. So, in the second example above, only Hello would get reversed.

So let’s look at that reverse function. We’ve defined the function with type String as it’ll return our reversed string to be printed to the console. It takes the parameter input as an undefined variable but we’re assuming here that it will be a string value.

The Dart:core library String class contains the split method which will split a string or list of strings into a list of substrings based on the pattern given to it. If the pattern is empty as in our reverse function, split will break up the input into single-code unit strings (individual characters). So ‘Hello’ with the empty pattern '' returns [H, e, l, l, o].

After we’ve broken the string into characters with split, we’ll use the reversed property from the Dart:core library’s List class. This property simply takes a list and returns it in reversed order as an Iterable object. So our example list, [H, e, l, l, o], becomes (o, l, l, e, H).

For the purposes of this sample program, there is very little difference between List and Iterable objects. Both are in fact iterable. At a high level, lists will have additional functionality such as indexed read/write access to its elements and sorting functions. Iterables on the other hand are typically created once then accessed as readonly data during an iteration operation like a for-loop.

Both Iterables and Lists have the join method which will take their elements and concatenate them into a string. We use join here on the reversed Iterable which is returned as the final string value of our reverse function. This value is then printed out to the console from print function within main.

How to Run Solution

To run the Dart string reversal program, download the dart file from GitHub, install the Dart SDK as described at, and run the following from the command line:

dart reverse-string.dart "Hello, World!"

Alternatively, you can copy the source code into DartPad, an online Dart interpreter. Just keep in mind that you won’t have access to the command line arguments input using this method so you’ll have to populate the args variable in the code instead. For example:

void main(List<String> args) {
    args = ['Hello World'];
    print( reverse(args[0]) );
String reverse(input) {
    return input.split('').reversed.join();

Sample Programs in Every Language

Jeremy here again! At this point, that’s all we have to share on how to reverse a string in Dart. If you want to learn more about Dart, head on over to the Sample Programs repo and check out the snippets. Alternatively, we have a page dedicated to the language.

In the meantime, we’d appreciate it if you gave the article a share. If you’d like articles like this to hit your inbox, hop on the mailing list. Finally, you can show your support for this website and all its associated projects by becoming a patron.

At any rate, that’s all we have today. If you’d like to be featured like this, head on over to the repo and share an article!

The post Reverse a String in Dart appeared first on The Renegade Coder.

]]> 0 19425
I Created a Portfolio Site Mon, 28 Oct 2019 14:00:01 +0000

As a part of a professional development course, I've created a portfolio site which features my experience and education.

The post I Created a Portfolio Site appeared first on The Renegade Coder.


This semester, I’m taking a professional development course in the Engineering Education department. As a part of that course, I was asked to put together a portfolio which I was pretty excited about. Naturally, I wanted to share that portfolio with you.

Table of Contents

Portfolio Requirements

Since I put together this portfolio for a class, there are obviously some requirements. For example, I have to have all of the following:

  1. About Me / Homepage
    • Who are you? (What is your background? Where are you from?)
  2. Education / Experience
    • Links to downloadable CV and Resume.
    • Link to downloadable cover letter. This can be either academic or industry focused per your targeted professional goals.
    • Skills and experience that you want to highlight.
    • LinkedIn.
    • Memberships in professional societies with links.
  3. Teaching
    • Link to Teaching Statement (downloadable).
    • Teaching experiences / viewpoints you want to highlight.
  4. Research
    • Link to Research Statement (downloadable).
    • Research experiences / viewpoints you want to highlight.
  5. Personal Highlights
    • Interests, hobbies, community engagement, other.

Of course, I don’t necessarily have all of these items in my portfolio. For example, I excluded links to the CV and Resume for privacy reasons. On each of these documents, I include my address which is not something I am comfortable publishing.

That said, I think my portfolio goes above and beyond these core requirements which should make up for the lack of links to certain documents.

Portfolio Tech Stack

Before I share my portfolio, I just wanted to take some time to share how it was built. Like many of my websites, I used WordPress. Of course, I used a different theme: the Total theme by HashThemes. Honestly, I only chose Total because I wanted something lightweight, and I only needed the most basic of features. After all, I have no plans to blog on my portfolio.

In addition, I used the same 1&1 Ionos hosting that I use for The Renegade Coder. In fact, I can have up to 5 websites on my current package, so I just tacked it on at no extra cost. Now, I have three websites on the same hosting package with room for two more!

Beyond that, there’s nothing really exciting about how this portfolio was put together. For this course, we were allowed to use tools like Wix which apparently make portfolio building easy. That said, I wanted my own domain, so I didn’t go down that route. In addition, I didn’t feel like learning any new tools.

Portfolio Reveal

At rate, let’s finally reveal the portfolio. Naturally, I chose a domain named after myself: Jeremy Grifski. In other words, you can learn all about me at

Also, you can find a link to the portfolio in the navigation bar at the top. Lately, I’ve been fiddling with that navigation bar, and I think I’m finally content with how it’s turned out.


At any rate, the portfolio features seven main pages:

  • Homepage
    • Features a picture of me, an about section, links to main pages, and student testimonials
  • Awards & Certifications
    • Lists awards and certifications by organization in reverse chronological order
  • Education
    • Lists education by university in reverse chronological order
  • Experience
    • Lists experience by company in reverse chronological order
  • Leadership & Service
    • Lists leadership and service opportunities by organization in reverse chronological order (with pictures)
  • Projects
    • Lists software projects by organization
  • Tools
    • List proficient software tools like Git and Python

In addition, you’ll find links to documents and other content in the footer. For instance, you can read my teaching and research statements.


If you then dig into each of these pages, you’ll find that the entire portfolio is written in third person. In other words, I describe a lot of my experiences from the perspective of an outsider. Honestly, I’m not sure that was the right way to go, but I like it.

In addition, you’ll find a ton of links throughout to various articles, videos, and projects I’ve worked on over the years. Hopefully, that’ll drive some traffic to my work, but who knows.

Also, I made sure to use bold text to highlight anything in the portfolio that I felt was important. For example, I highlighted university and employer names, so people could quickly see the breadth of my experience. Outside the bold, I explain the significance of that role or project.

Portfolio Feedback

Overall I’m quite pleased with how the portfolio turned out. Why not check it out and share your thoughts? I’ll be getting some feedback from my peers, but you’re welcome to help out as well.

In the meantime, I’m looking to grow my network of support. In particular, I’d love it if you ran over to Patreon and pledged your support. If not, no sweat! I have plenty of ways for you to get involved. For instance, you can check out my YouTube channel, follow me on Twitter, or hop on my mailing list.

If you’re looking to take control of your own professional development, check out some of these resources on Amazon:

With all that said, thanks for taking some time to check out my work! I appreciate it.

The post I Created a Portfolio Site appeared first on The Renegade Coder.

]]> 0 18445
When Did I Become a Mentor? Fri, 25 Oct 2019 14:00:30 +0000

As I continue to look for support in grad school, I find myself falling into the mentor role for my students. When did this happen?

The post When Did I Become a Mentor? appeared first on The Renegade Coder.


One thing I’ve noticed lately is that the balance between asking for advice and giving it has started tipping toward the latter. In other words, I’m at a point in my life where I’m starting to play the role of mentor more than mentee, and that carries a lot of responsibility. As a result, I thought I’d put together an article about my mentoring experience while asking the question: when did I become a mentor?

Table of Contents

The Case for Mentorship

If you’ve followed my blog at all, then you know that my life can be hectic and confusing. For instance, I recently failed my qualifying exam, and I constantly contemplate switching careers. In fact, I’ve already abandoned engineering, and I’m not really sure I’m where I want to be yet.

To make matters worse, I find that almost every process in life is deliberately opaque. For example:

  • Looking for a job
  • Applying to college
  • Taking an exam
  • Doing research
  • Paying taxes

Whatever it may be, everyday tasks seem to shrouded in mystery. If they weren’t, why are there literally thousands of companies profiting off of them? Think about it! I can name probably a dozen companies off the top of my head that profit off of deliberately complex processes:

  • Magoosh (GRE practice)
  • LinkedIn (Job networking)
  • Indeed (Job search)
  • US News (College rankings)
  • Intuit (Tax help)

In all this chaos, you’d think that someone would have come along and made some of these processes a bit more transparent—or at the very least made these processes easier. Unfortunately, that just isn’t the case.

Over time, I’ve realized that life is all about blindly navigating these complex processes. After all, no one helps you figure these things out. You’re just expected to learn the hard way, and that’s really a shame.

Personally, I find myself constantly learning things the hard way. For instance, I recently had to relearn how to study after failing multiple exams in my first semester. In addition, I’m also learning how to run a website without any help. That’s why I’ve decided to start seeking out some mentorship.

Becoming a Mentee

As you can imagine, I bring all this up because adults have no idea what we’re doing. We’re all just sort of stumbling around, bumping into things, and hoping to get where we want to go. Unfortunately, most of us aren’t getting there, and it sucks.

That’s why it’s nice to have support from someone (aka a mentor) who has been through what we’re going through. That way, we have someone who can help us avoid some of the common pitfalls.

Unfortunately, I haven’t been all that lucky over the past couple years. That’s why I decided to spend the last couple months building up my support network. For instance, I now have a handful of professors I can lean on for help. In addition, I’ve met a ton of peers that can help me moving forward.

For once, my future as a PhD student seems far less uncertain. Now, I have some definitive goals with a support network that can help me get there. Finally, I am getting some help, and it feels great.

Becoming a Mentor

Despite all this confusion in my own life, somehow I’ve also become a mentor for several people, and it feels weird. After all, I feel like I have a major case of impostor syndrome. How could anyone possibly look up to me? I have no idea what I’m doing.

That said, I still have a lot of students coming to me for support, so I’ve been trying to do my best to help them out. In fact, just this week, I’ve had 4 people ask me for help. Naturally, I want to take some time to share their stories.

Major Requirements

At The Ohio State University, students have to complete pre-major requirements before they can actually get into the major. Unfortunately, I currently teach the last class that students have to take to get into the Computer Science and Engineering major. As a result, I get a ton of students asking for help, so they don’t fail.

One of my students in particular is a transfer student, and they’re finding the class pretty tough. As a result, I’ve been spending a lot of time with them outside of class to provide some form of support.

Beyond assisting with assignments, I’ve also had to provide them with supplemental work to further cement some of the concepts. In addition, I’ve been trying really hard to prove to them that everything will be okay. Of course, I can’t guarantee that, but I’m trying my best to ensure it’s true.

If you had told me I would be doing something like this in the past, I wouldn’t have believed you. After all, who would be leaning on me for this kind of help? Yet, here we are.

Internship Resumes

Surprisingly, my students aren’t the only ones asking me for help. In fact, one of my graduate student peers recently asked me for support. Apparently, I’m one of the only ones in my research group with industry experience. As a result, I’m the best person to ask for help with scoring an internship.

Naturally, all they wanted was a sample resume they could use to score an interview. To help them in their job search, I passed off my most recent resume as well as my resume from when I was hunting internships. By the end of the week, they received an interview. How cool is that?

Now, I don’t think I played that much of a role in their success, but it felt good to be asked for help. That said, I’m not a resume expert! However, I do know one. One of my friends from back when I worked at GE, Lizzy, has long been helping folks build their resumes. In fact, she’s so good at it that she decided to start a side hustle doing it. If you’re interested in learning more about her services, check out Resume Revival.

Exam Performance and More

Later in the week, I bumped into a student in one of my labs that was looking for a little bit of help in the class. To be quite honest, they’re doing well, but they wanted to perform even better.

As a result, I tried to figure out exactly where they were performing poorly to see if I could provide some support. After some investigation, it turned out that they were making small mistakes that were accumulating over time. Apparently, the sometimes felt rushed which lowered the quality of their work. My advice was to work on their time management by including a bit more structure in their schedule. We’ll see how that plays out.

After discussing grades, they asked me how to get a job. Again, I didn’t feel all that qualified to answer, but I tried to help. For whatever reason, they felt like not having a resume would hinder their chances to score a job. Of course, I mentioned that they could easily put together a resume even without any formal experience. We just had to figure out what they could leverage.

One of my tips was to leverage their travel experience. After all, they’re an international student, so I feel like they’re significantly more ambitious than many of their peers. From there, I asked them several questions like “are you a part of any clubs?” and “do you have any personal projects?” In the end, I was hoping to hit something tangible that they could leverage on their resume.

As I continued to fire off questions, our conversation shifted from “I want a job” to “I don’t know what I want to do with my life” which is something I can definitely empathize with. In fact, I still don’t know what I want to do, so I tried to help them the best I could by probing further. While we never settled on what they might want to do, we definitely eliminated some possibilities, so I felt like I did a decent job. Hopefully, they feel the same way.

Life in a New Place

In that same lab, I bumped into another student who was looking for a bit of life advice. In particular, they wanted to know how they could motivate themselves to get work done. Ever since moving to Columbus, they had been tempted by everything going on around them. Over time, they started to develop a Fear of Missing Out (FOMO) which was causing them to abandon assignments. Ultimately, they ended up turning to me for help.

To be honest, I was quite stunned at this point. Being a workaholic, I can’t really identify with their situation, so I had to really think on my feet. First, I asked if they had any noise cancelling headphones. After all, I’d love a pair myself because I definitely struggle with staying focused.

When they mentioned that noise wasn’t really an issue, I recommended being more disciplined with their time. In other words, I figured that maybe they just needed to schedule in their work time. That way, they would force themselves to at least put in an hour an a day, so they could slowly work into a better habit.

By that point, I realized the root of the problem: they were living with others who were influencing their bad behavior. At that point, I mentioned perhaps setting boundaries with their friends and roommates. If people were really the issue, they would need to address them directly. Otherwise, they may never get work done again.

After that discussion, I started to really feel like an adult for once. Not only was I giving advice, but I was helping someone problem solve their issues in real time. Now, I’m not sure I helped all that much, but I think they appreciated me hearing them out.

Balancing Act

Since graduating from college, I couldn’t have felt more lost. As of today, I’m still not sure I’m where I want to be, and I’m having a lot of trouble finding people to support me along the way. That said, it feels good to be able to help someone else. Perhaps mentoring a few more people will help me find my way.

At any rate, thanks for letting me treat this space like a public diary. Hopefully, I can figure out my own life soon.

If you’d like to help me make this journey a bit easier, consider supporting The Renegade Coder over on Patreon. At the moment, I have 5 dedicated supporters, but you’re welcome to join the cause. At the very least, I’d love it if you hopped on the mailing list.

Otherwise, thanks for stopping by! See you soon.

The post When Did I Become a Mentor? appeared first on The Renegade Coder.

]]> 0 19257
What Is Web Scraping? Mon, 21 Oct 2019 14:00:18 +0000

Today, I'm bringing you yet another guest post. This one is all about web scraping thanks to Kite and Zac Clancy.

The post What Is Web Scraping? appeared first on The Renegade Coder.


Jeremy here! Once again, I decided to share this space with the kind people of Kite. This time, they’ve brought you an article by Zac Clancy on web scraping. Check it out!

If you are enjoying these guest posts, let me know! I’ll be happy to work with Kite and other sources to get more. For instance, here’s an article on Data Science by Kirit Thadaka.

Table of Contents

Introducing Web Scraping

Simply put, web scraping is one of the tools developers use to gather and analyze information from the Internet.

Some websites and platforms offer application programming interfaces (APIs) which we can use to access information in a structured way, but others might not. While APIs are certainly becoming the standard way of interacting with today’s popular platforms, we don’t always have this luxury when interacting with most of the websites on the internet.

Rather than reading data from standard API responses, we’ll need to find the data ourselves by reading the website’s pages and feeds.

Some Use Cases of Web Scraping

The World Wide Web was born in 1989 and web scraping and crawling entered the conversation not long after in 1993.

Before scraping, search engines were compiled lists of links collected by the website administrator, and arranged into a long list of links somewhere on their website. The first web scraper and crawler, the World Wide Web Wanderer, were created to follow all these indexes and links to try and determine how big the internet was.

It wasn’t long after this that developers started using crawlers and scrapers to create crawler-based search engines that didn’t require human assistance. These crawlers would simply follow links that would come across each page and save information about the page. Since the web is a collaborative effort, the crawler could easily and infinitely follow embedded links on websites to other platforms, and the process would continue forever.

Nowadays, web scraping has its place in nearly every industry. In newsrooms, web scrapers are used to pull in information and trends from thousands of different internet platforms in real time.

Spending a little too much on Amazon this month? Websites exist that will let you know, and, in most cases, will do so by using web scraping to access that specific information on your behalf.

Machine learning and artificial intelligence companies are scraping billions of social media posts to better learn how we communicate online.

So How Does It Work?

The process a developer builds for web scraping looks a lot like the process a user takes with a browser:

A URL is given to the program.

  1. The program downloads the response from the URL.
  2. The program processes the downloaded file depending on data required.
  3. The program starts over at with a new URL
  4. The nitty gritty comes in steps 3 and, in which data is processed and the

program determines how to continue (or if it should at all). For Google’s crawlers, step 3 likely includes collecting all URL links on the page so that the web scraper has a list of places to begin checking next. This is recursiveby design and allows Google to efficiently follow paths and discover new content.

There are many heavily used, well built libraries for reading and working with the downloaded HTML response. In the Ruby ecosystem Nokogiri is the standard for parsing HTML. For Python, BeautifulSoup has been the standard for 15 years. These libraries provide simple ways for us to interact with the HTML from our own programs.

These code libraries will accept the page source as text, and a parser for handling the content of the text. They’ll return helper functions and attributes which we can use to navigate through our HTML structure in predictable ways and find the values we’re looking to extract.

Scraping projects involve a good amount of time spent analyzing a web site’s HTML for classes or identifiers, which we can use to find information on the page. Using the HTML below we can begin to imagine a strategy to extract product information from the table below using the HTML elements with the classes products and product.

<table class="products">
  <tr class="product">...</tr>
  <tr class="product">...</tr>

In the wild, HTML isn’t always as pretty and predictable. Part of the web scraping process is learning about your data and where it lives on the pages as you go along. Some websites go to great lengths to prevent web scraping, some aren’t built with scraping in mind, and others just have complicated user interfaces which our crawlers will need to navigate through.


While not an enforced standard, it’s been common since the early days of web scraping to check for the existence and contents of a robots.txt file on each site before scraping its content. This file can be used to define inclusion and exclusion rules that web scrapers and crawlers should follow while crawling the site. You can check out Facebook’s robots.txt file for a robust example: this file is always located at /robots.txt so that scrapers and crawlers can always look for it in the same spot. Additionally, GitHub’s robots.txt, and Twitter’s are good examples.

An example robots.txt file prohibits web scraping and crawling would look like the below:

User-agent: *
Disallow: /

The User-agent: * section is for all web scrapers and crawlers. In Facebook’s, we see that they set User-agent to be more explicit and have sections for Googlebot, Applebot, and others.

The Disallow: / line informs web scrapers and crawlers who observe the robots.txt file that they aren’t permitted to visit any pages on this site. Conversely, if this line read Allow: /, web scrapers and crawlers would be allowed to visit any page on the website.

The robots.txt file can also be a good place to learn information about the website’s architecture and structure. Reading where our scraping tools are allowed to go – and not allowed to go – can help inform us on sections of the website we perhaps didn’t know existed, or may not have thought to look at.

If you’re running a website or platform it’s important to know that this file isn’t always respected by every web crawler and scraper. Larger properties like Google, Facebook, and Twitter respect these guidelines with their crawlers and information scrapers, but since robots.txt is considered a best practice rather than an enforceable standard, you may see different results from different parties. It’s also important not to disclose private information which you wouldn’t want to become public knowledge, like an admin panel on /admin or something like that.

A Simple Example

To illustrate this, we’ll use Python plus the BeautifulSoup and Requests libraries.

import requests
from bs4 import BeautifulSoup

page = requests.get('')
soup = BeautifulSoup(page.text, 'html.parser')

We’ll go through this line-by-line:

page = requests.get('')

This uses the requests library to make a request to and return the response.

soup = BeautifulSoup(page.text, 'html.parser')

The requests library assigns the text of our response to an attribute called text which we use to give BeautifulSoup our HTML content. We also tell BeautifulSoup to use Python 3’s built-in HTML parser html.parser.

Now that BeautifulSoup has parsed our HTML text into an object that we can interact with, we can begin to see how information may be extracted.

paragraphs = soup.find_all('p')

Using find_all we can tell BeautifulSoup to only return HTML paragraphs <p> from the document.

If we were looking for a div with a specific ID (#content) in the HTML we could do that in a few different ways:

element ='#content')
# or
element = soup.find_all('div', id='content')
# or
element = soup.find(id='content')

In the Google scenario from above, we can imagine that they have a function that does something similar to grab all the links off of the page for further processing:

links = soup.find_all('a', href=True)

The above snippet will return all of the <a> elements from the HTML which are acting as links to other pages or websites. Most large-scale web scraping implementations will use a function like this to capture local links on the page, outbound links off the page, and then determine some priority for the links’ further processing.

Working with HTML

The most difficult aspect of web scraping is analyzing and learning the underlying HTML of the sites you’ll be scraping. If an HTML element has a consistent ID or set of classes, then we should be able to work with it fairly easily, we can just select it using our HTML parsing library (Nokogiri, BeautifulSoup, etc). If the element on the page doesn’t have consistent classes or identifiers, we’ll need to access it using a different selector.

Imagine our HTML page contains the following table which we’d like to extract product information from:

Shirt Athletic $19.99
Jacket Outdoor $124.99

BeautifulSoup allows us to parse tables and other complex elements fairly simply. Let’s look at how we’d read the table’s rows in Python:

# Find all the HTML tables on the page
tables = soup.find_all('table')

# Loop through all of the tables
for table in tables:
	# Access the table's body
	table_body = table.find('tbody')
	# Grab the rows from the table body
	rows = table_body.find_all('tr')

	# Loop through the rows
	for row in rows:
    	    # Extract each HTML column from the row
    	    columns = row.find_all('td')

    	    # Loop through the columns
    	    for column in columns:
        	  # Print the column value

The above code snippet would print Shirt, followed by Athletic, and then $19.99 before continuing on to the next table row. While simple, this example illustrates one of the many strategies a developer might take for retrieving data from different HTML elements on a page.

Data Processing

Researching and inspecting the websites you’ll be scraping for data is a crucial component to each project. We’ll generally have a model that we’re trying to fill with data for each page. If we were scraping restaurant websites we’d probably want to make sure we’re collecting the name, address, and the hours of operation at least, with other fields being added as we’re able to find the information. You’ll begin to notice that some websites are much easier to scrape for data than others – some are even defensive against it!

Once you’ve got your data in hand there are a number of different options for handling, presenting, and accessing that data. In many cases you’ll probably want to handle the data yourself, but there’s a slew of services offered for many use cases by various platforms and companies.

  • Search indexing: Looking to store the text contents of websites and easily search? Algolia and Elasticsearch are good for that.
  • Text analysis: Want to extract people, places, money and other entities from the text? Maybe spaCy or Google’s Natural Language API are for you.
  • Maps and location data: If you’ve collected some addresses or landmarks, you can use OpenStreetMap or MapBox to bring that location data to life.
  • Push notifications: If you want to get a text message when your web crawler finds a specific result, check out Twilio or Pusher.

Next steps

In this post, we learned about the basics of web scraping and looked at some simplistic crawling examples which helped demonstrate how we can interact with HTML pages from our own code. Ruby’s Nokogiri, Python’s BeautifulSoup, and JavaScript’s Nightmare are powerful tools to begin learning web scraping with. These libraries are relatively simple to start with, but offer powerful interfaces to begin to extend in more advanced use cases.

Moving forward from this post, try to create a simple web scraper of your own! You could potentially write a simple script that reads a tweet from a URL and prints the tweet text into your terminal. With some practice, you’ll be analyzing HTML on all the websites you visit, learning its structure, and understanding how you’d navigate its elements with a web scraper.

The post What Is Web Scraping? appeared first on The Renegade Coder.

]]> 0 19165
Say Hello to Anders Rydholm Fri, 18 Oct 2019 14:00:28 +0000

One of my longtime supporters, Anders Rydholm, has finally joined the subscriber spotlight! Check out what they had to say about their coding journey.

The post Say Hello to Anders Rydholm appeared first on The Renegade Coder.


Welcome back to another one of these subscriber spotlight articles. This time, I’m featuring Anders Rydholm!

If you’d like the opportunity to have an article like this written about you, head on over to Patreon and join one of my subscription tiers. After that, you can fill out the survey, and I’ll get straight to writing one of these articles.

Table of Contents


Today, we’ll get the chance to meet Anders Rydholm, one of my longtime supporters. In fact, Anders is currently one of my only supporters that I don’t know personally. Based on some of their answers to this survey, there might be a few opportunities to grow this relationship a little bit.

At any rate, as a bit of a refresher, each of my Patreon subscribers has the opportunity to fill out a survey which I use to generate these articles. Of course, the survey looks a little different depending on how you fill it out. In this case, Anders self-identified as someone learning to code everyday.

In the following sections, we’ll take a look at the responses.


To kick off the survey, I like to ask a few introductory questions which you can find below in bold.

Tell us a little bit about yourself.

Hello, my name is Anders Rydholm. I run TypeTrail Media, a digital marketing agency from Mankato, MN. For a while I’ve been interested in learning about technology relating to web design, marketing, and advertising. It would also be fair to say that I’m obsessed with SEO. I would describe myself as belonging to a generation that, “had to live without the internet for a little bit,” and, “was the first to be able to learn to code for free,” by using open educational resources online. In 2012 I made a new years resolution to learn to code. There was no formal curriculum at my University so I googled resources and started with Khan Academy and Codecademy, and later used many other resources including Free Code Camp, Treehouse, Udemy, and

How did you find The Renegade Coder?

I found The Renegade Coder on Twitter while working through the #100DaysOfCode challenge. Jeremy is constantly keeping up to date on the latest technologies, which is something I relate to and admire. There is a lot more to running an agency than just coding, and The Renegade Coder touches on a lot of topics I find interesting. I’d say it took me well over a decade to adequately learn the skills to be an expert in my field, and I still continue to learn and perfect my skills every day while I search for better solutions to different projects with help from resources on The Renegade Coder.

Why did you decide to become a paid subscriber?

I’m a creator myself, and I know how much time, particularly unpaid time, goes into putting together a website like The Renegade Coder, and the value extremely outweighs the cost of support, so I became a Patreon subscriber and I highly recommend subscribing to The Renegade Coder for the exclusive content and other awesome benefits, but I mostly subscribe to support the time and energy put into creating The Renegade Coder. I would really like it to be sustainable and I’d also like to be a part of the growing community.

New Coder Questions

In the next phase of the survey, Anders said they were learning to code. That said, I wouldn’t say they’re a new coder. Instead, they seem to have a positive relationship with the code (i.e. learning something new every day). As a result, I decided to ask them a few questions about their learning process.

How has The Renegade Coder helped you learn to code?

I think data science will play a giant role in the IT industry over the next thirty years, so I’ve been particularly interested in learning Python. I’ve personally found the videos and downloads on The Renegade Coder useful, maybe one day The Renegade Coder will solve the riddle of why Richard Hendricks codes in Python and prefers tabs over spaces! I am absolutely a fan of everything The Renegade Coder is doing as far as teaching others to learn to code.

What is one tip you’d give to anyone interested in learning to code?

It’s a long never ending road, so just start immediately. The old saying that, “the best time to start was five years ago, the second best time to start is today,” is true. Also don’t get discouraged if you are confused, because you need to immerse yourself for a long time where it seems like nothing makes sense and everything is just way over your head before a things will start to fall in place. Once you get the hang of it, a lot of the separate parts of a framework will start coming together and it’s an awesome experience when you reach a moment where things just click and you suddenly have a new valuable skill set to add to your expertise.

Everyday Coder Questions

In the following section of the survey, I asked Anders to tell me whether or not they wrote code every day. As it turns out, they do! Naturally, I then asked about some of their coding projects and how my website helps them out. Then, I asked them to share some advice for folks who might want to do what they’re doing.

What sort of coding projects do you work on?

I do a lot of web development projects, so I work on custom WooCommerce websites, and I also create a lot of marketing emails. I’m also a big fan of writing programming scripts and solving data problems. Using programming to make sense of data for analytics purposes, and making the complicated operations in that process as easy and as automated as possible.

How has The Renegade Coder changed the way you approach those projects?

I’ve progressed more from front-end developer to full-stack developer. The days of creating complete desktop, tablet, and mobile comps in PhotoShop are gone. Web developers are now owning more of the design process that designers used to own anyway. Getting websites and progressive web apps into the browser as soon as possible and baking responsiveness into that process is now more often one person’s job, and that presents a highly rewarding challenge for anyone that can acquire the full stack developer skill set.

What advice do you have for people looking to get involved in the same type of projects?

I’m cautious about this advice being evergreen or how it will age over time, but for web developers I would recommend learning WordPress, that could change and you have to adapt. For software engineers, pick a technology stack suited to the projects you will be working on. There are a lot of flavor of the month programming languages and frameworks, get a foundation in a few languages so you can see the similarities and shared concepts between between them. Then master the plain (aka vanilla) languages most suited to you and specialize in the frameworks where you can complete rewarding projects. There are different languages for web development and programming, so I think getting a sense of the technology stack or learning path that you are going to pursue from the beginning is a really smart idea.

What is your go-to programming language and why?

My go to language is JavaScript. I’d say it’s a safe bet that React JS will play a big role for the foreseeable future since the advent of Project Gutenberg for WordPress. You also see a lot of large applications and e-commerce platforms opting entirely for a JavaScript stack and using React JS on the backend. I think C# is also great choice for software engineers for similar reasons, because of it’s power, versatility, and popularity in a number of applications.

Any additional tips you want to share?

It’s really two tips, but it’s kind of one tip because actually they are connected. Number one is start immediately and number two is don’t give up. I believe a strong desire to learn along with persistent determination is the main contributing factor to success, it’s rare to hear a programmer say, “I was very comfortable when I started out and I never wanted to give up, after a few months I knew this was something I could do.” The story I commonly hear is, “I was met with a lot of obstacles, and I kept trying until I found the solution, over time it got easier and it was definitely worth it, enduring the pain upfront to learn the skills to get to where I am today.”

Closing Remarks

Finally, I asked Anders to share their thoughts on The Renegade Coder. Then, I gave them the floor to share whatever they wanted.

What is your favorite article on The Renegade Coder and why?

5 Great Strategies For Learning to Code is my favorite. When I first started out, I got stuck a lot, all I wanted was to find someone who could point me in the right direction, and there were a lot of pitfalls to avoid. Each generation now has incredible access to resources compared to the previous one, but a nudge in the right direction is still the number one thing I wish was more available for someone new who is interested in learning to code.

What is one thing you would like to see more of on The Renegade Coder?

I’m a big fan of The Renegade Coder YouTube channel, I really enjoy watching the videos. I would like to see that series continue to get made. I hope to one day have my own video channel with guests, it would be great to do a hangout and get to ask The Renegade Coder a few questions some time.

Do you have any shameless plugs for the community?

You can find me at My username is @typetrail on all social media networks. Thanks everyone for reading now please go subscribe to The Renegade Coder on Patreon. Happy Coding!

Thanks for Subscribing!

And with that, I just have to say thanks! I really appreciate all your support, Anders. Perhaps, we could hop on a call to kick off your YouTube series soon! Also, it looks like I need to start watching Silicon Valley.

For everyone else, if you’d like to be featured in one of these articles, you’re welcome to head over to Patreon to join the community. I’m happy to write as many of these articles as I get patrons, so feel free to make me very, very busy.

Also, if there are any questions you’d like to see on this survey, feel free to share them in the comments. I’m sure Anders (as well as Robert) wouldn’t mind following up on them!

The post Say Hello to Anders Rydholm appeared first on The Renegade Coder.

]]> 0 19117
My WordPress Website Is Really, Really Slow Mon, 14 Oct 2019 14:00:30 +0000

Is your WordPress website really slow? Same! Luckily, I found a few ways to fix it. It just took a little bit of research.

The post My WordPress Website Is Really, Really Slow appeared first on The Renegade Coder.


As someone who has been blogging with WordPress for a little while now, I was starting to wonder if I was ever going to be able to speed up my site. After all, I didn’t personally think it was all that slow, but various page testing tools told me otherwise. Naturally, I felt like it had to be affecting my page rankings, so I decided to accept the fact that my WordPress website is slow and take matters into my own hands.

After improving my site speed, I was able to come up with three tips. First, get an idea of where your site is at right now using some performance auditing tool. Then, take a good look at your theme and plugins in isolation. If all else fails, disable advertisements—they are slow!

If you’re interested in the entire process I went through including performance screenshots, check out the remainder of this article. Otherwise, jump straight to the Lessons Learned section for some quick tips.

Table of Contents


Right now, I’m nearing my 3rd year of blogging (started in December of 2016), and I’m starting to wonder what I can do to improve my results. While I’m not exactly upset with my progress, I do think it could be better.

As I try to dig into what I’ve been doing wrong, there’s a lot I can point to:

  • Not focusing enough on a niche
  • Writing content that no one cares about
  • Not writing evergreen content
  • Not focusing on speed

And, there it is! One of my biggest hurdles with this site is speed. After all, if you couldn’t tell, my site is really, really slow.

How Slow is Slow?

Depending on where you open my website, you might not notice any issues. For instance, the only issues I really noticed were related to asynchronous resources not loading right away. In other words, it’s not like you couldn’t read my articles; you’d just be waiting for those resources for a few seconds.

That said, if you were to run any performance testing software on my site. you would have gotten some very different results. Naturally, I want to share some of those results with you. As it turns out, my WordPress website is slow.


Throughout this article, I will refer to a lot of different performance metrics, so I want to be sure that I lay out exactly how testing was performed first.

To test my website, I used a combination of Incognito Mode and Google’s auditing tool, Lighthouse. That way, my performance tests were all handled through Chrome DevTools without any interference from plugins.

When using Lighthouse, there are several settings you can choose. Personally, I stuck with all the default settings:

  • Device: Desktop
  • Audits
    • Performance (check)
    • Progressive Web App (check)
    • Best practices (check)
    • Accessibility (check)
    • SEO (check)
  • Throttling: Simulated Slow 4G, 4x CPU Slowdown
  • Clear Storage (check)

Then, after execution, you’ll get a breakdown of all the audits above with scores between 0 and 100. From there, the tool attempts to provide additional feedback like diagnostics and opportunities, so you can find ways to improve your site.

In addition, I used the Health Check & Troubleshooting plugin to isolate problem plugins. For more information, check out my article on WordPress cleanup.

Overall, the testing you’ll see throughout the remainder of this article took me about two days. Hopefully, it won’t take you nearly as long.

Homepage Speed

If you run Google Chrome’s auditing tools on my homepage, you’ll get the results below. In particular, the SEO is fine, but the performance is atrocious.

Initial WordPress Homepage Speed Test
Performance test on my current homepage.

When you dig into why the performance is so bad, you’ll find the following:

  • First Contentful Paint: 3.0 s
  • Speed Index: 14.1 s
  • Time to Interactive: 17.7 s
  • First Meaningful Paint: 4.8 s
  • First CPU Idle: 16.4 s
  • Maximum Potential First Input Delay: 3.090 ms

Then, apparently, I’m able to fix these times by addressing the following issues:

  • Properly Size Images: 2.8 s
  • Eliminate Render-blocking Resources: 0.99 s
  • Preconnect to Required Origins: 0.53 s

Of course, this is the homepage, so does performance really matter? After all, I don’t think people are finding me through my homepage. Instead, they’re hitting specific articles, so I figured we should test one of those.

Article Performance

When I ran the performance experiment on one of my latest articles, I found that the performance was just as terrible.

Initial WordPress Article Speed Test
Performance test on my The Lisp Program Language article.

In particular, the tool mentioned the following:

  • First Contentful Paint: 2.9 s
  • Speed Index: 9.4 s
  • Time to Interactive: 18.3 s
  • First Meaningful Paint: 6.6 s
  • First CPU Idle: 17.4 s
  • Max Potential First Input Delay: 1,950 ms

In addition, the tool mentions I can do the following to fix up the site:

  • Eliminate Render-blocking Resources: 0.77 s
  • Preconnect to Required Origins: 0.5 s
  • Removed Unused CSS: 0.42 s
  • Defer Offscreen Images: 0.15 s

Clearly, after peaking at a couple of pages, there are some systematic issues on my site.

Systematic Issues

If my site is slow across the board, I need to start looking at systematic errors. To start, I decided to ask the following questions:

  • Is my theme at fault?
  • Are my plugins at fault?
  • Is my host at fault?

To me, these are the three main sources of systematic error. As a result, I decided to dig into the first two.


Before I ran any tests, I decided to perform a control test. To do that, I used the health check plugin to run my site in troubleshoot mode. Then, I ran the same performance test from above.

Control WordPress Homepage Performance Test
Performance test on homepage—Twenty Nineteen Theme and no plugins.

In this state, my website is running the default theme without any plugins. As a result, we get excellent performance. In addition, we also improve a few other metrics as well:

  • First Contentful Paint: 1.8 s
  • Speed Index: 4.2 s
  • Time to Interactive: 2.3 s
  • First Meaningful Paint: 2.0 s
  • First CPU Idle: 2.1 s
  • Maximum Potential First Input Delay: 110 ms

In terms of opportunities, the tool mentions:

  • Improve Server Response Times (TTFB): 1.14 s
  • Removed Unused CSS: 0.91 s
  • Eliminate Render-blocking Resources: 0.22 s
  • Minify CSS: 0.17 s

Clearly, we’ll never be perfect, but I do think this gives us a nice best-case scenario. Regardless, I decided to run this again on our test page:

Control WordPress Article Performance Test
Same idea! Just on the Lisp post.

Interestingly, it seems that mid-80s are about as good as we’re going to get in terms of performance. At any rate, here are the diagnostics:

  • First Contentful Paint: 2.0 s
  • Speed Index: 4.6 s
  • Time to Interactive: 4.1 s
  • First Meaningful Paint: 2.0 s
  • First CPU Idle: 2.7 s
  • Maximum Potential First Input Delay: 300 ms

Then, in terms of opportunities, we have the following:

  • Defer Offscreen Images: 2.17 s
  • Serve Images in Next-gen Formats: 1.65 s
  • Reduce Server Response Times (TTFB): 1.0 s
  • Remove Unused CSS: 0.45 s
  • Eliminate Render-blocking Resources: 0.27 s

In other words, there’s surprising still a lot I can do in terms of performance even with everything turned off. That’s good to know!


At this point, I decided to reactivate my theme to see what sort of effect it has on my website performance:

Base WordPress Homepage Performance with Theme
In this execution, all I had loaded was the theme—no plugins.

Clearly, the theme took its toll. In particular, I dropped about 20 points in performance just from activating it, so this is my knew ceiling—assuming I keep the theme. Of course, let’s take a look at the diagnostics:

  • First Contentful Paint: 2.3 s
  • Speed Index: 5.1 s
  • Time to Interactive: 4.8 s
  • First Meaningful Paint: 3.6 s
  • First CPU Idle: 4.2 s
  • Maximum Potential First Input Delay: 200 ms

Then, in terms of opportunities, it looks like most of our issues are image related (so perhaps that’s on me):

  • Serve Images in Next-gen Formats: 7.05 s
  • Efficiently Encode Images: 3.6 s
  • Eliminate Render-Blocking Resources: 1.16 s
  • Remove Unused CSS: 0.6 s
  • Defer Offscreen Images: 0.15 s

Of course, I’m more interested in seeing the results on an actual article, so I launched up that Lisp article once again:

Base WordPress Article Performance with Theme
Again, theme and no plugins—this time on an article.

Interestingly enough, we actually get a speed improvement. Of course, I believe this is related to the lack of image issues. See for yourself:

  • First Contentful Paint: 2.4 s
  • Speed Index: 4.0 s
  • Time to Interactive: 3.9 s
  • First Meaningful Paint: 3.9 s
  • First CPU Idle: 3.9 s
  • Maximum Potential First Input Delay: 40 ms

Oddly enough, I actually felt like this page loaded noticeably quicker than normal, so that’s a bonus. At any rate, here were the tips:

  • Eliminate Render-Blocking Resources: 1.23 s
  • Remove Unused CSS: 0.9 s
  • Reduce Server Response Times (TTFB): 0.55 s
  • Serve Images in Next-gen Formats: 0.45 s

Overall, I think this page gives a better idea of where I might be making some mistakes on my website. Sure, this theme has some bloat, but I think the plugins seem to be the bigger issue here.


At this point, it’s probably a good idea to start looking at which plugins are making the most impact. Of course, I won’t bore you with the details, so I’ve distilled my testing down to the following table:

TestPerformanceFirst Contentful Paint (s)Speed Index (s)Time to Interactive (s)First Meaningful Paint (s)First CPU Idle (s)Max Potential First Input Delay (ms)
Ad Inserter752.
Akismet Anti-Spam902.
Akismet Privacy Policies902.
Brave Payments Verification892.
Breadcrumb NavXT902.
Broken Link Checker902.
Easy Table of Contents812.
Featured Image in RSS for Mailchimp902.
List Categories892.
List Category Posts822.
Media File Renamer892.
No Plugins912.
OnePress Plus872.
Organize Series902.
Patreon WordPress892.
Remove Admin Toolbar902.
Share Buttons by AddThis742.
W3 Total Cache962.
Wordfence Security832.
WP Author Slug892.
WP Last Modified Info892.
Yoast SEO892.

As it turns out, there are really only a handful of plugins that were seriously impacting my site’s performance. By far, the most detrimental plugin was Jetpack. Just activating it caused my website performance to drop by nearly 40 points. Naturally, I decided to tackle that first.

Addressing the Problem

After looking at all this data, I realized that there were a few quick ways to make some fixes. First, find out how to limit Jetpack’s effects. Then, start trimming some of the plugin fat.

Disabling Jetpack Modules

Primarily, I looked at Jetpack and how I can limit its impact on my site. After turning off a few features, I was able to increase my homepage performance metric by nearly 20 points:

New homepage performance with several Jetpack features disabled.

Of course, who cares about the homepage? How about an article?

New article performance with several Jetpack features disabled.

Apparently, the performance is slightly better. Although, I’d argue that it’s negligible.

Removing Slow Plugins

As a result, I decided to do a bit of housecleaning. For instance, I removed the sharing buttons:

Article performance after removing the AddThis Sharing Buttons plugin.

At that point, I decided to remove my Ad Inserter plugin which gave me a noticeable improvement in performance:

Article performance after removing the Ad Insert plugin.

Taking Another Swipe at Jetpack

Then, I decided to remove even more features from Jetpack including Infinite Scroll (which I wasn’t using) and Comment Likes (which are unnecessary):

Article performance without Jetpack’s Infinite Scroll and Comment Likes features.

Again, there was only a slight boost in performance, but I’ll take it! At that point, I removed the JSON API as well as Site Stats (sadly) from Jetpack:

Article performance without Jetpack’s JSON API and Site Stats features.

Clearly, we’re seeing some improvement, so I decided to push forward.

Removing Even More Plugins

Next, I removed the List Categories plugin which didn’t really have much of an impact, but Gutenberg has the feature built in:

Article performance without List Categories plugin.

Again, we see a very minor improvement, but all these changes are trending in the right direction. After that, I removed the Health Check plugin that we used to collect our data:

Article performance without Health Check plugin.

Clearly, the removal of that plugin had little to no effect, but it felt good as a minimalist. After that, I decided to remove the List Category Posts plugin which I really was only using in three places. As a result, I was able to convert those areas to static text while happily removing the shortcodes as well as the plugin:

Article performance without List Category Posts plugin.

Again, we’re not seeing an obvious improvement in performance, but I think the performance is quite a bit more stable.

Optimizing Database and Images

At this point, I decided to run the WP-Optimize plugin to clean up the database a bit. For context, this plugin removed 649 post revisions, 637 transient options, 23 posts from trash, 46 unused comment meta data by Akismet:

Article performance after database optimization.

Clearly, this plugin didn’t add much value. That said, the plugin also offers an image compression service, which I decided to take advantage of:

Live execution of image compression using WP-Optimize.

Unfortunately, this process takes forever—over two hours for me! And, it doesn’t look like it did too much. In total, I only saved about 35 MB of data, and the compression ratio was less than 15%. That said, I felt like I might as well try it and see if it improves my website performance:

Article performance after image compression using WP-Optimize.

Again, we’re not really seeing much of an improvement anymore.

Giving Up on Advertisements

Then, I had a sudden realization: I have Jetpack ads (WordAds) and Google Adsense turned on. After disabling those, I was able to boost my site speed by a mile:

Article performance after removing advertisements.

Now, that’s awesome! These were the kind of metrics I was getting with a completely stripped down site, so I know I can’t really get any better without changing the theme or tweaking the cache.

And with that, I decided to stop! No amount of ad revenue from those two networks was going to make the performance hit worth it.

Lessons Learned

After taking a couple days to really address my website’s performance, I learned a few things about how to tune up a WordPress website.

First, I bet your WordPress website is slow. When you work with a website often, it becomes cached. As a result, it can run quickly for you. However, your users aren’t always that fortunate. In other words, their experience could be much worse, and you might not even know it. That’s why it’s important to pay attention to the following lessons.

Second, it’s a good idea to run a control audit on a page in incognito mode. If done properly, you’ll be able to see just how slow your site is without having to deal with the effects of browser plugins. In addition, this gives you a performance floor. You can only improve from there!

Third, take a good look at your plugins. Do you really need all of them? Honestly, I’ve added and removed a lot of plugins on my site over the years, but I’ve never tried to actually isolate their performance impact. Once I did, I realized that only a couple of my plugins were really causing me trouble.

Finally, consider removing ads from your site. As someone who has been blogging for nearly 3 years, I was tired of not getting compensated for my work. Of course, no amount of ad revenue is worth the performance hit they incur. Unless you’re getting enough traffic to jump on a premium ad network, I wouldn’t even bother with it. Stick to affiliate marketing or creating info products.

With these three rules in mind, I was able to dramatically improve my website performance. Sure, it’s not perfect, but I think it’ll pay dividends moving forward.

Future Plans

With my website back up to speed, my focus now is probably going to be on YouTube. That way, I can generate revenue using advertisements without any negative impacts on my site. In addition, I plan to build up a store again—something I failed at awhile back.

If you found this article helpful, let me know in the comments! Then, head on over to Patreon and pick a tier that’s right for you. Otherwise, hop on the mailing list, so we can stay in touch. In the meantime, check out some of these related articles:

While you’re here, check out some these awesome products on Amazon:

And with that, I thank you for taking time out of your day to check this site out. I appreciate it. Take care!

The post My WordPress Website Is Really, Really Slow appeared first on The Renegade Coder.

]]> 0 18754
AT&T Is a Disaster Fri, 11 Oct 2019 14:00:07 +0000

As if things couldn't get worse, AT&T is continually screwing me. In this episode, AT&T decided not to even show up as scheduled.

The post AT&T Is a Disaster appeared first on The Renegade Coder.


Awhile back, I wrote a trilogy complaining about AT&T, and I figured that my frustrations with them had met some sort of equilibrium. In other words, it really couldn’t get worse, could it?

Table of Contents

AT&T Refresher

In case you haven’t had the chance to read the following articles, I figured I’d recap my experience with AT&T:

First, I picked up AT&T when I moved to Atlanta in the summer of 2017. At the time, I was pretty happy with the internet because it was cheap and better than I anything I had before.

Eventually, however, I was forced to move for school. At that point, I ended up in Columbus at an apartment complex which only offered AT&T. For me, that was fine since I already had AT&T. As a result, I just had to bring the modem with me.

Unfortunately, that’s where the fun ended. First, I was forced to drop my plan to a lower tier for the same price. Then, I was fined for not returning my modem even though I was using it.

When I decided to reach out to some of their competitors, I found out that AT&T had a monopoly on my complex through a contract. In other words, every single unit had to have AT&T—literally no competition.

Of course, I eventually did get a better internet tier, but I still was pretty irritated with AT&T. Unfortunately, they didn’t really do anything to help out.

Latest Fiasco

A couple months ago, I was kicking off my second year of my PhD program by attending a pretty large event on campus called Buck-i-Frenzy. At the time, I was wandering around the event trying to pick up free swag like hockey tickets and pop sockets.

AT&T Employee Behavior

As I was rounding the last bend, I noticed that AT&T had a booth. For whatever reason, I was feeling a little frisky, so I decided to go to their booth to start some shit.

While I waited in line, I realized that their booth was the only one on campus that wasn’t just giving stuff away. In order to get a chance to spin their stupid prize wheel, you had to open an account with them. That’s a bit ridiculous.

Apparently, a lot of students were annoyed after waiting in line only to be confronted by a salesman. As a result, a lot of students were pretty candid with phrases like “can I just spin the wheel?” and “I live in the dorms.”

Of course, this irritated the AT&T employees, so one of them came up with a “genius” idea: you can only spin the wheel if you open an account or scream “Go Blue!”. Naturally, no one took them up on that offer, so they lost most of their potential customers.

My Turn

By the time I got to the front of the line, I was also pretty candid with my opening line: “do you know if fiber is ever going to come to my area?” Naturally, they couldn’t answer that question without looking up my account. At that point, they told me all the same information I already knew:

  • I have the 50MB package with a 1TB data limit
  • All units in my complex have either the 25MB package or the 50MB package
  • No fiber in the plans

However, they also told me a few things that I didn’t know:

  • My modem wasn’t good enough for the speed I was getting
  • Data limits start to throttle bandwidth at 70% usage
  • There’s a TV bundle for $10 extra which removes data limits (and I could get my modem replaced)

Obviously, I caved to the last statement and agreed to get the new package. After all, I upload data all the time. It would be nice not to have to worry about data limits.

At that point, they set me up with an appointment on September 6th (about two weeks from the time I met with them) from 9 – 11 AM. All I had to do was wait.

AT&T Visit?

About two weeks later, I got up earlier than usual in anticipation of a call from AT&T. After all, their technicians are supposed to call before they show up. Since I was the first stop of the day, I figured they would actually show up on time.

By 9:30 AM, I was starting to grow a little worried, so I called the employee I had spoken to previously. Obviously, they didn’t pick up because why would anyone at AT&T do their damn job?

After leaving a calm voicemail, I was hoping to hear back. At the time of writing, it’s been a week, and I haven’t heard anything. Not only did the technician never call or show up, but the person I called didn’t even call back.

Now, I’m sitting here wondering if I should even bother trying again. After all, they already wasted a half day. Do I let them waste more of my time, or do I stick it out with their trash service until I can move?

How Are They So Bad At Their Job?

You would think that a company that is as massive as AT&T would have their shit together, but they don’t. In fact, I think their business model relies heavily on screwing over their customers. That way, they can offer them some “solution” that costs even more money.

If I had literally any other choice over AT&T, I would take it in a heartbeat. Hell, I’d take Spectrum at this point, but I can’t even do that. At this point, it’s almost worth moving just to get some kind of internet service that isn’t complete garbage.

At any rate, thanks for taking some time to enjoy this rant. Hopefully by next year, I’ll be living somewhere else with respectable internet service. Until then, expect me to blast AT&T on twitter on a regular basis—just like John Oliver:

If you enjoyed this rant piece, check literally any of my other rant pieces. They’re likely far angrier than this one:

As always, thanks for sticking around, and don’t forget to hop on the mailing list or become a patron!

The post AT&T Is a Disaster appeared first on The Renegade Coder.

]]> 0 18657