Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts

Saturday, March 5, 2011

Programming: What Exactly Is It

Computer Science is a misnomer. A science is the study of a particular subject with the aim of building a body of knowledge through observation, experimentation and prediction. Physics is a science; we've worked to understand the natural laws that govern material objects, their movement and their interaction with each other.

In contrast, a programmer does not study and try to understand a set of laws inherent to an existing, mysterious system. A programmer creates. The computer does not cease to function if you put everything into the global namespace or create a God object. It's just a bad judgement call. Science doesn't have judgement calls. It's either true and testable, or it isn't.

So programming is a craft. A craft is something that requires skilled labor. Unlike art, it generally produces something practical and usable. Unlike unskilled labor, one of the worker's responsibilities is to make judgement calls that greatly affect the quality of the result.

A programmer named Dan North wrote a winding and controversial article defending his opinion that programming is not a craft but a trade. I don't feel like picking apart his entire article, but here are a couple points:
  • He doesn't argue in terms of concepts. Depending on your take on the words "craft" and "trade" (which, according to some dictionaries, are synonyms), you may agree or disagree with him. That's a shaky basis for an argument.
  • He focuses on the attitude of some programmers who claim to be craftsmen. He has more of an issue with conceited posers than good programmers who consider their work a craft.
  • He says that clients don't care how well-crafted the code is; they simply want it to do what they want it to do. That's true, but they also want to save time and money in the long-run.

Unskilled labor can be unskilled because they've been given a design formulated by someone else; there are few or no judgement calls left to be made. E.g., an assembly line worker who bolts pre-stamped parts to a car or a worker in an electronics factory who solders components to a board according to a schematic. Unless you have a software architect who spells out every class, every package, every method and every interaction, you make hundreds of judgement calls every day as you code, and those decisions affect the long-term viability of the software.

No matter what features our bosses or clients want from us, we're the programmers. We're responsible for knowing how to implement those features in a way that will benefit the company or client, not just right now, but in the long-run. If your only focus is to get the code to do what the the client wants, I pity the developer who has to maintain it and the client who has to foot the bill to extend it. That's where craftsmanship comes in. We're paid by clients to craft a quality product that they will continue to be pleased with.

Friday, March 4, 2011

Architectural Notes

These are just a few things related to programming I've been thinking about.

  • There's rarely a right answer; if you're fortunate, there will be an obvious choice with fewer trade-offs.

  • Design is very subjective. If you give a problem to five programmers, you will get five different implementations, and it's quite possible that all of them are good. Every carpenter knows that a dovetail is the strongest joint, but the curve of the chair's back, the spread of its legs and the finish of its grain are all judgement calls that go into making something elegant but practical.

  • Programming is a craft, not a science.

  • Expect to do one major refactor of any project or feature. It's OK---you had no way of knowing that what you thought you needed at first wasn't what you actually needed, and your first attempt will finally give you a standard for comparison to create what you actually needed to begin with.

  • Code something with the simplest solution possible without ignoring extensibility or flexibility. Worst case, you have to do a major refactor, which is quite nearly inevitable, anyway (see above point). Best case, the solution works and you're done. Either way, you didn't spend more time than was necessary.


All things considered, this means we're the blue-collar workers of the future. I hope you're OK with that.

Friday, July 30, 2010

My Health As a Programmer

People often separate general health into categories--physical, emotional, mental, congenital, hexagonal, Portugal. Although some degree of health in one area or another is possible while ignoring the others, I firmly believe each category is dependent on the others.

Good programmers are proud of their capacity for resolving issues and breaking down problems into their salient parts. Quips about co-workers aside, mental and intellectual health are crucial, and I'll bring that up again later. But that's a very small part of a very large picture.

Physical

I had an undiagnosed medical condition for a couple years that affected my energy, motivation and self-image. I didn't have enough energy to keep a routine of physical exercise. On some days, I struggled to stay awake. Focus was hard to come by.

After a successful diagnosis, proper medication helped tremendously. I still felt, though, that my work performance was suffering. I began exercising.

