TravisSwicegood.com

Shocking, I know, but it's true. Earlier today, Kansas Governor Mark Parkinson participated in an online chat in which he admitted it. I asked why he did not have any blog-like features on his self-styled blog (which Artur Bagyants properly deemed an e-newsletter) such as commenting. His full response can be read in the chat transcript, but here's the interesting part:

I've received lots of input [after the launch of the site] that to be a real blog we need to make it interactive. We're looking at that possibility right now. I would love to know what people are thinking but we have to balance that with the very real fact that there are inappropriate postings all over the web. We're trying to figure out if there is a way to make the blog interactive and still keep it [to only brief nudity, some acts of violence, and the occassional use of profanity].

Wow!

Ok, so he didn't really say that. It was actually that he wanted to "still keep it at least PG rated," which as Jake Lowen points out includes what I just attributed to him. I believe everyone who read what he wrote understood what he meant, but things still get taken out of context. By not having comments on his "blog" directly, he can limit the official exposure he gives to such trivial content.

I'm sure there's also the fear that someone'll post a link to goatsee pictures or some such and ok, that's fair enough. But that's what comes with the territory. The world, including the Internet, is full of crazy people. Deal with it. Someone posts a link to an offensive site, take it down. Someone uses language that's beyond what you deem polite, edit it. Publicly, though. Make sure you replace the text with something that shows its been edited.

This isn't that hard. Blogging is about being out there. He acknowledged that in his first post. He said he'd be the only one posting with his name. Anyone else posting would be posting with their name. Bravo! He's sticking by his content as his. That's great. But... That's only part of the battle. Enable unmoderated comments and reserve the right to take anything down. Afterall, we're stepping into your domain (pardon the pun). Don't put up with it people screwing around on your site, but don't discourage the conversation right off the bat.

19 June

Fuck off, humanity!

Author's note: This is for me, and me alone. Don't like it? Don't agree? Replace "humanity" in the title with your name.

