Monday, July 25, 2011

Singleton Abuse

I know this is a tired topic, but when explaining how not to abuse the singleton pattern, I explain it this way:

Many developers ask themselves this question: "Is there any reason anyone would want to have two instantiations of this class?" This is the wrong question and leads to an over-abundance of singletons. Really, they should be asking, "If I instantiate more than one object of this class, will everything break?"

An additional benefit of approaching the pattern this way is that an answer of "yes" leads to the questions, "Why would my code break? Can I refactor and generalize so that the singleton pattern won't be necessary?"

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.

Monday, December 13, 2010

List File Plugin for Vim

A while back, I had a post about managing lists in vim. Since then, I've found greater and greater use for the script and have invested more time into it. I've decided to put it on vim.org.

I'm going to reproduce the documentation in the plugin itself with the addition of some in-depth explanation.

Check this post often, as I will keep the documentation up-to-date with the latest features and tweaks.



The plugin helps me manage a plain-text file of nested lists. I use it to manage to-do lists, shopping lists, URLs---all in the same file. It manages priority, status, date, custom folding, among other things. It supports tagging, timestamping and searching with vim's quickfix list. Aside from the shortcuts and commands below, indentation and folding are managed by the standard vim mappings.


First Step

:Lcreate <name> - create new list file in current buffer with <name> (".list" is added automagically)


Creating Items

,n - create new item
<enter> - (insert or normal) create new item
,s - create sub item
<tab> - (insert or normal) create sub-item
,u - create super item


Marking Items

:Lmark <mark> - (normal or visual line) mark item(s) with <mark>
,p - mark item with '=' (in progress)
,x - mark item with 'x' (completed)
,o - mark item with 'o'
,? - mark item with '?'
,- - mark item with '-' (default, incomplete)
,N - set priority as N, where N is 1-5


Tagging Items

:Ltag <tag> [tag ...] - (normal or visual line) add tag(s) to line(s) (has auto complete)
:Ltagr <tag> [tag ...] - (normal or visual line) remove tag(s) from line(s) (has auto complete)


Searching For Items

:Lsearch mark <mark> - find all items with <mark> (e.g.: =, 1, -, etc.) using location list
tag <tag> - find all items with <tag> using location list
due [date] - find all items due on [date]. Today is the default.


Setting Due Dates

:Ldue [date] - (normal or visual line) set due date. Today is the default.
:Lduer - (normal or visual line) remove due date
Due dates are in the format YY-MM-DD or any of: yesterday, today, tomorrow,
N day[s], N week[s] (where N is a number)
N:M day[s], N:M week[s] (where N and M are numbers and N <= M)
E.g.: To see all items due this week or next week: :Lsearch due 0:1 week
To see all items due next week: :Lsearch due 1:1 week
To see all items due last, this, or next weeks: :Lsearch due -1:1 week
To see all items due tomorrow or the next day: :Lsearch due 1:2 day
To make an item due end of next week: :Ldue 1:1 week
To make an item due one week from today: :Ldue 1 week
To see all items due in exactly four days: :Lsearch due 4 days


Sorting Items

,r - (visual line) sort highlighted items
,r - (normal) sort entire file


Et Cetera

,t - add/update last-modified timestamp on item


Configuration

listFile_timestamp = 0
Should timestamps be added to each item by default? Set to 1 to show a timestamp by default.

listFile_indent = 4
Standard indent for nesting.

listFile_ranks = ['=','1','2','3','4','5','o','-','?','x']
Rank of marks for sorting. Note that your own, custom marks can be added to this list and used with the :Lmark command above.

listFile_mark = '-'
Default mark for new items.

listFile_dateFormat = '%y-%m-%d'
Default format for due dates.



Advanced Configuration

Here's an example of something you may put in your .vimrc file:

" add new "!" mark to ranking
let g:listFile_ranks = ['=','1','2','3','4','5','!','o','-','?','x']

" open local projects list file
nmap <Leader>l :60vsplit ~/projects.list

" add my mappings when a list file is loaded
autocmd BufNewFile,BufRead *.list call MyListFileStuff()
fun! MyListFileStuff()
" add "!" mark for normal and visual modes
nmap <buffer> ,! :Lmark !<CR>
vmap <buffer> ,! :Lmark !<CR>

" tag lines with "quick" tag
nmap <buffer> ,tq :Ltag quick<CR>
vmap <buffer> ,tq :Ltag quick<CR>

" find all lines tagged as "quick"
nmap <buffer> ,sq :Lsearch tag quick<CR>

" set an item as due today
nmap <buffer> ,dt :Ldue today

" find all items due this week
nmap <buffer> ,sw :Lsearch due 0:0 weeks
endfunction

In this example, I've added a new mark for me to use: "!". I've also added it to the mark ranks so that sorting will put "!" items in their proper order. I created a shortcut ("\l") to open my projects.list file in a narrow sidebar in vim. I added some things to help me manage items that are quick tasks---a mapping to easily tag items as "quick" and another to search for them. I also added a way to set a due date of today and to find all items due this week.


If you'd like this simple tool in your belt, go get it.

Thursday, September 2, 2010

Vim, PHP, TagList, and Ctags

I spent a good bit of time figuring out how to get vim to play nice with the spectacular TagList plugin, Ctags and PHP, so I've decided to sum up everything I did to get it working perfectly for the next person who comes along.

Installing TagList itself is simple---just follow the instructions, standard to installing any vim plugin. However, getting Exuberant Ctags, which is TagList's workhorse, to work properly with PHP is another matter. Ctags doesn't understand PHP very well. It picks up on variables (which is sorta useless in PHP, anyway) but not functions whose definitions specify access ("public", "protected", etc.), interfaces or abstract classes. How useless!

Creating a useful Ctags file for PHP is not difficult, thanks to the info at these two resources. Just use these flags:


ctags -R --exclude=.svn --tag-relative=yes --PHP-kinds=+cf-v --regex-PHP='/abstract\s+class\s+([^ ]+)/\1/c/' --regex-PHP='/interface\s+([^ ]+)/\1/c/' --regex-PHP='/(public\s+|static\s+|abstract\s+|protected\s+|private\s+)function\s+\&?\s*([^ (]+)/\2/f/' lib/


Notice that I exclude variables via the --PHP-kinds option. This isn't C, tyvm.

What I didn't understand, at first, is that TagList calls Ctags every single time it's opened so that it generates an up-to-date temporary tags file. This makes perfect sense, but when Ctags is called by TagList, it doesn't have all of our required command-line options. Enter the Ctags config file. Put the following in your ~/.ctags file:


-R
--exclude=.svn
--tag-relative=yes
--PHP-kinds=+cf-v
--regex-PHP=/abstract\s+class\s+([^ ]+)/\1/c/
--regex-PHP=/interface\s+([^ ]+)/\1/c/
--regex-PHP=/(public\s+|static\s+|abstract\s+|protected\s+|private\s+)function\s+\&?\s*([^ (]+)/\2/f/


And, amazingly, TagList becomes useful for PHP development. The last step is to tweak TagList to work in a way that's most convenient for you. Personally, I like these options:


" set the names of flags
let tlist_php_settings = 'php;c:class;f:function;d:constant'
" close all folds except for current file
let Tlist_File_Fold_Auto_Close = 1
" make tlist pane active when opened
let Tlist_GainFocus_On_ToggleOpen = 1
" width of window
let Tlist_WinWidth = 40
" close tlist when a selection is made
let Tlist_Close_On_Select = 1


TagList has a ton of options, so check them out. You may also be interested in my most up-to-date .ctags and .vimrc.

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.