A note about exercise: I hear people say "Oh, I'm not the exercising type." These are always people who have never had an exercise routine before. Anyone I've ever met who has had a routine and fell out of it (for whatever reason) has spoken fondly of the days when they had a routine and of how good they felt--not just physically, but about themselves. So don't give me that "not the exercising type" crap. Unless you have a doctor's note, get out there, even if you have to start small, like, walking-two-blocks small. You will not regret it.

Anyway, so I started exercising. And it was awful. I was exhausted. Panting, tired, and the next day, painfully sore. But after a couple weeks, I started to really look forward to my exercise. Then I started setting goals. Then I started running barefoot. Now I'm six seconds away from beating my best-ever mile time (I ran my best mile in eighth grade).

More importantly, I feel I'm more productive than ever at work. I've started exercising in the morning before I go into the office, which means I'm alert and ready long before I get there. My body is fully awake, my blood is pumping and my brain is active. I walk into the office with a plan, confident and proud of myself for sticking to my routine.

Family

I also try to resolve issues at home. As a married man, I have to occasionally resolve conflicts, of course, with my wife. And bills have to be paid, the car has to be detailed and the trash has to be taken out. I like to keep up with these things, not letting them pile up, go unresolved, or otherwise weigh on my mind. This prevents me from being distracted during the day by stress.

A note about motivations: Of course, I don't do all of these things to be a better programmer. I do them to have a better life in general. I have noted, however, that they have a huge effect on my performance at work and as a programmer.

Intellectual

I've also started caring for my intellectual health. I've had an addiction to certain web sites that waste my time. Considering the GIGO principle, I shouldn't be reading them, anyway.

I've noted how I used to have far more original ideas years ago. In fact, I used to deliberately avoid reading certain things because I thought they'd spoil my creativity by filling my head with other people's ideas. At some point, I started questioning that theory and started reading obsessively. Now I'm finding that a balance between these is best. Say no to Hacker News. Say yes to Schneier on Security and The Old New Thing.

Attitude

One of the most effective things I've done to be a healthy programmer is made an effort to be more humble:

  • Programming is hard.

  • Neither I nor anyone else is perfect.

  • There exists someone who is smarter than I am.

  • There exists a programmer who could do my project better.

  • I will never be done improving my craft.


I find that, when I remember these things, I am more open to advice, willing to accept constructive criticism, and curious to learn more, and I feel like I get along with my coworkers better. If I'm willing to listen to what others around me have to say, their knowledge is added to my knowledge. Imagine taking the knowledge from five, ten, fifty good programmers and sticking it in your own head. How can that be a bad thing?

I think a lot of this could be applied to any craft or profession. I, however, am only a programmer. I can say, from first-hand experience, that living and thinking this way has made me a better programmer.

Tuesday, January 19, 2010

Orlando Perl Workshop (OPW) / Perl Oasis

I had a really great time this weekend with all the guys at OPW! Although I'm obviously not a Perl guy, it was neat to see some of Perl's capabilities and some of the cool things this community is doing to improve web development. Some of these ideas could even be applied to PHP development. I'll have to give that more thought.

