Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • I Hate Your Framework

    I Hate Your Framework

    The plugin itself was one PHP file and three JS files.

    The framework was over two megs.

    The plugin added in a new setting to select which one of the three javascript files should be called.

    The framework ‘made it pretty.’

    I’m right up there telling people that the WordPress Settings API is a giant bag of wet hair. It’s confusing, it’s cryptic, it doesn’t always play well with everything, and sometimes it makes you feel like the point is to make us have decisions, not options, for our plugins. But I don’t think plugin frameworks are the answer. At least not the way most people seem to be going about them.

    When I say frameworks, I don’t mean the libraries like the AWSSDK for PHP framework that you package up into your plugin and do a proper check for a function, calling yours if the the library isn’t there. No, I mean the plugins that are totally separate plugins but are meant to be called by yours in order to make development easier and more consistent.

    That’s what I hate.

    I love the idea of these frameworks, actually. I think that a boilerplate plugin, similar to _underscores, where I can put in my plugin name, my information, and press a button to have the basic plugin files generated for me is brilliant! But I think most of the libraries out there are doing it in a way that will annoy and upset most people.

    The problem is less the framework and more the people using them as a ‘quick fix’ without properly thinking about what they want to do.

    They’re Too Large

    In the case of this plugin, one file with three settings could just be done with two functions (maybe three) and instead he’s made a download half the size of WordPress core. The zip is large, it makes things take just a little bit longer for people on slow servers to download and upgrade, and the larger you get, the worse you are for the really small shared hosts. I know a lot of people argue with me about this, but remember than a high number of hosts still default you to allow 7M in PHP upload size. That means when your plugin becomes the 30 meg behemoth with all your dev files, you’ve made things pretty bad for some users. But even when you’ve only made your plugin 2 or 3 megs, why would you do that when you have one file of actual code?

    The logic escapes me.

    They’ve Got Too Many Files

    Not the same thing as too large! There are hundreds of files in a framework, and if you’re using only 4, that means you have 96+ files to review for security. You just increased your workload for not enough value. Which is really a major part of my next issue. The point here is you, the developer, are responsible for every single file in that framework. You are expected to know everything about it, where it installs, what it uses, why it uses it, and when to upgrade. This is a pain. It’s a chore. And it’s your job now.

    You Don’t Know How to WordPress

    This is also why I don’t like the idea of making Multisite too much easier. The further you take a developer from writing this code, the further they get from understanding how it all comes together and the harder it is for them to debug their own plugins. If you’re developing a plugin you plan to share with other people, even a teeny tiny one, you need to understand what you’re doing. You need to learn about the way the code interacts with the CMS tool, you need to understand why some things are secure and others are not.

    You Use the Frameworks Wrong

    I said before, I love the idea. And I do. They’re a brilliant idea and, when done right, work perfectly. The problem with them is, a bit, a problem with WordPress, which is we really don’t have a way to handle children plugins. You see, the best thing for a true framework plugin would be to have it be a separate plugin. But without plugin dependency support in core or the directory, it becomes another level of hassle for users.

    For example… if you have the plugin as a separate plugin, these are the issues we’ve see for end-users (not developers):

    • Not recognizing the framework plugin, and thus deleting it (causing the plugin(s) to break)
    • Not recognizing the framework plugin and thinking they’ve been hacked
    • Updating the framework plugin separately from the dependent plugins, possibly leading to breakage
    • Updating a dependent plugin without updating the framework, possibly leading to breakage
    • Different plugins requiring different versions of the framework

    And bearing in mind that the framework and plugin developers are different people, that’s another level of coordination/compatibility issues. Frameworks and libraries should be packaged with each plugin (hopefully in a way that doesn’t conflict with other plugins using the framework or libraries). At least until core supports plugin dependencies.

    But I still think that’s wrong.

    I still think the best framework plugin isn’t a plugin at all, it’s a tool to help you design and build a plugin via your editor of choice. Or maybe a Grunt Script that lets you build it out based on parameters. Time spend making a framework for making the plugin ‘interface’ better would be better spent making the Settings API better.

  • The Ebb and Flow of Automation

    The Ebb and Flow of Automation

    Repetitive tasks suck. Let’s be honest here, we hate doing them most of the time. But also we’ll forget things and mess up our day. With code that’s pretty terrible.

    Over time, I’ve managed to automate a lot of things. WordPress upgrades itself, including plugins and themes. My code changes are auto-deployed via Git when I update them. I use a cool Coda plugin to automatically generate css from multiple files.

    I’ve now added Grunt to the mix. Grunt runs tasks for you so you can be lazy (efficient) but it’s not perfect. One of the things I love about my other tools is I don’t have to think about them. WordPress takes care of itself, git has hooks to know what it’s doing, and Coda monitors my files. I don’t have that for Grunt.

    What you have, instead, is ‘grunt watch’ which is great but it only runs while you’ve told it to watch. You have to remember to activate it every time. And I understand why. Watching is a rather expensive (computer wise) tool. But it annoys me because I already struggle to remember that the way a tool I use works, I have to run this to checkout the code: git checkout [tag_name] -b [my_branch_name] (which for some reason my brain thinks is ‘better’ than scripting a zip).

    So why would I use Grunt?

    On a site I run, I have a folder filled with scripts that are used on four separate CMS tools. One is WordPress. I’m often adding new scripts and I like to have the scripts separate because that’s easier for me. But that also means I have to edit all my CMS to add in the new JS. But with Grunt I don’t.

    Instead, I have one simple Grunt file that says “Any js file in /content/code/js/dev/ should be combined into one mondo js file and then uglified to compress it down.”

    Installing Grunt

    I didn’t have Node installed, but I do use homebrew, so this was it for me:

    brew install node
    npm install -g grunt-cli
    

    Okay. Now what?

    My First Project

    I knew I wanted to make a folder in my /content/ folder for this, so I made /content/project/. In that folder I ran the command npm init and answered the questions to generate my package.json file. That was the easy part actually. After that had to decide what I wanted to do.

    1. Concatenate (combine) all my JS files into one.
    2. Compress those files to make them minified.
    3. Watch the files while I was working on them and automate that.

    In order to do that, I need to install three grunt ‘plugins’: concat, uglify, and watch:

    npm install grunt-contrib-concat --save-dev
    npm install grunt-contrib-uglify --save-dev
    npm install grunt-contrib-watch --save-dev
    

    Doing it that way, with the save dev call, automatically adds it to my package.json file so it knows to call that.

    Next I had to make a filed called Grunfile.js and put my actual code in it. I’ve got a copy of the file below but you can break it up into some pretty basic sections. Here’s a sample file:

    module.exports = function(grunt) {  
    
        grunt.loadNpmTasks('grunt-contrib-uglify');
    
        grunt.initConfig({  
            pkg: grunt.file.readJSON('package.json')
    
            uglify: { ... }
    
        });
    
        grunt.registerTask('default', [] );  
      
    };
    

    The first call is to load the npm (node) tasks, which means I’m telling it ‘include these plugins’.

    The second call is my init command which runs when the ‘grunt’ command is used. In there I’ll put the name of my json file, where I’ve defined all my dependancies (not all get loaded by the Grunt file you see) and then I’ll make a ‘case’ for my code. That’s what the uglify: { ... } bit is.

    The last is registering the default tasks. At this point, if I want to do anything I would have to type grunt uglify to do anything, so what you can do instead is make it this:

    grunt.registerTask('default', ['uglify'] );
    

    Now when I run ‘grunt’ it will automagically uglify. If you have multiple steps, put them in order of what you want to happen, and off you go.

    At this point, I’m now a GruntJS rookie, but I can see why it’s amazing. One can use this in plugin development to make it easier to mush up all your code into something smaller to load.

    My Scripts

    For those wondering, here are my scripts:

    package.json

    {
      "name": "jfo-content",
      "version": "1.0.0",
      "description": "JFO Content Scripts",
      "main": "Gruntfile.js",
      "dependencies": {
        "grunt": "^0.4.5",
        "grunt-contrib-uglify": "^0.7.0"
      },
      "devDependencies": {
        "grunt-contrib-concat": "^0.5.0",
        "grunt-contrib-uglify": "^0.7.0",
        "grunt-contrib-watch": "^0.6.1"
      },
      "author": "Mika Epstein <ipstenu@halfelf.org>",
      "license": "WTF"
    }
    
    

    Gruntfile.js

    module.exports = function(grunt) { 
    	
    	grunt.loadNpmTasks('grunt-contrib-uglify'); 
    	grunt.loadNpmTasks('grunt-contrib-concat');  
    	grunt.loadNpmTasks('grunt-contrib-watch');
    	
    	grunt.initConfig({
            pkg: grunt.file.readJSON('package.json'),
    
    		concat: {  
    		    dist: {  
    		        src: '../code/js/dev/*.js',
    		        dest: '../code/js/content.js',  
    		    },  
    		}, 
    
    		uglify: {
    		    build: {  
    		        src: '../code/js/content.js',
    		        dest: '../code/js/content.min.js',
                        }
    		},
    
    		watch: {  
    		    scripts: {  
    		        files: '../code/js/dev/*.js',
    		        tasks: ['concat', 'uglify'],  
    		    }
    		}
    
    	});
      
        grunt.registerTask('default', ['concat','uglify'] );  
      
    };
    

    post_update (git)

    I added in a line here to delete the package folder from my live site. That’s where all my Grunt stuff lives and I really don’t need it. It also nukes the dev folder. Sometimes. In some cases I leave that alone, since it’s not like I’m worried about space.

    #!/bin/sh
    export GIT_WORK_TREE=~/public_html/content/
    git checkout -f master
    rm -rf ~/public_html/content/package/
    rm -rf ~/public_html/content/code/js/dev/
    
  • Mailbag: Learning Resources

    Mailbag: Learning Resources

    Ann asked about books:

    [..] if you’re open to throwing a few key book recommendations – sites – blogs – whatever resources that you use/have used and particularly liked – I would be grateful. Essentially – I love your blog and am always looking to improve my WP developer skills. I want to get better. I want to be really really good. So I ask the greats if there’s something in particular that they think I should read – out of the huge sea of articles/books/blogs/etc out there. Something that they’ve singled out and thought was really worth paying attention to. And then I read it! [..]

    She got an email reply right away, but here’s for everyone else.

    The best advice I have is to pick something you like (or that drives you absolutely up the wall) and poke at it.

    I got started and good because I really, really, really, wanted to do something that (at the time) WP didn’t do. After banging my head a lot, I started googling and trying to figure out what was there to use. I looked at a lot of code that was ALMOST what I wanted. And I broke my test site. A looooooooot.

    The biggest problem is we all learn differently. I learn by doing, so for me the act of writing BAD code helps me understand it better. I hate videos.

    But do I have a specific resource for learning? Sometimes I do. The majority of my ‘research’ remains search engines and constantly refining parameters, or trying to remember the name of the one thing with the thing. The problem is that I’m very haptic, I learn by doing things, so for me it’s way easier to take the examples and break them than anything else.

  • What I Learned From The Man

    What I Learned From The Man

    It’s no secret I worked for “The Man” for nearly fourteen years. I’ve learned some pretty amazing technical things from that, but I also learned some tricks about ‘working’ with a big company that have yet to fail me no matter where I worked. They were all lessons my family instilled in me, but having some pretty amazing people like Bonine, Margie, Joe P., Nikki, Rae, and a host of other amazing people all reinforce the morals of the stories, and it made me know that these were the right things.

    Always Admit Fault

    Scariest moment of my life was the day I accidentally rebooted a trading server at 10am on Thursday. Those were only supposed to happen at 10pm on Thursday nights, well after all trading was done for the day. I did it mid-day which meant there was a high risk that in-flight data could be lost. I was tasked with diagnosing what had happened and, after a lot of review, I came back and said the only logical reason was I had typo’d when I scheduled the time. We since changed to 24/7 clocks and not AM/PM to mitigate, but I was up front about the error being me. Similarly, when a bad change I made to a script broke the internet for all of our UK offices, I said it was me, I fixed it, and I took the hit. This meant later when a change I’d fought against was put in and caused an outage, everyone believed me when I said I’d done it, but it was someone else’s idea. I had credibility and history and (of course) documentation on my side.

    Document It Or It Didn’t Happen

    I had a boss whom I did not like. I liked the work, but working with him was terrible. He didn’t grove like I did, he was misogynistic and racist. He also had a flagrant disregard for protocol. Love it or hate it, when your company has specific steps to follow to do a thing, you do the steps. He didn’t want to and demanded I make an on-the-fly change. Verbally. I didn’t. This ended in a shouting match which our manager had to step in and settle. But before that event, I was told to make a change I knew was wrong. I demanded it be documented that this was a change in scope and a requirement by him. I then, under duress, made the change. It broke. I backed it out. That marks the last time I ever let it go that far and may explain to many people why I’m so firm about not letting people do ‘wrong’ or ‘bad’ actions. If I know something’s wrong, I won’t do it and I won’t help you do it.

    Remember You’re Special, And So Are They

    I’m a techie. I know all sorts of weird things. Remembering that I know those things and understand the different between minimizing a screen and closing a window is important. Joe reminded me about that once. I never forgot it. I also don’t forget that my place is to make sure problems are solved. So just because I don’t panic doesn’t mean I’m being cavalier, but at the same time I have to make sure the other person knows that.

    "Oh, you're using their Chrome APP, not their Chrome EXTENSION. They're very similar but one handles window creation differently." is a thing I hope I can stop saying soon.
    Credit: xkcd

    That window resize via a resolution change was the only way to fix a specific problem with a specific app. I used to travel across town to do it for people because trying to walk them through it on the phone was too difficult.

    Use Your Calendar

    “I’m sorry, I’m really busy.” has a lot more weight when they look at your calendar and see it’s booked. Solid. When I know I need to spend time working on a specific project, I schedule it as booked time and that way everyone can see and understand I’m busy. This is also a respect issue. If someone schedules a meeting, you confirm and click that damned ‘I accept’ button. It’s a contract, or a friendly agreement, in order to tell someone ‘Yes, I will be there.’

    Don’t Waste Group Time

    Irony. If you think about big companies, you think about wasted meetings where people never get anything done. I’m not talking about that (which is a thing). I’m talking about wasting time with being disrespectful of the meeting. Keep your phone/mic on mute in a conference call so no one hears you pounding on a keyboard. Turn off your video feed if you’re not presenting so you speed up the internet for everyone. Joining in a massive meeting with hundreds of people? Get a conference room for your location to prevent overwhelming the system. If it’s an on-line, text meeting, follow the announced protocol.

    What Did You Learn?

    I’m not the only open-sourcer who used to work for the Man. Did you learn anything that you still use today?

    Those meetings, by the way, are generally a waste of time. I greatly prefer stand-ups. Everyone gets 60-90 seconds to state status. Everything after is taken outside meetings.

  • Markdown Isn’t All Bad

    Markdown Isn’t All Bad

    It’s not a secret I hate markdown. It’s annoying to remember various commands, and one of the things I loved about WordPress from the start was that I didn’t have to learn bbCode or anything beyond the HTML I knew. When Jetpack included Markdown, I was a huge opponent. I thought it was useless and pointless and a waste of space.

    I now use it in many of my posts.

    You see, I don’t write in the visual editor. I used to, but there are ‘glitches’ with it. Like I couldn’t see the embed for Facebook (it showed up blank for some reason), and I had trouble embedding video content that required me to paste in script code. Then when I starting writing code, like I do on this site, I needed to make sure the formatting didn’t get mangled. It all boiled down to giving me two places where I use the Visual editor, and everything else is text.

    That’s all well and good until I fell in love with my iPad mini.

    You see I also have a major annoyance with the iOS app for WordPress. It’s too easy to post to the wrong site and it’s problematic when you want to upload featured images or make custom excerpts or have any custom post types. That means I use Chrome or Safari on iOS to write blog posts. If I’m offline, I write it up in Notes or Byword and just have it there until I’m ready to import. But I use WordPress in my browser because that’s where it works ‘best.’

    Except HTML on an iPad is a pain in my ass.

    It really, really, is. The number of clicks you have to do just to make a header, or strong text, is annoying. It’s three clicks to make an <h2> and it’s not even in the same place. It’s one click to get to the numbers, another (one up from where you hit to get to numbers) to go to advanced characters. Then you can press the button. Any chance I have to minimize my clicks means I can type even fast.

    And you bet your bippy I’m fast at typing on my iPad.

    Markdown’s syntax is intended for one purpose: to be used as a format for writing for the web.

    John Gruber’s Markdown syntax primer is the only place that really took the time to make sense of Markdown to me. Everyone else just said ‘It’s what we use’ or ‘It’s faster’ or (worst) ‘It’s better.’

    No. No. No. Better is what works for you. HTML, for the most part, works for me. And for me, a small subset of markdown syntax terms work very, very well to speed up my writing:

    
    ## Title
    
    ### Subtitle
    
    &amp;amp;gt; Blockquote
    

    There are a few more, like the codeblock (which I don’t use, since I like pretty formatting better) but the ability to use backticks and say <code> is pretty nice.

    So do I like Markdown? No. It’s hard to remember ‘new’ syntax. But the ones I can use without having to close tags makes me a little happier and speeds me up a bit. For that, it’s pretty good. I can use it to enhance my HTML, and I wish that MediaWiki let me use HTML and Markdown instead of their woe begotten WikiSyntax. My kingdom for <table> in MediaWiki. Am I right?

    Now. If I could just get John Gruber to increase his font size.

  • Mailbag: What Code Makes You Sigh?

    Mailbag: What Code Makes You Sigh?

    When I was talking about ThemeForest, I mentioned we had code on WordPress.org that made me sigh. Or cry depending on the day.

    Here it is:

    if (!defined('WP_CONTENT_URL')) define('WP_CONTENT_URL', get_option('siteurl').'/wp-content');
    if (!defined('WP_CONTENT_DIR')) define('WP_CONTENT_DIR', ABSPATH.'wp-content');
    if (!defined('WP_PLUGIN_URL')) define('WP_PLUGIN_URL', WP_CONTENT_URL.'/plugins');
    if (!defined('WP_PLUGIN_DIR')) define('WP_PLUGIN_DIR', WP_CONTENT_DIR.'/plugins');
    

    Why do I sigh?

    It’s not needed.

    You can use functions to determine those directories and while I’m sure someone’s thinking “But WP_PLUGIN_DIR is shorter than plugins_url()!” it’s not.

    That code block above was used so that one line of code could exist.

    include(WP_PLUGIN_DIR.'/PLUGINNAME/settings.php');

    Those four lines, plus the include, could be replaced with this:

    include( plugins_url( 'settings.php' , __FILE__ ) );

    So yes, I sigh. Because with just a little work, you could see that there’s a more efficient way to make your plugin smaller.