ledger basics and habits

Some time ago, I wrote about the CLI accounting program ledger, specifically building ledger from source and a small pet project of mine for visualizing ledger data called ledger-stats. I’ve even given a short presentation on the subject. I thought I’d take a blog post to talk about some basics of using ledger and some of the habits I’ve cultivated in my own usage of it. For more comprehensive info, check out the ledger manual.

Journals

A journal is a file in the ledger format. It can be of any size, though I typically like to keep one per year. This keeps file size relatively small (my largest one to date is about 150 KB), so searching them is easy, and makes it easy to report on annual figures (e.g. business expenses that can be written off) without having to manually specify date ranges.

Accounts

An account is a label that represents a source or destination of money. A lot of people find this concept confusing because they associate it with an account at a bank rather than considering it as a more general concept. If you do any sort of computer programming, an account is similar in concept to a variable: it’s just a name with which a value (in this case an amount of money) can be associated.

ledger supports hierarchical organization of categories separated by colons, so you can have accounts like Expenses:Entertainment:Movies where Movies is under Entertainment and Entertainment is under Expenses. This allows you to have ledger report at various levels in the hierarchy so that you can see what you spend only on Movies or what you spend for all of your Entertainment.

Conventional top-level accounts are Equity, Liabilities, Assets, Expenses, and Income, but I only tend to use the last three myself. Assets are things I own that hold or are worth money, such as my bank accounts. Expenses are things I spend money on, such as food and housing. Income constitutes sources from which I obtain money, such as the salary I draw from my job or book royalty payments.

Transactions

An event in which an account accumulates a quantity, such as adding $36 to your Expenses:Auto:Gas account to represent when you topped off your car’s gas tank today, is known as a posting. Because ledger uses a double-entry accounting system, however, you also need a posting representing the source of the funds from which you obtained this $36, such as the Assets:Checking account representing the checking account you have at your bank.

A transaction is two or more postings representing a financial event, such as the above example of purchasing gas, where the amounts balance out to zero. In a journal file, a transaction is formatted like this:

; Comment
Date Description
Account1  Amount1
Account2  Amount2
AccountN

If you don’t include an amount for the last account, ledger will automatically use whatever quantity causes the transaction to balance to zero. Most transactions involve two postings, so the second quantity will often be the same as the first but with the opposite sign (i.e. negative or positive). Here’s what a real world transaction might look like:

2006/10/15 McDonald's
Expenses:Dining  $5.36
Assets:Checking

In this instance, $5.36 is deducted (or debited) from the checking account and added (or credited) to the account for dining expenses. I often include things like initial posting dates (for which you can also use auxiliary dates) or transaction identifiers from paying bills in the transaction description (i.e. “McDonald’s” in the above example).

You may have a transaction where you’re spending money on several things that you want to track in separate accounts. Here’s an example of what that would look like:

2006/10/15 Exxon
Expenses:Auto:Gas   $15.00
Expenses:Cigarettes  $4.80
Liabilities:MasterCard

Here, money is being spent on gas and cigarettes and the total of the two expenses, $19.80, is what’s debited from the credit card account.

If you’re like me, most of your transactions will only involve two postings, like the first example of an expense above. Another common type of posting represents when you receive income, which might look like this:

2006/10/15 Employer
Assets:Checking  $1000.00
Income:Salary

These may look a bit odd when they show up in ledger reports because the quantities will be negative since you’re debiting the amounts from them. This is normal and you’ll get used to seeing it appear this way.

When a transaction clears your account, you can denote this by adding an asterisk delimited by spaces between the transaction date and description like so:

2006/10/15 * McDonald's
Expenses:Dining  $5.36
Assets:Checking

One small potential pitfall: the segments of account names between colons can have spaces in them. As such, in order to denote the end of an account name, you should place at least two spaces between the account name and amount in each posting.

Reconciling accounts

