Author Archive

PDOQuery: jQuery Style Database Access and Manipulation

PDOQuery Logo
No Gravatar

I’ve been working on a new database library recently. It’s written in PHP, since that’s what I need, but nothing says it couldn’t be ported to other languages (possibly Java, Python, or Ruby). I’ve had a de-facto library that I’ve used for my projects for nearly six years, but it just isn’t cutting it anymore.

My old one is a relatively simple generic class with standard CRUD functions for batch and single primary-key-based operations. I wrote it myself when I first learned about object-oriented programming, and I’ve made a few tweaks here and there through the years. It’s just too heavy though, and not very intuitive. Anyone unfamiliar with my code would really have to study the library for a long time to figure out how to use certain parts—I am sure of this because even I have to really study it sometimes to refresh my memory. That’s a bad sign when the library in question is a simple database access layer.

Enter PDOQuery. PDOQuery is my new library. It’s modeled to a limited extent after jQuery syntax, though obviously not all the same kinds of functionality apply, and the language difference (PHP vs. Javascript) means that PDOQuery uses -> for chaining instead of a period. The query language is built in a similar fashion, only PDOQuery selects and manipulates a database instead of DOM elements.

It’s also meant to give you as much power as possible with as little pain as possible. Query modifications are built to return a PDOQuery object, just like jQuery, so you can link modifications together or apply a new selector to an existing object. The library takes full advantage of PHP to provide powerful object integration, making it extremely simple (and mostly automatic) to create a PHP class that directly represents a database table row. It also supports table references, so with a single line of PHP, you can select a user and all related tasks, for example.

Consider the following implementation code:

include 'PDOQuery.class.php';
PQ() -> connect("mysqli:dbname=testdatabase", "testuser", "testpass");

The PQ() function is a shortcut to the main PDOQuery class. It takes an optional selector argument and returns an instance of the class. Note that this single include and call to the connect() method are the only bits of code necessary to start using the library. Now for some usage:

$s = PQ("users.join:permissions[UserID]");
$users = $s -> select();

The first line above creates a PDOQuery object that parses the selector into appropriate MySQL query, but it doesn’t actually run the query. The second line is what runs it and stores the result. For the MySQL database type (the only one coded at this point), the default result returned is a native MySQL result. You can optionally request a numerically indexed array of rows, an associative array of rows, a numerically and associatively indexed array of rows, or an array of objects. The native result is the default because it has the smallest memory requirement.

You could also run the following code:

$s -> delete();

…though I wouldn’t recommend it. Because the selector in the $s object is parsed and stored in individual pieces (table name, criteria, joins, etc.), it doesn’t assume you’re going to just be selecting. The line above would use all of the selector parts applicable to a DELETE query (just the table name, in this case), ignoring all the rest (the JOIN option), and run the following MySQL query:

DELETE FROM `users`

You could also do the following:

$s2 = $s -> where("UserID=3");
$s2 -> delete();

This would delete only the user whose UserID is equal to 3. Much safer.

Currently, the PDOQuery library supports the following database-related methods:

  • query()
  • select()
  • selectRow()
  • selectColumn()
  • selectValue()
  • insert()
  • update()
  • delete()

The query() method is used by all the others, and can be used by you to run a raw query if you cannot accomplish it using other methods. It returns a native database result. The selectRow() method returns a single row, selectColumn() returns an array of values from a single column and multiple rows, and selectValue() returns the value of one column’s content from within a single row.

PDOQuery also has these chainable selection methods:

  • join()
  • naturaljoin()
  • leftjoin()
  • rightjoin()
  • outerjoin()
  • leftouterjoin()
  • rightouterjoin()
  • where()
  • groupby()
  • orderby()
  • having()
  • limit()

The outerjoin() method is a the exact same as leftouterjoin(). All of these return a PDOQuery object for further chaining or manipulation.

However, while this stuff is all important, it isn’t the best feature of the library. PDOQuery includes a discover() method which creates a map of fields, data types, and indexes of tables in the database. This information can then be used to generate code for you to inject into your object classes to enable many convenient shortcuts. You can add just a bit more information yourself to establish relationships between tables for even greater conveniences.

Consider a database with a users table and a projects table. A user may have zero or more projects. The following code is mostly generated by PDOQuery, except for the class names and the references index keys:

class User extends PDOQueryObject {

    public static $PDOQueryTable = "users";
    public static $PDOQueryStructure = array(
        "timestamp"=>"Fri, 25 Jun 2010 10:27:02 -0600",
        "fields"=>array(
            "UserId"=>array("type"=>"int(10) unsigned", "simpletype"=>"int", "null"=>false, "key"=>"PRI", "default"=>null, "ai"=>true, "indexes"=>array("PRIMARY"), "extra"=>"auto_increment"),
            "EmailAddress"=>array("type"=>"varchar(128)", "simpletype"=>"text", "null"=>false, "key"=>"", "default"=>null, "ai"=>false, "indexes"=>array(), "extra"=>""),
            "Password"=>array("type"=>"varchar(32)", "simpletype"=>"text", "null"=>false, "key"=>"", "default"=>null, "ai"=>false, "indexes"=>array(), "extra"=>""),
            "FirstName"=>array("type"=>"varchar(32)", "simpletype"=>"text", "null"=>false, "key"=>"", "default"=>null, "ai"=>false, "indexes"=>array(), "extra"=>""),
            "LastName"=>array("type"=>"varchar(32)", "simpletype"=>"text", "null"=>false, "key"=>"", "default"=>null, "ai"=>false, "indexes"=>array(), "extra"=>""),
            "LastLogin"=>array("type"=>"datetime", "simpletype"=>"datetime", "null"=>false, "key"=>"", "default"=>null, "ai"=>false, "indexes"=>array(), "extra"=>""),
            "Deleted"=>array("type"=>"tinyint(4)", "simpletype"=>"int", "null"=>false, "key"=>"", "default"=>null, "ai"=>false, "indexes"=>array(), "extra"=>"")
            ),
        "indexes"=>array(
            "PRIMARY"=>array("unique"=>"", "collation"=>"A", "cardinality"=>"1", "fields"=>array("UserId")),
            ),
        "primarykey"=>"UserId",
        /* USER-SUPPLIED SETTINGS */
        "references"=>array(
            "projects"=>array("key"=>"UserId", "autojoin"=>false, "relationship"=>"multiple", "class"=>"Project", "local"=>"Projects"),
            )
        );
}

class Project extends PDOQueryObject {

