Sunday, October 30, 2011

Learned Optimism

Trust me (I'm a doctor)--it's not a self-help book. I don't like anything that even smells like a self-help book. But I've been interested in psychology for a long time and recently heard of a relatively new strand called positive psychology. My psychologist friends tell me that its strongest proponent is Martin Seligman, a professor at the University of Pennsylvania who became famous for disproving strict behaviorism by showing that dogs could learn to be helpless. If dogs (and people) can learn to be helpless, why can't they learn to be healthy?

Positive psychology has three roots: 1) the unfortunate fact that most psychology focuses on deviance rather than prevention, 2) studies showing that how we think impacts our lives in many ways, and 3) therapeutic evidence proving we can change how we think, and for the better. In brief, Seligman and other positive psychologists want to fix how we think before we have problems.

According to Seligman, everyone understands events along three dimensions: how representative or pervasive they are, how permanent their effects will be, and how personally responsible we are for them. If something goes wrong for a total pessimist, he will say "Everything is going wrong for me. Things will never change. And it's all my fault." If something goes wrong for a total optimist, she will tell herself, "This one thing is bad right now. It won't always be like this. And many people and circumstances are at fault." Seligman has shown that optimistic people tend to be happier and more successful than pessimists. People prone to depression and people who are depressed tend to have pessimistic explanations of events.

Becoming more optimistic and avoiding depression involves learning how to argue with yourself. You have to interrupt the pessimistic explanatory patterns that may have become natural to you and use more optimistic ones. When you say to yourself, "It's all my fault; I'm a bad person," you catch yourself and say, "I'm just having a bad day" or "The person who yelled at me is just having a bad day."

This book was fascinating to me, because, as a card-carrying philosopher, I see the pessimistic explanations as bad reasoning. Pessimists use false generalizations to understand particular events. To look at one misfortune as representative of a supposedly failed life is simply a logical fallacy. Learning to be an optimist, then, is learning to be more rational.

However, optimists can fall prey to the exact same fallacy. When something good comes their way, they tell themselves, "My life is great. It will always be this way. And it's all my doing." This rose-colored vision has pitfalls of its own, and Seligman is careful to say that what we need above all is balance in our thinking. The pessimistic explanatory style should be used when you're thinking about something risky, like financial planning, career moves, or performing surgery on others. The optimistic style should be used for explaining everyday events, especially other people's behavior.

I think programmers tend to be optimists, since they are usually confident about their own abilities and quick to point to other causes when things don't go well. I often hear explanations like, "Our delivery is late because the customer changed the requirements," or "The code is terrible, but I didn't design it," or "It works on my machine--I can't imagine why it doesn't work anywhere else." It's easy to place the blame on the complex systems we collectively build, because, in the end, no one can really be said to be at fault. We can always be sure, however, that our code is good, since we complete projects and don't get fired much, as we're in high demand.

The problem with optimism is that confidence can breed arrogance and that systems-thinking can breed quiescence. Arrogance is a problem because it makes you hard to work with. It causes you to underestimate how long a project will take. It can also lead you to miss changes in the field. It's easy to coast for a while as a programmer, until you suddenly find that no one uses your technology of choice any longer. One way to fight arrogance is to force yourself to learn new technologies. You'll quickly realize how dumb you really are.

The main way to fight quiescence, unfortunately, is to change corporate culture. Google and other companies have experimented with giving programmers a fixed amount of time to do whatever they want. Programmers typically fix things that have been driving them crazy or build in-house tools to do what they do more easily. If you don't work at Google, you have to be the change you want to see. If you want to work on a system with good code and with people who take responsibility for it, take the initiative yourself. Programmers don't like to be shown up. Once one person starts, it will be hard for others not to join in.

Links:
-Take the Learned Optimism Test

Sunday, October 23, 2011

Gödel, Kuhn, and Human/Computer Co-evolution

Kurt Gödel showed that all formal systems are incomplete, meaning that there are truths that can be stated within a system that cannot be demonstrated within it. This means that truth cannot be reducible to axiomatic principles and, therefore, that there is no single system to which all truths could be reduced, whether it be physics, mathematics, logic, or any other system of abstraction.

These principles have become widely accepted within mathematical and scientific communities. After Thomas Kuhn's Structure of Scientific Revolutions, it has become common to think of domains of knowledge as paradigms which are never proven or disproven but which are eventually abandoned in favor of new, more helpful, or more interesting paradigms. What makes a paradigm valuable cannot be shown within the paradigm itself but by the problems it helps solve or the vistas it allows.

I've been trying to think through the implications of these insights for technology ever since reading Douglas Hofstadter's Gödel, Escher, Bach. As I understand it, the book's main point is that any attempts to create artificially intelligent systems that are grounded solely in deductive logic are doomed to failure. Human thought involves deduction, but it involves much more. As Hofstadter writes in his introduction to Ernest Nagel and James Newman's Gödel's Proof, the goal of AI research should be to devise systems "guided by visual imagery, the associative patterns linking concepts, and the intuitive processes of guesswork, analogy, and esthetic choice that every [person] uses."