I use a bank that offers online banking, including a web site and mobile app that allow me to view activity on my accounts almost any time. ledger may seem redundant in relation to something like this, but there are a few reasons why this isn’t so:

  • Transactions may not show up in the banking interface right away because some vendors often post several days’ transactions in a single batch every few days.
  • Transaction amounts may not be accurate. For example, initial postings from some gas stations may only show an amount of $1 and won’t reflect the correct amount until they clear. Initial postings from restaurants often don’t include any added gratuity.
  • Some activity may be fraudulent, which may not be immediately obvious if your card information is stolen in a business you frequent.

Every time I spend money and am able to get a receipt, I do so. I save them until they clear or, for larger purchases, until the period in which I may return the purchased item expires.

Tracking these receipts with ledger solves all of the above issues: I know about transactions that may not be reflected in my online account activity yet, I know when transaction amounts are inaccurate, and I can identity potentially fraudulent transactions when my online account activity shows a transaction for which I don’t have a receipt.

Every few days, I record any new receipts in my journal file, update any transactions that have cleared, and compare the journal file to my online account activity to ensure the two are consistent. This is a process called reconciliation.

Pro-tip: tracking cash withdrawals and purchases can be a pain. I typically just maintain an Expenses:Cash account for these sorts of things. If I can remember how I spent a bit of cash, great: I can just debit Expenses:Cash and credit the appropriate account for what I spent the cash on after the fact. Otherwise, I just leave the amount attributed to Expenses:Cash. It’s often not worth the trouble of trying to keep finer track of cash purchases than that.

Register

The register command in ledger displays all postings from a journal file that involve one or more specified accounts. I typically use this to ensure that my journal and online account activity are consistent by listing all activity for those accounts.

$ ledger reg checking -f stan.txt
08-Jan-01 Opening Balances Assets:Checking     $1550.00 $1550.00
08-Jan-01 New Seasons Assets:Checking           $-60.91 $1489.09
08-Jan-01 Panda Express Assets:Checking          $-7.24 $1481.85
08-Jan-02 Sizzle Pie Assets:Checking             $-7.38 $1474.47
08-Jan-03 Kettleman Bagels Assets:Checking       $-7.60 $1466.87
08-Jan-03 Mio Sushi Assets:Checking              $-5.76 $1461.11
08-Jan-03 Eddie's Flat Iron P.. Assets:Checking $-22.26 $1438.85
08-Jan-04 Food Carts Assets:Checking             $-7.24 $1431.61
08-Jan-05 Burnside Brewery Assets:Checking      $-11.76 $1419.85
08-Jan-05 Tastebud Assets:Checking              $-42.13 $1377.72
08-Jan-07 Salary Assets:Checking               $1084.00 $2461.72

In the above example of register command output, “reg” indicates that the register should be used, “checking” is part of the name of the account being queried, and the value following “-f” indicates the journal file to be read.

The last column in the command output is a running sum of all quantities from postings for that account, where that column’s value in the last row of output is the account balance. The register command is useful when the balances of journal and online accounts aren’t consistent and you need to find where a transaction is missing or has an incorrect amount.

The output of the register command can be limited by transaction date (as well as many other options) using either or both of its “–begin” and “–end” flags like so:

$ ledger reg --begin=2014/02/01 --end=2014/02/28 -f stan.txt

Balance

Speaking of balances, ledger also has a balance command. This outputs balances for accounts at each hierarchical level. This allows you to see, for example, numbers as general as your total Expenses and as specific as what you spent going to the Movies.

$ ledger bal expenses -f stan.txt
$157874.79 Expenses
$5212.85   Entertainment
$21526.95   Food
$1377.36     Breakfast
$3174.59     Dinner
$11171.71     Groceries
$5803.29     Lunch
$8568.00   Insurance
$3948.00     Car
$4620.00     Medical
$5136.40   Interest
$4618.79     Car
$517.61     Student
$33600.00   Rent
...
--------------------
0

Budgeting and Bills

ledger offers support for budgeting that can forecast when bills come due based on an interval and compare entered transactions against budgeted amounts to show whether you came over or under budget for any given time period. While this is a really cool feature, I don’t really use it the way it was intended to be used.