I was also graciously invited to speak about roles in PHP (since they were inspired by Perl's Moose::Roles module). I'll throw up another post with more details about the talk later.

There were some great speakers; I really enjoyed the talks and getting to meet fellow programmers. Stevan Little gave a great talk on everything, particularly wiring up a new app with URL routing and Bread::Board. The colorful Matt Trout told an epic poem about database management, and Marty Pauley give an interesting talk on functional programming in Perl, which actually refreshed a lot of the basics I'd forgotten from school. Shawn Moore revealed even more geek than I thought possible in his talk about conquering NetHack with an artificially intelligent bot.

Of course, there were more good things that happened there, but these are the highlights that came to mind. Many thanks to Chris Prather and his very organized and hard-working wife Jamie for their putting this shindig together. Well done! I look forward to next year. Also, I wanted to mention a particular Perl web server named Plack.

Wednesday, September 2, 2009

Vim Tip: Debug Path

I work for a company whose code is in thousands of files in hundreds of directories. We have multiple VCS repositories. Function libraries, class files, HTML, XSL--a convoluted maze to navigate, especially when trying to debug something.

Whenever I'm debugging, I may follow the rabbit hole from function to function, through various libraries and classes, only to find that I'd taken a wrong turn somewhere and come to a dead end. I then either have to sift through the multiple tabs I've opened to find where I should pick up the search again, or, if I've been closing files along the way, I have to start the search from the beginning. This is annoying and time-consuming.

I decided to write a simple vim script to save my cursor's current line, along with the file name and line number, to a file in my home directory. I can then continually save lines as I follow a path through the code. If, at any time, I hit a dead end, I simply go through this "trace" file and find where to pick up the search again. Combined with vim's "gf" command, this file is very useful!

Here's the code you can add to your own .vimrc file:

nmap <F8> <ESC>:call WriteTrace()<CR>

function WriteTrace()
let lineNum = line('.')
let lineFile = bufname('%')
let lineVal = getline(lineNum)

let allLines = readfile("$HOME/trace.txt")
let allLines = add(allLines,lineFile.":".lineNum)
let allLines = add(allLines,lineVal)
let allLines = add(allLines,"")

call writefile(allLines,"$HOME/trace.txt")
endfunction

In the code above, F8 will save the line under the cursor, but the nmap can be changed to map to any key, of course.

Wednesday, August 26, 2009

PHP Is a Husk

I thought there was hope. I really did. Maybe it was naivete, or simply denial because it's the language I use day-in and day-out. But there is no hope for PHP.

No, I don't think the project will die; I'm sure it will continue to grow. It's no new revelation that the language has a lot of problems. Even when we finally got prepared statements with the MySQLi interface, there were a lot of problems with the way it worked such that writing a thorough DBAL for it was nearly impossible. But lately I've been pretty positive about the direction PHP has been going--with 5.3 came namespaces, lambdas and closures, among other things.

And then I started playing around with these new features. The namespace delimiter is odd, but big deal. Lambdas and closures, though, are broken and useless for anything but the most basic applications.

For instance, I've been messing around a little with Perl and an awesome OO extension for it called Moose. Moose has a ton of features, but one particular feature is Roles. Roles, as defined by the Moose devs, are somewhere between abstract classes and mixins, with multiple inheritance--but more flexible and easier to develop with. You know, pure awesome.

So I set out to try my hand at making something similar to Roles with PHP's new lambdas and closures. That should give me all the power I need to hack something together, right? This is the best I could come up with:


// class used to enable roles for other classes
class Role {
// used by the class the role is applied to
// must be in that class's __call() method
static public function call($obj,$funcName,$args) {
$func = $obj->$funcName;
array_unshift($args,$obj);
call_user_func_array($func,$args);
}

// applies a role to the object.
// for best results, use in the constructor.
static public function apply($obj,$name) {
$mixin = new $name();
foreach ($mixin as $funcName=>$func) {
$obj->$funcName = $func;
}
}
}

// my example role that I want to apply to other classes
class MyRole {
public $yar = 'role\'s test string';

public function __construct() {

// prints a string, including a var from the object
// that is using this role.
$this->roleFunction = function($obj) {
print('This is a role function! '.$obj->blah."\n");
};

// prints the object that is using this role.
// this will also show the methods it has received
// from the role.
$this->printr = function($obj) {
print_r($obj);
};

// a function that gets overridden by Test class's
// native method by the same name.
$this->overriddenFunction = function($obj) {
print("You'll never see this.\n");
};
}
}

// my class that I want to apply a role to. Note the
// call to Role::apply() in the constructor.
class Test {
public $blah = 'test string';

public function __construct() {
Role::apply($this,'MyRole');
}

// overrides MyRole's version, as it should
public function overriddenFunction() {
print("I beat the role's method!\n");
}

// necessary mess to get $object->roleMethod() to work
public function __call($funcName,$args) {
Role::call($this,$funcName,$args);
}
}

$test = new Test();
$test->printr();


The above will print_r the Test object, as it should, including the public attributes that hold the lambdas from the Role. Neat, right?

Well, not really. This is so messy, so impractical. The limitations are ridiculous. For example, the following works:


$someFunc = function() { print('Hello, blog!'); }
$someFunc();


But this doesn't:


$obj = new StdClass();
$obj->someFunc = function() { print('Hello, blog!'); }
$obj->someFunc();


Whoops! That object method doesn't exist! And what about this:


class MyNeatoClass {
public $someVar = 'Hello, blog!';

public function __construct() {
$this->someMethod = function() { print($this->someVar); }
$this->otherMethod = function() use ($this) { print($this->someVar); }
}
}


Neither the lambda nor the closure works. $this cannot be used in lamdas or closures. So, when it comes to using these new features with objects, they're quite nearly completely useless. These are just a couple examples of what makes my above attempt at creating Roles broken and useless.

And as I mentioned before, this isn't the first time the PHP devs have botched up new features. They seem to be committed to adding "big boy" features, which should be a good thing, but not to building them correctly. This leaves developers--who actually know what these features are and how to use them in other languages--frustrated and disgusted. For what audience are they coding? Do they think Grandpa Jo's 14-year-old nephew, who "builds websites", is going to use closures? No, real developers are going to try to use them, and then give up, because they're useless.

This trend is obviously going to continue. PHP had the opportunity to recover from past mistakes with recent new features. They have not learned a thing from past mistakes. PHP, you are dead to me.

Sunday, August 23, 2009

Chaos vs. Best Practice: Let Them Eat Cake

Even if you didn't know who _why was a couple weeks ago, most likely you've gathered enough since then to know that he was a very bright and artistic programmer (or a very bright and logical artist?) who inexplicably erased his digital presence.

But enough about _why, as that dead horse has been and is currently being beaten to horse pudding. However, in looking through some of _why's archives (things are rarely truly erased), I found this insightful and interesting blog post.

To sum up, _why feels like so called "best practices" are dead, boring, and stifling. Good, artistic and revolutionary code comes from chaos. Diagrams and TDD are simply scripted banality. I see his point, but I responded to his post thus:


Refusing to be stifled by best practices is one thing, and it’s not a new thing; to touch on the gagging cliches, everyone who’s ever caused a shift in perception or the field of possibilities--Beethoven, Lennon, Newton, DaVinci--questioned the “best practices” of their field in their day. But you mentioned yourself that we can’t possibly understand every avenue, every corner, of the systems we work with. Isn’t that why we have best practices? To invent the wheel without understanding friction coefficients is foolish. Even though you disagree with their choice, maybe your predecessors decided a sleigh made more sense because you didn’t realize that you live in North Dakota.

Chaos is for after-hours. Chaos is a bunch of possibilities and fewer probabilities, with only one or two sure things. Once you’ve polished all that and have one sure thing in your hands, use it at your day job. At that point, it’s a best practice. Best practices have an origin. Chaos has a conclusion; to claim to subscribe to one and reject the other is short-sighted. To accept both as part of the process shows your passion and dedication to your field.


To expand on this response, there are three types of programmers with respect to chaos and best practice:

  • Great programmers who can dabble in chaos, confident that a best practice will rise from the ashes of many smart--but failed--attempts. They then share and use these practices. These are the French elite of programmers.

  • Decent programmers who dabble in chaos but do not develop best practices. Such dabbling helps them to see the wisdom in best practices and use them wisely to make solid software. These are the French bourgeoisie.

  • Programmers who shouldn't be programmers--the peasant farmers.


I appreciate _why's contributions to programming-as-art. And I really believe that he is brilliant enough to develop best practices from chaos. But his advice to abandon best practice for chaos is saying to the rest of us, "Let them eat cake!" I'm sure his elitism is unintentional, and I certainly don't mean to villianize him by any means. But cake is a luxury and an artistic tribute to the beauty of food. Buildings are built by men eating meat and potatoes. Solid, robust and maintainable software is developed by programmers who use best practices.