Saturday, March 24, 2012

Gnome 3 - A loving critique

My Desktop view while writing this article

Comparison to Gnome 2

Before switching to Gnome 3, I had used Gnome 2 for years. I also had a brief stint with Unity. Many Gnome 2 users have lamented that 3 is not as customizable as 2. Therefore, given less control over their desktop experience, they loudly blast 3. You've probably heard them on places such as Slashdot. I mostly think this attitude stems from an ideological distaste for 3. The most vociferous objectors seem to be the long time Linux users. They come from a traditional Linux culture which places customizability above almost everything else. Therefore, opinionated software, such as Unity or 3, strikes them as anti-Linux. The point the Gnome developers believe, and which I agree with, is that there is a difference between customizability and distracting clutter. However, any efforts to reduce distracting clutter will, almost by definition, remove some control from you. This is not necessarily a bad or wrong thing. As one commentator on Slashdot put it, long time Linux users are some of the most conservative people in the world.

Just because Gnome 2 allows for easier customizability in some areas does not mean it is better at fulfilling the primary purpose of a desktop environment (launching and maintaining applications). For one, it has a "start menu" like interface for selecting applications. So you have to navigate a categorized list to find and launch an application. That always seemed problematic for me when I wanted to run a more obscure app. For example, I would constantly forget which apps were in the "Preferences" category and which ones in the "System Settings" category. Therefore, I usually ended up scanning through both looking for a name or icon that seemed correct enough. This problem could be partially mitigated by installing Gnome-do (or a similar launcher). The Gnome-do experience, seemed like a combination of 3's Activity view and its pop-up command dialog. An experience by itself that wasn't quite as nice as those two avenues are separately.

In Gnome 2, it is easier to pin favorite applications to the top panel. This makes launching a new instance of each application a one-button click interaction. This works well for applications that naturally have multiple instances open. However, it does not work as well for single instance applications such as the music player Rhythymbox. For them, you want the desktop to open the application on the first click then activate the running application on the second click. Gnome 3 does this. Actually, it is possible to have it both ways in 3 since there is the Panel Favorites extension that emulates the Gnome 2 top panel favorites.

Comparison to Unity

Ubuntu Unity

Unity

Ubuntu's Unity is similar to Gnome 3 in some ways. It has a left hand side bar application launcher which is similar to the Dash. It allows you to search for applications to launch. However where Unity fails, in my opinion, is in trying to be both a tablet environment and a desktop environment at once. Largely because of this, Unity's windows take up more space, the icons are blockier, and the application launcher system is even less configurable than in 3. Furthermore, the Activities view in 3 has more functionality than the equivalent view in Unity. The equivalent view in Unity (called the Dash view) does not let you switch to workspaces, select open windows, or drag app icons into workspaces. Where Unity is stronger is in keyboard shortcuts. After opening Unity's Dash view, you are presented to a variety of ways to select applications, files, and music without using a mouse. For example, the top 9 items in the Unity side bar (analogous to 3's Dash), can be selected with the 1-9 numeric keys. In some ways, these extra, temporary key bindings can be faster. Often they don't amount to much, though. I've found myself better remembering the keyboard shortcuts in 3's simply because there are fewer of them.

As of time of writing, launching a new instance of an app is a lot easier in 3 than in Unity. In 3, from the Dash, you always have the opportunity to launch a new instance of an app from a right-click context menu. Strangely in Unity, not every app gives you that choice. This behavior might not even be customizable, either.

Another big advantage 3 has over Unity is its extension ecosystem. While the ecosystem is currently in its nascency, it shows potential. It could be the killer app that vaults 3 over Unity in the same way that the Firefox extension system helped vault it over Internet Explorer (at least among choosier tech savvy users). Unity currently doesn't have an extension ecosystem.

The Activities view

My Activities view while writing this article

In Gnome 3, most of the action happens in the Activities view. It can be launched three different ways:

  1. Alt+F1
  2. Windows key (only the left Windows key on my system: Fedora 16)
  3. Slamming the mouse pointer into the top left corner of the screen (hot corner)

The Activities view is one of the most well designed parts of Gnome 3. You can tell the Gnome team spent a lot time on getting this right. Most of the functionality does what you expect it to do. For example, single clicking a workspace preview square shows the windows within that workspace. Clicking again on it again moves you to it and back to the Desktop view. Escape also does what you expect most of the time. When you first access the Activities view, hitting Escape will take you back to the Desktop view. If you do anything within the Activities view such as typing or right-clicking the Dash, Escape will only back out of that action. It keeps you in the Activities view. This seems like the exact right way Escape should be implemented.

The one quibble I have about the Activities view is that after typing to search for something (ie an application), you can only use the up/down arrows to navigate through the found icons. You cannot use the left/right keys. The reason for this is that the left/right keys are used for editing your search text. Therefore the up/down arrows scroll through the found icons in reading order: left-to-right, up-to-down. The problem is that icons at the very bottom of the screen take a long time to reach. This forces you to either refine your search or use the mouse. An interesting solution could be an extension that reserves all of the arrow keys for navigation but uses Emacs style key-bindings for editing the text.

Opening the Activities view opens up some different views:

  • A left hand side bar called the Dash. This shows your favorite applications on top followed by running applications below.
  • All open windows within the current workspace on the left-screen (if you have more than one screen) plus all right-screen windows from all workspaces on the right-screen. Clicking on a window takes you to it and to the workspace where it resides. This is called app activation. You can also close windows by clicking on a circular X that is displayed after you move the the mouse over it.
  • A panel showing previews of the different workspaces. Clicking on a workspace takes you to it. Dragging an app from the Dash opens it in that workspace. You can also drag windows to different workspaces.
  • The notifications panel. This is a place on the bottom of the left-hand screen which shows notifications and some other background running applications (such as Dropbox).
  • A search textbox that allows you to immediately start searching for an application to launch. You do not need to put this box "in focus". Typing at any time will start searching for applications.
  • Two tabs labeled "Windows" and "Applications". Windows is the default. Clicking on Applications gives you a view of all applications which can be filtered by category. Filtering by category is similar to the Gnome 2 Applications menu.