The budgeting feature uses what are called periodic transactions. These are slightly different from normal transactions in that they use a period expression rather than a date and have no description. They are formatted like so:

~ Monthly
Expenses:Rent      $500.00
Expenses:Food      $450.00
Expenses:Auto:Gas  $120.00
Expenses:Insurance $150.00
Expenses:Phone     $125.00
Expenses:Utilities $100.00
Expenses:Movies     $50.00
Assets

I keep blocks of these at the top of my journal, organized by the pay period in which I pay the bills they each contain. When I sit down to pay bills, I make a copy of the appropriate block at the bottom of my journal and comment it out. Then, as I pay each bill, I uncomment the appropriate posting and move it out into an actual transaction. This gives me a way to easily check which bills haven’t been paid yet (e.g. if I’m waiting on a paper bill for the exact amount I owe).

I generally use vim to edit my journal files. There’s a contributed plugin for adding ledger format syntax highlighting, which is nice. I also use my fork of the visSum plugin for vim (the fork adds support for decimal quantities) to visually highlight and sum remaining bill amounts. I can compare the output of that with the balance of my account (from ledger’s register or balance commands) to determine how much I actually have left in excess of bills.

Benefits

Even though I’m only using a very small amount of ledger’s overall feature set, I’m gaining several benefits by putting in the time to maintain these journal files:

  • Peace of mind in knowing that I know where my money is and where it’s going, despite whatever records my online banking interface may yet be lacking.
  • Information I can use to forecast future financial events, such as how much I’ll spend on electricity to keep my house at a comfortable temperature during the summer and winter, how much I spend on average for gas and groceries, or how much I spend on sporadic luxuries like eating out.
  • At tax time, I can very quickly and easily provide exact figures to my accountant for business-related expenses without having to take time to compile them manually.

Some people have asked me what I think of services like Mint. While such services may offer a nice interface, those interfaces are often intentionally kept very simple, to the point where I’m limited in the ways I can report on my data in their system. Additionally, there’s rarely a way for me to easily get that same data out of their system and into a format I can use elsewhere. In short, I like having control of my data and what I can do with it. These services may work for others, but they just don’t suit me.

Hopefully this blog post has given you some perspective on the benefits of accounting with ledger and how you can go about adopting this approach yourself if that prospect entices you. Feel free to leave a comment if you have a question or would like to discuss the topic further with me.

Travis and Composer and virtPHP, oh my!

I recently ran into an issue with one of my repos on GitHub when integrating it with Travis. When I installed dependencies with Composer and ran the PHPUnit tests on my local system running Ubuntu 13.10 and its stock PHP 5.5.3 apt package, they passed. However, I’d configured Travis to also do this under current 5.3 and 5.4 versions as well.

In the first build, everything worked fine under 5.4 and 5.5, but upon getting to the composer install instruction to install project dependencies and PHPUnit, the job for 5.3 failed with some rather unintuitive output from Composer that implied it didn’t recognize the platform package requirement that I’d provided for the minimum PHP version.

Your requirements could not be resolved to an installable set of packages.
Problem 1
- The requested package php could not be found in any version, there may be a typo in the package name.

Side note: While Travis does support Composer, the version of it available by default when running a job is frequently behind the current build. I’ve brought this up with them, but it doesn’t seem they’ve addressed it as of this writing. In any case, it’s easy enough to work around by including a composer self-update instruction as part of the build like so. This ensures that you won’t be affected by any recently fixed bugs in Composer.

Since the cause of my issue wasn’t immediately obvious from Composer’s output, my first thought was that I needed to begin my attempt at troubleshooting the issue by replicating it on my local machine. My second thought was that seemed like an abysmally miserable prospect, as it would require that I have several different versions of PHP installed other than the current one on my system.

I’d heard recently about a new project recently via Twitter called virtPHP that purported to be PHP’s answer to virtualenv for Python or rvm for Ruby. Thinking that my situation seemed a great use case for it, I proceeded to install it.

