Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • Be Nice to Future You

    Be Nice to Future You

    Sometimes the brunt of my education of developers is a constant reminder to be nice to the future them. Future you, or Drunk You if you’re Otto, loves you most when you take the time to prepare things for them. A little bit go foresight and planning will make life so much better for future you, and I’m going to break down six tips to make you love yourself in the future.

    Document, Document, Document

    Yes. Document everything. Did you make an API for your system? Document it somewhere everyone can get to. For my LezWatch TV project, I painstakingly documented out all of that, plus how the git repositories worked, how they deploy code, and how to get access. This is for something that two people work on. But by documenting it, we all know what to do! The better my documentation, the less likely I get a panicked message from my cohorts in crime.

    Make Good Commit Messages

    I’m terrible at this when it’s for personal use (the number of commits that are ‘I am stupid’ cannot be counted), but at work I’m pathological about a good subject and a descriptive summary. I want someone down the road to know what the patch does, but also why I did it.

    icons: Add new icon set

    Add 17 new icons from LIBRARY. This adds support for iconography with job descriptions, as well as better defaults for taxonomies and categories.

    It’s not complicated, but it’s helpful when someone wonders “When did we add those new icons?”

    Inline Document Weird Stuff

    One of my coworkers is great at this. Ben litters his code commits with them, and I’m sure some people find them annoying but I see them as helpful and amusing. Sometimes he puts in “I hate that we do this, but I needed to pass X.” That tells me two things: First, this code could be better. But second, I know what he’s trying to do and generally why. He’s given context to the situation, and future us will hopefully be able to make this better.

    Make Note of To-Do Items

    Another great habit is to put in notes, as inline comments sure, but also in the documentation. I’ve been using Trello in addition to inline comments (usually things like “To Do: Add in a check for foobar”) to make sure that my future plan is known. You want to make sure future you knows where you were going, and those to-dos are your sticky notes.

    Follow Existing Project Standards

    Okay. I hate this one. But. If your project has a standard, keep using it. The other day I ran into a problem where a new version feature wasn’t behaving the same way as the old one, but only in very specific situations. I walked backwards through the code until I determined a parameter didn’t exist on the new version. I had two options. One was to edit the code to check “If this new version, also…” and the other was to add the parameter to the 500 or so impacted items and then fix my code so it was always fixed going forward.

    The project had been using the parameter method for years, so that was my solution. It followed the standards.

    If You Have A Plan, Use It

    This sounds weird, doesn’t it? It came up when I was reviewing a plugin and noticed that some code looked very ‘generic’ while still being specific. I thought that it had to be a library the company had made for themselves, and asked if that was the case. I explained, if it was an original library they planned to reuse, they should use an if-exists check.

    What Are Your Tips?

    What tips do you have to make life better for future you?

  • Query Strings vs Static Resources

    Query Strings vs Static Resources

    If you ever do a page speed check on your site, you may have seen the notice to “Remove query strings from static resources.”

    What Are They And Why Do I Care?

    At their most basic, a query string is any URL that has a ? in it. For example, if you go to a url of https://example.com/?lang=en then that last bit is the query string. It’s job is to tell the browser to pass on specific information to the website. It’s essentially a variable that will be read by the website or the browser.

    A static resource is a file used by a website that doesn’t change much (if at all). These are usually images but also CSS (style sheets) and javascript files. These resources can be stored on web servers, proxy/CDN servers (like Cloudflare or MaxCDN), or even a web browser, which makes your sites run faster.

    However. The explanation is that browsers don’t cache anything with a query string. Which means, yes, if your static resources have one, they won’t get cached.

    Or will they? (It’s complicated.)

    Why Do My Resources Have Query Strings?

    If query strings break caching, why would anyone have them? Because we don’t always put version numbers in our paths for common files. For example, in WordPress if you call jQuery (a common javascript library), you’re calling a path like https://example.com/wp-includes/js/jquery/jquery.js and that has no version number. But WordPress has certainly updated that a number of times.

    In order to make sure that jQuery gets properly cached when you upgrade, WordPress adds a query variable like this: https://example.com/wp-includes/js/jquery/jquery.js?ver=1.12.4

    This is important because otherwise when you upgraded WordPress, you’d see a page formatted weirdly and misbehaving, all because the wrong (cached) jQuery was loaded.

    Should I Remove The Query Vars?

    Maybe.

    Yes, allowing your resources to be cached will make your site faster, and it will get you a higher score in those page speed checks. At the same time the speed benefit is pretty low compared to the dangers of those files not being properly updated. Features on your site will, literally, cease to function.

    So you’ll need to decide for yourself which is more important.

  • Is This A Good Idea?

    Is This A Good Idea?

    I’ve joked about this a few times, that I should go into business telling people if their web idea is a good one or not. The prices would be simple.

    • $25 – A quick yes or no.
    • $100 – I’ll tell you if it’s dangerous or possibly illegal.
    • $500 – Details of everything.

    While I doubt anyone would ever actually pay for that, let me tell you some things I think are bad ideas for the web, and why.

    Obvious Bad Ideas

    Excluding the whole “Facebook but for pets!” and “Uber but for Pizza!” ideas, and dismissing every single ‘disruptive’ concept out there (seriously, no they’re not), some ideas are really easy to point at and say ‘this is a bad idea.’

    If you’re thinking about making something new for WordPress, before you start coding, please use google. Because the first kind of bad idea is the idea that’s been done before, ad nasueum. For example, sliders, snowfalls, BMI calculations (actually ANY sort of calculators including loans), ‘simple’ contact forms, and Google Analytics.

    These are bad ideas because they are overdone.

    If it’s been done more than 10 times, and you’re not introducing something totally new (this includes the fellow who made a ‘login logo slider’ – no, it wasn’t new), then file it away as a good experiment. Write the code, but don’t publish it.

    Illegal/Dangerous Ideas

    Depending on how often you hear me rant, you may or may not be surprised to find out how often people write code that’s illegal.

    Now hold on. Before a single one of you says “But the GPL!” let me remind you. The GPL doesn’t make things magically legal just because it’s open source. You can use GPL code to break laws (like, say, make a child porn website), and while that’s fine for the GPL, it’s still illegal.

    On a less creepy but still illegal note, the Yahoo! finance APIs aren’t actually legal for you to use in your code. Yes, I am well aware of the number of people who make packages for it. I’ve actually spoken to Yahoo about this and the way they explained it was this. Their Finance API is for your personal use. You’re not meant to use it to retrieve data for apps (and yes, plugins are apps) or any third-party usage (again, plugins). Also they do make it pretty clear with this comment:

    By accessing the Yahoo! site, you agree not to redistribute the information found therein.

    A lot of public APIs have these restrictions, including Airbnb and even some Google APIs (finance again). And using them without checking the terms of use and verifying they’re allowed to be used in your situation puts you at risk for breaking the law and that is dangerous because, in the case of a plugin, it’s not just you who pays the price.

    Ignorant Code

    Really the magic of everything, the answer to all ‘is this a good idea’ questions can be found in this. Did you bother to do the research first? And no, I don’t mean did you do market research (though that’s a good idea too).

    Did you check if the idea existed already? Did you check if the tools you want to use permit that kind of use? Did you read the terms of use of any service? Did you listen to your gut or not?

    Think first. Look before you leap. And above all, please don’t make yet another snowflake tool. No one actually likes them.

  • Loading Common Libraries Smartly

    Loading Common Libraries Smartly

    When you’re writing code, there’s a desire to not reinvent the wheel. This is a good desire. If someone else has made the code you need, using it is a better use of your time. But there’s a right way and a wrong way to include those common libraries, especially in WordPress themes and plugins.

    PHP Is Dumb

    Okay, PHP isn’t dumb, but it’s a very top-down/left-right kind of language. The whole reason we tell people to name functions and classes uniquely in WordPress plugins and themes is that if two people name a function the same thing, PHP gets dumb and errors, telling you it can’t define the same function twice.

    This means that commonly used PHP libraries should also be uniquely named. To their credit, most do. But still, what happens if two WordPress plugins or themes include the same library? That same error comes back about not defining the same function twice!

    What this means is that when using a common library, it’s important that you enqueue it safely and smartly.

    Check If The Library Exists

    The magic is that you need to detect if the code is already included and not re-include it. PHP gives you two straightforward ways to do this: class_exists and function_exists.

    It’s much easier for me when the code is wrapped nicely in a class. Assuming you have a library file that includes the class but doesn’t call it, you can check like this:

    <?php
    if ( !class_exists( 'MyLibraryClass' ) ) {
        include( 'path/to/library.php' );
        $mylibraryclass = new MyLibraryClass();
    }
    

    If it does include the class (with a new MyLibraryClass() in the library) then you can leave that bit out.

    When you have a library that perhaps predates classes, you’ll want to pick the primary function and call it like this:

    <?php
    if ( !function_exists( 'my_library_function' ) ) {
        include( 'path/to/library.php' );
    }
    

    What About The Weird Stuff?

    There are two things I left out. What about namespaces and javascript libraries?

    First of all, it’s impossible to check for the existence of a namespace. You see, a namespace doesn’t really exist. What does exists are the structures within the namespace. That means if you wanted to check for the class ClassName in the namespace of MyName you have to do this:

    class_exists( '\MyName\ClassName') );
    

    Second, if you’re looking for javascript libraries, and you’re using WordPress, you don’t have to. Just enqueue it.

    Schnieder from One Day at a Time (2017) going 'Mind blown'

    The WordPress function wp_enqueue_script() registers the script but does not overwrite and enqueues it.

    Now there is a trick to all this. If you use the enqueue command properly, then this always works. By this I mean if you do it this way, it’ll work:

    wp_enqueue_script ( 'chartjs', 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.bundle.min.js' );
    

    But… A lot of people do this:

    wp_enqueue_script ( 'my-plugin-chartjs', 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.bundle.min.js' );
    

    And that means WordPress will load both chartjs and my-plugin-chartjs which sucks.

    Also you don’t need to append -js (or -css) to your enqueues, as WordPress will do that for you.

  • You Don’t Know Paths

    You Don’t Know Paths

    A common issue with plugins is where people insist they must call wp-load.php directly so that they can call WordPress functions and data when WordPress isn’t loaded. When I push back on that code, the common rationale is that there’s an external service that needs to ping a reliable URL to run code.

    You Don’t Know Where WordPress Is

    When you hardcode in paths, or assume that everyone has WordPress in the root of their domain, you cause anyone using ‘Giving WordPress it’s own directory’ (a very common setup) to break. In addition, WordPress allows users to change the name of the wp-content folder, so any plugin that tries to guess where it is would break on any site that choses to do so.

    This cuts both ways. First your clever script that tries to go to example.com/wp-content/plugins/your-plugin/yourfile.php is going to fail if someone moves that folder. Second your clever file that looks for wp-load.php by going up a couple folders will also fail.

    You can’t know where WordPress is. The only way to know all that would be to do things from within WordPress.

    Never Call Files Directly

    The only files you should ever call directly in your code is your code’s files or if you’re checking for the existence of another plugin or theme. This is the only time it’s smart to be hardcoding in paths of other code directly into your code.

    if ( is_plugin_active( 'plugin-directory/plugin-file.php' ) ) { } 
    

    Since most people call these files to have access to WordPress ‘without loading WordPress,’ the actual correct fix is to tie processing functions (the ones that need but don’t have access to core functions) into an action hook, such as “init” or “admin_init”.

    Code you add to WordPress should be inside WordPress, only accessible to people who are logged in and authorized, if it needs that kind of access. Plugin’s pages should be called via the dashboard like all the other settings panels, and in that way, they’ll always have access to WordPress functions.

    What’s The Right Answer?

    Okay. There’s one case where it makes sense that you might possibly need to call a URL directly. If you’re hooking WordPress up to a service and you want to have a good URL to call, then yes, you would be well served by having one of the following:

    • example.com/?myplugin=runstuff
    • example.com/myplugin/

    Don’t those look nice? There are two main ways to get there.

    External Rules

    An external rule is basically you adding an redirect rule for a URL to point to a file. You could do this in .htaccess or nginx.conf but if you do it in WordPress, it looks like this:

    add_action( 'init', 'myplugin_external_rules' );
    function myplugin_external_rules() {
        global $wp_rewrite;
        $plugin_url = plugins_url( 'yourfile.php', __FILE__ );
        $plugin_url = substr( $plugin_url, strlen( home_url() ) + 1 );
        $wp_rewrite->add_external_rule( 'myplugin$', $plugin_url );
    }
    

    Now the obvious issue here is that you’re still calling a php file directly, which means you don’t get any access to WordPress functions. Boo. Thankfully there’s another answer.

    Internal Rules

    While more complicated and weird, this is a better solution.

    First you need to actually make the rule:

    add_action( 'init', 'myplugin_internal_rules' );
    function myplugin_internal_rules() {
        add_rewrite_rule( 'myplugin', 'index.php?myplugin=runstuff', 'top' );
    }
    

    This means that those two example URLs I pitched before are the same thing.

    Next you need to tell WordPress not to stomp all over the query variables:

    add_filter( 'query_vars', 'myplugin_query_vars' );
    function myplugin_query_vars( $query_vars ) {
        $query_vars[] = 'myplugin';
        return $query_vars;
    }
    

    You have to do this because otherwise WordPress won’t know what to do with the query variable.

    Finally we tell WordPress what to actually do with your variable:

    add_action( 'parse_request', 'myplugin_parse_request' );
    function myplugin_parse_request( &$wp ) {
        if ( array_key_exists( 'myplugin', $wp->query_vars ) ) {
            include 'yourfile.php';
            // Call your functions here!
            // function_name_thingy();
            exit();
        }
        return;
    }
    

    You’ll notice that // your functions here code is waiting for your code. That’s because this time we’re including the PHP file and then in there you’ve theoretically written your code in a nice little function. And that function? Uses WordPress functions because it is one.

  • Dogfooding DreamPress

    Dogfooding DreamPress

    While I work for DreamHost, and I’ve used DreamPress since day one, I haven’t have the opportunity to put a serious, stress site up on it. The reason for that is simple. The two sites I have that I might do that for are ineligible for pretty much all managed WordPress hosts … because they’re not 100% WordPress.

    But. There is one domain that is, and I’ve moved it over. And this gives me an opportunity to determine what needs to be done to this site to make it fly on a different host.

    All Hosts Require Site Tuning

    This is possibly an unpopular opinion, but no matter which host you pick, there will never be a ‘drop it in and forget it’ option for any web host. The reason is that no two sites are the same. No two sites use the same code, have the same data, and have the same traffic patterns. And all those things come together to determine how well your site will run.

    No matter who your web host is, you will have to adjust. It may be something as simple as editing an .htaccess file or removing a plugin you no longer need. Maybe it’s as complex as PHP settings or having someone write you custom code.

    I don’t mean to say that no two hosts are equal, or that one is better than another. What I mean is that no two situations are identical. Of course a site will work, out of the box, better on one site than another. But when we have the capacity to understand what it is that makes our site work, what it does and how it does it, we can make any site work on nearly any host.

    For DreamPress, I Made Four Changes

    After I moved the site over to a test setup, I quickly debugged the ‘big’ issues. I had a white screen of death. Thankfully I knew right away what it was, because I was clearly aware of what went into my site and how it worked.

    First, a lot of sanity checks I’d put in to my .htaccess didn’t work. Primarily it was a case of how I’d handled redirects, since I was using an Apache4 format that didn’t work universally.

    Second, I wanted to use a phar file, so I had to add custom lines to my PHP settings to let it know how to run properly.

    Third, I replaced the old caching system with the new one. DreamPress has Memcached and Varnish, so I removed some of the object caching I didn’t need anymore.

    Fourth, I wrote some customized code to teach my site how to talk to Varnish, since I do weird things.

    That’s it. Four things. And I was able to debug this in about an hour because I took stock of the moving parts of my website. Not everyone can do this, I understand that, but when you build out a website, even if you can’t code, it’s incumbent on you to document what you did.

    When you add a plugin or a theme, you need to make a note somewhere of what it is and why you did it. I recommend someplace not on WordPress, since if your site is down, it won’t do you any good at all.

    The Immediate Impact

    With those four changes, the result was immediately obvious.

    A change in page timings - basically everything went balls faster.

    In the chart above, there are two major drops in speed (in this case, a drop is good). At the end of July, I reoptimized how images were processed by using Photon via Jetpack, I applied caching for FacetWP, and I removed all Google Ads. In doing so, I halved my time to load. This is a great thing.

    But then, just by moving to DreamPress and doing no changes to code, I halved it again.

    The average site load is now .8 seconds. It ‘spikes’ to 1.2 seconds if you hit a non-cached page. The time to first byte, which is shown on the graph as the yellow/orange line, went from 1.6 second to .1 second.

    Was Everything Perfect?

    No. But as it turned out, everything that wasn’t perfect had nothing to do with my new hosting setup. I reproduced the site locally and found I had some seriously slow database queries on a couple pages, which resulted in poor load times. Once I fixed that, a few of my archive pages began to fly.

    Also as I mentioned in the four things I changed, I did have to write new code. The bonus for the new code is that I was also able to back port some of that into the Varnish plugin itself, which means fewer people will have to write that code. You’re welcome. But that really was more for convenience as the site ran fine, it was just a bit overly aggressive in caching.

    Is DreamPress Right For Everyone?

    No host is right for everyone. Period. End of conversation.

    Is it right for you? Maybe. It certainly can be, and not just for generic ‘blog’ type sites. But you have to know what your site does, who uses it, and what they do to really know the right questions to be asking.

    The question isn’t “Is this good for me?” but “What does this do to a site that does what I do?”