    public static $PDOQueryTable = "projects";
    public static $PDOQueryStructure = array(
        "timestamp"=>"Fri, 25 Jun 2010 10:27:02 -0600",
        "fields"=>array(
            "ProjectId"=>array("type"=>"int(10) unsigned", "simpletype"=>"int", "null"=>false, "key"=>"PRI", "default"=>null, "ai"=>true, "indexes"=>array("PRIMARY"), "extra"=>"auto_increment"),
            "UserId"=>array("type"=>"int(10) unsigned", "simpletype"=>"int", "null"=>false, "key"=>"", "default"=>null, "ai"=>false, "indexes"=>array(), "extra"=>""),
            "Name"=>array("type"=>"varchar(64)", "simpletype"=>"text", "null"=>false, "key"=>"", "default"=>null, "ai"=>false, "indexes"=>array(), "extra"=>""),
            "Deleted"=>array("type"=>"tinyint(4)", "simpletype"=>"int", "null"=>false, "key"=>"", "default"=>null, "ai"=>false, "indexes"=>array(), "extra"=>"")
            ),
        "indexes"=>array(
            "PRIMARY"=>array("unique"=>true, "collation"=>"A", "cardinality"=>"0", "fields"=>array("ProjectId"))
            ),
        "primarykey"=>"ProjectId",
        /* USER-SUPPLIED SETTINGS */
        "references"=>array(
            "users"=>array("key"=>"UserId", "autojoin"=>true, "relationship"=>"single", "class"=>"User", "local"=>"User")
            )
        );
}

Notice the extended PDOQueryObject class, which provides most of the convenience functions. Also notice the references key down at the bottom of each class definition. For each of these:

  • key is the correlating field name
  • autojoin determines whether to select this related information automatically
  • relationship is either “single” or “multiple” depending on whether it is 1-to-1 or 1-to-many
  • class is the name of the class that represents the joined table rows
  • local is the name of the local variable to assign the joined data

This allows us to do something like this:

$user = new User(1);

Now, $user is an object that contains a copy of the data row from the users table that has UserID equal to 1. The fields are stored in respective member variables: UserID, EmailAddress, Password, etc. These can be modified directly, since they are public. If you want to make changes, simple assign new values to the fields, then run the following code:

$user -> update();

Voila! Because that update() method is running on an instance of a single User class, it knows to treat it as a database row, and it already has all of the table structure and primary key information handy. It even performs automatic data validation and formatting (most conveniently for DATE, TIME, and DATETIME fields). You could even assign a new UserID value (or set it to NULL) to your $user object and then run:

$newID = $user -> insert();

…and you’ve got a new row inserted, just like that. But wait, there’s more! Because of the references array value, we can also do this:

$user -> loadReference("projects");

…and now you have a new Projects member variable which contains an array of objects pulled from the database and instantiated using the PDOQueryObject child Project class. If the autojoin value had been set to true, this would have been done for us automatically. Now that is convenient.

I’m still working on a few more convenience functions (data table and entry form displays, and lambda functions for automating per-row operations), and I still have to finish the documentation. It’s going to be really, really useful at least for me, and hopefully for many others. I’ll release the code as soon as I’m satisfied with it.

History and Economics Like You’ve Never Seen It

No Gravatar

I’ve recently re-developed interest in Richard Maybury‘s book series on history, law, politics, and economics. I say “re-developed” because I’ve always been interested ever since I first heard of them—sometimes more and sometimes less—but I never actually made time to read them. I know that they are an incredible resource of clear and concise knowledge. Richard Maybury always succeeds in presenting a logical thought process from start to finish using language and analogies that are a pleasure to read and not difficult to understand. While I wouldn’t say he makes history and economics fun, his delivery is the best and most honest I’ve seen so far.

I don’t get any kind of kickback from recommending these, but I’m going to do it anyway. The following summaries come from the books themselves. The order is a little bit arbitrary, as the actual series is not numbered, but this is the recommended order. The 2nd one in the series (Penny Candy) is the one to get for a basic intro to economic principles.

All of these books are suitable for junior high students. They are written as a series of short letters from “Uncle Eric” to his nephew/niece Chris. The books include a glossary of potentially unknown terms. All of these are worth reading. You will not find another resource quite like them.

#1: Uncle Eric Talks About Personal Career and Financial Security

Uncle Eric’s Model introduced. Models (or paradigms) are how people think; they are how we understand our world. To achieve success in our careers, investments, and every other part of our lives, we need sound models. These help us recognize and use the information that is important and bypass that which is not. In this book, Mr. Maybury introduces the model he has found most useful. These are explained in WHATEVER HAPPENED TO PENNY CANDY?, WHATEVER HAPPENED TO JUSTICE?, and THE CLIPPER SHIP STRATEGY.

#2: Whatever Happened to Penny Candy?

The economic model explained. The clearest and most interesting explanation of economics aound. Learn about investment cycles, velocity, business cycles, recessions, inflation, money demand, and more. Contains “Beyond the Basics,” which supplements the basic ideas and is included for readers who choose to tackle more challenging concepts. Recommended by former U.S. Treasury Secretary William Simon and many others.

#3: Whatever Happened to Justice?

The legal model explained. Explores America’s legal heritage. Shows what is wrong with our legal system and economy, and how to fix it. Discusses the difference between higher law and man-made law, and the connection between rational law and economic prosperity. Introduces the Two Laws: 1) Do all you have agreed to do. 2) Do not encroach on other persons or their property.

#4: Are You Liberal? Conservative? or Confused?

Political labels. What do they mean? Liberal, conservative, left, right, democrat, republican, moderate, socialist, libertarian, communist – what are their economic policies, and what plans do their promoters have for your money? Clear, concise explanations. Facts and fallacies.

#5: Ancient Rome: How It Affects You Today

This book explains what happens when a society ignores the model. Are we heading for fascism like ancient Rome? Mr. Maybury uses historical events to explain curent events, includng the wars in the former Soviet Empire, and the legal and economic problems of America today. With the turmoil in Russia and Russia’s return to fascism, you must read this book to understand your future. History does repeat.

#6: Evaluating Books: What Would Thomas Jefferson Think About This?

Most books, magazines, and news stories are slanted against the principles of America’s Founders. Often the writers are not aware of it, they simply write as they were taught. Learn how to identify the bias so you can make informed reading, listening, and viewing choices.

#7: The Money Mystery

The first sequel to WHATEVER HAPPENED TO PENNY CANDY? Some economists refer to velocity, others to money demand. However it is seen, it is one of the least understood forces affecting our businesses, careers, and investments – it is the financial tigger. This book discusses precautions you should take and explains why Federal Reserve officials remain so afraid of inflation. THE MONEY MYSTERY prepares you to understand and avoid pitfalls in your career, business, and investments.

#8: The Clipper Ship Strategy