First, you have to read a bit past the cursory installation instructions on the landing page of virtPHP’s web site, particularly the “Using phpenv and php-build” section of virtPHP’s README file including the portion on package requirements. virtPHP doesn’t accomplish this great feat all on its own. It actually builds on two other existing projects by Christoph Hochstrasser, phpenv and php-build, and functions (in a rather PHP-like vein) more like glue to make working with these projects and managing what they produce easier. More specifically, it provides support for things like differing per-project PHP, PECL, and PEAR configurations.

In reality, all I ended up needing for what eventually proved to be a rather quick-and-dirty sort-of use case was phpenv and php-build alone, though I suspect virtPHP will be indispensable when I inevitably need a more long-term setup like this. Installing all three based on the installation instructions in their README files was fairly straightforward. I used them to create three PHP installations of the versions used on Travis (5.3.27, 5.4.25, and 5.5.9 as of this writing) and to quickly switch between them to re-run the composer install command that had failed on Travis, which consistently failed under 5.3 and worked under 5.4 and 5.5 on my local system.

Eventually, I opened the composer.json file and realized the problem: I’d misrecalled the minimum PHP version I’d set for my project to be installed as 5.3 when I’d actually set it to 5.4. Composer appropriately, though perhaps not intuitively, reacted by outputting errors when the local environment was running 5.3, a PHP version that did not meet the requirement I’d set in composer.json. In poking around, I found that this sort of user error is not entirely uncommon. Once I changed the requirement to 5.3 and pushed it to GitHub, the next Travis build succeeded for all PHP versions I’d specified.

So, thanks to the folks behind virtPHP for producing this project. I suspect I’ll be making more use of it in the future. :)

Sunshine PHP 2014

Due to uncertainties in my work schedule, I decided this year not to submit to the Sunshine PHP 2014 conference. However, the schedule turned out such that I was able to attend the conference. Many thanks to my awesome employer Blopboard for providing the time and funding to make this possible.

I was a speaker at the inaugural Sunshine PHP conference in 2013 and enjoyed that experience, but being able to just be an attendee this year was a nice change of pace. I’ve enjoyed the awesome content presented by excellent speakers.

With this year’s Sunshine PHP came a new member of the elePHPant family: Sonny, the yellow elePHPant. The process of obtaining your very own Sonny was a rather novel idea thought up by the hosts of Sunshine PHP. Attendees were given a bingo sheet where each space was branded for a sponsor and would visit the sponsor’s booth to get that space stamped. Once all spaces were stamped, you could turn in the bingo sheet to get Sonny.

In going through this process, I spoke with some very friendly guys at AppDynamics. I was able to learn more about their product, which is an alternative to the New Relic service I currently use at work for monitoring the performance of our product. I noted that AppDynamics isn’t currently listed in the Heroku add-on marketplace, but they clarified for me that it can still be installed on Heroku and pointed out related documentation.

The interaction was great and I’ll certainly be checking out the product further, but this quest to get Sonny is what instigated that conversation, which I think is awesome. Many thanks to Zend for sponsoring this fun activity within the conference.

Thanks to everyone who made Sunshine PHP a spectacular event to attend. I hope to see you again next year.

Sonny the yellow elePHPant

 

How to be a Great Developer

I’ve shamefully ripped off the title for this blog post from what I expect will be a phenomenal session given by Ed Finkler at php[tek] 2014. Sadly, I haven’t seen the session and may not be present at the conference. However, I’ve spoken with Ed and seen him give sessions on several occasions, so I know he sets the bar pretty high.

If you’ve not considered attending the conference and his session, I highly recommend doing so. Ed has plenty of insightful things to say about being a great developer. Today, the subject coincidentally crossed my mind and I realized I had a few things to say on the matter that may also prove useful to others.

Humility

A friend of mine who had some previous programming experience, but was not a developer, recently set out to learn more about what it’s like to be one. This led to many conversations between the two of us that reiterated a few things to me: this person is very intelligent and very determined, and while they felt quite out of their element in this pursuit, they were iteratively making progress toward their goal of understanding what being a developer is like.