The kind of AI we are most familiar with is Google. It is probably a stretch to say that the Google engine thinks, but it is certain that the algorithms it uses to filter and aggregate trillions of bits of information are guided by analogies and associations if not esthetic choice. Google gets feedback from users in the form of click-throughs, so it can better predict what sites to show in the future. Feedback loops like this are at the center of thought and learning. The more the Google engine can modify itself instead of relying on engineers to tweak algorithms, the more it can be said to think.

But the computer side of this loop is only one half of the picture. Just as computer systems learn from us, we learn from the systems. It's a dynamic, co-evolutionary process, and we need to think about the kinds of choices that computers make available to us. Eli Parser has coined the term 'filter bubbles' to describe the ways that applications like Google and Facebook filter information for us and thus structure the choices we make. This is not necessarily a bad thing, since we desperately need ways of filtering out information that is not relevant to our purposes. However, it will be a co-evolution that requires careful attention, for, unlike the bee and the flower, we can control our collective destiny.

This brings me back to Kuhn, since he suggests that the terms we currently use to think about our co-evolution are not necessarily the best for the job. One of the interesting things about computing is the way its concepts and language have been used to understand other things. Metaphors from other walks of life permeate computing, like 'the cloud', 'friend', or 'stream', but computing has also shaped the ways we understand each other and the world. It's not simply a matter of words like 'Google', 'text', and 'filter' becoming commonplace, because everything is either a computer or something to be computed today. For example, it's hard not to think of human minds (or 'wetware') along computational lines now. Not only do we 'process data' and 'filter out noise', but we act on information that has been computed so that we can better operate computers. Commercials tell us that our very personhood is threatened if our personal data are lost.

I wonder if we're seeing the waning of a paradigm, or the waxing of a new one. Will the next years of computing see more of the same, only faster? Or will we come to understand thought, action, art, ethics, and even humanity in an entirely different, techno-saturated vein? Are computers just machines (with which have have been long familiar--we are eating machines, sex machines, and poop machines). Or are they something different?

Links:
-Jaron Lanier's You Are Not A Gadget

Sunday, October 16, 2011

Database Refactoring

I'm taking ownership of a database, so I've been reading about database development best practices. Database development is unique from other kinds of development for a number of reasons. Most crucially, you can never start from scratch with a database, because it's a living, breathing thing--you can't simply recompile and redeploy. Second, you have to design your database so that it can be set up with representative data on developers' workstations, in a development environment, and a testing environment. Third, you have to make sure that any scripts can be deployed on any environment (it usually helps to have some way of knowing what 'version' a database is on). And you may have to do all this while being unsure of all the applications that access a database, or the manner in which they do it.

These challenges led me to read Scott Ambler and Pramod Sadalage's book on database refactoring (2006). "Refactoring" is a term popularized by Martin Fowler's eponymous book (1999). He defines it as a "disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior." It is important to have a concept like refactoring, because development is usually focused on adding functionality only. When things change quickly, who has time to refactor?

There is some anecdotal evidence that spending time refactoring will decrease the amount of time coding later, but there's no rule for how much time you should spend refactoring. However, if you can't do any of the things mentioned above (limit access to your database, know what version it is, deploy to multiple environments), you must refactor. The hoops you'll have to jump through just to do normal development are far costlier than the effort needed to refactor. Ambler and Pradalage also suggest that it might be time to refactor if you notice any of the following "database smells": multi-purpose columns, multi-purpose tables, redundant data, tables with many columns, tables with many rows, "smart" columns, and fear of change.

Defining refactoring in the way Fowler does is also important, because it simplifies testing by separating the development of added functionality from development that should preserve existing functionality. Ambler and Pradalage embrace a Test-Driven Development approach, where you test, deploy, and test again. If you make testing central to your development process, you can be sure that you're not breaking anything during refactoring.



Though refactoring seems necessary only in (hopefully) rare circumstances, the steps that constitute it should bleed into normal development. For example, it's always a good idea to develop in small, easily testable pieces, rather than making many large changes all at once. An iterative process also allows for feedback from users. In short, refactoring should help you to embrace AGILE principles in database development, and it should make further development faster and easier. Even if you can't make your database development completely AGILE, these principles should help you evaluate bottlenecks in your process and suggest means of addressing them.

Links:
-An article that contains the main sections of the book

Sunday, October 9, 2011

The OO Factor

TIOBE releases statistics on the popularity of programming languages every month. The methodology behind the study is not without its limitations, but it's definitely worth checking out. The information is culled entirely from search engine statistics, and there are some difficulties interpreting the data, as the popularity of languages forms a long tail. One of the best things about the study is that they have data going back 25 years (though I'm not entirely sure how).

I don't want to start any arguments about whether your favorite language is increasing or decreasing in popularity. Instead, I'm interested in what this data means for your career. Chad Fowler likens your investment in a language to financial investing. You might pick ole faithful and get consistent returns, or you might take a gamble and hit the mother load. Here are some of the lessons I think are worth noting.