The second sequel to WHATEVER HAPENED TO PENNY CANDY? Conventional wisdom says that when the government expands the money supply, the money descends on the economy in a uniform blanket. This is wrong. The money is injected into specific locations causing hot spots or “cones” such as the tech bubble of the 1990s. Mr. Maybury explains his system for tracking and profiting from these cones. Practical nuts-and-bolts strategy for prospering in our turbulent economy.

#9: The Thousand Year War in the Mideast: How It Affects You Today

Mr. Maybury shows that events on the other side of the world a thousand years ago can affect us more than events in our hometowns today. This book explains the ten-century battle the U.S. has entered against the Islamic world. It predicted the events that began unfolding on September 11, 2001. It helps you understand the thinking of the Muslims in the Mideast, and why the coming oil war will affect investment markets around the globe. In the last three decades this war has been the cause of great shocks to the economy and investment markets, including the oil embargoes, the Iranian hostage crisis, the Iraq-Kuwait war, the Caucasus Wars over the Caspian Sea oil basin, and the September 11th attack–and it is likely to remain so for decades to come. Forewarned is forearmed. To successfully manage your career, business, and investments, you must understand this war.

#10: World War I: The Rest of the Story Story and How It Affects You Today

The explosion of the battleship Maine in Havana Harbor in 1898 was the beginning of a chain reaction that continues today. Mr. Maybury presents an idea-based explanation of the First World War. He focuses on the ideas and events that led to World War I, events during the war, and how they led to World War II. Includes the ten deadly ideas that lead to war.

#11: World War II: The Rest of the Story and How It Affects You Today

An idea-based explanation of the war. Focuses on events in the Second World War and how our misunderstanding of this war led to America’s subsequent wars, including the Korean and Vietnam Wars, the Iraq-Kuwait War, and the “War on Terror” that began September 11, 2001.

You can buy these books as a set for $164.95 shipped, or individually from the same page. Again, I get nothing from recommending this, but I wholeheartedly do so anyway. I only wish there were electronic and audiobook versions available for sale as well.

Maybury also has a monthly financial/economic newsletter called the Early Warning Report for $160/yr. That seems like a lot for the newsletter, but it gives investment advice (historically reliable through multiple decades and wars), and is highly reviewed by many subscribers.

If you get any of these books, and you actually read them, you will not be sorry.

Using Music to Boost Productivity

Sheet Music
No Gravatar

I often enjoy listening to music while I work. I don’t just mean physical labor like laundry or dishes; I am talking about the programming work I do for my job. While I was still in college, I would also listen while I studied.

I realize that many, many people like to do the same thing. The idea of using music to boost productivity is not new, and I certainly didn’t come up with it. What interests me the most about the whole idea is that everyone has a different preference about precisely what music is the best. I bet that most people have at least a semi-good reason for their own preferences, whether or not they’ve actually thought about it.

Most people don’t know that I didn’t start listening to the radio until I was about 12. It wasn’t that I couldn’t, but I never really had the desire to do so, and I wasn’t around others who did either—I was home-schooled through high school (and no, I’m not socially inept). Most of the music I heard during my younger years was either 60′s and 70′s hits that my dad had cassette tapes and records of, or else piano music which I had to learn during my six years of on-and-off piano lessons.

I developed a taste for classical music in general, piano music specifically, and a random selection of oldies. The earliest I can remember making use of these preferences is when I would pop the Scott Joplin Piano Rags CD by Joshua Rifkin in at 4pm every weekday and spend 45 minutes working on my algebra homework. I listened to that CD probably a hundred times at least during the course of one school year, and I still rank it among my favorites. I instantly recognize any of the songs, though I can’t actually name them even though I can hum them all.

I started listening to online streaming radio stations about the same time I started listening to the radio, and so I developed a very eclectic taste in music. While I can’t pin down a favorite style, I learned to enjoy at least some classical, classic rock, 80′s rock, contemporary rock, folk music, oldies, techno, country, and even some rap. I know each of those are comprised of dozens of subgenres, and I couldn’t begin to really differentiate between most of them. Basically, I listened to a lot of very different music.