This same person recently told me that, over the course of this pursuit, I was the only person they interacted with regarding it who, in their own words, didn’t make them feel like an idiot when they approached me. While I was glad that they had someone like this, I was sad that I was the only one who fit that description.

One thing I have learned over the course of my life is that “genius” is a very relative term: it all depends on who you’re sitting next to. I can name people who make me feel fairly smart just as I can name others who make me feel fairly dumb. I know these people well enough that I can say the latter don’t do this intentionally. Nevertheless, the sentiment keeps my ego in check, which I believe is a good thing.

We all start at the bottom of the totem poll. It benefits you to never forget this and to empathize with those who are going through that journey. Be open to learning from everyone, whether that person is perceived as a master or an apprentice. Nikola Tesla once said, “Our senses enable us to perceive only a minute portion of the outside world.” His words are worth remembering in the context of the limits of our individual knowledge.

Patience

Whether it’s with troublesome technology, difficult people, learning newbies, or even yourself as you go through the process of being a newbie once again to pick up a new skill, you will invariably feel frustrated by one thing or another in the process of being a developer. You have to learn to recognize when frustration is transient, when you can use it as motivation to continue and succeed, and to recognize when it’s a sign that you’ve done all you can do and that you should move on.

Imperfection

There is no silver bullet for anything. This applies as much to one’s technology stack or personal tool belt of choice as to one’s self. There is no state of enlightenment that a developer eventually attains. As cliché as it sounds, being a developer is more about the journey than the destination. The best goal you can set for yourself is to be better at what you do than you were yesterday. Compete with yourself, not with others. Aim to solve problems and be pragmatic, not dogmatic, in how you approach them.

Epilogue

These are things I’ve learned from my own experiences. I state them here realizing that they may be more applicable to me than they are to you. You must form your own opinions and find your own wisdom. I’ve said before what and who make me love what I do. I hope you share in some of that, and in some of what I’ve spoken about in this post. In the end, you must find your own path. Regardless of what that path is, I hope you find the passion shared by myself and those who inspire me and I wish you well in your pursuits.

Sniffing Outgoing HTTP Traffic on an iOS Device

I’m posting this mainly for my own benefit, but hopefully someone else finds this useful. A lot of people have recommended Charles as a debugging HTTP proxy for OS X. It looks like a great piece of software, but does require that you pay for it after 30 days. I was looking for something quick, easy, and free to analyze outgoing HTTP traffic on an iOS device.

Sadly, such options are few and far between, but if you’re willing to install a JDK (which Mavericks handily prompts you to do the first time you try to run a JAR file, and automates much of the installation process), they’re slightly better. I found a free edition of one called Burp Suite and managed to figure out how to get it working, so I’m documenting that here for future reference.

I’m using a Macbook Pro and an iPod Touch to do this, but since Burp Suite is written in Java, it should be possible to do this using any Java-capable device on your LAN and any device running iOS.

On the device with Burp Suite:

  1. Open up a terminal (I use iTerm2), run the ifconfig utility, and note the LAN IP address of the local machine (e.g. 192.168.1.113)
  2. Run the Burp Suite JAR file from a terminal like so: java -jar burpsuite_free_v1.5.jar &
  3. In Burp Suite, click the “Proxy” tab and, within that, click the “Options” tab
  4. Under the “Intercept Client Requests” section, uncheck the checkbox marked “Intercept requests based on the following rules” if you don’t want to modify requests, only view them (because individual intercepted requests are blocked by the proxy until you manually opt to forward them from the “Intercept” tab within the “Proxy” tab)
  5. Likewise, under the “Intercept Server Responses” section, uncheck the checkbox marked “Intercept responses based on the following rules” if you don’t want to modify responses, only view them
  6. Under the “Proxy Listeners” section, select the existing entry in the table and click the “Edit” button
  7. In the “Edit proxy listener” window that appears, next to the “Bind to address” label, select the “Specific address” radio button and, from the drop-down menu next to it, select the LAN IP address of the local machine, then click the “OK” button
  8. Make sure the “Running” checkbox next to the proxy listener is checked, then click to the “History” tab within the “Proxy” tab