1) All of the top languages are object-oriented (with the exception of C). Whether you specialize in Java, C++, or C#, you're OO. These languages are far from being identical, but their similarities are much greater than their differences. It's a testament to the OO paradigm that it has enabled the development of enterprise applications with reusable code in a wide variety of syntaxes and styles. Really I'm shocked by how popular C still is, as it is not technically an OO language.

CategoryRatings Sep 2011Delta Sep 2010
Object-Oriented Languages56.2%+1.7%
Procedural Languages37.7%-2.5%
Functional Languages4.3%+0.5%
Logical Languages1.8%+0.3%


2) Everything else is a grab-bag. After the top 10 or 20 languages, you have a long tail of less popular languages, especially procedural languages. I see Haskell, Scala, F#, and a whole bunch of languages I've never heard of. It's tough to pick one of these to focus on. Will Erlang experience a meteoric rise now? Will COBOL finally bite the dust?

3) Conclusion: Diversify your knowledge resources. In a market like this, all you can do is diversify. It's a good idea to become familiar with a couple of OO languages and development environments, though I'm not going to spend all my free time learning Java in the off-chance that Microsoft platforms take a nose dive (which this article suggests might happen). If you're a Windows-only programmer, download Linux, Eclipse, and do some Android programming.

Once you have those bases covered, it's hard to say what you should learn next. For this reason, I think about learning languages in much the same way as I thought about studying philosophy. If you want to learn philosopher X, reading his/her works will only get you so far. You also have to read lots of other philosophers to understand what X is responding to and what makes X different. In the same way, languages develop historically in response to the successes and failures of other languages. If you really want to learn an OO language well, you'll have to understand what makes it different from Prolog, Lisp, and some of the other alternatives out there. That way, you'll be able to better understand and articulate why the approach you want to take to solve a problem is the right one. That's a valuable skill in any market.

Links:

-Chart of the evolution of programming languages

Sunday, October 2, 2011

Silverlight, Security, and Sandboxing

I'm taking ownership of an application that uses Silverlight for a front end. I had never programmed in Silverlight before and only really knew of it from Netflix's Instant Streaming. I've come to really appreciate Silverlight, since it provides a rich user interface while leveraging the resources of powerful platform like .Net.

It's easiest to think of Silverlight as an alternative to Adobe Flash, which does not easily integrate with other code. The recent Internet-based UI revolution has taken two paths: Flash-like applications (called Rich Internet Applications (RIA)) and AJAX-powered pages like GMail. It's hard to remember the days when you had to refresh an entire page to gain new content, since AJAX and Flash provide such a seamless experience.

Developing in Silverlight is just like developing Web Forms, Sharepoint controls, or User Controls. It just uses XAML instead of ASPX. See the snippet below:
<stackpanel name="LayoutRoot" background="White">
<textblock text="Hello, World!" horizontalalignment="Center">
<ellipse name="FirstEllipse" height="100" width="200" fill="SlateBlue">
<button name="FirstButton" width="100" content="Click" click="FirstButton_Click">
private void FirstButton_Click(object sender, RoutedEventArgs e)
{
FirstButton.Content = "Click Again!";
}

(taken from this example)

As a long-time ASP.NET Web Forms developer, I was surprised that I couldn't just make a DataGrid object and connect it to a DataSource object. To connect to any data, you have to create a Windows Communication Foundation (WCF) web service. This entails learning yet another technology (more on that in a later post), and all the difficulties entailed in creating, deploying, and debugging web services.

I had a hard time finding anything explaining why all this was necessary, until I found this article by Josh Twist. Since a user downloads a Silverlight application that runs in their browser, it cannot be trusted by a server. You need a boundary of abstraction and authentication in order to ensure that the integrity of your data (and your servers) is maintained.


When you have a standard Web Forms application, all of the code is executed on the server. Even though Silverlight code looks like server-side code, it's really executing on the client's machine. For this reason, it faces all of the same limitations as client-side code you might be more familiar with, such as JavaScript and Java applets. A Silverlight application can't be trusted, since its code is non-deterministic and might become corrupted at any time. For this reason, it is sandboxed by your browser. It can't take up all your memory. It can't access the file system. And it certainly can't access your database.

This secure sandbox model is going to become more and more prevalent. The 2000's saw a resurgence of the client-server model in which thin clients (like web pages) did little processing but produced a lot of network traffic with servers. But with the rise of mobile phones, tablets, and other cheap devices, there is no reason to continue to put such a strain on servers and networks. RIA's also provide a great user experience--so great that Windows 8 is going to make it a major part of its architecture. The Windows Metro platform is meant to emulate the touch-driven interface of mobile apps while maintaining the tools many developers have continued to use.

If you want to port an application to desktop, tablet, and mobile devices, you'll have to make this architecture your friend.

Links:
-MSDN article on Silverlight sandboxing
-Windows Metro preview at Engadget
Related Posts Plugin for WordPress, Blogger...