Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • On Saying No

    On Saying No

    We are, for the most part, accustomed to getting our way. We have a problem, we contact support, they fix it.

    Once in a while, however, support says ‘No.’

    I’m sorry, I can’t do that, Dave.

    There are technical limits to all products. Due to our own failures of imagination, we cannot foresee every possible iteration of usage for the things we build. These failures are, of course, not the fault of anything but our own lack of omniciense. We cannot know all things. We cannot predict all things.

    In this way, we have learned to expect limitations over time. We know that there is a line drawn in what the computer can do. If we have not programmed the computer to do a thing, it cannot know to do the thing. The reason for the limitation is just that the code’s author didn’t wish to write a thing. Why? Many reasons, none of which matter.

    We can, however, accept that systems and software are written by humans. Humans are fettered with limited vision. Computers are shackled by the humans who create them.

    When a program says it cannot do a thing, it cannot do the thing.

    I’m sorry, the system’s a bit limited.

    The problem with our shackles is that the one who has to tell a customer that the computer cannot do a thing is a person, not a computer.

    We cannot delete user accounts on WordPress.org for a number of reasons. If the site was just a blog, or a BuddyPress network, it would be a simple matter. Instead we integrated a wiki, multiple bbPress 1.x instances, a BuddyPress network, a multisite, theme SVN, plugin SVN, and core SVN.

    So no. We no longer have the technical ability to remove a user ID. Not even in the case where you accidentally used your gmail address as your username and are now ipstenugmailcom … It says username, but people do what they do. And no, we can’t rename users either. Same reason.

    We coded ourselves into a situation where we are technically limited. We cannot do the thing because we didn’t develop a way to do the thing.

    I’m sorry, but it’s against policy

    Then there’s a different kind of reason that someone tells you no. Like when someone asks for an embarrassing post or comment be deleted. Obviously this can be done. Comments and forum replies can always be deleted. That’s how they work. You may have your own site and you’ve deleted spam.

    But every site has a comment policy. They have the right to moderate their site however they want. Some delete things right away. Some moderate and manually approve all comments. Others let things run until the shit hits the fan and then spend hours and weeks and months cleaning up. However they choose to moderate and maintain their site is their business and their choice. You don’t have to stick around if you don’t like it.

    A large issue occurs when you don’t realize until after the fact that one of the policies is, perhaps, not removing posts. That’s when things get really messy, because now you’re being told no and not only is it by a human, but it’s a human who makes the choice.

    Your rights are subjective

    The rights you have on someone else’s website are subjective.

    The rights you have when you use a product are as well.

    If you download Microsoft Office, you agree to a lot of terms and conditions. Whether or not you read them, you agreed to them. Same with Apple’s iCloud terms and conditions.

    You give up some of your freedoms in exchange for their convenience. Your rights are subject to the agreements you make when you chose to use software, comment on a site, join a community, sign a contract, etc. etc.

    Be gracious in victory and defeat

    Once in a great while, someone will make an exception for you. Most of the time you really don’t want it.

    Perhaps you think it proves that all policies are mutable, but the reality is not. You see, that exception means it’s worth more to them to shut you up than it is to abide by policy.

    Of course a post can be deleted. Of course someone can lock your account for you. Of course you can be granted an extended warranty. But, for the most part, in order to get that far and get that level of ‘reward,’ you will have had to become the person no one wants to talk with.

    An example. A user asked for his account to be deleted and was informed of the technical impossibility of the request. He then asked for his posts to be removed and was informed of the policy prohibiting such a request. He finally asked for his account to be made inactive and to ban him from the site. He was told (after confirming that these requests were all to calm his paranoia and not that he was being harassed or stalked by someone) that the site was not his parents, and if he wanted to leave, the answer was to log off and walk away.

    Instead he began to post nothing but vulgarities.

    His account was locked and he was banned.

    He will likely never be welcome again.

    He might think he ‘won’ the argument, but all that happened was he showed his deplorable behavior, in public, in a way that Google captured. He tainted his reputation. He tarred and feathered himself. He burned his bridges. And he bragged about it.

    Support are people too

    When you are told ‘no,’ try to understand why. Accept the fact that you cannot get what you want all the time. Sometimes it’s just impossible. It’s understandable to be upset and angry. But the people tasks with enforcing policy or educating you to as to limitations, they are people just like you.

  • The Trouble With Libraries

    The Trouble With Libraries

    I’ve had the same argument over and over, to the point that people follow me here and complain that I suck. You’re welcome. I’m going to spell out the issues, as I personally see them with frameworks as plugins. If you want to talk about this in so far as it applies to the WordPress plugin repository, please read this post and keep the discussion there.

    The Problems

    Problem 1 – Users have no idea what the ‘library’ plugin is for.

    Most users understand “I have an add-on for WooCommerce, I probably need Woo.” They do not always understand “I have plugin Slider Joe. Why do I need Advanced Custom Fields?”

    Problem 2 – We don’t have true ‘dependancies’ in WordPress

    I think everyone can accept that’s a problem. We literally do not have a perfect way to require things. Look at Themes. If you try to delete a parent theme, you get warned there are children around. We don’t have that for plugins. We probably should.

    Problem 3 – Users are responsible for something they don’t understand.

    By having a library as a plugin, the onus of version compatibility and updates is now on the person least likely to understand it when it breaks: the user. They have to update the library, and your plugins, every time there’s a new version.

    Problem 4 – Frameworks and libraries can no longer break backwards compatibility.

    This is hugely restrictive, by the way. With a framework-as-plugin you can’t break things because you (the framework developer) are responsible for all the plugins that use your framework. If you break how things work from V1 to V2, and one of the myriad plugins a user has doesn’t work on V2, and the user updates your framework, you broke things. True, this was always the case, but at least the plugin contained the library and could use it’s own version.

    Problem 5 – Plugins will still break.

    I have to say ‘still’ because we have one version of the problem today, and we’ll have another tomorrow. Right now, if four plugins include the same library, and they’re all different versions, we don’t have a clear and perfect way to know which version of the library the user will get. Tomorrow, if a framework is a separate plugin, there’s absolutely no assurance than every plugin that requires that library has been tested with the version the user has install.

    The Options

    Today we really have two.

    Option 1 – Frameworks are plugins and users have to install them.

    This means all new plugins that include said framework have to remove it and change it to a require. All existing plugins should be contacted and told to change their code. Some users will complain about installing ‘extra’ plugins and some developers will lose users (it’s already happened).

    All developers have to put in this requirement themselves, possibly using a library like TGM (until we have dependancies). Also all developers have to ensure they, now and forever, keep up with the frameworks and ensure compatibility as well as proper alerts if a user removes the framework by accident. Their code has to break elegantly if the user doesn’t upgrade the library. Your plugin takes advantage of the latest feature in a framework? Awesome. Make sure your plugin checks “If this feature exists, use it” and fails gracefully if not.

    Option 2 – Frameworks that are not ‘functional’ frameworks, but really libraries are treated as all libraries are with all projects, and included separately.

    Developers have to code the calls to the library, making sure that the ‘right’ version is included no matter what someone else includes. Developers also have to update their plugins when a library updates. though if they properly handle the code calls, they don’t HAVE to. They could use namespaces and cleverly call use MYPLUGINAWSSDK as /aws/AWS/foo/bar instead, so their version is what’s used. They’ll probably want to code in a failsafe “If a version higher than mine is used, show a warning.”

    The Solution

    Looking at the options we have today, we have to ask “Which is better?”

    Neither. They both suck for developers. They both suck for the users. They both frustrate everyone. I have heard arguments from the same number of developers for each option. Some developers want to include the ‘core’ or a framework in their plugin because it’s ‘better’ than requiring another plugin. Other developers want the other plugin so they don’t have to be responsible to update the library.

    There is, clearly, an argument to be made in both cases. There isn’t a win here. Personally, I think once a framework or library exists as a plugin in the .org repository, you should remove it from your plugins and require it. Of course, good luck figuring out how to do that in a sane way without breaking people. The best I came up with was have a period of time where you keep the library while using TGM or something to require the other plugin. Make an alert or notice to tell users to install the requirement. Keep that for a whole major version. Then, on the next major version release, drop the library.

    With all that in mind, we have to ask this instead “Which option annoys users slightly less?”

    That’s – libraries as libraries, not plugins. The one where the users don’t have to know (or care) about it anything except “I have plugin X.”

  • Unique vs Common

    Unique vs Common

    Someone asked me if I could explain why sometimes I tell people to name their functions uniquely and sometimes I don’t.

    I get how this is confusing, even though it makes perfect sense to me. Here’s how to remember:

    • What’s yours is unique to your plugin
    • What’s common is unique to what’s common

    Okay, maybe that didn’t help. Let’s try a practical example!

    I have a plugin called ‘Genericon’d’ which includes the Genericons library inside. In that plugin, I have the following enqueues:

            wp_enqueue_style( 'genericons', plugins_url( 'genericons/genericons/genericons.css', __FILE__ , '', self::$gen_ver ) );
            wp_enqueue_style( 'genericond', plugins_url( 'css/genericond.css', __FILE__ , '', self::$gen_ver ) );
    

    The first one is for Genericons, the library. There I use the common name of genericons which means if anyone else also enqueues Genericons with this name, one of ours will win depending on load order. For my personal plugin CSS, I use the name genericond (notice that D?) as it matches the name of my plugin and, therefore, is less likely to conflict with someone else’s plugin.

    Conflict is the name of the game here. I actually want genericons to conflict. Well, not conflict. I want it to be recognized as a shared library, so WordPress only loads it once. If I had named it genericond-genericons then, in the event someone has Jetpack or a theme like TwentyFifteen which both include Genericons, they would load the entire library twice! And I would suck. On the other hand, if we all share the library name, WordPress will check, see it’s loaded, and carry on.

    Name what’s yours in a way unique to your plugin or theme.

    Name what’s shared in a way that’s unique, but also stupid obvious and easy to share.

    Font-Awesome? Use font-awesome for your enqueues.

    As for functions and class names, even if you put in a check for ‘if this doesn’t exist…’ the logic works the same. If it’s yours and yours alone and only exists in this code, name it unique to your plugin/theme. If it’s a shared library, like the aws-sdk, name the class in the standard way and wrap it in an ‘if this doesn’t already exist…’ so that if it does exist, it only gets called once.

    Standard names for shared libraries.

    Unique names for your personal codes.

    And bonus! If you keep your names to a standard, while being unique, someone may call your functions too.

    By the way, anything global like DEFINE( 'FOO', true ); should always be unique. Those are globals. Everyone uses them. I’ve made that mistake too.

  • The Big Picture

    The Big Picture

    Decisions, Not Options

    WordPress’s core philosophies are what has allowed it to be extendable, supportable, extensible, and surpass 25% market share.

    One of WordPress’ hallmarks is a massive plugin repository and the ability to extend WP to do pretty much anything. Instead of making the core software huge and bloated, filled with aspects the majority don’t use, WordPress decided to follow a path of ‘decisions, not options.’ With that, the onus is on the developers to deeply learn and understand the implications of any and all changes and additions to the core software. We’re encouraged to separate our personal feelings from what is best for the project and the users.

    We need to think about the big picture.

    I Fight for the Users

    I often say this when I’m in core meetings about ideas for changes that will impact users. Generally these are visual changes, like moving a menu or adding in a more obvious button. When we, as developers, make a decision, we need to have the big picture in mind. Do most users need to decide what quality of image compression to use for WordPress? No. Not because they don’t care, but because the information to explain it is overwhelming to many.

    Recently WordPress increased the default image compression (you’ll see it in WP 4.5). In the proposal, an incredible amount of research went in to figuring out what settings would be best for the majority of users.

    Will the minority, the photography site runners, be possibly upset? Yes. But when we look at the big picture (ironic, I know) we remember that most people will only notice that their sites are loading images faster.

    It’s Okay To Be A Minority

    Most of us started using WordPress and were the majority. We were the target audience and the people it aimed at. Over time, the ways we use WordPress become more and more specific, and suddenly we have at least one way where we are unique and special. We no longer ‘just blog’ on WordPress. We sell our wares, we write novels, we build communities.

    We are, suddenly, a minority in how we use WordPress. This makes it harder and harder to keep the big picture in mind. We are, as humans, inclined to see ourselves first and put our own needs first. Our websites need these things, therefor they are the most important aspect of the upcoming changes in WordPress.

    This isn’t true, of course. But we lose sight of the big picture very easily when the changes impact us, and it tends to make us concentrate on the wrong things.

    I Prioritize the Users

    I speak up for the users in developer meetings when they’re not there.

    I think of them first.

    When I make a change, when I design a change, it’s for the users first. Even when it inconveniences me, even when I feel it’s not the perfect solution for my plans, I consider that what I’m making only is what it is because of the users.

    The big picture is that users make the software what it is. Putting them first in as many things as possible makes it so that they can trust me when I make a decision. When I say “No, this would be better for you as a user but not for your safety.” I know I can say it from a place where I’ve earned the respect and trust of the users.

    You cannot get to that place of trust without putting the users first in all possible things.

    The big picture is bigger than just you, who wrote the software, and you, who used the software. The big picture is all of us.

  • Cooking as a Dev Skill

    Cooking as a Dev Skill

    My friend Dan asked if I’d be talking about cooking as a dev skill for WordCamp Minneapolis.

    While I won’t be making that camp this year (sorry folks), I thought I’d take a moment to talk about cooking as a dev skill. Or rather, what cooking teaches you about developing a website.

    Know What You Want to Cook

    You can’t just decide to throw things together until you’ve been cooking for so long, and you’re an expert at winging it. Most of the time, we pick a recipe we know, or feel we can follow, and decide what we want to make. We have to temper this with what we need to make. If I’m making dinner, I need protein and vegetables. If I’m making a pie, do I need the pie or do I just want something sweet?

    Websites are the same way. We pick the site we want to make before we start building. When you go into making your site, you have to know what you want the site to be. You also have to know what you need. I need a web presence (it’s 2016, yes you do), but I don’t need a video and an interactive game and all the bells and whistles.

    Check Your Ingredients

    Open the door to your refrigerator and make a list of what you have. Look at the recipe. Do you have what you require to make this dish? If you’re ordering out, you get the meal pre-made. When you’re making it yourself, you need to make sure you have salt and butter and tofu and eggs.

    When we talk about webpages, we talk about the code behind it. Can you design something out of nothing? Do you have the tools with which to do so? Can you write javascript and PHP and HTML? These are things you need, these are your ingredients. They’re also going to be your libraries like Backbone and React.

    Mise En Place

    In cooking, setting up everything beforehand makes the entire cooking experience better. I’m terrible at it, but I’m doing my best to get better, because once I’m prepared, everything flows and I’m less of a whirling dervish. The setup doesn’t just keep you organized, it keeps you real. It lays everything out and sometimes, when you look at 10 pats of butter, you may think about maybe cutting down a little.

    Speaking of those libraries, make sure you have only what you need. The whole Backbone repository is over 5 megs. The one file you need is 69kb. Use only what you need. The more individual pieces you need, the more you should scrutinize them. Did you really need all that in the first place? Do you really need eleven css files for options of display, or should you make a basic one and let people build what they want?

    The Cake Will Collapse

    You’re going to mess things up. You’ll burn the caramel, overcook the pasta, underboil the egg, and so on and so forth. These mistakes are okay. As Julia Child said it, “No on will ever know!”

    Do I even need to say it? Your code will fail. A lot. In weird ways. You may spend an hour wondering why WP-CLI fails, only to remember it’s WP_CLI instead.

  • Poor Support Experience

    Poor Support Experience

    I broke my watch. I have an Apple Watch with the Sapphire glass screen, and I broke the glass.

    For reasons that are frustrating, I don’t have AppleCare+. The short version is that I didn’t realize I didn’t have AppleCare until September. The Watch was a present in May (June). I was deemed ineligible, which is annoying, but I appealed and pointed out I couldn’t know I didn’t have it until it was way too late. But I was declined. I didn’t have a receipt, I didn’t have proof, they couldn’t believe me. Fine. I acutally understand that and, were it me, I’d probably reject the claim as well. That meant I knew I was going to have to shell out if I ever needed a repair for a crack. And February 2016 was that time. I took it to the Apple Store and had one of the shittier repair experience of my life.

    I did not schedule an appointment since they had nothing until Monday anyway, and I knew this would be a “We can’t fix it, we’ll send it in.” sort of thing. I got there and was told that they don’t have a walk-in repair for the Apple Watch like that. They do for the iPhone, and the iPad, but not the Watch. Okay. Stupid. Fine. I set a Walk In appointment for an hour away, and went to run an errand. When I got back, the appointed time came and went. So I asked a nice person in an Apple Shirt how that worked.

    This was the first rude person I’ve ever dealt with an an Apple store. I wish I’d gotten his name. He was condescending, brusque, and unsympathetic. He said I should have known that the time was an estimate (sure, I did) and that it could be up to another 90 minutes. I stared at him. How the hell should I have known that? I asked if there was a different line for repairs, he said not and then chided me for not making an appointment. Sorry, make an appointment for four days out when I broke something today that will need to be mailed to a repair center? I did not say that, I looked at him and said “I see. So when you said ‘Around 1:55’ what you meant was ‘Between 1:55 and 3:30’? The guy who checked me in didn’t say that.” He shrugged and I walked off.

    It took another 45 minutes to get to check in. Once I did, they just said ‘Sit at any open stool.’ This is poorly planned, but okay. I sat and after a few minutes, a fellow asked for my name. He tapped on his iPad, found my appointment, looked at the words on it, looked at my watch, and promptly apologized.

    “I’m sorry you had to wait so long for what’s about to be a really fast case.”

    I’d already taken the watchband off and nodded. I knew it had to be mailed in. They can’t replace a screen at the store. He filled in a form, the AppleCare+ conversation was had, and we left being told a link would be sent to me.

    No. Actually I got a receipt for the work order (fine) and no link. I logged into my Apple ID account at https://supportprofile.apple.com/ and was surprised to see my Apple Watch not listed. I added it and went to the ‘repairs’ link (which said I had 1 repair) only to have this:

    Apple could not locate any repairs for the Apple ID: [Me]. Please try again with a different Apple ID or look up a single repair on this page.

    Since the work order had the Repair ID, I put that in and the serial and got a pretty useless status page:

    Screenshot of my apple repair status which only says 'service requested'

    Step 1 | Request – February 10, 2016 : Service requested

    That’s it. Step 2 is Service and Step 3 is Return, but there’s no information like an estimated date or even verification it was sent out. At the store I was quoted 3 to 5 days. Now here’s the thing. I know what’s going to happen. They will get my watch, go “Oh, it’s broken, look at that!” and send me a refurb. I will not get my watch back, I’ll get a new one (a new used one) and it sucks, but there it is. I accept this. It’s a watch. Then they will send that watch back to the store and I will pick it up. And I was told 3-5 days (I asked ‘business?’ since it was about to be a long weekend, and the fellow said they were working Monday), and that I would get notified of status changes.

    But after a few days of nothing, I called Apple and asked two things:

    1. Why doesn’t it show up on my open cases for my Apple ID?
    2. What actually is the status?

    The guy on the phone and the woman at the store were helpful, if disappointing. The Watch had not been shipped out right away. The Dispatch Center did not have it. The store claimed to have sent it and received a sign off, though the shipping folks said that was not the case and status on that repair page still said ‘Service requested.’

    The phone tech said to call back in two business days days if I didn’t get any emails or any information, and he added the case to my account. No not the repair, the case. And the direct link to the repair works, but it’s still not associated with my account. I did what any neurotic would do, and I left the page open, hitting refresh once in a while.

    Three hours later the status zoomed to step 3: Returned.

    February 13, 2016 : Product replacement pending

    So why do I call this a bad service experience?

    It should have been much shorter. Apple could have a simple hardware check. Is it really broken? Yes it is, we’ll send it to repair. And this would be for things that are sent in only. If you want to try and trade it in for a fixed one then and there, it’s separate. But if you just want to express mail in your broken whatsit, why not make this easier? The front gate person can ask two questions: Is it really broken? Do you want to send it in for repair/replacement or trade it in today?

    I also never once got a single email from Apple about this.

    Well that’s not true. I got the first email but that was it. I never got a single status report, like they swore I would. I have root access to my server, I run my own email server, and I checked for every single email with ‘apple.com’ in it for the last 7 days. I found one from bounces@email.apple.com and none from GR_R###@APPLE.COM (I’ve removed the identifying numbers). I checked and yes, they were sending to the right email. The one email I did get was from donotreply@apple.com.

    But. Why were none of these emails recorded in my profile or my repair ticket? Why did I never get the promised texts? Why was there no communication? Why, when I contacted Apple, did they actually say their ticket system still said the device was ‘submitted’ and nothing more? They had to contact other teams to find the information which I was never able to see in my profile.

    As much as I deride my ticket system at the office, the fact that every email is logged twice (once as email and once in the ticket) means I can always go back and see exactly what was sent, by whom, and when. Clearly they have multiple systems, and none talk to each other.

    I did get my Watch back. On day 5. I could have had it back on day 2 if they’d learned how to properly communicate.

    And guess what? The new watch was broken. It wouldn’t vibrate.