On the iOS device:

  1. From the desktop area, click the “Settings” icon
  2. In the “Settings” menu, click the “Wi-Fi” option
  3. In the “Wi-Fi” menu, click the option for your LAN
  4. Scroll to the bottom of the screen, find the “HTTP PROXY” section, and enter the LAN IP and port on which the HTTP proxy is running (8080 by default, you can find it in the proxy listener rule in Burp Suite)
  5. Return to the desktop area, then select the app for which you want to monitor HTTP traffic
  6. Perform some operation that kicks off an HTTP request, then find details on it in the Burp Suite “History” tab

The OOP in PHP Slides Posted

I’ve posted the slides from my “The OOP in PHP” session that I presented at Lone Star PHP 2013. You can find them in the Publications section of this site.

Thoughts on Working Remotely

There’s been a lot of hubbub recently with regard to the recent decision of Yahoo! CEO Marissa Mayer to mandate that all employees, including those currently working remotely, either commute to a corporate office or face termination. This has spurred a lot of speculation in regards to her reasoning behind the decision, from being a less conspicuous form of layoffs to shed expense while saving face with investors to stemming from a more traditional camp of management thought for which productivity requires physical presence in an office. It’s even spurred some accusations of hypocrisy being that Mayer recently paid to have a nursery installed in her office. Be that as it may, I thought I’d take a blog post to share some highlights from my own thoughts on remote working that I’ve gained over the course of doing it for over four years.

Remote working is not for everyone

As much of a public proponent as I may be for remote working, I’ll readily agree that it’s not an ideal arrangement for everyone. Some people need the atmosphere of an office and the presence of managers and coworkers to be productive. These things can have a very real and substantial psychological effect on the motivation and productivity of an individual.

Think about how much time you spend either at work, sleeping, or performing necessary day-to-day tasks like grocery shopping or paying bills. If work doesn’t necessitate that you leave home, you spend a lot more time there and less out in the Real World™. This can be extremely isolating and difficult to tolerate if your employer doesn’t maintain channels of communication that enable you to feel connected to your peers. It also takes a lot of self-discipline to be committed to getting your work done despite there being no one physically looking over your shoulder to ensure that you’re getting the job done.

Remote working has mutual benefits

My commute is the distance from my bed room to my living room. I have time to feed my kids a hot breakfast and put them on the school bus in the morning, then brew a pot of coffee and check my personal e-mail before starting my work day. If I need to, I can step away from my work laptop for a bit in the afternoon to get my kids off the school bus and get them started on their homework or take a short lunch and knock off a bit early to run errands before I pick my kids up from after-school care. Telecommuting and flexible hours enable me to do all these things and thereby significantly reduce my stress level.

I use my own home and internet connection for my work, so I don’t contribute to any needs for equivalent office space or bandwidth in an office. I’m one less car on the roads during the morning and evening rush hours that might be delayed by traffic jams or weather conditions. I’m just a phone call away in an emergency situation. If I’m within reach of my work laptop and an internet connection, that’s as far as I have to walk to provide support. I can communicate in real time via IM, VoIP, Skype, or any number of other tools and mediums.

Remote working has disadvantages

My coworkers need to check their e-mail or be on IM for me to communicate with them; I don’t have the ability to physically track them down or stop by their desk in an office. I may miss out or be the last to hear about casual or in-passing conversations and office news that isn’t formally announced via e-mail. I can’t go out to a local bar for happy hour with my coworkers. I have to open an IM window instead of turning my head to verbally ask a question or make a remark. To at least some degree, I’m out of sight, out of mind, and coworkers must be vigilant to include me in communications, both professional and casual, as much as I must be vigilant to be present and heard. Culture is top-down and has to be maintained both in person and online.

