Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • Dependency Disaster

    Dependency Disaster

    Over the last few weeks and months, the nightmare that is WordPress plugin dependency hell has waxed and waned with the ire of a thousand burning suns. It flared up when I, perhaps naively, posted a reminder of a rarely called upon guideline to not submit Frameworks for hosting on WordPress’s official plugin repository.

    This brought up the perfectly valid arguments that these repositories are useful as they allow for deployment and updates that were hitherto unavailable when rolled up into one package. And at its heart, I understand their point and agree with them as to the benefits. But since WordPress core doesn’t have true plugin dependencies at this time, it’s exceptionally complicated and a hassle to include them.

    Personally, I feel that the NPM or Composer style development of plugin is the way to go. Development. Not deployment. With few exceptions, I feel the best way to release a plugin is all in one, rolled up together. The exceptions are, of course, plugins that are add-ons to others, like a plugin that adds a new email integration hook to MailChimp, or a new payment gateway for WooCommerce.

    The rest of our plugins should be self contained, reliant on naught but ourselves. I have two plugins which contain the same AWS SDK libraries, written in a way to check if the library is already loaded and to make sure it only loads what’s needed. Why did I do that? Because then someone can have one or the other or both without conflicts.

    The user doesn’t have to care about dependancies. They are invisible. That is as it should be. Users don’t have to care.

    But there’s also a danger with dependancies, as recently came to light in the JS world. Azer Koçulu liberated his modules from NPM after the threat of a trademark based lawsuit had NPM remove one of his projects.

    Sidebar: Open Source has no right to impinge on trademark law. Period. However some lawsuits are frivolous and daft and should be contested. Sadly most communities (NPM, WordPress.org, etc) do not have the money or resources to fight that battle for a developer. If you chose to fight, please contact the EFF.

    As is his right, Azer pulled all his packages from NPM. The fall out from this package removal is that a lot of automated builds failed. This has to do with the way Composer is often bundled. Instead of a wrapped up package like an exe or a dmg, it’s a stub that reaches out and downloads all its requirements on the fly. Just like the TGM Plugin Installer. Right? And what happens when those requirements are missing? The build fails.

    Perhaps worse, by unpublishing the name slugs used can be taken over by anyone else, and used to push more nefarious code. This did not happen. NPM checked everyone and verified they were as decent as one can before handing over the old names to new owners.

    My first thought was “Could this happen to WordPress?”

    Yes and no. First up, we don’t reuse names. If you have the plugin ‘foobar’ and ask to have it closed, the name is still reserved. In extremely rare cases we’ve turned over names to trademarked owners (like how Facebook owns the facebook slug) but always with communication of both parties and always with awareness to how many users might be impacted.

    But could we pull a plugin for trademark infringement and screw up package dependancies? You bet your ass.

    We’ve been lucky that all legal parties involved in similar arguments have been accepting of the ‘grandfathered’ ruling. That’s why we still have plugins with slugs like ‘google-analytics-by-joe’ out there. But it’s also why we don’t allow any more. And yes, when a plugin with a unique name is submitted, we do take the time to check if it’s already trademarked. To spare people this drama.

    But yes. It could totally happen. And since we have to name our dependancies and rely on those slugs, there’s no easy way out.

    I suggest reading the Hacker News thread on the matter. They weigh both sides of the issue, and show you how the pros and cons make this even more complex.

  • The Pressure to Succeed as a Woman Who Codes

    The Pressure to Succeed as a Woman Who Codes

    I feel a disproportionate amount of pressure to succeed in coding.

    I call it disproportionate because it’s only about 1/3rd of my career. The other two are support/training and public speaking. And while I used to have a fear of public speaking, I’ve somehow managed to discard that and I’ve got no concerns at all about screwing up on stage. I might. My talk might flop. My training might not be understood or adopted. My support may be wrong.

    But what scares me to the point of tears is coding.

    It’s not that I’m bad at it. Intellectually I think that I’m pretty good. I’m not the greatest in the universe, but that’s a realistic stance as opposed to anything else. And I enjoy playing with it, inventing new things, seeing how they work, helping people solve problems with code. It’s honestly fun.

    Looking at the Stack Overflow Developer Survey I noticed that only 5.8% of the participants identified as female. Taken a different way, 92.8% of people had no problem saying they were men. Now, SO is aware of the disparity, and mentioned this:

    Our survey results demonstrate a dramatic disparity in tech among men and women. In fact, we know women make up a more significant proportion of the developer workforce than this suggests. According to Quantcast, about 12% of Stack Overflow’s readers are women. (We don’t actively track gender internally.)

    I have a personal theory that gamification appeals more to men than women. This stems from reading about Richard Bartle’s player types way back in the 90s. It was a big thing in MUDs and MUSHes, and the Bartle Test is essentially a series of questions that can be used to identify the classification of a player into one of four types: Killers, Achievers, Socializers, or Explorers.

    Now it helps if you’ve read a little of Hearts, Clubs, Diamonds, Spades: Players who Suit MUDs, but you can get by with the Wikipedia article. The main point is that we can classify people into player ‘types’ based on what they enjoy doing and how they like doing it.

    In general, winning and hacking are associated with Killers and Achievers, while helping and curating fall under Socializers and Explorers. And when I say it like that and you look at things like programming vs support forums (of which I do consider Stake Overflow), lines start to be drawn. These lines are carved in stone when you consider some of the research gamerDNA did into what kinds of player played what kinds of World of Warcraft characters, and what their genders were.

    What does all this have to do with the unrealistic expectations on women who code?

    If one buys in to the hype and typecasting, then one would say that women (nurturers) are more likely to be socializers and explores. Regardless of if this is accurate, there certainly is an expectation on women that they are ‘mothers’ and, from that, they are often unconsciously perceived of being a specific player type. And when someone steps out of what people feel their norm is, they’re often set upon.

    This is not solely endemic to women, of course. Men who express emotions publicly, like crying for example, are also set upon by others for not being manly enough. And that is precisely my point. People who don’t fit the stereotypes of what gender is get pushed back. People who act ‘out of character’ are looked upon as odd.

    Okay, so why do women keep feeling pressured? Because shit like this happens:

    You can look up the ‘fake geek girl’ phenomenon on your own. The fact is that it applies to anything not stereotypically female that a woman does. And it means that, in order to be taken seriously as a coder, we have to achieve great things or all we’ve done is prove we’re only good for the ‘fluff’ of support.

    Eddie Izzard makes a joke in his “Dress to Kill” routine about men who wear dresses and heels:

    You know, if a woman falls over wearing heels, that’s embarrassing, but if a bloke falls over wearing heels, then you have to kill yourself. It’s the end of your life. Its quite difficult.

    And while we laugh at it, the truth is that ‘abnormal’ behavior is treated with incredibly high expectations. Unrealistic ones. Unfair ones.

    I don’t have an answer to this, and for now women shoulder the burden of being expected to be greater than men of identical backgrounds, simply because of how we were born.

  • Chart.js Category Statistics

    Chart.js Category Statistics

    One of the sites I work on is using the Metro Theme by StudioPress Themes for WordPress. And on that site, I have a page dedicated to some odd stats based on the categories and tags and custom taxonomies.

    What I have is a post type ‘shows’ and a custom taxonomy called ‘clichés’ and from that I was easily able to generate a percentage of how many shows use the cliché of queers in law enforcement (38%) or how many have the death of a queer (also 38% right now). But that wasn’t enough. We wanted ‘pretty graphs’ and for that I needed a tool like Chart.js and a little PHP magic.

    How to Chart.js?

    Chart.js is a super cool and super responsive and super flexible way to include a chart. And using it is incredibly easy once I figured out that I could just use inline script tags. A very basic chart that would show you how many days each month has looks like this:

    <script src="Chart.js"></script>
    <canvas id="barDays" width="600" height="400"></canvas>
    
    <script>
    var barDaysData = {
    	labels : ["January", "February", "March", "April", "May", "June", "July", "August", "September", "November", "December"],
    	datasets : [
    		{
    			fillColor : "#7d3255",
    			strokeColor : "#532138",
    			data : ["31","28","31","30","31","30","31","31","30","31","31"]
    		}
    	]
    }
    
    var barDays = document.getElementById("barDays").getContext("2d");
    new Chart(barDays).Bar(barDaysData);
    </script>
    

    If you’re using WordPress, you’ll want to use wp_enqueue_script to call it. Here’s what I did for my theme:

    wp_enqueue_script( 'chart.js', get_bloginfo('stylesheet_directory').'/inc/js/Chart.min.js' , array( 'jquery' ), CHILD_THEME_VERSION );

    But that’s the basics of it. Once I understood that, I was good to go.

    The Code

    Before I can do anything, I need to make sure I have the data I needed. What I wanted was a list of all the shows that were published and a list of all the cliches, ordered in the way I need them. The order is simply comma separated values, enclosed in quotes, enclosed in brackets:

    labels : ["January", "February", "March", "April", "May", "June", "July", "August", "September", "November", "December"],
    

    And the data is similar:

    data : ["31","28","31","30","31","30","31","31","30","31","31"]
    

    Since I’m lazy, I checked that the array worked if it ended in a , and it did! That means my PHP looks like this:

    $count_shows = wp_count_posts( 'post_type_shows' )->publish;
    $cliches = get_terms('cliches');
    
    $barshow_labels = '';
    foreach ( $cliches as $cliche ) {
    		$barshow_labels .= '"'.$cliche->name.'",';
    }
    
    $barshow_data = '';
    foreach ( $cliches as $cliche ) {
    		$barshow_data .= $cliche->count.',';
    }
    

    And my js looks like this:

    <script>
    var barShowsData = {
    	labels : [<?php echo $barshow_labels; ?>],
    	datasets : [
    		{
    			fillColor : "#7d3255",
    			strokeColor : "#532138",
    			data : [<?php echo $barshow_data; ?>]
    		}
    	]
    }
    
    var barShows = document.getElementById("barShows").getContext("2d");
    new Chart(barShows).Bar(barShowsData);
    </script>
    

    You may notice the simple call of <?php echo $barshow_data; ?> in there? That’s where it outputs the data I sorted out in the PHP section. Done. I’m could put it more inline, but I liked to separate them as much as I could.

    Putting it in the theme

    This is a Genesis theme so while I am making use of the Genesis loop, the call to get_template_part can be used by anyone. I’ll explain in a moment. First, here’s the page template:

    <?php
    /**
    * Template Name: Lezbian Stats Template
    * Description: Used as a page template to show page contents, followed by a loop
    * to show the stats of lezbians and what not.
    */
    
    // Show Dead count below the content:
    add_action( 'genesis_entry_footer', 'lez_stats_footer', 9 );
    
    function lez_stats_footer() {
    	get_template_part( 'stats' );
    }
    
    genesis();
    

    This works like any other page template. You make a page, you select the template, and it loads this custom design.

    The magic sauce is in get_template_part( 'stats' ); which calls the file stats.php and that file has all the code you saw above. This means I can edit my post with all the explanations I want, and then it always outputs the stats on the bottom. By calling the Genesis code in the bottom, I retain all of it’s magic while pulling in what I want.

    The Result

    The graph of cliches about queer women on TV

    Looks nice, doesn’t it? I’m quite fond of it.

  • Project Bloat

    Project Bloat

    Can we have a serious talk about project bloat?

    During the framework kerfluffle, I remarked that I hated seeing a 10 line plugin needlessly include a framework like CMB2 because of the size of plugin it created. Someone remarked that if the library helped them write something in ten lines instead of 100, wasn’t that better?

    And the answer to this is maybe.

    My issue is not using a library when the library is the best solution. My issue is people defaulting to use a library before they think about if it is the best solution.

    And my point is really quite simple and obvious to a large number of developers. I’ve touched on it time and again. I’ve told you how I handle packaging my vendor folders. Simply put, I think that before you include anything in your project, you should evaluate it’s merits and flaws.

    Look. There are always, and will always be, good reasons to use a library. There’s never a reason to use a library thoughtlessly, and that’s what I see every day. By ‘thoughtlessly’ I meant someone who has a plugin that adds one setting, a custom meta field let’s say, into all posts. And in order to do that, they wrap ACF into their plugin.

    For one field.

    One.

    Literally one.

    Jackie Chan WTF Meme Face

    And I get it, I really do. The settings API is a bag of wet hair, and the fields API needs love (so much props to Scott Clark for his work there), and figuring out how to do things can be a comprehensive battle of trial and error vs ‘How much hair do I have left?’ And yes, I do use some of those libraries, like CMB2 and ACF, when the need calls for it. When I’m making a massive custom tool or theme and I need to do a million things. But …

    What I don’t do is use it for one field. Sure I could, but that would make my plugin very large and to no real benefit except it’s ‘easier’ for me. And even that is questionable. When I do use them, and yes I do, I do so thinking about the weight I add to my project.

    A pause here. I say this a lot, the weight of a project.

    Everyone seem to assume I only mean the size (in MB) of a project. I don’t. When I say the ‘weight’ of a project I mean the file sizes, of course. Making your 10kb plugin over 500kb just to add one field (I’m being literal here, folks) is sketchy at best. Making it over a meg is borderline ignorant. But I also mean the weight of how it impacts the speed of the site. Will having the library called make a site slower? It might. And I also mean the weight of technical debt. Am I going to update the plugin and the library every single time? This is my responsibility now, and I have to test and test and ensure I don’t break anything.

    The weight isn’t just the size, it’s the time sink. It’s everything that has to go into keeping a library included in a way that doesn’t conflict with anything else. It’s managing my time so I can test and evaluate changes. It’s making sure I push code that won’t break on new versions of my main project (i.e. WordPress). It’s making sure my changes don’t break other co-projects (like WordPress plugins and themes), by assuming they’ll always work on the newer versions. Backwards compatibility isn’t a requirement for all projects, but when it is, you bear that weight too.

    And the weight is also the fact that I’m robbing myself of a greater understanding of WordPress core. Using a library isn’t ‘cheating’ but it does mean I might be less capable of debugging a conflict, if it’s due to the library.

    That’s the real weight of a library included in your project. If you’re not considering it when you add a library, you’re doing yourself a massive disservice.

  • Composer and WordPress’ Plugin Preflight Check

    Composer and WordPress’ Plugin Preflight Check

    When you upload a plugin to WordPress.org’s repository, it does some pre-flight checks to make sure the code is okay. More than once it’s caught a missing ; for me. But one day it caught this:

    PHP error in: myplugin/tags/0.6/aws/Doctrine/Common/Proxy/ProxyGenerator.php:
    Errors parsing myplugin/tags/0.6/aws/Doctrine/Common/Proxy/ProxyGenerator.php
    

    I stared for a moment, Googled to be sure, and sighed when I figured out that what was happening was my library was a PHP 5.6+ version and that didn’t pass the 5.4 checks.

    Regardless of how annoying this is, it’s not too hard to fix. No, I’m not going to tell you how to avoid the scan, nor am I going to talk about the stupidity of the scan. Instead I’d like to tell you how to get around this problem.

    It’s so easy, too.

    You see, my issue is that I use Composer to build my resource libraries and in my composer.json file, I have this:

    "require": {
    	"aws/aws-sdk-php": "2.7.*",
    	"doctrine/orm": "*",
    	"monolog/monolog": "*"
    },
    

    And for what it’s worth, this is great. I have it download all my libraries. Then I have it run a script to copy over just what I need to my aws folder and I have Git and SVN ignore the vendor folder. Everyone wins! The problem is that Composer sees that my laptop is running PHP 5.6 and so it installed version

    Fix PHP on Your Computer

    Since I use Homebrew on my Mac, this is super easy for me.

    $ brew unlink php56
    $ brew install php54
    

    Then when I re-run composer update it will install what I need.

    The problem here, though, is that this is tied to a specific computer, and if a coworker downloads my stuff and plans to fork it, they’re SOL and merges fail and it’s sad times all around. So with that in mind, uninstall 5.4 and go back to 5.6.

    If you have a problem with installing 5.6, run it this way:

    $ xcode-select --install
    $ brew unlink php54
    $ brew install php56
    

    Fix PHP in Composer

    I like this fix better. Put this above your require statement and you’ll force Composer to build based on PHP 5.4:

    "config": {
    		"platform": {
    		"php": "5.4"
    	 }
    },
    

    Now we’re cooking with fire. This works for everyone, it forces Composer to download 5.4 compatible libraries, and my very long transmission worked.

    Is This Perfect?

    Obviously not. There are going to be cases where your code absolutely has to be the code for PHP 5.5 and up. The latest version of the AWS SDK is v3, for example. But it’s for 5.5 only. I personally don’t feel there’s enough of a buy-in for PHP 5.5 and up yet to make an issue of it. And having no check at all won’t fly.

  • The Awareness of Method

    February and March were weird for me. A lot of personal drama, and none of it really mattered to the masses so I kept it to myself and my close friends. I don’t feel the need to publicly broadcast my personal pain on everyone, and I do my best to step back and let it (hopefully) not impact my reactions to everyone else.

    This was very hard because a goodly portion of my drama was from the public sector, and it boiled down to people unintentionally hurting me. And as I grumbled on Twitter, I feel like I need to explain how having hurt feelings doesn’t mean I’m over reacting. Which is preposterous.

    I understand that, for the most part, the people who hurt me certainly did not intend to attack me or sound combative. And I’m well aware that tone is a terribly difficult thing to read in the written word. That’s why good authors take the time to explain things in detail. Things like italics and bold and capital letters are important for reading into the meaning of a sentence.

    At the same time, any time a comment aimed towards me starts with a remark about how they don’t care for drama, I walk away. You should never say that. If you don’t want to talk about the drama, don’t invite the drama. It’s really that simple. And if you’re worried that how you’re saying something, it’s a sign that you should rethink what you’re saying and how you’re saying. This is where the method comes in to play.

    The intent of what you’re saying is subject to the manner in which you say it. If you ask a sincere question and people react strongly and negatively to it, then your intent was lost in the method. Communication in text-only is complicated. You can’t see people’s faces, you can’t hear their tone, and most of us don’t know each other to the degree that we can reliably read intent. Simply put, your intent is subject to how it’s read.

    For a long time, I’ve advocated people remember that when someone misinterprets what they’ve said, the fault lies in both parties. If I say something and it’s read as aggressive, this is in part my fault for not tempering my tendency to be direct with the need people have for humanity in a conversation. At the same time, no matter how nicely I say “Your plugin has been closed…” someone is rightly going to read it and be angry and interpret that I am being mean or offensive.

    It’s a no-win situation. Or at least it’s one I’ve never figured out how to win. I’ve been told the default ‘your plugin has been rejected…’ email is too angry because it uses all caps for one line, even though it apologizes and explains it’s trying to get the reader’s attention and encourage them to … well … read. That email was developed over years of communications with thousands of developers. It’s the one we determined to have the highest success rate of people actually reading and processing what was said.

    Still, at least once a day someone replies to an email asking ‘How do I resubmit my plugin?’ This invariably comes in reply to an email that says “When you’ve corrected your code, reply to this email with the updated code attached as a zip, or provide a link to the new code for us to review.” And at that point, I honestly don’t know how to make it more clear.

    When people say the email is too aggressive, I explain that we’ve cultivated them over years, but we’re always willing and welcome to make it less so. And we ask if they have suggestions? Not a single person has ever replied with advice, except the person who said “Don’t use emoticons, they’re unprofessional.”

    Seriously, you just can’t win.

    Which brings me to the point and it’s that winning isn’t the point. Losing is the point. We lose when we don’t take into consideration the reaction to what we say. We lose when we dismiss someone else’s reaction. We lose when we over-react to what we perceive as an over-reaction.

    We will never be able to always speak clearly and without accidental misunderstandings. We will never be able to ask every question in a way that makes everyone feel welcome to join a dialogue.

    We can be aware that our words have weight and meaning, especially because an increasing number of us communicate in text first (if not text only). We can try to learn from our mistakes. We can apologize sincerely for those mistakes.

    What you say can and will be taken out of context. It can and will be read the wrong way. When it happens, it hurts and it tends to make you react poorly. But being hurt by someone’s words doesn’t mean you’re over-reacting. And it would do us all good to remember to respect other people’s feelings and reactions.

    Yes. Even me.