Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: coding

  • Customizing a Sidebar Profile – BuddyPress

    Customizing a Sidebar Profile – BuddyPress

    I was looking at BP Tricks and thought ‘You know what would rock my site? A sidebar profile controller!’ Turns out this is pretty easy and only ‘requires’ two plugins.

    My final product (see left) isn’t super impressive, but it’s pretty simple and easy to use. The basic idea is that I have two master widgets. One is what the non-logged in user sees (a simple signup window) and one is what the logged in user sees. The logged in user should be able to see their profile info, their notifications and anythign else I want. Before I got started I made a list of what I wanted them to see.

    • Profile – This lists your profile, edit links, settings links, and a logout link
    • Notifications – This lists everything that can email you: notices/messages, comment subscriptions, newsletters, mailing lists
    • Achivements – I use Paul Gibbs’ Achievements for BuddyPress
    • Activity – Links to the various activity screens

    First I decided I wanted an accordian style profile, where you had sections. I grabbed Tabbed Widgets and tossed that in my widget area. Then I used Widget Logic and set the tab to only show if a user was logged in. If the user is NOT logged in, I used the PHP Code Widget to display a login form. Since I’m using BuddyPress, I just grabbed this wholesale from the source.

    <form id="sidebar-login-form" class="standard-form" action="<?php echo site_url( 'wp-login.php', 'login_post' ) ?>" method="post" name="login-form"><label><!--?php _e( 'Username', 'buddypress' ) ?--> <input id="sidebar-user-login" class="input" type="text" name="log" value="<?php echo esc_attr(stripslashes($user_login)); ?>" /></label><label><!--?php _e( 'Password', 'buddypress' ) ?--> <input id="sidebar-user-pass" class="input" type="password" name="pwd" value="" /></label>
    <p class="forgetmenot"><label> <input id="sidebar-rememberme" type="checkbox" name="rememberme" value="forever" /> <!--?php _e( 'Remember Me', 'buddypress' ) ?--></label></p>
    
    <center><!--?php do_action( 'bp_sidebar_login_form' ) ?--> <input id="sidebar-wp-submit" tabindex="100" type="submit" name="wp-submit" value="<?php _e('Log In'); ?>" /> <input type="hidden" name="testcookie" value="1" /></center></form>
    

    I could have probably done this with a widget, but I like being able to customize my PHP as I want to. Next it was time to build my tabs. The Tabbed Widget plugin is pretty easy to use. You make your widgets in the Invisible Widget area and they show up available for the Tabbed Widget. Using the list I made above, I pulled in the obvious widgets. Three are PHP and one is the Achievements widget which came with the plugin. I dislike using plugins just for widgets, so my PHP is how I customized things. The PHP for notifications has extra cruft you probably won’t need, but I wanted you to see how you could easily port in any link.

    My profile

    <div>
    <div style="float: left; padding-left: 5px;"><strong>Hello, <!--?php echo bp_loggedin_user_fullname() ?--></strong>
     • <a href="<?php echo bp_loggedin_user_domain() ?>profile/">Visit My Profile</a>
     • <a href="<?php echo bp_loggedin_user_domain() ?>profile/edit/">Edit My Profile</a> 
     • <a href="<?php echo bp_loggedin_user_domain() ?>settings/">Edit My Settings</a> </div>
    </div>
    

    My Notifications

    • <a href="http://jorjafox.net/comment-subscriptions/">Edit Comment Subscriptions</a>
    • <a href="http://jorjafox.net/wp-admin/users.php?page=s2_users">Edit Daily Update Emails</a>
    • <a href="http://jorjafox.net/csiwatch/">Edit CSI Watch Subscription</a>
    • <?php if ( messages_get_unread_count() > 0 ) {
    	?><a href="<?php echo bp_loggedin_user_domain() ? rel="nofollow"><?php echo BP_MESSAGES_SLUG ?>">Inbox (<?php echo messages_get_unread_count(); ?>)</a><?php 
    } else {
    	?><a href="<?php echo bp_loggedin_user_domain() ? rel="nofollow">/messages/">No new messages</a><?php 
    } ?>
    

    Activity

    <div style="padding-left: 5px;">
    <ul id="user-menu">
    	<li><a href="<?php echo bp_loggedin_user_domain() ?>activity/">Site Activity</a></li>
    	<li><a href="<?php echo bp_loggedin_user_domain() ?>activity/just-me/">My Activity</a></li>
    	<li><a href="<?php echo bp_loggedin_user_domain() ?>activity/favorites/">My Favorites</a></li>
    	<li><a href="<?php echo bp_loggedin_user_domain() ?>activity/groups/">My Groups</a></li>
    	<li><a href="<?php echo bp_loggedin_user_domain() ?>activity/mentions/">@<!--?php echo bp_loggedin_user_fullname() ?--></a></li>
    </ul>
    </div>
    

    Once I was done making those, I just pulled them into my Tabbed Widget in the order I wanted, with the style and defaults I wanted. The rest was all CSS, which you can do yourself.

    Basically, this just goes to show you that you can do pretty much anything you want with WordPress plugins. I really only needed two to do this, though the third (PHP Code Widget) really helped me take it to the next level. If you’re PHP shy, you can use Login with Ajax instead of my ‘Login’ code, BP Notification Widget instead of my Notification code, and I’m sure people can pick out some alternatives to other code bits.

    Hope this gets you started!

  • Failure of Imagination

    Failure of Imagination

    This is not an excuse.

    People make mistakes, and we all accept that. But what I find astounding is that a lot of users look at the software developers and say things like “I find it unacceptable that you let this critical error slip through.” They seem to think that anything less than a perfect piece of software coded by perfect people with no errors is cause to demean the programmers.

    The other day my father (a seasoned risk analyst – see http://woody.com) passed me an article by Herbert Hecht called Rare Conditions – An Important Cause of Failures, where in Hecht explains that “rarely executed code has a much higher failure rate (expressed in execution time) than frequently executed code during the early operational period.” The point, for those of you who felt your eyes glass over at the big words, is that the less often a piece of code is used, the more likely it is to break.

    I read this article and immediately shouted “Yes! Exactly what I’ve been saying!” And it’s not because we don’t try to write the best code we can, either. It’s because most of us use conventional test case preparation. We say ‘This is what we want the code to do, we shall test it and see if it works. Great! Now what if I did this…’ The problem there is you need a skilled person coming up with the ‘what if.’

    Back in my desktop-software support days, I was testing a piece of software I’d never used before, and I crashed the program. Hard. I had to reboot. And I found I could crash it repeatedly doing that. I called the vendor, who sent their best techs out to look at it. I showed him what I did and he started laughing. What I was doing was something no one familiar with the software, and it’s purpose, would do, because it was simply wrong. Like putting in your phone number in the field for your first name. They agreed that they should error trap it, however, and it certainly shouldn’t crash the system.

    Why didn’t that problem ever show up in their tests? To quote Frank Borman on the Apollo 1 fire “Failure of imagination.” They simply couldn’t conceive of a world where in someone could be that ignorant of the right way to do things. They didn’t document it, because it wasn’t a requirement of their software, but of the process being completed, and they didn’t error-trap it because no one in their right mind would do that.

    The world keeps making bigger and bigger fools, doesn’t it? When you test code, you’re always going to have a bias. You’re looking at it from the perspective of someone familiar with both the program and its purpose. When we test WordPress (and I include me on this as I beta test WordPress and file trac reports when I find problems) we test it from the perspective of experienced WordPress users. We’re the people who read the documentation on what changed. We’re familiar. And that’s the problem.

    So we look at Hecht’s second suggestion. “Random testing over a data set that is rich in opportunities for multiple rare conditions.” Basically it’s making a list of everything that could go wrong, the really wild and rare errors you’ve seen (in the case of WordPress, you could probably cull some great ones from the forums, at work I review my trouble tickets and make a list of the most common), and testing that. Testing stuff you KNOW will break. Again, this has the problem of bias, but it allows you to make sure when your code fails, it fails elegantly. This kind of testing has the other problem of finding the right data set. This really is the hardest part, and takes some seriously dedicated people to come up with one that limits bias.

    Hecht’s final suggestion is “Path testing, particularly where semantic analysis is used to eliminate infeasible paths” but he quickly points out the problems:

    [This] technique can be automated and is the only one for which an objective completeness of test criterion can be identified. However, it is costly and will practically be restricted to the most essential portions of a program.

    So what can we do, other than be smarter? We can test better, certainly, but that’s more difficult than it should be. And why does all this happen in the first place? We’re smart people! We should code better! In a related article (also sent by my father) by David Lorge Parnas discusses Software Aging. In that paper, he posits that too often we concentrate on getting the first release done, rather than looking at the long term goals of the software.

    This article I find has particular relevance to the open source community, which is filled with people who become software ‘engineers’ via non-traditional paths. How non-traditional? In Parnas’ article (dated 1994) he mentions that software designers come either from the classic computer science background or they’re home-grown from their business specialty. This means that a person who writes code for a bank either is a programmer who knows their coding languages and the basics of how to think ‘in computer’, or it’s a bank employee who picks up code and learns it on the job. There are, obvious, drawbacks to both backgrounds. A banker understands the desired end functionality of the program, and the CompSci guy understands who to write it, but not how it’s used. They are, both, too specialized.

    I inherited some code that was undocumented and had the problem of inelegant failures on rarely run processes. Over the last five years, I’ve steadfastly cleaned this up to error-trap correctly and output meaningful errors. I don’t have a CompSci degree. Actually, I don’t have a degree at all, in anything, and while I never declared my major, it was Anthropology (by virtue of the courses I’d taken). As luck would have it, I’m also somewhat ignorant of the purpose of most of the code I write. This means every time I’m tasked with a new project, I look at it with fresh eyes, and I can see the flaws people in their little boxes are unable to see. I’m perpetually on the outside, which means my perspective is almost always ignorant, but rarely is it unintelligent. On multiple occasions, my simple question of ‘Why are we doing it this way? Is it to make it easier on the end user or the programmer?’ elicits astounding reactions. I can help pull the programmers out of their heads and look at the long-view.

    Parnas calls that ‘designing for change’ (a familiar ad slogan in the 1970s). Part of the problem, he thinks, is that people don’t have the appropriate education to their job and, thus, are untutored in the basics of programing and the related thought process. I disagree, and not just because I am inappropriately educated to my day job. It’s true my ‘training’ didn’t prepare me to write code, but my education did. I was taught, from a very early age, to think and reason and question. Those basic principals are why I’m able to do my job and follow along with Parnas’ work. Perhaps he would be better put to say people have not made the effort to learn the basic groundings of good software design, independent of your education and ‘purpose.’ The banker can learn software design irregardless of the intent of his code, and the CompSci programmer can master enough of banking to understand the purpose of what he writes. The middle ground that has the view of goal and design is what allows us to design for the future and write code that can grow and age.

    That all depends on if the code is well documented. Parnas’ rightly twigs to the most common problem I’ve seen in programing. No one likes to write documentation, and when we do, it’s clear as mud to someone who is unfamiliar with our goal and design. If you don’t the goal of the programmers when they came up with Drupal (to pick on someone else for a change), then none of the documentation will help you. Software, being based on mathematics, should have documentation that reflects its parentage, says Parnas. This should not be confused with user documentation, which should have none of that. Developer documentation should resemble mathematical documentation if it has any hope of being useful and lasting.

    While Parnas’ paper was written in 1994, I wonder if the problem of crossover between developer and user was as prevalent as it is today. Today there’s no clear line between the developer who writes the code and the end user who wants to use it. This is the case most noticeably in open source projects, like WordPress, Drupal, Joomla, and so on. These projects are championed by the developer/user, a creature that may not have existed as such as widespread phenomenon 17 years ago. While Parnas does mention the possibility in use-cases, he only does it to highlight the problem of isolation among developer groups, and not as a potential root cause to why problems are missed. They are missed in the isolated groups because we cannot see outside our ‘box’, for lack of a better room, and envision that particular ‘what if.’

    This is why we have a great need for reviews. When a doctor tells you that you have cancer and you’re going to die, you seek out a second opinion. The same is done with software. The code works for you, so you let it out into the world for other people to test. We need the outside sources to come and bang on the rocks and tell us what’s wrong. That’s why you see people like @JaneForShort asking more people to join the WordPress beta tests. She knows the core developers can’t possibly test everything, and the more use-cases we can come up with, the more we can make the end result better.

    Would having more professionals solve this problem? Parnas seems to think so. He thinks that having more people trained in engineering and science combined will produce better programmers. After all, what is coding but math applied to engineering? I feel it’s the techniques that are more important. A grounding in basic algebra (and some calculus, certainly) should be enough to be able to program in most languages. And a well-formed understanding of the disciplines of engineering should allow a person to look past ‘This is my problem, how do I solve it?’ You need innovation, understanding, and a respect for how things work in order to write effective programs.

    Why did we miss a critical error? Because we didn’t see it. It’s always going to remain that simple. With better education, will we be able to see it in the future? Perhaps. But all the traditional book education in the world cannot teach a person how to think. Even if we can perfect the creation of the well-thinking human, we will always be loosing a battle against the universe creating bigger fools. But those thinking people can find the problem, once it’s reported, solve it, and learn to make it better the next time.

    And that should be our goal.

    Make the code better, test it smarter, document it clearly, and plan it thoughtfully.

  • Don’t Fear Wandering Off Topic

    Don’t Fear Wandering Off Topic

    Sometimes when you’re debugging, you haven’t the foggiest idea how someone managed to screw something up so badly that they got this particular error. Naturally they’ll tell you that they didn’t do or change anything, and sometimes they’ll even be telling you the truth! It’s at that point I try to teach my guys that it’s okay to wander off the script and start talking about anything else, in order to learn how the person thinks.

    Everyone’s thought process is different. Some of us learn by reading, some by watching, some by doing, and others by listening. There’s no one perfect way to solve a problem, but that doesn’t stop managers from trying to codify the how-tos into a script to follow. We’ve all been there, where we’re told to reboot our PC to solve a modem problem. There is no secret shibboleet call to get you to the smarter people.

    I will say that the reason the scripts exist is because they do work. I couldn’t begin to tell you how many help tickets are solved when I ask ‘Are you using the default password of changeme?’ Heck, even telling people ‘Reboot.’ is correct sometimes. That’s the thing, though. SOMETIMES. You have to learn how to tell when ‘sometimes’ is now and when it’s not. For example. I add a user to a domain group on Windows. Our setup of Windows XP systems pull down domain group info (and all permissions allocated therein) on login. User says the permissions that come with the group aren’t working. I tell them ‘Reboot so XP can apply the settings. Sometimes it gets persnickety.’ They reboot, we’re done. But notice, I know how and why the problem occurred, and I can explain it to the user.

    But. Sometimes you get yourself down the rabbit hole with a crazy problem. “Hi! Every time I add a file, it locks the system.” Okay, time to sort out what’s getting locked. What’s not cleaning itself out, what’s acting ‘weird.’ Does it work for you? It does. Interesting. What’s HE doing? Let’s ask. “I’m using a home grown script to add files.” Oh. Betcha that’s it. I actually spent three days and a call to the vendor trying to debug a problem like this because the guy refused to accept that HIS script was POSSIBLY screwing things up. Actually he didn’t even mention the script until I started chatting about workflows and productivity and he mentioned, in passing ‘Yeah, we had to write a script because it took too long.’

    This isn’t about how when you ask for help, be specific and tell them exactly what you’re doing in as clear and simple a way as possible. This is about how, when you’re talking to someone, it’s totally okay to wander off topic and ask something off the wall. “Are you using Firefox beta 4? You are? Did you know that there are problems with that and TinyMCE?” Sure the question sounded hella random, but it was the debugger’s brain pinging off the wall at a memory.

    When you’re helping people, remember that they learn differently from you as well. As much as people tout ‘thinking outside the box’ as a call to innovation, I think that’s not what they mean. What they mean is being willing to take a chance, a risk, and make a stab in the dark at a possible answer. A genius is the one who looks at a moldy cheese sandwich and thinks ‘What the hell is IN that green stuff?’ A genius is the one who says ‘It’d be easier if could clone a server.’ A genius is the one who both thinks and applies the thought to something.

    When you’re stuck troubleshooting, wander off topic. Be willing to think of the crazy things and voice them aloud. Be willing to say ‘I doubt this has anything to do with it, but what happens if you do this…’ Be willing to ask the ‘stupid’ questions. Go ahead and talk about Bad Wiener day. The scrunchy joke may make you remember something totally off the wall.

  • My WordPress Scripts

    My WordPress Scripts

    I actually have a couple little scripts I use to update my site instead of using the WordPress built in tools. Invariably, when someone has problems with the automated upgrade tool I comment that I rarely use it. That means people ask me ‘Well how do you update WordPress?’ and I tell them ‘Manually.’ Which isn’t really true. Sometimes I say ‘I wrote a script.’ So … here’s my scripts for upgrading WordPress. I don’t have one for themes, since I always do that manually and check everything. That’s the bane of having highly customized child themes.

    These are both Bash shell scripts and run perfectly happily on my server (Linux running CentOS). They’re GPL2, free, and somewhat use at your own peril.

    WordPress Upgrade Script

    WordPress Plugin Script

    As I went to post these, I took a bit of time cleaning them up, putting in comments (the ‘Blame Nacin’ bit is a joke) and formatting them nicely. When I started to look at the plugin one, I realized how freakin’ crazy it is and how many weird custom things I tucked in there. Also I made it so you always had to put in a version number, which if I wanted to ‘release’ that, is something to do away with. One of the catches with it is that a plugin’s ‘default’ zip file of plugin-name.zip is the trunk build. So you’d always have to know your version to upgrade.

    On the WordPress upgrader, I could trick that with a simple “if the version is ‘latest’, then download latest.zip”, because the WordPress most recent release is latest.zip. Now, I never call that. I like being master of my domain (pun? maybe) so I always make the time to know what I’m calling. I could have assumed that if you don’t put a version in, you want to install the latest, which is pretty easy to flip around, but I don’t like to assume like that. Still, you can take the code if you want it and do that.

    On the other hand, I think if someone wants a plugin, then they should be able to go ‘Get me the plugin’ and it should default to the latest. Probably this is because I test trunk WordPress a lot, but rarely do I trunk a plugin. Since there’s no easy to gank default like that for plugins, I came up with this really fun bit of code, shoved in an if-then check. I really like awk, by the way. It’s insanely powerful.

      # We're getting the readme from the repo and using that to calculate the latest stable release.
      wget -qO $1-readme.txt http://plugins.svn.wordpress.org/$1/trunk/readme.txt
    
      if ! [ -f $1-readme.txt ]
      then
        echo "FAILURE: The plugin is goobered in the WordPress repository, so we can't determine the latest stable release."
        exit 1
      else
        tr -cd '\11\12\40-\176' < $1-readme.txt > $1-readme-tr.txt
        VERSION=.`awk '/Stable/ {print $3}' $1-readme-tr.txt`
        rm $1-readme.txt $1-readme-tr.txt
      fi
    

    All these are free for use, and both are under GPL2. I can offer SOME support, but they’re filed under ‘Works for me!’ in my bin.

  • When to Code

    I used to say “Don’t hack core, make a plugin. Don’t make a plugin when you can edit your functions.php. Don’t edit functions if it’s a one-liner in your .htaccess.” The concept behind it was that people tend to over-complicate things by over-coding. I don’t say that much anymore, since I’ve found that plugins are more useful than functions a lot of the time, and really those are theme specific. But I maintain my basic argument that the simple way may be the best way.

    No software design is perfect, and much of picking the software you use comes down to personal preference, at the end of the day. I worked through Y2K in desktop-software, testing it and validating its usage. One of the many things I learned was that personal preference will kill you, and spending a lot of time customizing an interface to be perfect for you is time wasted. At work, I use the bog standard Windows XP install. I have no customization on my desktop, fonts or display, save to make the screen resolution something easy on my eyes. The rest of the time spent making it ‘pretty’ is wasted for the purpose of work. My desktop is my desktop. The software I install is as much customization as I ever get.

    I also don’t generally customize my fonts in applications. Again, this is time wasted, and minutia I will have to remember later on when I inevitably re-build my computer from scratch. The only ‘customization’ you should be doing is adding in that which is required to use the software (user name, server name, passwords). And all of those should be saved in a config file, call it a day. The exception to this rule is how I customized Putty, but again, I saved the configuration in a putty.reg file (I know, I know) and when I have to reinstall it, I re-load that. Anything I want to customize must be easy to re-apply, both technically and mentally. I don’t want to spend an hour farting around trying to remember ‘what was that setting…’

    Similarly, when I look at wanting to do something on a website, I take the time to determine if this is a one-off change for one moment, or something I want to repeat. I think about how the change is going to affect the overall workflow of my day-to-day functions. Will this improve everything or just make today easier. Can I apply it to many things, or is it specialized and localized. Most importantly, do I need to recode to do it, or can I utilize something that already exists.

    It’s not a factor of being lazy, though like everyone else in the world, I am. It’s a factor of reinventing the wheel. Many times I end up writing from scratch, but other times I’ll sit and think ‘You know, this works about 90% of what I want. I’ll just change it.’ Now, as a good little coder, I fork my code when I do that, or split entirely and make something with a new name. I don’t ever hack core. If I can’t do it in a hook (be that a function or a plugin) or a config tweak or a customization, then something’s wrong with what I’m trying to do. Or possibly the way I’m trying to do it.

    Sometimes I find the best solution is to accept the limitations and make it the best I can within them. That’s always a fair cop too. But I never presume there’s only one way. I’ll chase the rabbit down the hole, through the tunnel and out the other end multiple times, in order to come up with the best way, not just to fix the problem I’m having today, but to make sure I fix it for everything, without impacting anything, and that it’s the right solution for the long run.

    This process usually begins with writing down, in plain english, what I want to do. Then I study the source code to find out where to change it. At this point, I stop coding again, and go into the documentation. On WordPress I review the trac tickets related to this portion of code, and for vended software I actually read their documentation and support sites. You see, now I want to know if I can sort out why they do things this way.

    For example, if I wanted to make the new WordPress 3.1 admin bar show up for all users (like the BuddyBar on BuddyPress) and have the login option (like the WordPress Admin Bar on WordPress.com), I could do this via hacking the code easily. But. In reading JaneForShort and Nacin’s comments in trac and on IRC, I followed their logic as to why this isn’t available out of the box. After all, these guys have access to the code on WordPress.com, so they could have lifted it whole sale. While I can see value in having it available, it would include too many options for a first-round change in 3.1. Maybe this will start to slide over in 3.2, but for now, the idea is to get the world used to it, so your options are on-or-off, and that’s it. I then wrote a new plugin, pretty much a raw duplicate of the admin bar code, that disabled their admin bar and ran mine instead for tests.

    Perfect? No, but it lets me test what I want without hacking core. Right now, I can see exactly why you don’t show the bar for logged off users: it’s ugly. This is something I knew going in, though, because I took the time to understand why the code was done the way it was. Do I agree with it? Yes and no. I agree that, as a short term goal, it was better to fix what was in and add more later. I don’t think this should be the end of it all, and I’m sure it won’t be. Growth and change are inevitable in most things.

    The real decision is if I want to implement my code now, or wait till 3.1 is out and then posit it as a change on trac. In the end, I’m playing with it on my desktop instead of anything else. I want to see where the thought processes for 3.2 takes things, and I want the time to clean up my code. It might be a passing fancy right now for both me and WordPress. It might be something I go “Oh! Shiny!” and change my mind on. But I have the time because this is something to interest me and it’s not a need.

    That’s the real crux of the matter: wants versus needs.

    Knowing the difference between a want (like shiny flash graphics) and a need (readability) helps me determine if the change I want to make is worthwhile. Knowing how to look at my desires and separate them from the demands is imperative when you’re writing code or building a house. You may want all the cool bells and whistles, but you have to take the moment to strip them out and get to the basics. There are always basics to fall back on, and ignoring them due to the blindness of bling will hurt you in the long run. Don’t let your customer base pull you from that track either. Sure, they want all the features the competitor has, but pay attention to the downsides of that, and educate them. If they’re right? Of course you should listen, but it’s your job to teach the customer to have realistic expectations. Yes, you can remove the /blog/ stub from your MultiSite installation, but there are risks. Be aware that the shiny removal may not solve every problem you’re having.

    When do you code and when do you say ‘This is what it is’? There’s no right answer. But knowing how to think through it and apply your mind to the entire problem, not just the ‘this is what I want now’ but also the ‘and this is the big picture’ will help you in every aspect of your life. Listen to the wants, respond promptly to the needs. We would like a jacuzzi tub in the bathroom, but all we need is a shower. Don’t let the fancy spigots distract you.