I can’t physically raise my hand to a whiteboard to draw a picture or gesture with my hands. My coworkers can only see my face in photos or video chat. Most of the time, they’re limited to text or my voice and whatever obscure contributions they may make to my ability to communicate. Much of the excitement, disappointment, or general nature of my responses may be lost in translation. I miss out on watercooler conversation and the social element of employment and am forced to find time and opportunity to seek it elsewhere.

Remote working is necessary

The global nature of the job market is only increasing. The state of the US economy is making remote working more of a necessity and less of a privilege. Commutes directly affect the livelihood of those who undertake them in fuel costs, vehicle maintenance, and time commitment. The state of the real estate market and the high variability of cost of living and salary offerings make relocation a difficult or infeasible prospect for many homeowners, which comprise much of the older and more experienced work force.

Limiting hiring to those who are local or are able to relocate significantly diminishes the available talent pool. Companies who dismiss the option of allowing employees to work remotely are forced to hire those who are more convenient rather than those who are best qualified. This leads to a relatively stagnant talent pool as well. Experienced non-local talent is less commonly brought in from the outside, perspectives are limited by locality, and local opportunities for professional development experience less growth. That any of these things need be limited by geography is a limitation that exists entirely in the mind.

Sufficient technology exists for day-to-day operations to carry on remotely in at least close approximation of efficiency to a traditional office space given individuals truly dedicated to that purpose. Any organization that would say they’re “too big” or “culturally incompatible” with remote working is either in trouble or in denial. Either way, they’re doing themselves a disservice that will be illustrated by others like Synacor, GitHub, and Mozilla successfully recruiting the best and the brightest.

Epilogue

Remote working may not  be for every company or employee, but it’s dismissed more often than it should be as a viable employment arrangement. The technological and economical state of the world is only making it more commonplace and will eventually render those who resist it ancient fossils of an industrial era gone by. The age of the knowledge worker has arrived and that knowledge is a commodity that must be sought after regardless of its origin or residence. Any institution that will stand the test of time must follow this principle and eventually globalize or perish.

Why I Love the PHP Community

I had my first contact with the PHP community in late 2005 or early 2006; I can’t remember exactly when it was. Before that point, I’d spent the better part of my life struggling with being bullied and depressed and to some degree still do. If my peers didn’t show me ostracism, they mostly showed me indifference. I often felt like my life had little meaning and that I had no one I could relate to.

Then I found the #phpc channel on the Freenode IRC network. I had the honor and privilege of meeting too many individuals to list here. They didn’t belittle me with ego, much as I might have put some of them on pedestals and perhaps still do. They didn’t admonish me for my lack of knowledge or experience at the time. They didn’t laugh or insult me when I asked questions and showed desire to learn like one might expect in other communities.

They welcomed me. They befriended me. They supported me in my endeavors to become better, as a professional and as a person. They made me feel liked, accepted, and respected. They made me feel like a part of something greater, a community, a family of friends. If everyone could have this, I believe the world would be a much better place.

That’s why I’m so sad when I see public displays that I think might prevent people within that community from sharing my feelings or discourage them from taking part in it. I know what it’s like to feel excluded, marginalized, demoralized, degraded, and discouraged. I don’t wish that on anyone, least of all people I know and respect within this community. I feel that people shouldn’t be singled out or made to feel inferior or objectified. Gender, gender identity, race, creed, ethnicity, sexual orientation — no one should be made to feel like this based on those attributes.

I’m a very sympathetic and empathetic person. I feel things very deeply. I try to consider carefully who I might hurt when I say or do something. I may not always succeed, but I try anyway. In any situation, I do my best to understand where other people are coming from and what their position is. I don’t do this for its own sake, but because I know what it’s like to be hurt and I don’t want to inflict that on another human being. And I especially don’t want it inflicted on others in my beloved community either. And I’m not the only one.