App launching

Within the Activities view, you use the Dash to activate a running application or launch a new instance. For people coming from Gnome 2, where clicking on an icon always launched a new instance, this can take some getting used to. There are a few different ways to do both:

Left clicking on an icon in the Dash will only launch a new application instance if an instance of that application is not already running. Otherwise, it will activate that app. As I have already defined, activating an app means putting it in focus, then moving you to its workspace. App activation is most useful for applications that are naturally single instance (eg Rhythmbox). For multi-instance apps (eg gnome-terminal), this behavior can be slightly frustrating. App icons are highlighted when at least one instance of them is already running. Unfortunately, the highlighting isn't really bright enough to be noticed unless you are already looking for it.

Right clicking on an icon brings up a small menu. This menu shows already running instances for you to activate. It also has a "New Instance" choice and a "Save as Favorite" choice. The latter will keep that icon permanently in the Dash even after all running instances are closed. Dragging an icon to a different place along the Dash will also save it as a permanent favorite. This makes the assumption that if you are going through the trouble of positioning an icon on the Dash you expect it to permanently remain there. Apps already saved as a favorite have a "Remove from Favorites" choice.

The whole concept of "app activation" takes a little getting used to if you are coming from a Gnome 2 mindset. I am slowly warming up to it. I still find that I don't choose to click on an already running app to "find" it as much as I notice if it is running (via the subtle highlighting) then click accordingly. This is probably because most of the time I only have 4-5 distinct apps open: Chrome, Emacs, Gnome Terminal, Rhythmbox, and maybe something else. Of them, only Rhythymbox is a naturally single-instance application (perhaps Emacs, too) and I already know where it is located (I keep it in Workspace 4). So middle-clicking (detailed below) to open a new instance is what I do more than left-clicking to activate. This does take slightly more brain cycles than clicking on a top panel favorite did in Gnome 2. Still, I'm staring to find it not terribly annoying. Maybe I'm just getting used to it.

There are a couple of other ways to launch a new application instance within the Activities view.

  1. Searching for an application by typing some of its name, then using the up/down arrow keys to highlight it, then pressing enter. This will always launch a new instance of the app. Clicking on it with the mouse will also work here.
  2. Middle-clicking on an icon in the Dash. Middle-clicking with my mouse means clicking the scroll wheel.

Middle-clicking an icon in the Dash actually creates a new instance of the app in the workspace just below the current one. The reason for moving it to a different workspace has to do with a new concept known as dynamic workspaces. I will discuss the concept of dynamic workspaces a little bit later. Also, there is an extension you can install which keeps the new instance within the current workspace. I will discuss extensions a little bit later, too.

There is another way to launch applications (not counting dropping into a terminal shell). You can use the pop-up command dialog. This is like a bare-bones version of Gnome-do. You press Alt+F2, the screen dims slightly, and a small textbox appears in the middle of the current window. You then type the exact command desired into this textbox. This pop-up is super fast for short, known commands (eg gedit). If you develop Gnome 3 extensions, you'll find yourself using this a lot with "lg". Unlike after finding an application in the Activities view, you can pass arguments to the command using this dialog.

Pop-up command dialog

The Good and the Different

Gnome 2 was a kludge of an environment. It featured an ugly, heterogeneous mix of panels, drawers, and bars. In comparison, Gnome 3 is simple, elegant, and dare I say it for a Linux desktop, beautiful. The first thing I noticed is how sparse it is. In the desktop view, only a slim top bar is visible (in addition to the application windows). Even the draggable bar on top of each window is slimmer than its Gnome 2 equivalent. It certainly achieves the goal of being non-distracting. There is hardly anything visible to distract you! I think it also achieves the more difficult goal of having functionality that with few exceptions does what you expect it to do. Functionality that works as expected is more easily remembered and absorbed into your workflow.

With a fresh look the at desktop paradigm, the Gnome 3 developers have done away with some of the old patterns they thought were of low value. They've also created some new ones. Some of these I like; some I don't.