More to the point, here is what I’ve discovered about myself and how I use music: (links take you to Grooveshark to listen free)

  • I prefer piano solos or concertos while I’m learning something new. (Examples: Celes (FF6) by Nobuo Uematsu, Eternal Harvest (FF9) by Nobuo Uematsu)
  • I prefer heavy, melodic, rhythmic, bass-infused rock music while I’m using knowledge I already have to build something. (Examples: Last of the Wilds by Nightwish, Amaranth by Nightwish, Prepare for Battle by Frank Klepacki
  • I prefer silence if I am working on something extremely complex. (No examples, ha!)
  • I prefer music that I know to music that I don’t know.
  • I prefer lyric-free music (though I can work with the alternative).

The second point is perhaps the most surprising. I don’t generally just listen to heavy rock music. Actually, other than that situation (programming, typically), I just about never do. But there’s something about the full sound, the solid beat, and the pounding, pushing rhythm and complex harmonies that make a huge difference in my concentration and enjoyment. It’s just so…motivating.

The first point is probably common to a lot of people, though I know some others who couldn’t possibly concentrate with classical music playing. Then, my need for silence illustrates that, at least for me, there is a limit to how music helps me think. If I need every analytical aspect of my brain available, I can’t be subconsciously distracted by anything. I can function at 90% efficiency with heavy rock music playing while I only need to use 50% of my analytical capabilities, but if I try to push that analytical throughput above 80% or so, my efficiency drops through the floor unless I remove all other activity. (Yes, I totally made those numbers up, but they are just supposed to illustrate the point.)

The last two points is where I see the most odd variation. Musical tastes are different enough that it’s easy to see how people work best with different genres. However, why would there be such variation on known vs. unknown music, and lyrics vs. no lyrics?

I like music that I know because I actually concentrate on it less. The many years of piano lessons I took included a lot music theory, and so I am constantly analyzing music. I hear a song and take it apart mathematically: time signature, accented beats, syncopation, chord progressions (oh I love chord progressions!), key changes, anomalies, patterns, similarities to other songs, anything I can hear. I can’t just listen to a song that I haven’t heard before; I have to discover it. But if I’ve heard it before and I know how it goes, then I’ve already done all that. I know what to expect, and therefore it demands less attention.

Some people like prefer music that they don’t really know because they take it in differently from the way I do. For those people, hearing music they know demands more of their attention because they want to sing or hum along, whether out loud or not. Music they don’t know becomes something more like background noise.

I like music that doesn’t have lyrics, whether or not I know it, because it’s one fewer element to distract me. If I don’t know the song, then in the discovery process, I’m not just analyzing the music, I’m also trying to take in the words and whole story (if the story is intelligible and/or not a boring load of repetition). If I do know the song, then the story separates itself from the music, and I can’t subconsciously take it in the same way. I repeat (or sing along with) the words in my head. It’s not a huge distraction if I already know the words, but I still prefer songs without words.

On the other hand, my wife likes music with words, because she loves to sing. Music without words becomes a glaring invitation for her to substitute her own words, or those of another song, and that is immensely distracting. Her mind is so in tune with singing that she can concentrate better if she has something to sing along to (again, whether out loud or not).

Music strikes everyone differently. Some people relax best while listening to speed metal. Some need the Nutcracker Suite. Some need silence. I don’t know if it has anything to do with personality type, since sometimes people have musical tastes that are completely not what you would expect. I think (though I don’t know) that tastes are probably defined more by your birth year than by your age—it will be very interesting to see if the 90-year-olds in 2080 are still listening to Eminem because it’s “their music.” I can’t imagine that it will still be “young people music” by then.

But musical tastes are also defined simply by what you listen to most. I have seen many people (including myself) learn to like something new, even something they never would have thought they could ever appreciate, just because they hung around places where that new something was played all the time. We become acclimated, and then hooked. It’s very much like a drug in that way.

How do you use music? Not just consume it, but actually use it?

A Non-Working Vacation

No Gravatar

As mentioned in my post a week ago, Courtney and I had a chance to take a much-appreciated week-long vacation to celebrate our anniversary. We visited Colonial Williamsburg, the Jamestown Settlement, the Yorktown Victory Center, and of course the nearby Busch Gardens. It was my first time visiting any of those places, and I had a great time at all of them, with the possible exception of the record heat in the area that occurred on a few of those days.

The best part about the trip—besides the fact we were celebrating our anniversary, of course—was the fact that I actually got to disconnect myself completely from work.

Because I work from home doing web application programming, I can literally work from anywhere with a decent internet connection. If I have that and my laptop, I can do everything I need. In reality, this means that I am never far from work. With occasional side jobs on top of my official full-time position, some kind of work often finds its way into my evenings or weekends as well.

Now, honestly, I really like what I do for work. My answer to the “What if you had a million dollars?” life purpose test is that I’d actually want to be doing exactly the same thing, though perhaps a bit less of it. Programming is creatively invigorating and immensely satisfying to me. But that doesn’t mean I want to do it all the time. I have been burned out on multiple occasions, and I am quite sure it’s no fun.

However, my high availability makes it easy for me to work, and as I said before, also difficult to fully disconnect myself for any length of time. Being able to work from anywhere gives me a huge amount of flexibility, but whenever I travel, I usually end up bringing work with me out of necessity—making sure I put in enough hours, or making sure I’m available should something immediate and critical arise.

For this trip though, I covered all of the bases, let everyone know I was going to be unavailable, and even setup some email filters so I wouldn’t see any new items that might arrive during the trip. By the time Courtney and I left, everyone knew what to expect of me (namely nothing), and I was fully prepared to live up to that expectation.

It was one of the most restful weeks I have had in a long time.

Don’t get me wrong, it was physically exhausting just about every day. Everywhere we went involved a whole lot of heat and a whole lot of walking around. It was not rejuvenating in that sense. But being able to suspend that part of my brain for a week and to feel free from outside responsibility even for just that long gave me a great feeling of relief.

Non-working vacations are definitely the best kind.

First Anniversary

No Gravatar

No technical post from me today, everyone! I get a free pass this week. Courtney and I are celebrating our first anniversary—one year of absolutely excellent marriage. Exactly one year ago, we were standing at Salt Creek Beach in Dana Point, CA in front of family and friends pledging our love for each other. This last year has been exciting in all of the best ways, and without any significant negative experiences. I don’t think I could have asked for a better first year.

Thanks for all that you are, Courtney! I love you.

The Importance of Multiple Options

No Gravatar

I recently finished up an article summarizing the differences between a few of the mobile application development frameworks that are in existence today. I covered three major players, two individual platform-specific tools, one per-device shortcut approach, and my own fledgling project, AML. After researching and writing, here’s what I concluded:

  1. There are a lot of people trying to accomplish the same goal in different ways.
  2. That’s really great.

Now, honestly, the first point was already assumed. Anyone who’s done a simple web search on the topic would realize that. But what about the second point? More directly relevant in my case, what about my AML project, which is entering a field that already has a lot of competition and projects which have a great big head start over mine? Why would it be great for my project to have a lot of competition?

Well, first of all, I didn’t look at the playing field and think, “How can I do what they are doing, only better?” No, I started with a specific personal need. I have a problem that I need to solve, and I thought up what I believe is a great way to solve it. Then I searched for something that did what I needed, and came up empty. There were some things that were similar, of course, but nothing that did exactly what I wanted. So, I decided to build my own tool. Even if it ends up being similar to the other ones, I am still going to build it because it will solve my problem perfectly, and there are probably other developers out there who will need to solve the same kind of problem who will benefit from my project.

That is why having all of those different options is so great. If I were trying to solve a slightly different problem, I could use an existing tool, because somebody else already did the same thing I did, only they had a different problem to solve. Instead of everyone needing to bend a universal tool to fit their criteria, we have a multitude of choices, each with its own strengths and weaknesses.

In the case of mobile platform development frameworks, this is excellent. I wouldn’t want to have only one of them to choose from, since I can easily come up with a problem for each framework that would be a pain to solve completely if that was the only one available. Everyone has their own idea of what is best, and this creates a competitive arena. They each build what they need or want, taking inspiration from other designs, and come up with a solution. Sometimes the products converge into a single product, and sometimes they remain separate, but they continue to give developers different options to choose from.

This is really just the principle of the free market applied to software development, which explains why I appreciate it so much.

Rapid Android Development with AML

No Gravatar

7/13/2010 update:

Thanks to the great response (and many hundreds of visits to this page over the last two days), I’ve gone ahead and created a real project website for AML at http://www.amlcode.com, as well as the @amlcode Twitter account. If you’re interested in more updates, check those out. Thanks for all the comments and ideas! Keep them coming!

This post still has some good info and some great comments, so don’t neglect it completely. It might get lonely.

I gave myself a crash course in Android development over the last few days. I’d officially been part of an Android team as part of a project management class in my last quarter at Cal Poly Pomona, but some of the other members on the team ended up doing most of the actual development, so my instructive coding experience was pretty minimal. I knew enough to get the Android SDK installed in Eclipse (which is painfully slow, by the way!), but that was all. Everything else was new to me.

Now, I am very familiar with C, C++, and Java, even though most of my coding for my job is done in PHP, so picking up the Android vocabulary within Java was much easier for me than it would have been if I had no programming experience at all.

I don’t have a specifically defined project to work on yet, but I do have some general requirements for the Android app(s) I’m sure I will be developing in the near future. Specifically, I know I will need these features:

  1. Native implementation (Android UI, not HTML5)
  2. Dynamic externally generated content and navigation

Both of those two features together are, I believe, not a common combination. It’s simple to have dynamic externally generated content and navigation, if you use HTML and a browser. It’s also simple to have a native UI support externally generated content, if that content always fits into a pre-defined structure which you build into your app. But what if you want an app that supports a system with very little known ahead of time—just an email address and password, for instance—and the rest of it need is determined based on parameters, permissions, and a web service API?

Then, I thought, why not write a native Android library that will accommodate that very thing?

And that’s what I did.

I even had the presumptuous audacity to give it an official-sounding name, though it is by no means official (or truly useful) just yet. There is no W3C specification for it. And for all I care, it may never become official, but even if I’m the only one who uses it, this library it will certainly make things easier for me. And on top of that, it’s been a great learning experience over the last four days.

Ladies and gentlemen, I introduce to you AML, the App Markup Language, a simple XML-based language that allows you to easily build a clean, functional application for your mobile device.

It resembles HTML in some ways, but it is not a subset of HTML. It is designed to be intuitive and easy, and while it does not implement every possible feature achievable with native Android code, the goal is for it to cover the vast majority of what is necessary for information-based apps, and leave the rest up to you to implement as you desire. It probably won’t help out much with games, but it’s perfect for mobile implementations of websites. It can even be used as part of a local-only application to quickly build the UI instead of using Java code or Android’s layout XML structure.

Additionally, I would love at some point to extend AML in two directions: one, to have it support other devices (namely the iPhone and iPad), and two, to support different languages for the markup (namely JSON, perhaps YAML). While I don’t need these right now and may not actually need them for some time, there is nothing really Android-specific or XML-specific about the language. I have never written code for iOS, so I don’t know if the behavior is inherently different enough to cause a problem, but I bet it isn’t. You should be able to use the same AML markup to generate nearly identical experiences on Android and on iOS.

So, why is AML so cool? Why would anyone want to use it? Check this out.

The images on the right shows a set of different input objects in an Android app. It’s just an example, obviously—an app in the Market that looked like this would be odd indeed. However, it does illustrate a very basic layout with a few different objects.

Now, anyone who has done any Android development know that there isn’t anything truly difficult about building something like this. If you write your own “main.xml” layout file and use it for your Activity object’s content view though, it can be a little tedious. You can use a tool like DroidDraw to speed things up (which is an excellent idea if you need a static layout), but with both of these approaches, your design will be hard-coded into your app. You can only make changes on the fly through clever uses of the LayoutInflater service.

Your other option is to build the layout using only code. This allows for more dynamic design, for sure, but doing this manually is still tedious. AML bridges the gap between an external data source and the native application, so that the external source can very simply instruct the app what to build and how it should behave.

This is the Android layout XML necessary to create the layout shown above in the screenshot on the right:

<LinearLayout
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Test Button" />
    <CheckBox
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Test Checkbox" />
    <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/icon" />
    <ToggleButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:checked="true" />
    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Test Text"
        android:singleLine="true" />
    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Test Password"
        android:password="true"
        android:singleLine="true" />
    <RadioGroup
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <RadioButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:checked="true"
            android:text="Radio Button 1" />
        <RadioButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Radio Button 2" />
        <RadioButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Radio Button 3" />
    </RadioGroup>
</LinearLayout>

Keep in mind that the above code is basically fixed, and cannot really be customized at runtime on a large scale. Now, for comparison, here is the AML necessary to create the layout above:

<aml>
  <input type="button">Test Button</input>
  <input type="checkbox">Test CheckBox</input>
  <input type="togglebutton" checked="yes" />
  <input type="imagebutton" image="drawable/icon" />
  <input type="text">Test Text</input>
  <input type="password">Test Password</input>
  <radiogroup>
    <input type="radiobutton" checked="yes">Radio Button 1</input>
    <input type="radiobutton">Radio Button 2</input>
    <input type="radiobutton">Radio Button 3</input>
  </radiogroup>
</aml>

It’s that simple. Additionally, for my tests, this layout info was actually being pulled from a web service, just so I could prove to myself that I could do it. The web service dynamically built that layout.

Here is a sample Android ListView constructed with the following AML:

<aml>
  <list>
    <item>Sample Test List Item A</item>
    <item>Sample Test List Item B</item>
    <item>Sample Test List Item C</item>
    <item>Sample Test List Item D</item>
    <item>Sample Test List Item E</item>
    <item>Sample Test List Item F</item>
    <item>Sample Test List Item G</item>
    <item>Sample Test List Item H</item>
    <item>Sample Test List Item I</item>
    <item>Sample Test List Item J</item>
    <item>Sample Test List Item K</item>
    <item>Sample Test List Item L</item>
    <item>Sample Test List Item M</item>
    <item>Sample Test List Item N</item>
    <item>Sample Test List Item O</item>
    <item>Sample Test List Item P</item>
    <item>Sample Test List Item Q</item>
    <item>Sample Test List Item R</item>
    <item>Sample Test List Item S</item>
    <item>Sample Test List Item T</item>
    <item>Sample Test List Item U</item>
    <item>Sample Test List Item V</item>
    <item>Sample Test List Item W</item>
    <item>Sample Test List Item X</item>
    <item>Sample Test List Item Y</item>
    <item>Sample Test List Item Z</item>
  </list>
</aml>
And another sample TableLayout that uses alignment and column spanning, generated by the following AML:

<aml>
  <table expand="2">
    <tr>
      <td colspan="2">This is a block of text contained within a single table cell. This cell has a colspan of 2 so that it looks good on top of the label/field pairs below.</td>
    </tr>
    <tr>
      <td align="right">Email:</td>
      <td><input type="text" width="fill" /></td>
    </tr>
    <tr>
      <td align="right">Password:</td>
      <td><input type="password" width="fill" /></td>
    </tr>
    <tr>
      <td colspan="2">Here's another 2-column cell. Is this awesome or what?</td>
    </tr>
    <tr>
      <td colspan="2">Notice the slight visual break from the text above. This text is in yet another row. The field labels above on the left are aligned to the right, and the table is instructed to make the 2nd column expandable (like an "auto-width" kind of thing).</td>
    </tr>
    <tr>
      <td colspan="2">Additionally, the fields have their widths set to "auto" so that even though they are empty, they fill their parent cells.</td>
    </tr>
  </table>
</aml>

Seriously, can it get any easier than that? You can store this kind of layout definition in your app code and reference it directly from there, or you can use a web service to build this stuff on the fly and send it to your app (though you might want to implement some sort of caching mechanism in that case, for efficiency). The AML library is in its own package, and doesn’t require any imports from your package to work. You do need to put the template layout XML files into your /res/layout folder, but that’s all. AML doesn’t require you or your web service to know the details of how Android builds its views. It doesn’t depend on some extra plugin installed on your device, and it isn’t passing your app code through another service. You probably still have to write some Java code to accomplish your goal, but this makes the whole thing easier.

So far, what I have written only supports layouts, but no actions. Many objects support attributes like align, valign, fontsize, padding, color, and bgcolor, to name a few. The rest of the code just isn’t there yet. I have been building the tap and hold attributes into buttons and other clickable objects, but I’m not done. I haven’t done a date picker, time picker, or spinner (Android’s version of an HTML <select> element). But it’s coming together very quickly—a lot faster than I thought it might. It’s been an awesome learning experience so far though.

I’m writing this for me, honestly, but I’m really interested in any kind of outside interest. Any questions, comments, or recommendations? Has anyone else done this? Would you be excited to get your hands on this code? If you used it, what would you need it to be able to do?

Let me know in the comments!

Getting Rid of Stuff, Revisited

No Gravatar

I’ve had some good feedback on the How to Get Rid of Stuff post that I wrote a couple of weeks ago. I wanted to update everyone to let you all know that I do indeed follow my own advice.

This weekend, Courtney and I finished going through our own stuff in a very quick clean-up process. It was Courtney’s idea originally—not that I wasn’t thinking about it, but I wasn’t going to make a point to do it now. She initiated it and did most of the work, actually. I mainly provided some input here and there on items that were mine. We digitized some cassettes and made a trip to the local Goodwill earlier this afternoon, and the few things that remain will be going on eBay soon or else to Goodwill too, if we decide it isn’t worth the time to sell them online. Our small closet dedicated to storage has returned to a more organized state, and we’ve both been encouraged and emotionally liberated by the whole event.

It’s just so darned nice to get rid of stuff.

Political Labels and Logical Fallacies

No Gravatar

What do you think when you hear the term “Left-wing Liberal”? How about “tea party”? “Right-wing extremist”? “Die-hard Republican”? “Card-carrying member of the NRA”? “Reactionary”? “Obstructionist”? “Moderate”? “Libertarian”? “Independent”? “Neocon”? No matter what you believe, or what your personal political affiliation is (if you have one), the odds are good that those terms conjure up quite a few different images, some of which are bad.

While some of these kinds of labels are meant to be derogatory caricatures of the people we disagree with, many of them are not. The problem is that even the more “harmless” of these words mean significantly different things to the people who use them regularly. A self-identifying Republican thinks “Republican” is a good thing, while a self-identifying Democrat thinks “Republican” is a bad thing. Say the word in front of both of them, and two very different mental pictures will form in their respective heads. From a linguistic and logical standpoint this means that these words are fundamentally useless for worthwhile communication because their meanings have become arbitrary—not depending on context, which would still allow usefulness, but instead depending only on the personal meaning ascribed by the one using it.

I subscribe to many different political or environmental email newsletters. I don’t agree with most of them, but I like to read through the agendas of different organizations just so I get a well-rounded idea of what’s going on around the country. It’s saddening to me that the content from the organization I disagree with most (MoveOn) is usually the least full of distracting propaganda. Don’t get me wrong, they do have many other more subtle forms of propaganda. But the most blatant name-callers of all of them are often the ones that I agree with in principle. I just can’t stand their method of delivery, and I doubt their credibility because they resort to that kind of communication.

Political labels allow for an easy way for group members to identify themselves. However, I am virtually certain that most of the people who consider themselves part of a large group (such as MoveOn or, say, the Tea Party) either don’t agree with 100% of the agenda, or more likely don’t know 100% of the agenda and so cannot truly agree or disagree across the board. It is challenging even among family members to find someone who completely agrees with everything you believe.

Labels create a simple but inaccurate group identity among ideological subscribers, while at the same time they create a shallow but intense divisiveness between “believers” and “non-believers.” People often treat their own political beliefs like religious dogma and use opposite labels on their opponents as spiteful, condescending pejoratives. This makes it easy to fall prey to a logical fallacy commonly known as a straw-man argument. A straw-man argument entails the misrepresentation of the position of our opponent for the purpose of easily shooting it down. Such a position is easy to defeat, but it is not a true victory because we have ascribed viewpoints that the opponent does not really hold. The reality is that people that identify with an opposing group often have worthwhile points, and they are rarely as idiotic as they are made out to be either in our minds or our conversation.

Corruption, deception, and ignorance admittedly run rampant among politicians and their constituents. But when you listen to or talk to others about politics, try to keep in mind what effect some of those seemingly benign labels have, and remember that just because they call themselves something else doesn’t automatically mean they are less than you in any way.

How To Get Rid of Stuff

Pile of Junk
No Gravatar

Over the last decade, I have developed a penchant for getting rid of stuff. I do not lead an austere life, but I appreciate simplicity and order very much. I don’t have a lot of furniture, books, CDs, dishes, clothes, papers, or many other things that some people seem to collect or, at least, have difficulty controlling.

Part of this comes from the fact that I am only 25 at the moment, and so have not had as much time as some have to accumulate a depressingly large collection of material. Another part comes from the fact that I haven’t ever been a junk collector, and I’ve always liked being organized. I haven’t always consciously desired not having stuff, but I’ve always leaned that way.

Last Wednesday, I got home from a three-week visit to my parents’ house in California. While I was there, I tried to take the opportunity to get rid of a few things that have been stored there in my absence (since last July). I didn’t intend to do much of that at first, but when I got there, it struck me as being very important especially that I not burden other people with my stuff, beyond my desire not to burden myself with it in the first place. I even have some things in a storage unit that my aunt is graciously letting Courtney and me use part of for free—I didn’t even know our stuff had been moved there until this trip, since I wasn’t part of the moving crew (it was done for us after we moved to Virginia). As evidenced above, I’ve never been a self-storage-using sort of person, so having even a few boxes in storage is unnerving to me, though I definitely appreciate the convenience of it and the generosity of the people who made it happen with zero effort on my part.

My parents have also been going through the same get-rid-of-stuff process, though they have more stuff than I do by somewhere between one and two orders of magnitude. Their task seems much more daunting than mine does, especially to them. We talked a bit about this very thing while I was out there during this recent trip. So, I thought, why not compile a basic set of rules that I would follow if I had that much stuff to get rid of, and pass it on to them and anyone else interested?

The Problem

It seems to me that collecting a bunch of things that you don’t know what to do with, which then causes you to need more and more storage space, is analogous to getting fat. To qualify that assertion, let me say that I don’t mean that you should never buy or otherwise obtain new things. But, like consuming food, it should be done in moderation. If you eat more than you need, you get fat. If you continue to do so, you become obese to the point of being disabled and in danger of death.

While having way too much stuff doesn’t put you in the same kind of physical danger or create the same type of inconveniences, it is easy to see the parallels. Consider for instance how someone under a strenuous exercise regimen might legitimately consume perhaps 4,000 Calories per day, whereas if I ate that much, I would gain excess weight at an alarming speed. This is similar to the phase of life that parents go through while they have children; obviously, it is necessary to have more things to accommodate a developing family of five than a newly married couple, or than that same married couple after their kids have grown and moved out. If our example person stopped exercising, he would certainly need to cut back on his food consumption or risk terrible heath.

The Solution

There are two basic decisions that need to be made if you want to get rid of your stuff. They are related, but neither really depends on the other one:

  1. Decide what to get rid of.
  2. Decide how to get rid of it.

These decisions are often so hard for people that they will actually pay someone else to make them on their behalf. Companies like 1-800-GOT-JUNK exist for this reason. You may have seen people with this same problem on Extreme Makeover: Home Edition. People become too attached to their things, or they simply don’t know how to approach a problem that seems so massive. The longer they put it off, the more massive it becomes.

The first decision is definitely the harder of the two. I will assume for the sake of my rules that you want to get rid of things because you want more space, and not because you want more money. Money is sometimes a convenient byproduct of getting rid of stuff, but if you are only willing to sell things to get rid of them or you are only looking to get rid of things that are worth some notable amount of money, you probably won’t make much visible progress unless you happen to be liquidating an art gallery. If the desire to recoup your original investment is secondary to your goal of simplicity and orderliness, the whole process will be less complicated and more efficient.

So, if I were faced with the same collection of stuff as my parents have, here are the basic rules I would follow to eliminate the excess. Not all of these are absolute rules, but if you can manage to follow them 95% of the time, you’ll be much better off. (I would like to point out before going on that my parents are not stuck and/or helpless in the battle against their stuff; they have been making progress for quite some time. They just want to make progress faster, which is what prompted me to write this.) There are general principles as well as rules for specific kinds of junk, since applying general principles isn’t always easy.

General Principles

  1. Getting rid of stuff is really liberating.
    If you have a lot of stuff, it’s like having a ball and chain. You cannot move around easily. It takes time and effort to keep it organized and maintained, or if it isn’t perfectly organized, it takes time and effort to find things in the mess if you need to. It’s a psychological weight, even if you don’t need to look through it on a regular basis. Getting rid of stuff decreases your overall responsibility and gives you freedom of movement, not to mention less clutter and more space.
  2. Keeping something because you think you might use it is not worth it.
    One of the hardest hurdles to overcome is the desire to keep something because you might have a use for it one day. If you value simplicity and order, this is a more costly approach than getting rid of everything and then just re-buying things that you really end up needing. You will probably discover that you don’t miss having any of that stuff. Empty space is refreshing and motivating.
  3. Nostalgia and sentimentality are not friends of simplicity.
    This is another really difficult hurdle. If you collect gifts, cards, children’s schoolwork, baby toys, or anything like that, it can be hard to get rid of them even if you can openly acknowledge that they have no practical use. It’s emotionally worthwhile to keep things if the sentimental value is truly large enough. That is something only you can decide. But think about who will be able to enjoy it, and what will actually happen when those people are no longer alive (a morbid thought, I know, but it is important). If it’s going to gather dust for 50 years and then end up in an estate sale, you might consider saving your offspring the trouble. You might also consider digitizing sentimental things and getting rid of the physical objects, so the memories remain but the space is reclaimed.

Rules for Any Kind of Stuff

  1. If you don’t want it, get rid of it.
    Let’s start with the obvious. Voila, problem solved! This is not usually a difficult choice most people have though.
  2. If it belongs to someone else, give it back.
    If you borrowed or rented something, return it to the person who owns it. Let them deal with their own stuff.
  3. If someone else could benefit from it, give it to them.
    Often, other people can find good uses for the things you no longer need. However, this is not an excuse to pawn off your stuff on other people who have a junk problem. The idea is to continue the useful life cycle of something if possible, rather than simply getting rid of it.
  4. If you haven’t used it in over a year, get rid of it.
    If you never use it, then you might not need it. A year is a good benchmark, though of course there are exceptions. Reclaim the space now, and if you need it or something similar again at some point in the future, get a new one. You may never need it.

Rules for Self-Storage

  1. If something has been in a self-storage unit for over a year, get rid of it.
    Once again, you probably don’t really need it if you never use it. On top of that, think about what you’re paying for the storage unit. An average-size unit can easily run for $100 per month. What would you rather be doing with that money?

Rules for Clothing

  1. If you don’t like how it fits, it goes.
    If something doesn’t fit, you won’t wear it often enough, or at all. It will continually get passed over when you pick outfits, and will eventually be relegated to the back of the closet or even a box somewhere.
  2. If you don’t like how it looks, it goes.
    The exact same reasoning as the previous rule applies here. Just get rid of it.
  3. If you haven’t worn it in over a year, it goes.
    This is a little more difficult, but the same principle applies to clothes as to anything else. If you don’t use it, you probably don’t need it. Additionally, with clothing, styles change rapidly, and older clothes may not fit the style you like. Get rid of it, and get something new when the need arises.

Rules for Chemicals/Cleaners/Paint

  1. Cleaners and old chemicals should be minimized.
    Old chemicals are not only ugly, they could also be health hazard. It is rarely necessary to have many strong chemicals or cleaners on-hand for normal household use. If you have a large collection, consider paring it down a bit.
  2. If extra paint is more than a year old, get rid of it.
    The older paint gets, the more difficult it is to work with. If you’re keeping paint for a specific project, then just do the project and be done with it. If you’re keeping it just in case, then it should go.

Rules for Raw Materials (Wood, Concrete, Pipes, etc.)

  1. If it isn’t already designated for a specific project, just get rid of it.
    Raw materials are great to have on hand if you need them for something specific. But keeping them just in case you need them is a waste of space and, often, a psychological burden. It’s worth it to get the space back and the clutter gone.
  2. If it is designated for a specific project, get it done!
    It doesn’t do any good if you bought all of the wood to build a fence…ten years ago. Either use the material, or get rid of it. Simply declaring that something has a purpose is pointless (and demoralizing) if that purpose is never fulfilled.

Rules for Books

  1. If you’ve already read it, get rid of it.
    Unless it’s that very special kind of book that you know you will want to read over and over again, how likely are you to read it again? Probably not very. Save the space and get rid of it.
  2. If you need it for reference, consider getting an electronic copy instead.
    This works very well for device manuals and how-to books. You can buy or find legitimately free copies of all kinds of books. Try Mashable’s list of 20+ Places for Public Domain e-Books to get started.
  3. Try finding the same information online to eliminate the need for the book.
    The internet is your friend. You can find virtually anything, even really obscure stuff. If you’re keeping a 200-page book because of five pages of important info, it might be readily available online. If it is, bookmark or save it, and then just get rid of the book.
  4. If you’ve had it for years but haven’t “found time” to read it, get rid of it.
    Unless it’s really important and out of print, it’s far more liberating to get rid of it and then buy a new copy if and when you need or want it again. You might never notice its absence.
  5. If someone else wants it, give them your copy.
    Recycling books to other interested people is a great idea. You probably won’t be able to do it on a large scale because of the time required to match books with interested new owners, but you might be able to make a few people happy without much effort. Think about the interests of people you know and the books you have, and make some offers.

Rules for Movies and Music

  1. If it’s a VHS or 8mm video tape, convert it to digital video.
    If you don’t have the hardware to do this, services such as Digital Pickle will do it for a fee. Magnetic tape media deteriorates rapidly compared to digital video, so this should be done as quickly as possible. Keep it stored on a hard drive, or burn it onto a DVD.
  2. If it’s a cassette tape, convert it to digital audio.
    The same principle applies here (and the same company mentioned will do that, too). Digital media is easier to organize and much easier to keep intact. You can do this yourself with a tape deck and an audio cable, or you can make it even easier on yourself with a Plusdeck 2c PC Cassette Deck (I have one of these, and it works beautifully).
  3. If it’s an LP or 45 record, convert it to digital audio.
    There are services that will do this for you as well, or you can use a USB turntable. Once again, the key idea here is to convert analog to digital, then toss the analog copy. Digital media takes up far less space—virtually zero by comparison, if you store it all on a few ginormous hard drives.
  4. If you have a huge DVD collection, consider Netflix instead.
    Depending on your movie collection, this could be a massive change. Consider how much space you could recover and how much money you could recoup if you sold all of your movies, and then just used Netflix to watch what you actually wanted to see. Their average plan is less than $15/mo and gives you access to thousands of watch-instantly movies and TV shows, and just about every other movie ever made available for free shipment both ways and unlimited borrowing time. It’s almost impossible to beat. If you have 200 DVDs, how many will you actually watch, ever? If you’ve seen them once, how many will you watch again? If you sold them, how much would you get back? Netflix is a great alternative to building a physical movie collection, especially considering that most media services are moving towards an instantly available subscription model anyway. Do you really want to buy every movie again once Blu-ray becomes the everyday standard instead of the expensive option? I didn’t think so.

Rules for Papers

  1. Digitize anything important, then get rid of it.
    I go paperless whenever I possibly can. If it’s an option, I use it. It’s far easier to organize a digital file than a physical one. However, if you don’t have the option, or you’ve accumulated a lot of papers that you feel the need to keep, you can at least digitize them. Get a flatbed scanner and set aside some time to scan the papers. Just do a few a day, or pick one stack and go through it. Recycle or shred them after scanning.
  2. Shred anything unimportant yet sensitive.
    This one is kind of obvious. I use the Aurora AS890C 8-sheet shredder, and I have no complaints. It shreds anything I throw at it, provided it’s eight or fewer sheets at a time. The basket is a nice feature. Any decent shredder will get the job done. You shouldn’t have any excuses for keeping sensitive but otherwise unimportant papers around. Shred, then recycle them!
  3. Recycle everything else.
    Again, this one is obvious. If it isn’t important and it isn’t sensitive, recycle it.

Rules for Photographs

  1. Digitize them.
    That’s right—only one rule. Unless the photo has real monetary value, there is no reason to keep a physical copy when digital media is so cheap these days, and scanning is easy. Just get a flatbed scanner, as mentioned above, and scan them. You may want to look for scanners that allow slide or negative scanning as well, if you need that functionality. Once scanned, you won’t need to worry about photos losing their coloration due to temperature or moisture, and you won’t have to store them anywhere.

Whew. Okay, remember, these aren’t absolutely strict rules. You probably shouldn’t follow them 100% of the time, since there are definitely valid exceptions (in the midst of significant life changes, moving, death in the family, inheritance, etc.). But most of the time, this will really help.

What To Do With The Stuff That Is Going Away

But what about the other decision? How do you decide how best to get rid of something? Sometimes, people can decide what they want to get rid of, but they don’t know how, or they are stuck on the idea of getting some money back for their hard word and/or presumably valuable stuff. This is a difficult idea to overcome. Certain things lose their value extremely quickly, and others just have very little resale value in the first place.

It is not a bad idea to try selling something before you either give or throw it away, but it is also good to have an ultimatum for anything that doesn’t sell. For instance, you might put up a sign at your garage sale that says “Anything still here after 1pm is free!” (Incidentally, that’s not a bad idea if you want to get rid of a lot of stuff very quickly.)

Different items will sell better in different venues. Additionally, different venues require different amounts of work to get through the complete selling process:

  • A garage sale is easy for a large quantity of items, but provides the least exposure and income potential.
  • craigslist, an online classifieds site, offers good local community exposure and decent income potential, but requires more work for each sale (email or phone communication).
  • eBay offers the best exposure and maximum possible income potential, but requires a tremendous amount of work to sell individual items unless you have an assembly-line-like process for photographing, describing, listing, and shipping every item.

Trying to list everything on eBay is way too difficult unless you plan to make a business out of it. Craigslist offers a far better return-on-investment for most items. Only use eBay if you are convinced that you need maximum exposure. Rare antique items may fall into this category. Use a garage sale if you want to move lots of stuff quickly, and don’t mind a smaller profit.

Here is my general order of steps for getting rid of things, once I’ve decided it needs to go:

  1. If it’s hazardous waste (paint, chemicals, etc.), take it to an appropriate waste facility.
  2. If it’s recyclable trash (cardboard, shredded paper, etc.), take it to an appropriate recycling facility.
  3. If it’s trashed computer hardware (displays, drives, I/O cards, keyboards, mice, etc.), take it to an appropriate tech junk facility.
  4. If you expect to make less than $20 on the item (or set of items), give it away instead. The time you save is worth it.
  5. If you expect to make $20 or more, try to sell it once on the appropriate venue. If it doesn’t sell, give it away instead.

I value my time highly. If it takes me 30 minutes of time to sell something that will only make $10, it’s not worth it to me, and I’ll just give it away instead. Whether you have a fixed dollar amount on your own time or just a general gut feeling about whether or not it’s worth it, it’s important to realize that some things just aren’t worth selling. Pick a local thrift store or charity and donate the stuff instead. You might make more with a tax write-off than you would selling it even if you put in the time, and the result is instant—your stuff is gone, and you never have to deal with it ever again.

That, dear readers, is my goal. Don’t collect stuff, and don’t keep stuff longer than you need it. Don’t get too attached to your stuff, and understand that simply not having stuff is quite valuable in itself.