There, I said it. I just got through reading this post (warning, you'll hate humanity after reading it). Seriously people, what the fuck is your problem?

Ok. I'll use my inside voice now. If you've read this blog for a long time, you know that I am firmly in the gay rights camp (it's equal protection under the law, stupid). I've been taunted in some posts for it, called names, had family members "pray for me", etc., etc. But the one that gets me: I've been asked "you're not gay, why do you care?"

She rode her bike to go to the store. She never came home. They found her bike in a dumpster. Late that evening they found her. She had been assaulted with a sledge hammer, they think, judging from the bruises all over her body. Her knee caps had been broken. She had been gang raped. They buried her alive.

Why do I care? Cause there's a family right now that's reeling from tragedy upon tragedy. Their father just died, their mother was maimed, and now their daughter was tortured, gang raped, then buried alive. Think about that for a minute. She had both of her knee caps broken with a sledge hammer, then buried alive.

Why do I care? More importantly, why the fuck don't you?

Recently a friend of mine came out to their parents. Their mom broke down in to tears. Not because of any disappointment or anything like that, but because she was worried. She was worried that the world was a mean place, and that people would be mean to them and their partner. When I heard that for the first time, I chuckled. I live in a little bubble in Lawrence. That doesn't happen here.

But this is why their mom thought that. This is what went through her mind. What century is it again? Are we not above this? Have certain parts of our species not evolved past grunts and pointing?

Right now all I want to do is think of insanely violent and cruel things to do to the people who did this. It doesn't serve a purpose, but it makes me feel better. Makes me feel like I have some sort of control over this blue marble.

She worked her way out of the almost grave and crawled for three hours to get help. She was put in the ICU and given little chance to survive. Last night she died.

She dug herself out of the grave and crawled for 3 hours. She got help. Then she died.

Has an amazing what's it all for feeling to it.

2 June

My goals for the PHP standards group

A few weeks ago at php|tek, I corralled developers from all of the major PHP frameworks into one of the conferences rooms. The idea was simple: in the PEAR Group we've been discussing our new PEAR2 Coding Standard and have come to some conclusions on how PHP 5.3 code should be handled moving forward. A standard is only a standard if people use it, though, and PEAR is not entirely representative of the community at large.

That's where this group comes in. By having official representatives from PEAR, Agavi, Cake, Solar, and Zend Framework and unofficial representation from Phing and Symfony, we had a good cross section. I went into the meeting with 3 items I wanted to pick off, which were, in order:

  1. Namespace usage and package/component naming structures
  2. Naming of classes, interfaces, and abstracts
  3. Naming standards for Exceptions

I had hoped that we'd make it through the first one, but fully anticipated it taking longer. About 20 minutes into the meeting, we were already moving on to the second item! We flew through the list and were all extremely energized by our productivity. We decided to form an official group of our projects to oversee the creation of this standard and work toward better, more widely adopted standards across our projects.

We also decided to setup a mailing list. Given all of our experience with the proletariat, we decided to make the list moderated. This has proven to be the biggest flash-point so far, drawing criticism from the creator of PHP, himself.

For better, or worst, I stand by my decision to vote for a moderated list. Below is what my vision is. It's my vision and mine alone, but this is where I'm coming from. I posted it earlier this morning to the internal list that we've started to discuss moving these standards forward.


I'd love to see an officially sanctioned standard come out of our work. All of us are too busy, both with real jobs and our various projects, to fight the battles that come of trying to make this a completely open process where anyone with an email address can contribute. Sad as it may be, pear-dev has demonstrated that coding standards *must* go the way of sausages and laws lest they devolve into a constant "but I think <insert favorite coding standard pet peeve> is better, and this is why..." followed by pages of well meaning, but generally irrelevant content.

My reason for wanting a standard is simple, I move among other coding communities in addition to PHP and I am constantly put in a position that I must defend PHP against criticisms that it is unmaintainable, barely useable, and only useful if the least common denominator is your sole concern. Needless to say, I think those are opinions are misguided at best, and patently wrong at worst; but then someone looks at WordPress or phpBB or <insert favorite "I'm amazed it actually runs" project written in PHP> source code and has all their criticisms validated.

As a community, we need to be able to come together and agree on a coding standard. When code is published for public consumption in a year, I would love it if the first comment on blog posts or mailing list messages announcing the new code is "wow, that's great, but you should run it through phpcs." In Python it's not uncommon for pastebin'd code or newly published code to have a response "read pep 8." They aren't trying to be mean or petty, they're just trying to guide someone down the path to good citizenship in the Python community.

Given it's frigid—even hostile in some cases—reception, it does look like having an official coding standard for frameworks and libraries is our best outcome. Hopefully, with the projects in the community we have behind this we'll be able to build up a consensus and prove our decisions the correct ones. If not, then at least we've expanded the number of projects we can easy move between out from our small enclaves to a wider swath of the PHP landscape.

Tags: php, standards

13 May

Magic is to Python as Java is to PHP

Wow. I touched a live wire today in IRC without meaning to. I lamented over the inconsistency that Django has between it's generic views. It has to do with what the Python community calls magic and goes something like this.

Django ships with these great generic views (if you're coming from another web framework, consider their views as controllers). Working with any framework long enough, you know that there's only so much to do. Handle posts to update, grab a list of objects or a single object, pass them off to the presentation layer, hand it off to designers and call it a day. They work great.

There's a series of generic views for handling object updating and deleting. They're the django.views.generic.create_update views. Of course, you don't want just anybody updating your content, so you probably want to be able to require that users are logged in. Easy enough, add the login_required variable to the dictionary of options you specify for the view and call it a day. One line of code in the dictionary that both your add and edit rely on and you're done.

Until you get to the list of objects. It's located over in django.views.generic.list_detail.object_list and it complains rabidly when you include a login_required value. Turns out, that generic view doesn't support what seems like an obvious option to modify it's behavior. After all, you might not want lists of your objects just floating around out there. It's an inconsistency between the generic views, and annoyed me.

I mentioned something to that effect on IRC and ended up in a lengthy discussion about it. Turns out there is an acknowledged inconsistency, but the problem is that the create_update views take login_required rather than the list_detail is missing it. There's a perfectly acceptable way to fix it: decorators.

There's a problem with this, though. Decorators have multiple syntaxes. The convenient way to do them is like this:

@login_required
def some_view(request):
    ...


In a generic view where you're referencing a function that's already declared, that doesn't work. Instead, you have to declare it like this:

login_required(some_view)


Still doesn't seem horrible, but here's the catch. Everywhere else you work with URL patterns in Django, the tendency is to refer to the view as a string. Note that the parameter to login_required isn't a string. That means you have to explicitly import the views you want to use, otherwise Python has no way of knowing where that function exists.

That personally offended my sense of code aesthetics. I mentioned it and said that I would just allow login_required to be there. It's ubiquitous enough that it seems like it should be available all of the time, for every view that accepts parameters.

That was quickly shown to have errors as there were two ways to handle that:

  1. Every view everyone will ever write in every Django application everywhere must take a "login_required" argument and include the appropriate code to handle it.
  2. Anybody who wants the behavior can do "login_required(some_function)"

That's the two obvious ones. I added the third.

  1. or, the framework looks for the presence of login_required and decorates the function appropriately

And thus I touched the live wire and magic missiles started flying. If you're reading this post via Planet PHP and you've made it this far, you're undoubtedly wondering what all this Python and Django talk has to do with PHP. Well, it has to do with magic and Java.

See in PHP circles, the quickest way to end a discussion is to say that some piece of code acts or looks too much like Java. Try to code in object-oriented PHP and risk being dismissed with "PHP isn't Java". Once that's thrown into the conversation, you might as well call it quits. Java is tainted goods in PHP community. The culture is such that it's shear mention is enough to send shivers down the spine of aspiring PHP'ers.

That shiver inducing phrase in Python appears to be "magic." Be explicit, that's their motto. Doing anything without explicitly asking for it is considered "magic" and should be shunned like a leper with the plague. To be flip, you could change it around to "I'm fine, I can do it myself, leave me alone."

Me personally, I'm lazy. I like having hooks deep into a system where I can apply things at will. I think things like the user authentication system should be able to add framework-wide hooks so when a login_required is encountered in the parameters it can auto-magically make sure that the user is authenticated. I love it when a framework takes work away from me, that's why I use them in the first place.

I've always been slightly amused and distressed at the PHP community's need to shun Java. As an outsider to the other communities, I've often wondered what set them off. Now I've found at least one in Python and I'll keep my eyes open as I start my foray into Ruby to see what sets them off. Guess this just does show how similar all us geeks really are. Different words, same reactions.

Random question to my readers (all five of you): do you do Ruby? If so, what's the sacred cows there?

26 April

Race Report: God's Country Duathalon

Wow. It's been a long time since I've written one of these. Yesterday I participated in my first race in near (if not over) two years! Time flies, etc.

Yesterday wasn't a traditional mountain bike race, it was a duathalon. God's Country Duathalon, 4 mile trail run, 12 mile mountain bike loop. Before you go getting all impressed at my multi-sport abilities: I didn't run, I raced a relay. A friend of ours is training for the Lincoln Marathon, which is next week, so the 4 mile trail run was a nice warm-up for the real festivities.

If yesterday's run is any indication, she'll do great next week. I was hoping for a sub 40 minute time and she came in at a touch over 35 minutes. I knew there was at least one co-ed team in front of us, so I was off. The River Trails are really fun for 29'ers. You get in the big ring and never leave it. The lowest gear I hit the whole race was 44x28. It's a really ripping course.

We did a lap and a half. The first lap I picked off at least 30 riders. Most of 'em were solo, but I saw a few 700 numbers on legs as I went by. It felt amazing to be riding against a clock that wasn't on my handlebars again. It's been way too long for that feeling.

I wasn't running a clock, so I don't have the exact time, but I believe I turned the 8 mile lap in a bit under 35 minutes. The half lap was good too. Before I knew, I'd covered the two miles to the turn around and was heading back. I got caught up in a few places where riders were starting to pile up which lost a bit of time, but everyone's out there to race, so ya can't complain. Once I hit the levy for the two mile leg back, I turned it up. There was one guy about 200 yards in front of me that I couldn't close down any gap on, but I pulled in another 6 or 7 riders there too. The 29'er wheels with a 44 big ring really leg ya crank it out on those long straight aways.

We ended up with 2nd place. I was 51 seconds off of closing down the gap to first place. Really makes me wonder if that wasn't the guy who was up in front of me that I didn't catch on the levy. If that's the case, we were about 100' away from each other on the singletrack and I was closing. Too bad there wasn't more single track. :-)

I'm happy though. I felt strong and pulled us into 3rd place in the overall relay and 2nd in the co-ed. Out of some 9 or 10 relay teams, I'll take it.

With the leg only being 12 miles, it felt really short. The last race I did was the twelve hour race in Gallup as part of a team. I think I put in right at six hours on the bike that day. There was a mountain bike race after the duathalon, and though my legs still felt good, I knew I didn't have that kind of juice in 'em for two short races. Now, had this one gone for another 12 or even 24 miles, I'd have been stoked.

It's nice to see that the legs are still there, even with all of the neglect and abuse I've given them in the last few years. The nice thing is that I really think my lungs are just high altitude only at this point. I pushed my legs a few times into the red zone yesterday, but my heart and lungs were in great shape. I don't think it'd take much to get back into race shape again.

Hopefully, this won't be the last of these for the year. I have a few races in mind I'd like to make, just a matter of everything lining up properly.

30 March

Starting a New Chapter

Have you ever read a book where there's an empty page between chapters? You finish the chapter, turn the next page, and nothing's there. Quickly, you turn to the next page to make sure your book didn't ship with a page that went unprinted. It didn't, but it does give you that brief moment of pause.

I just turned to a blank page. I know there's a new chapter getting ready to start, but I'm going to take a moment to savor the green field that is that blank page. This week is my last Ning.

I've spent a lot of time and done a lot of soul searching, and just felt that it isn't the correct place for me right now. The team at Ning is truly amazing. I've never worked on a team with as much depth as the one they've assembled. Everyone there is a rock star. That said, I need something different.

I don't know what's next... yet. There's lots of great ideas out there and I have a few personal projects I want to spend some time on:

  • PHPT is is dire need of finishing and documenting. It runs, but doesn't handle everything in php-src which is it's true test.
  • I want to spend a bit of time with YABT. I've got some ideas I want to try out and see if they work.
  • I've been "learning" Cocoa and Objective C for something like 5 months now, I want to get actually get proficient in it as there's a few apps that no one else has done yet that I'm going to write.
  • I'm getting the itch to write more. That means more blogging and I have a few ideas swirling about for books. I said I'd never spend another summer writing, but I might just if one of these ideas gets some traction.
  • And as they say... and so much more.

Sounds like tons to do. Of course, I can't spend all of my time working on my pet projects, unless I find a benefactor/patron (and if you fit that description and are looking for someone to sponsor, please do email me), so if you're looking for a senior level PHP dev and have an interesting concept, drop me a line or leave a comment.

3 March

CoreNetworks.net: This customer's perspective

Following this blog as religiously as I'm sure you all do, you know that from time to time I get pissed off at the service I receive and use this blog to vent about it. This isn't one of those posts.

For the last few years I've had a dedicated host at CoreNetworks.net. I host my PEAR channel, my private Git repositories that I use to share things between computers, and a few miscellaneous things on the server. There's nothing major there, but there's a lot of stuff I don't want to lose.

My server runs Ubuntu Server Edition. For what I use it for, it's great. The packages stay up-to-date, the server keeps itself running, I'm happy. I was going on 6 month uptime cycles. Up for 6 months, do a distro upgrade, reboot, and be up for another 6 months. For whatever reason, I didn't get this last upgrade in. Sunday, I decided to fix it.

I checked the upgrade process to make sure it hadn't changed. Sure enough, it hadn't. A quick sudo do-release-upgrade and I was off to the races. That's when it all started.

My root partition was full. I started poking around to find out what was filling it up. All of the usual suspects were on their own partition and had plenty of room. I'd only allocated 500Mb to my root partition as I thought nothing important was going to end up on it.

Umm... this might not be good. Just moved /lib to /usr/lib2 and tried to symlink it (partitioning issues). ln can't run, nor ls :-/ #ubuntu

After a few minutes of investigation I found the /lib directory. It was taking up a little over 80% of my 500Mb. Simple enough fix. A quick mv /lib /usr/lib2 and a ln -s /usr/lib2 /lib and I would be done. No harm in that. Or so I thought.

As soon as the mv finished, I went to create the symlink and got an error. ln wasn't found. I tried an ls and got the same message. At that point I got a sinking feeling in the pit of my stomach. cd still worked, but not much else. Anything that's part of Bash was gone.

Now panic started to set it.

Seriously?! WTF #ubuntu. Am I *so* far out of date that I incorrectly assumed you wouldn't put anything in the fucking / directory?!

For those of you who follow me on Twitter, you'll recognize that I was a little miffed. I keep cursing to an absolute minimum on my Twitter account. Sure, I've only got 140 characters to fill with an update, but I don't have to be so lazy that I can't come up with something other than cursing to fill a post.

I hopped on the #ubuntu IRC channel and asked what my options were. Boot to a LiveCD was the only semi-helpful answer I got. The server's located in California, so that's why it's only semi-helpful. It's not like I can pop a CD in the drive and reboot it. My favorite response was someone trying to be clever with their "that's much more creative than rm -rf /" comment. Sure, in retrospect it was, but that's not the answer I was looking for at the time.

I called a buddy of mine who's a sysadmin, and T2 and Eric showed up at my front door. They'd seen my prolific cursing in a private IRC channel and wanted to come over and heckle—err, I mean help.

Now, to bring this back full circle to CoreNetworks. I determined my best bet was going to be the LiveCD via KVM. It basically lets you act like you're sitting there with a keyboard, video (i.e., monitor), and mouse hooked up to the machine. I checked the CN website looking for a phone number and couldn't find one. I fired off an email to their support email address asking if it would be possible to get a KVM instance going with a LiveCD and asked them to please call my cell if it was possible.

I need to back up just a minute to bring you fully up-to-date. Unless you've clicked on one of the links to CoreNetworks, you probably haven't heard of them. They're a dedicated hosting provided that provides excellent prices on dedicated machines. They have one server that starts at $29.95 a month! When I first started having web sites hosted, that's how much it cost for a shared account!

They don't offer lots of fancy extras, and it's just a plain ol' box. They're not bottom of the barrel on prices, but they're nowhere near the top. Their network is reliable, I've never noticed any major downtime on it. All of this for a really reasonable price. I don't have their $29.95 server, I pay a few bucks more for one of their upgraded machines, but it's still very low for what I get.

I've never had an urgent request go in to support in the time I've been using their service. At that, I think the only reasons I've ever contacted them were billing related (credit card expired and one time they randomly shut me off for an hour saying I hadn't paid my bill when I had). I had no idea how my email would be received. I honestly didn't expect a response until Monday.

About 5 minutes later I got a call from a number I didn't recognize. My heart jumped at the thought it might be them. Sure enough, one of the guys in support had seen my email and was wanting to verify what I wanted, then set off to get it going. Another 5 minutes and I had an email with instructions to connect to my KVM and told me that the LiveCD was loaded!

With that, it was a few quick commands to get the files back in the right place and reboot and it was done. Piece of cake with the KVM+LiveCD, but still, my heart skipped a few beats when I realized what had happened right after I saw that first error message.

This was amazing customer service, though. These guys won a customer for life by going above and beyond my wildest expectations for them. This is all from a provider that doesn't have a flashy web site. They don't push anything as whiz-bang or the latest gizmo. I doubt the words cloud or elastic appear anywhere on their site. I've never noticed a banner ad for them on any of the development websites I frequent.

The only time I've ever heard mention of them is when a friend of mine pointed me in their direction saying that they offered solid services at a great price. I've always recommended them to friends when they ask about hosting. Given this past weekend's experience, I wanted to recommend them to a broader audience.

I can't recommend CoreNetworks highly enough if you have a need for a dedicated server. It's reliable, and, should you need it, their support is excellent.

20 February

Flying under the radar

Yeah, I know it's been way too long. This isn't a real post. Sorry for getting your hopes up.

I'm just saying that I've been flying under the radar (as the number of tweets show), but that'll be changing before too long. I have a huge backlog of things I've been meaning to blog about so that should keep everyone happy for awhile.

4 January

Select isn't broken

It is rare to find a bug in the OS or the compiler, or even a third-party product or library. The bug is most likely in your application.

That's the 26th tip from Pragmatic Programmers. There's a funny story on pages 96 - 97 about an engineer who spent weeks trying to work around a bug he thought he'd found in the Solaris operating system. After all of his work arounds failed, he was forced to go back over the documentation. It's then that he found out what he was doing wrong and promptly fixed the problem.

I read that story some half decade or more ago now, but I'd do good to remember it more often. My mind jumps to the fanciful because it's more interesting. Chasing down bugs in the language or database or someone else's code means you get to play with new stuff, and what's more important to my subconscious is that it means I didn't write the bad code.

Working in new languages often brings this type of issue up. Those first few toy scripts I write working through a book or online tutorial often fail. I look over my code, find the problem, and fix it. Once I've got a little bit of a handle on the language, though, I revert. This just happened to me.

I'm still working on my site. Today I decided to refactor my Flickr integration into something a little more robust. xmerl has proven unreliable in odd cases and I've read a lot of good things about Erlsom, so I completely rewrote my XML parsing code to use Erlsom instead of xmerl, moved my main_controller.erl over to use the new code, and started running it. Had a few simple errors, then I ran into a nasty error being thrown by ErlyDTL:


crasher:
    pid: <0.93.0>
    registered_name: []
    exception error: no function clause matching 
                     proplists:get_value(square,
... snipped ...

And a huge big tuple followed that. I ran the code again, same error. Switched back over to the compiler, ran the code that was generated the square tuple and it came back fine. If you're familiar with proplists:get_value() or ErlyDTL, you already know the problem. I was passing in a tuple instead of a list. The fix is two characters changed, but I was already a few hours into a hacking session, about the time I should have been taking a break, but instead, I was off to the races.

I tracked the code down to erlydtl_runtime:fetch_value/2. Ahh, it only handles atoms and Erlsom returns the keys in its key/value pairs as lists. Simple enough condition to check for on an error and recover from. Wrote that up, tested it in the compiler, everything worked there. Loaded it up, still getting errors.

An hour later I discovered the tuple to list error. I got so caught up in the problem being somewhere else that I missed the obvious information right in front of me.

2 January

Playing with BeepBeep and Flickr

I love playing with Erlang. I don't have much occasion to use it, but then a perfect opportunity presented itself. Meg and I bought a house, and me being the eternal geek that I am thought it'd be fun to build a site that aggregates all of the content we generate on our blogs, flickr, etc., that have to do with the house. I could write a site in PHP that does this in a few hours, but where's the fun in that? Instead, I've decided to implement it in BeepBeep, a new Erlang, convention over configuration framework.

If you're not familiar with BeepBeep, don't worry—not many people are. It's the framework I would have built for Erlang had Dave Bryson not done it for me. It uses MochiWeb for HTTP, ErlyDTL—an Erlang version of the Django Template Language—for templating, and a router to translate URLs into a controller and action. The result? This:

Ok - so it doesn't look like much, but those 20 images are being generated off of this feed of photos from Flickr. It's nothing special, except that I had never worked with xmerl until this past week and it'd been nearly a year since I'd done anything with Mnesia. What do those have to do with Flickr? Well, there's no Flickr module for Erlang (yet), so I have to parse the raw XML that Flickr generates and I don't want to do that every request, so I'm using Mnesia to cache the photos from Flickr locally.

I had originally started out with an in-memory cache for the photos, but this evening I rewrote the entire lib_cache module of my app to use Mnesia. I still need to do the code that handles expiration, but that's coming. Once I have that in place, I'll be ready to rock. I don't have OmniGraffle installed on this computer or I would do up a diagram of the code. I'll save that for another post. :-)

Concurrency oriented programming is definitely fun. At Ning, we're always keeping an eye out for that sort of programming because of the volume of users we have to deal with. Why make a user wait when you can spawn off job in the background to do things like update caches, change data structures, and so on? The fact that we're doing this in a language such as PHP just goes to show that it really is what you're doing with the language, not the language itself, but there's a part of me that wonders what would happen if a site like Ning was coded in a language such as Erlang that's built for concurrency.

But I digress. I've got some cool plans for my little BeepBeep site. Keep an eye on this space for more articles as the site comes together.