PHP as a language irks me sometimes. Heck,  a coworker of mine started phpsadness.com and it’s difficult to disagree with him on many of the problems that the language has. They don’t stop me from using it, though. I may have come for the technology 11 years ago, but I stayed for the community. And hopefully now, after reading this post, you understand why.

Recipe: Gumbo

Once aspect of my identity that isn’t readily apparent to new acquaintances is that I’m a native of the state of Louisiana. I have red hair from my paternal Irish grandmother. The Welsch and Irish accents of my paternal grandfather and grandmother respectively seem to effectively cancel out the Cajun French accent of my maternal grandparents. I’m a far cry from what someone might expect of a Louisianian if their basis for comparison is comprised of programs like Swamp People. That said, I value my Cajun heritage, particularly its cuisine. A few coworkers of mine expressed an interest in that area, so I thought I’d share a recipe for a local dish: chicken and sausage gumbo.

Ingredients

  • 1 stick of butter
  • 1/2 cup of flour
  • 16 oz of diced onion, bell pepper, and celery or another common variation of the holy trinity
  • 1 12 oz can of amber ale beer
  • 2 32 oz boxes of chicken stock
  • 3 lbs of boneless skinless chicken breasts
  • 1 lb of sausage
  • 2-2 1/2 cups of rice

For the holy trinity mix, I generally use the Creole Seasoning from Guidry’s Fresh Cuts, which contains yellow onion, bell pepper, celery, green onion, parsley, and garlic. Cajun and Creole cuisine share some similarities, such as their common use of variations of the holy trinity, but also differ significantly from each other. Guidry’s is something of a local staple and an easier option than acquiring and cutting the individual vegetables myself, so it’s an instance where I veer a bit from the Cajun recipe for the sake of convenience.

For the amber ale beer, I use Abita Amber Ale, which is produced by the Abita Brewing Company located in Abita Springs about 30 miles north of New Orleans. Their Amber Ale brew has a great flavor that lends itself well to the gumbo.

Finally, for the sausage, I use Savoie’s Mild Pork Sausage.

Directions

  1. Cut the stick of butter into small segments. Place them into a large pot on low-medium heat (on my stove, which has settings of Low, High, and 1 through 9, I use 4 here) until the butter is completely melted.
  2. Use a spatula to stir in the flour. Continue stirring once every 20-30 seconds until the butter-flour mixture, or roux, is the color of milk chocolate. (This will take a while.)
  3. Stir in the holy trinity mix. Continue to stir often until the vegetables soften.
  4. Add the beer. Let the foam settle, then stir until the ingredients are mixed well.
  5. Add the chicken stock, then stir until the ingredients are mixed well.
  6. Increase the heat to medium-high (on my stove, I use 6 or 7) and let the mixture come to a boil.
  7. Carefully slide the chicken breasts into the pot. Let the mixture continue to cook for 45 minutes, stirring occasionally.
  8. Before you reach the 45 minute mark, prepare the rice. I use a microwave rice cooker, which takes about 15 minutes for this much rice.
  9. Also before you reach the 45 minute mark, cut up the sausage.
  10. Once you reach the 45 minute mark, carefully lift the chicken breasts out of the pot, shred them, and replace them into the pot. I just use two forks to do this.
  11. Add the sausage to the pot. (This is done late in the process to prevent the gumbo from getting overly greasy.) Let the gumbo cook for an additional 5 minutes.
  12. Place the rice into bowls and pure the gumbo over the rice. Optionally place the bowls in a freezer for 5 minutes or so to cool them down to eating temperature, stirring them again when you take them out.
  13. Serve and enjoy!
  14. Optional: prior to refrigerating leftovers, mix remaining rice into the gumbo. This will enable the rice to keep in the refrigerator better than it would otherwise and allows for ready-to-heat lunch-size portions.

Gumbo

Speaking at SunshinePHP

Just a quick post to announce that I’m speaking on “Database Testing for Fun and Profit” at the SunshinePHP Conference being held in Miami, Florida on February 8-9. Hope to see you there!

I am speaking at SunshinePHP. February 8th - 9th, 2013 | Miami, Florida