A decision I like was to remove the venerable "minimize, maximize, close" window button pattern. While all of these actions are still available, only the close button remains on the top right corner of a standard window (by default). Along with this is the removal of a bottom panel of window buttons (think Windows taskbar). Given that I use workspaces to group together logical windows of work, I usually do not use minimize at all within a given workspace. I typically move the windows into a certain workspace then set them at certain position and size. Sort the Warren Buffett buy-and-hold method of window configuration. Therefore, minimize and a taskbar are little value (on Linux that is; I still use them when I'm using MS Windows since it does not have workspaces).

Another welcome enhancement is the natural way the Activities view can be opened by the mouse. The top left corner of the leftmost screen is called a "hot corner". Slamming the mouse into that corner opens the Activities view. It's fast, intuitive, and easy to hit. Also, since the top left corner is an area of the screen not typically frequented by the mouse, there is little chance of accidentally triggering it. It is also consistent with the Linux paradigm of "focus follows mouse" by triggering an action without having to click. After opening the Activities view, it does what you'd expect by de-activating the view if you re-slam the mouse back into the hot corner. So it a nice little innovation without a downside.

A new feature I could not get used to was dynamic workspaces. Admittedly, I may not have given it enough of a chance. I quickly ran to the Static Workspaces extension. To me and to a lot of Linux users, workspaces are static. Each one has meaning. For example, I always keep Rhythmbox in workspace 4. Workspace 4 is my music workspace. I even have a hotkey to it (Ctrl+Alt+4). It's an easy, comfortable convention that I don't have to think about. With dynamic workspaces, there is no Workspace 4. In fact, you must have at least four windows open to ever even see a fourth workspace. You start out on Workspace 1. You can move an open window down to Workspace 2. However, you can never have an empty workspace. If you remove all the windows from a workspace, it goes away and the workspace numbers re-calibrate themselves. So if you have three workspaces and you remove all the windows from Workspace 2, Workspace 2 goes away and Workspace 3 becomes Workspace 2. It's a different way of approaching the concept of workspaces but one that doesn't work with my concept of categorizing workspaces.

Another new feature I found annoying was how windows will be re-sized by dragging them to different areas of the screen. This is a problem because I like to have some windows maximized (eg Emacs) in one screen and others manually sized (eg gnome-terminal) in the other. I like to be able to snap the medium sized windows to the top of the screen. With drag-to-resize dragging a medium sized window to the top of the screen became a chore. If I was overzealous with the mouse movement, the window would be accidentally maximized. That would cause me to curse and then unmaximize it. After this happened over and over, I finally turned off drag-to-resize.

Inconsistencies

Gnome 3 still being relatively new, I have also found it to have to some minor annoyances. For one, gui configuration in 3 is spread across three different editors: gconf-conf, dconf-conf, and the Gnome Tweak tool. The Gnome Tweak tool exists entirely for configuration of extensions written for 3. That I understand. I don't understand the need for two other editors, though. To me there seems to be almost no good rhyme or reason for why a particular configuration could be modified in dconf-editor or gconf-editor. I'm should someone more versed in the finer points of Gnome could tell me the difference. My point is that to gain adoption from a wider base of users there needs to only be one editor.

Another minor annoyance is that Looking Glass (lg), the debugger for developing extensions, is modal. After opening it, you cannot interact with any other window. In order to move or modify a window, you have to first close lg, do the action, then reopen lg. You'll find yourself repeating that sequence a lot. The developers page for 3 states that lg is inspired by the Firebug extension for Firefox. Firebug is not modal.

Looking glass debugger

There is small inconsistency in gtk support for extensions. In tinkering around I found it difficult (perhaps impossible) to open a simple, hello-world-style gtk window from within an extension. Therefore, extensions are restricted to a subset of windowing controls. Typically these controls have a different look-and-feel from standard gtk windows. You'll notice this difference in the various graphical "sudo" pop-up windows. If the window originates from an application or script it is in the form of a standard gtk window (eg gksudo, beesu). If it comes from a Gnome 3 extension, it looks like a Gnome 3 panel (ie black background with gray trim). This inconsistency is functionality meaningless. However, inconsistencies like this give you more of a disjointed experience.

Some of the hotkey bindings aren't quite as customizable as one would like either. For example, the key-binding for opening the Activities view is Alt+F1. That can be gui configured to something else in the System Settings dialog. In addition, the left Windows key will also open up the Activities view. Only the left Windows key, though. The right Windows key does nothing. Why? I have no idea. I also have no idea how to change this via a gui interface (or any other type of interface for that matter).

Bugs

In addition to the minor inconsistencies, there were also some things that appeared to not work at all. One of these being the Accessibility switcher within the Activities view. Perhaps this is just user error, but I couldn't figure out how to actually select an entry. To recreate this issue: first open the Activities view, then click Cntrl+Alt+TAB to bring up the Accessibility switcher. You should see the following selectable choices: Top Bar, Dash, Windows, Applications, Search. You can now use the arrows key to highlight one of them. At this point, I couldn't figure out how to actually select the highlighted choice. The Enter key does nothing; neither does any combination of a control key + Enter key. So far Google searching for this issue has been futile as all results only to point out how to launch the Accessibility switcher. Perhaps this is a bizarre issue with my setup and Fedora is to blame. Perhaps, but until proven innocent, I'm blaming Gnome 3.

Another buggy feature within the Activities view is dragging app icons from the Dash into a workspace. This is supposed to launch a new instance of that app within the workspace. Dragging the first app works as expected. However, if you immediately drag the same icon into another workspace, it launches itself in the currently active workspace and not the selected workspace. In addition, the mouse icon stays busy (ie spinner) until you exit out of the Activities view. Considering that I rarely use the drag-to-initiate feature, this is a minor bug for me. It is still something which should be tightened up.

Extensions

Functionality in Gnome 3 can be extended or changed via installable extensions. These are written by outside developers and are findable from the extension repository. As of time of writing, there are roughly 150 extensions found in the repository. Of these probably less than 20 are of any value. So extension developers are still sort of feeling their way around this thing. I briefly tinkered with writing one myself. I found the experience somewhat frustrating. First, there is almost no official documentation on how to write an extension. Even the official wiki points you to only two blog entries written by a guy named Finnbar P. Murphy. Two blog entries does not constitute documentation. Not to mention the fact that one of the entries is based on Gnome 3.0 and since the release of Gnome 3.2 is almost completely out of date. Good documentation would include both reference material and cookbook-style entries for implementing common patterns. The reference material would have to be specific to just extension development since extension development is only a subset of general Gnome application development. I found that some Gnome application code (eg opening a standard gtk window) will not work within an extension. This lack of documentation and examples never gave me confidence that I was developing my extension the right way. For an environment that prides itself on convention and consistency, it needs to do a lot better job of assuring developers that their code conforms to the Gnome way. I felt like any extension I would have managed to get working would have been filled with a lot of cargo-cult.

Shell Extensions tab in Gnome Tweak tool

There are some noteworthy and useful extensions. The ones I'm currently using are:

  • Alternative Status Menu For some Godforsaken reason, Gnome 3 doesn't let you fully power off your machine unless you hold Alt while choosing Suspend from the Status Menu. Suspend is a laptop feature, and I am on a desktop machine. So it doesn't really make sense to click on. Plus, sometimes you just need a good ole' fashioned power off. Alternate Status Menu gives you that option in the menu without making you remember which control key to hold down.
  • gTile This opens one panel per screen right in the middle of the in-focus window. By selecting tiles within the panel, you can resize windows to fit together on the screen. It works reasonably well at that task. It still seems a bit half baked. There are no key-bindings for it (eg Escape), and some of the buttons at the bottom of the panel make no sense to me. I couldn't find any documentation on what they do. Actually, they do not seem to do anything at all. So this extension is mildly useful but could certainly be improved.
  • Windows Alt Tab This changes Alt-TAB to behave like you expect. Instead of tabbing across all workspaces as is the default behavior, it only tabs through the current one. Also, multiple instances of an application are shown as different entries. The default behavior is to show them as a single entry and then force you to Alt-Tilde to the desired instance.
  • New Instance on Current Workspace By default, if you middle-click on a Dash entry, it will open a new instance of that application in a workspace below the current one. This only makes sense if you are using dynamic workspaces. I am using static workspaces. This extension changes the behavior to open the new instance in the current workspace.
  • Workspace Indicator This is a little dropdown located on the top panel (near the Status Menu) which displays your current workspace and lets you navigate to a new one with the mouse.
  • Frippery Static Workspaces It makes workspaces static and behave like they did in Gnome 2.
  • noally This removes the accessibility menu from the top panel.
  • Media player indicator This is a panel accessible from the top panel which displays which song your media player is currently playing. It allows for basic playback controls: play, pause, next song, volume control.

Of these, the extensions most important to me are: Static workspaces, Media player, and Workspace Indicator.

Summary

A critique like this tends to focus on the negative. I hope I didn't give the impression that Gnome 3 isn't ready for prime time. I believe it is. I use it on my personal computer and I'm not planning on switching. That being said, any sufficiently complex technology will have some disagreeable design decisions. Gnome 3 is no exception. The larger point is that Gnome 3 is a desktop paradigm improvement, and unlike Unity or MS Metro, it is not a hybrid desktop/tablet environment. So it is not saddled with their same compromising design decisions. It works with your mouse and keyboard and it works great by mostly keeping out of sight.

Tuesday, November 8, 2011

No really, it's a revenue problem.

We have a spending problem in Washington not a revenue problem. That is one of the most common refrains uttered by virtually every neoconservative in the past 30 years. Is it correct? Does our government irresponsibly squander ample revenue? Perhaps in some cases, but largely I don't think that explains why we consistently have a budget deficit or a massive Federal debt. One of the direct causes for both is simply that US citizens are paying less taxes than ever. In this post, I will demonstrate two truths about taxes that are commonly misunderstood. I will go on to argue that federal taxes are important to society and that further decreasing tax revenue will realize consequences most people do not want.

  1. Across the board, everyone is paying less tax than at any other post-war time.
  2. Wealthy people especially are being taxed significantly less than at any other time.

To prove that people are being taxed less per year, I used tax bracket data found at The Tax Foundation. With that data, I wrote a small Python script to calculate marginal tax in inflation adjusted (Real) dollars. Then I compared the taxes owed by 3 different levels of tax payer. The first was someone whose Adjusted Gross Income (AGI) is $49,445. That number was the median individual income for 2010. The second income I chose was $250,000. I selected it because Obama's 2008 campaign used it as a definition of wealth. I also compared someone whose income is $1M since someone making that is part of the 1% protested against by Occupy Wall Street. For each income, I compared what the taxes owed would be or have been in 2011, 2001, 1991, 1981, 1971, 1961, and 1951. All comparisons were done with the individuals filing status as "Single".

As is the definition of Adjusted Gross Income, this comparison is only related to marginal tax after all deductions and exemptions have been calculated.

As is obvious from these charts, across the board, marginal taxes owed have been dropping steadily for years. For the higher income levels, that drop started in earnest around the late 70s to early 80s.

Let's look at our current (2011) tax brackets. They are split into 4 columns.

  1. Married Filing Jointly
  2. Married Filing Separately
  3. Single (This is what I am using for comparison)
  4. Head of the Household

These 4 columns have been around in their current form since 1971. Within each column are six brackets. Here's what the Single column brackets look like:

  • 10% > $0
  • 15% > $8,500
  • 25% > $34,500
  • 28% > $69,675
  • 33% > $106,150
  • 35% > $189,575

So your rates go up for each dollar you make above a bracketed amount. Our current 6 bracket system is progressive (in other words, not flat). However, in the past we have been a lot more progressive. Here's what the Single column brackets looked like in 1969.

  • 14% > $0
  • 15% > $3,057
  • 16% > $6,114
  • 17% > $9,171
  • 19% > $12,228
  • 22% > $24,456
  • 25% > $36,683
  • 28% > $48,911
  • 32% > $61,139
  • 36% > $73,367
  • 39% > $85,594
  • 42% > $97,822
  • 45% > $110,050
  • 48% > $1222,278
  • 50% > $134,505
  • 53% > $158,961
  • 55% > $195,644
  • 58% > $232,328
  • 60% > $269,011
  • 62% > $305,694
  • 64% > $366,833
  • 66% > $427,972
  • 68% > $489,11
  • 69% > $550,250
  • 70% > $611,389

Whoa, that's a lot of brackets.

In 2011, the highest marginal tax rate is 35%. That rate was set as part of the infamous Bush Tax Cuts which are set to end in 2011. In 2012, the rate will move to 39.8%. Still, 40% is significantly lower than the 70% we were paying in 1969. The highest rate we've ever had was 94% in 1945. Of course that was only on income greater than $2.4M (Real) which was $200K in 1945 nominal dollars. Since then, we have been moving increasingly towards a flatter tax structure. This trend has accelerated in past 30 years as conservative economics have become the dominant ideology.

Why are the neocons so in love with flat taxes? One answer is they want a tax code everyone can understand. Another is that they want to justify a way for the wealthy to pay less tax. Flat taxes justify that under the guise of fairness. In fact, often flat taxes are called fair taxes. Ostensibly, they are called that because they do not go up or down depending on your income level. However, effectively a flat tax will raise taxes on the poor and lower taxes on the rich. This is because any flat tax rate above the lowest progressive tax bracket will raise taxes on people under that bracket. Flat taxes also have the undesired effect1 of significantly lowering government revenue. This is because wealthy people under a flat tax will pay taxes on most of their income at a significantly lower rate. Herman Cain's 9-9-9 plan was laughably bad in this regard. The Washington Post presented a chart which shows that 9-9-9 would raise taxes for most people and significantly lower them for the richest few. Of course, part of Cain's plan involved a national sales tax which would also have the effect of raising the cost of living by 9%. Actually, the three 9s combined would raise the cost of living for the poorest Americans by 27%.

So what's the problem with lowering the tax rate for the wealthy? Another common conservative argument is that paradoxically lowering the tax rate for the wealthy raises tax revenue. The theory goes this way: Instead of collecting a tax dollar from the rich, allow the rich to invest that dollar into the economy. This dollar investment could be turned into two dollars. Thus, two dollars will produce more tax revenue than one dollar. Thirty years of data suggests that this doesn't magically happen. This theory2 goes by a variety of names: It has been called supply-side or "trickle down" economics. Later, it was also called "Reagonomics."3 Currently, we are being warned not to tax the "Job Creators."

Allow me to get up on a soapbox. Given conversations I've had or overheard, my experience is that most people are clueless as to why paying less tax often hurts society in the long run. Our current policies have the effect of moving tax revenue to zero while increasingly turning our society in a private ownership society. This comes with a lot of unintended consequences.

For one, private, for profit, entities can only be enjoyed by people with money. So privatizing everything works to exacerbate inequality by stratifying access to resources and services.

Secondly, public money pays for common infrastructure (eg Roads). Private money can not and should not be responsible for infrastructure. There is just too much opportunity for special interest abuse. Consider the Interstate Highway System. It was built between the 1940s and 1960s. At the time, it was the largest public works project in the history of mankind. Everyone benefits from it. Because of it food and goods are cheaper because they can be distributed less expensively. So a modest tax investment can create public infrastructure with lasting economic benefits for everyone.

Thirdly, taxing the middle and upper classes allows for redistribution of wealth. In other words, it can mitigate aristocracies. For example, taxes pay for Medicaid which gives poor people access to healthcare. Devoid of this, poor people could have health concerns preventing them from participating in larger society, bettering themselves, and competing against wealthier people. Taxes can also be used to fix those kind of competitive imbalances.

My theory is that regular people want a balance in society. They want public works. They want lower income people to have a chance at a better life. They just don't understand the government's role in providing these things. I recently overheard coworkers of mine lamenting the condition of our highways. Said one coworker, "With all these people out of work, couldn't they be employed to fix up the highways?". I casually interjected that infrastructure improvements are a big part of the American Jobs Act. Both of these colleagues call themselves conservatives. Both dislike Obama. Yet they unknowingly made a liberal argument. I suspect a lot of conservatives, that is those whose minds haven't been warped by Fox News or Grover Norquist, would make similar arguments. So my theory is that average people know a balance should be struck between laissez-faire capitalism, central planing, and redistribution of wealth. Given the popular narrative that the Federal Government is at best inefficient and at worse incompetent, they are unsure about what role it should play in realizing this balance.

Given our current budget deficit and Federal debt, now is not the time to delude ourselves into thinking we can get something for nothing. Furthermore, since most individuals are paying less tax than ever and since rich individuals are paying significantly less tax than ever, most middle to upper class people can afford to pay more taxes. That is, of course, if you believe that Medicare, Medicaid, VA services, Social Security, public works, and the military are worth paying for. I do.


1 Flat taxes can increase government revenue in cases where compliance is an issue (former eastern bloc countries are an example) and can increase revenue depending on how income is distributed amongst the country, ex: if everyone has a similar income, flat taxes may not decrease revenue when compared with a progressive system.

2 Perhaps the genesis of this theory comes from the Laffer Curve. The original Laffer Curve was symmetrical. That is its peak, or highest tax rate before diminishing returns, was 50%. However, many believe that Laffer is really asymmetrical and its peak is really between 60% or 70%. This is a lot closer to what our marginal rates were in the 1940s - 1960s.

3 A lot of Reagon's actual tax policies (especially in the beginning) were progressive. For example, his administration raised the capital gains tax to 28%

Tuesday, August 30, 2011

backups-mode for emacs

github: backups-mode for emacs

John Siracusa's excellent Ars Technica review of Mac OS X Lion includes a page on Apple's new document model API. The intent of this API is to effectively end the practice of manually saving a document. Instead, applications will auto-save your documents in the manner of Google Docs or iOS applications. There are many scenarios where this will be helpful. John describes a few.

  • The student who writes for an hour without saving and loses everything when the application crashes.
  • The businessman who accidentally saves over the "good" version of a document, then takes it upon himself to independently reinvent version control—poorly—by compulsively saving each new revision of every document under slightly different names.
  • The Mac power user who reflexively selects the "Don't Save" button for one document after another when quitting an application with many open windows, only to accidentally lose the one document that actually had important changes.
  • The father who swears he saved the important document, but can't, for the life of him, remember where it is or what he called it.

Apple will now enable the following experience as written by John.

  • The user does not have to remember to save documents. All work is automatically saved.
  • Closing a document or quitting an application does not require the user to make decisions about unsaved changes.
  • The user does not have to remember to save document changes before causing the document's file to be read by another application (e.g., attaching an open document with unsaved changes to an e-mail).
  • Quitting an application, logging out, or restarting the computer does not mean that all open documents and windows have to be manually re-opened next time.

I will add that file versioning is another aspect of Apple's API.

  • The user can explicitly choose to save a version of the document.
  • Old versions can be found and viewed.
  • Old versions can be reverted to. This saves the current file as a version and switches the chosen backup with the current file.

With backups-mode I've set out to approximate Apple's Document Model idiom in emacs. Here's how I accomplish it.

  • emacs already has an auto-save feature that is turned on by default. Therefore, if emacs crashes, a user can revert from this file that is saved periodically.
  • I've redefined kill-buffer and save-buffers-kill-emacs to automatically save any file-based buffer when closing a file or quiting emacs.
  • I've turned on emacs' version-control and am saving old versions of a file to a central location instead of said file's location.
  • The user can save a version of the file they are editing with the save-version command bound to \C-cv.
  • The user can list all versions with the list-backups command bound to \C-cb.
  • After listing old versions via list-backups, the user is taken to a special backups-mode buffer where they can:
    • View an old version in read-only mode
    • Diff two versions
    • Revert from an old version
backups-mode buffer

Installation, configuration, and usage documentation can be found on github.

Monday, August 29, 2011

Smelly code, smelly code. Why are they writing you?

There are certain times in your career as a developer when you come across code so horrible, it causes you to question your faith in humanity. Such was the case when my boss and I were given the MicroMain Web Request application to install on one of our servers. We couldn't get it work even though we followed the instructions meticulously. We even spoke to one of their support people. Unfortunately, he was not one of their headset hotties. The error message we were getting wasn't too helpful, either:

Format of the initialization string does not conform to specification starting at index 0

This is a generic .net message. The issue was that we couldn't connect to the database. However, our SQL Server hadn't recorded a login attempt from the application. We were thinking it was a configuration issue. The web.config file was valid xml. Nothing looked terribly strange. Thankfully, they also provided us with the source code. Probably an accident. Nevertheless, we went to the function that was causing the error and were horrified by what we saw.

Public Shared Function GetConnectionString() As String
   'Dim sOleDb As String
   'Dim cn As OleDbConnection
   'Dim cmd As OleDbCommand
   'Dim dr As OleDbDataReader
   Dim returnConnString As String
   Dim sMethod, sColumns, sTableName As String
   sColumns = "DataLink, Platform, Login, Password, Server, Database"
   sTableName = "tblzApp"
   sMethod = ""
   If ConfigurationManager.AppSettings.Count > 0 Then
       sMethod = ConfigurationManager.AppSettings.GetKey(0)
   End If
   Try
       Select Case sMethod
           Case "ConnectionString"
               returnConnString = ConfigurationManager.AppSettings(sMethod).ToString
           Case Else
               Return sMethod
       End Select
       Return returnConnString
   Catch ex As Exception
       ex.Source &= "<br /> DAL.GetConnectionString"
       Throw ex
   End Try
End Function

Just for clarification, this is a 23 line function that should be a 1 line function. Here is what the body should look like:

Return ConfigurationManager.ConnectionStrings("MicroMain")

The beauty of this 1 line function is that if it fails, you know exactly why it failed. It fails fast. Conversely, their code fails slowly. In other words, it failed but didn't tell us why.

In addition to that, I happened upon at least 9 different code smells within this single function.

Code Smells within GetConnectionString

  1. getting a key/value item by position instead of name (appSettings is a key/value store)

    This is the equivalent of being a high school principal and walking into a classroom to fetch Jonnie. Instead of walking in and asking for Jonnie, you walk in and grab the student closest to the door, whisper into his ear "Are you Jonnie?". If he says "no", you walk out the door and do not complete your objective.

  2. using AppSettings for the connection string instead of ConnectionStrings (non-idiomatic)

    Since 2005, .net has a config section dedicated to connection strings.

  3. declaring unused variables (ie copy and paste programming)

  4. declaring unnecessary temporary variables (eg returnConnString)

  5. unnecessarily calling ToString

    Getting an AppSetting value implicitly returns a string. Calling ToString simply gives you the opportunity to fail with the generic error message "object not set to instance of object" instead of letting the caller handle the missing value case.

  6. try/catch is totally unnecessary (since ToString should not be called)

    Furthermore, try/catch blocks should not be put into most methods. Unhandled exceptions should be allowed to pop up the stack to a global exception handler.

  7. mixing html into data access code

    If I have to explain why this is bad, you need to find another career.

  8. commented out code still hanging around (lazy coding or perhaps they don't use source control!!!)

  9. naming the connection string key "ConnectionString" instead of "MicroMainConnectionString"

    This assumes that the application is the only application deployed on the server.

The disaster continues

  • no global exception handler (ie yellow screen of death)
  • SQL Injection attacks

    Looking through other methods within their code, I found them not using parametrized queries. Instead, they were building SQL by string concatenation which leaves them wide open to SQL injection attacks.

Makes you think...

Looking at their website and taking into account the fact that they sold their software to Newell-Rubbermaid (a Fortune 500 company), I get the impression that they have better salespeople than developers. Their code was head-scratchingly bad. It makes you wonder about the state of code in other off-the-shelf applications. Is it all this bad, or was this an anomaly?

As Jeff Atwood would say "Enterprisey to the bone".

Saturday, August 6, 2011

Alaska: The Last Frontier

Skip to the Photos

As I left work the Monday after returning from Alaska, I realized exactly who I resembled; Al Pacino from end of Insomnia. Fitting since that movie was set in Alaska. Alaska will do that to you. Especially in the summer when it stays light out almost all day long.

That fact was the first thing that struck us on our trip. While we were in Fairbanks we could look out our hotel room at 12:30AM and still see all the way across the town. It wasn't until we drove farther south into Homer that we were awake while it was dark outside.

From Alaska

Most Alaskans are very similar to "Americans" as they call us lower48ers. However, there are some notable differences.

One difference is gun ownership. Most Alaskans own, carry, and use guns on a regular basis. This is a big difference from your average Northern Virginian; At least the ones I associate with. Heidi's (my wife) grandfather has a huge gun collection. In fact, he keeps a vintage, working condition 1848 Sharps rifle under the couch in his living room. That discovery seemed astonishing to me; Both that he owns such an antique and that he keeps it under his couch. He also has a working 1898 Winchester shotgun in his kitchen resting against the counter. Heidi's uncle has a AK-47-like clone casually resting against the bookshelf in his living room. So it is a different culture from what we are used to here.

I don't know if most Alaskans also identify themselves as "westerners", but our experience indicated that they share similar traits. One such trait was an assertiveness with strangers. Whereas eastern Americans are often considered to be closed off to interacting with strangers, Alaskans are not. We met a lot of people in public areas who simply started talking to us. To me, as someone is as reserved as any easterner, this took some getting used to. My wife loved it. She's more outgoing. Perhaps this phenomena was simply a function of us spending most of our time in high traffic tourist areas. The sort where the locals are wont to give suggestions. However, often it wasn't. During our last night in Alaska, we were at a bar in Anchorage sitting a long, high table when a guy and his girlfriend sat down next to us and started up a conversation. They weren't giving us suggestions or selling us anything. They simply wanted to talk. That type of experience seems a lot more unlikely to happen in Virginia.

From Alaska

Seeing wild animals native to Alaska was one of the best ongoing experiences we had. The interesting animals we saw included: moose, bald eagles, a sea otter, and orca whales (killer whales).

Moose are like the Alaskan deer. The are everywhere along the side of the road in Alaska.

We saw the orca whales the first night we stayed in Homer. We were on the "Spit". The Spit is a 3 mile narrow strip of land that juts out from the town. We had just exited the famous Salty Dawg bar when Heidi says, "let's walk down to beach". So we walk down and stay just long enough for her to put her feet in the water. We turn to walk back when she catches a glimpse of something briefly pop up out of the water about 30 feet from shore. I sort of see it. She said, "I think those were orcas". I said, "What's an orca?". So we stood there for a second and sure enough, the two whales pop back up briefly. Their dorsal fins and black color where unmistakable.

Our trip was split into two halves. The first half was spent with Heidi's family. The second was more of a personal vacation for us. Most of Heidi's family lives in Palmer, Alaska. Palmer is about 45 minutes away from Anchorage. For you Palin fans or haters out there, Palmer is 5 miles away from Wasilla. We spent a couple of days there, then we drove to Fairbanks which is about a 6 hour drive away. We were in Fairbanks for Heidi's cousin's wedding. After leaving Fairbanks, we stayed with Heidi's aunt and uncle in their cabin located between Delta Junction and Tok. After staying with them for a couple of days, we returned to Palmer via Tok. This is the point in the trip when Heidi and I left her family and went on our own. We traveled south onto the Kenai peninsula after first staying one night at Alyeska resort in Girdwood. Our journey south brought us to Homer where we stayed for two days. After that, it was time to travel back to Anchorage and then back to Virginia.

Wednesday, July 6, 2011

Common Lisp lazy sequences

When we left things in Part 2, we needed a function that would return an infinite sequence of the same argument. In Clojure, we saw that function is used like so:

(repeat "+") ;; "+" is the argument to repeat infinitely

Common Lisp does not have infinite sequences built in, but they are easy to implement. The Common Lisp library clazy is an implementation of them. For the sake of demonstration, we will sort of reinvent that implemenation in a simpler fashion.

Lazy sequences

Without further ado, here is the code to implement a very rudimentary lazy sequence library:

(defpackage my-lazy
  (:use :cl)
  (:shadow cl:cdr cl:mapcar)
  (:export "CDR" "MAPCAR" "DELAY" "FORCE" "REPEAT"))

(in-package :my-lazy)

(defstruct thunk
  body)

(defun thunkp (arg)
  (eq (type-of arg) 'thunk))

(defmacro my-lazy:delay (expr)
  `(make-thunk
   :body (lambda () ,expr)))

(defun my-lazy:force (thunk)
  (if (thunkp thunk)
      (funcall (thunk-body thunk))
      thunk))

(defun my-lazy:repeat (arg)
  (cons arg
    (delay (repeat arg))))

(defun my-lazy:cdr (cons)
  "cdr for lists, force cdr for thunks"
  (force (cl:cdr cons)))

(defun my-lazy:mapcar (f list &rest more-lists)
  "Apply FUNCTION to successive elements of LIST. 
Return list of FUNCTION return values.
lists can be lazy"
  (cons (apply f
           (car list)
           (cl:mapcar 'car more-lists))
    (when (and (cdr list) (every #'identity more-lists))
      (apply 'mapcar
         f
         (cdr list)
         (cl:mapcar 'cdr more-lists)))))

The first thing you'll notice is that we create a lazy package called "my-lazy" that when used will shadow some core functions (cdr and mapcar). This shadowing is necessary because we need these functions to operate similarly regardless of if the sequence is a list or a lazy list.

Also, you'll notice that we create a structure called a "thunk" (eg defstruct thunk). Wikipedia defines a thunk as:

In computer science, a thunk (also suspension, suspended computation or delayed computation) is a parameterless closure created to prevent the evaluation of an expression until forced at a later time.

We define a thunk as a structure instead of simply a parameterless lambda so that our thunks have a type unique from any other parameterless function.

The two key items here are delay and force. Delay is a macro that creates a thunk from an expression. Force is a function that forces the evaluation of a thunk.

Cdr is redefined to "force" evaluation of the core cdr of a cons cell if the core cdr is a thunk. Otherwise, our cdr simply returns the core cdr of the cons cell.

Mapcar is also redefined. Basically, it is only redefined to use our version of cdr. Besides that, it does basically the same thing as the core mapcar.

Now let's check our example. First in Clojure:

user> (map (partial str "price & tip: ") [5000 100 50] (repeat "+") [2000 40 10])
("price & tip: 5000+2000" "price & tip: 100+40" "price & tip: 50+10")

Next using our new package in Common Lisp:

CL-USER> (in-package :my-lazy)
#<PACKAGE "MY-LAZY">

MY-LAZY> (mapcar (partial 'str "price & tip: ") 
          '(5000 100 50) (repeat "+") '(2000 40 10))
("price & tip: 5000+2000" "price & tip: 100+40" "price & tip: 50+10")

Huzzah! We have successfully replicated standard Clojure functionality in Common Lisp.

Conclusion

In Part 1 we looked at modifying the Common Lisp syntax using reader macros. In Part 2 we looked at simplifying function calls using currying techniques. Here, in Part 3, we implemented infinite sequences which eliminated a (sometimes) hard to find bug.

The great thing about Common Lisp is that it is extremely easy to implement all of these concepts. In most other languages, implementing these concepts would almost definitely be either more difficult or not possible. The only drawback is that often there is too much freedom. The Common Lisp ethos is such that developers are encoraged to implement these concepts on their own. The result is, unlike the Clojure world, often there is no cannonical answer to these problems (such as lazy sequences). As a fan of Common Lisp, I'd like to see it gain more traction. Perhaps that will take one killer application (like Rails for the Ruby language). For that to happen, it will probably also need more coherance across the community. Regardless, because of its flexibility, it is still, in my opinion, the ultimate hacker language.

Common Lisp currying

In Part 1 we looked at adding to the Common Lisp syntax using a reader macro. Now we are going to use a regular function to implement a technique called "currying". We do this to abstract away a function call with a common argument. So instead of calling the same function with the same argument over and over again in your code, you can curry that function call w/ argument into a symbol that can be called on its own.

Currying

Wikipedia defines currying as:

In mathematics and computer science, currying is the technique of transforming a function that takes multiple arguments (or an n-tuple of arguments) in such a way that it can be called as a chain of functions each with a single argument (partial application).

In Part1, we needed to curry the function "concatenate" with the argument "'string". There are a number of ways to do this. We are going to build a currying function called partial that approximates the Clojure function of the same name.

Partial

The example which uses the partial function in Clojure comes from here. Below is the same example using the #() reader macro from Part 1 along with a slightly more readable and compact version using partial.

user> (map #(apply str "price & tip: " %&) 
              [5000 100 50] (repeat "+") [2000 40 10])
("price & tip: 5000+2000" "price & tip: 100+40" "price & tip: 50+10")

user> (map (partial str "price & tip: ") 
              [5000 100 50] (repeat "+") [2000 40 10])
("price & tip: 5000+2000" "price & tip: 100+40" "price & tip: 50+10")

Notice how the use of partial gets us out of the prosaic work of using a reader macro and "applying" a list of arguments to the magic "%&" argument. The "%&" list argument is implied when we use partial.

Partial turns out to be another trivially easy function to write in Common Lisp.

(defun partial (f &rest args)
  "currying function"
  (lambda (&rest more-args)
    (apply f (append args more-args))))

Essentially, we are merging together the arguments we know with the arguments we will be passing into the curried function. Let's demonstrate it in action.

CL-USER> (mapcar [apply 'concatenate 'string "price & tip: " %&] 
          '("5000" "100" "50") (loop repeat 3 collect "+") '("2000" "40" "10"))
("price & tip: 5000+2000" "price & tip: 100+40" "price & tip: 50+10")

CL-USER> (mapcar (partial 'concatenate 'string "price & tip: ") 
          '("5000" "100" "50") (loop repeat 3 collect "+") '("2000" "40" "10"))
("price & tip: 5000+2000" "price & tip: 100+40" "price & tip: 50+10")

CL-USER> (setf (symbol-function 'concatenate-string) 
          (partial 'concatenate 'string))
#<CLOSURE (LAMBDA (&REST MORE-ARGS)) {1007DC0E09}>

CL-USER> (mapcar (partial 'concatenate-string "price & tip: ") 
          '("5000" "100" "50") (loop repeat 3 collect "+") '("2000" "40" "10"))
("price & tip: 5000+2000" "price & tip: 100+40" "price & tip: 50+10")

Now we are getting somewhere. Using partial we've been able to turn the symbol 'concatenate-string into almost the same thing as the Clojure function "str".

String methods

The more astute readers may notice the Common Lisp examples still contain a little extra cruft not found in the Clojure examples.

The two pieces of cruft I am referring to are:

  • The Common Lisp version contains double quotes around the price literals. Thus starting them out as strings. The Clojure version simply uses numbers and within the "str" function they get converted to strings. We'll adapt the Common Lisp version to do the same.
  • The more dastardly of the crufty items is the lack of Clojure's "repeat" function. The Clojure "repeat" function simply repeats the argument infinitely as a sequence of items. This works in our example because map stops when one of the finite list args runs out of items. Our Common Lisp version relies on us to use the "loop" macro. In using "loop", we must specify an iteration value that matches exactly the length of the longest of the other list args. Failure to do so will cause our code to short circuit. This can be the source of maintenance bugs in production code.

Let's tackle the first piece of cruft. Here's the Common Lisp code:

(defmethod to-string (arg) (string arg))
(defmethod to-string ((arg integer)) (write-to-string arg))

(defun str (&rest args)
  (apply 'concatenate-string  (mapcar #'to-string args)))

The first thing to notice is the use of "defmethod" instead of "defun". Defmethod is a way to create functions that are dispatched differently at runtime based on argument type. So if we pass an integer argument to "to-string", the result will be:

(write-to-string arg)

Whereas, if we pass an argument of any other type to "to-string" the result will be:

(string arg)

In other words, the latter "result" function is the default, whereas the former is a specific type implemenation. This gives us great flexibility to extend "to-string" in the future without redefining any current methods.

The "str" function behaves just like the Clojure equivalent. It takes in a list of arguments and turns them all into strings before sending them along to our "concatenate-string" function.

Approximating the Clojure "repeat" function is a little more tricky. It will require us to implement infinite lists. Part 3 will demonstrate how to do that.