Tuesday, December 15, 2009
Email not sent, because NO ONE COMMENTS
I would like to suggest a standard that almost no one else is the world things is sensible: a developer coming to unfamiliar code should be able to understand it by reading the comments. In my view, the comprehension of code is like a transuranic element -- rapidly decaying, short-lived -- and that's in the mind of the coder. Expecting someone else to read code and simply get it is unrealistic. Oft times, the coder spent a lot of time figuring out how to code something; the code embodies business logic. When that thought process is not captured in a comment -- it vanishes. And it has to be in a comment in the code, else it will be lost. "We wrote that up in the functional spec, that's never been updated and we can't find it anyway." That doesn't work.
It doesn't take that long to type comments. We type for a living! The confusion and uncertainty presented by poorly commented code yields wasted time trying to comprehend code, and more time chasing down bugs introduced because of a failure to comprehend the code correctly. Comments save time.
I have heard of the argument that excessive commenting is worse than no commenting, because the comments get stale and are misleading. The easy answer to that is "Maintain the comments as you modify code." I would encourage people to comment excessively -- because if they lean in that direction, the chances are increased that they'll comment adequately.
A while back, I incorporated this standard in a automated code reviewer utility: it computed an estimated ratio of comments to code, and while there was no specfic ratio required, a low ratio made the coder suspect, and more likely to get dinged for insufficiently commenting during the real code review. The utility worked with enhancements, in addition to new code, because we applied the utility to the differences listing for existing code.
I write to deaf eyes, I know. No one comments. It mystifies me and makes me crazy.
Thursday, December 10, 2009
DropBox: Switching out the music with ease
Today I put it to good use for the first time. I decided to would listen to the most recent 5 remastered Beatles albums at work today. So, this morning, I copied the albums to the DropBox folder on my home computer.
About 20 minutes after I turned on my notebook at work, the Beatles music was there in the notebook's DropBox folder.
It couldn't be much easier.
Do any operations on the DropBox folder -- adds, deletes -- and they are reflected in however many other computers have the DropBox client installed, associated with your account. When I'm done with the Beatles, I'll move some Frank into the folder; it's the anniversary his birthday Saturday.
DropBox gives you 2GB of space for free. The next price point is unfortunately expensive: $10/month for 50GB. If they charged by the GB, I'd sign up for 10GB for $1/month.
Maybe I'll suggest that.
Wednesday, December 9, 2009
Is CBMunger ready for prime-time (I should I bother?)
---- The question on Stack Overflow ----
It was my second C# project, undertaken years ago, and it has lived on, because (imho) it is Genuinely Useful Software. It's also badly designed and the code is embarrassing.
It runs C# code. You write a method, the method name appears in a listbox, you double-click the method name to execute it. That's it.
Examples:
When I open up my C# web project at work, a method runs a couple command-window apps my project needs, and checks to confirm that the requisite service is up. I never have to remember that stuff.
I hate UPPERCASE, so I have a method that lower-cases SQL, but preserves the case of quoted strings. Another method calls a web service to beautify SQL. Those both operate on the clipboard.
One method fixes the names of MP3 files: title casing, replacing underscores and hyphens, optionally removing/inserting text or prepending numbers. Creates a playlist!
I double-click to harvest all of my Twitter links, turning them into an HTML page with hyperlinks and a jQuery-powered search.
A method searches the specified log4net.log for every operation that took longer than the specified number of milliseconds.
I can create a restore point by double-clicking a method (and open up the corresponding dialog with another method).
When my wife had to write some sorting algorithms for school, the utility was an ideal testbed. I use it to test bits of code all the time.
None of these methods is in any way impressive. No large brain stuff. Most of it is just string manipulation, file system operations -- mundane stuff. Handy though!
This morning, I wanted to format some SQL output as rows in an Excel table. I wrote a method to read the output and format it as tab-delimited columns, for import into Excel. I have no idea how else I could have done that. It took about 8 minutes to write.
I have 300 methods, perhaps 50 of which are often useful, the rest there if the occasion arises. Occasionally I move the real cruft into the Zaps group, so it's out of the way.
The utility has lots of ease-of-use features. I prefer the keyboard to the mouse, so methods are tagged into groups that are accessible from a dropdown: control-T selects a different group. Don't remember the group? You enter control-F to find all the methods matching a string. Arrow down and press to run the method. The parameters window always remembers its state: if you entered Hoytster last time, it's there this time. You can right-click a method to see its tooltip; double-right-click to see its source.
I tried to make it easy to create new methods quickly.
A method generates your new function's prototype: you enter the method's name, group tag, tooltip, etc, and the new method is created with the requisite attribute decorations. The prototype is placed in the clipboard so you can paste it into one of the utility's source files.
It's easy to prompt for parameters:
...GetParameters("*Target File", "@Report File", "Open Report [No, Yes]");
opens a window with textboxes labeled Target File and Report File, and an Open Report checkbox with text that toggles Yes and No. Strings in curly-braces become radiobuttons. The Target File must exist, because of the initial asterisk; the parameters window will not close if an invalid target file is entered. The Report File must be valid (it CAN be created) because of the @-sign.
When you run the method and the parameters window appears, it has a [Capture] button you click to generate the code needed to capture the returned parameters, putting it into the clipboard again:
string targetFile = parameters["Target File"]; ... boolean openReport = parameters["Open Report"] == "Yes";
Ach, I go on too long.
So, how ambitious should I be? CodePlex? Maybe a dedicated web site, where people can upload their methods?
Getting the utility publish-ready would be a lot of work. I have to clean up the code; remove the really dumb methods and the never-finished methods; create a screen cast of the "make a new method" process, document the teeny "meta-language" (tongue-in-cheek) that drives the parameters window.
I like the idea of y'all using my utility to be a bit more productive. I love the idea of seeing what methods you invent and share. No doubt it's out there, but I'm not aware of places on the net where people share code as simple as a method "Fix the names of my MP3s".
Would you like to have this utility?
Besides being overworked and lazy, I have never put up a web site (!) -- and y'all might mock me because my GetParameters() method has about 200 lines (my poor excuse: I started out with FORTRAN). This utility was never designed; it accreted. :)
So let me know: Do you think this utility is useful enough to put up on CodePlex (or somplace)?
Thanks in advance! - Hoytster
Monday, December 7, 2009
Reqall Take 2
I find myself continuing to rely on my familiar, pre-Reqall tools, because...
1) The Reqall date-time voice recognition is very good, but not perfect, possibly because I am doing it wrong. My attempts at instructions like "...each second Wednesday of the month" have not worked, not even close. So it's more accurate to enter items into Google calendar, if I'm on my PC. Fortunately, Reqall provides a means to edit the calendar events, which I had overlooked until now. That helps.
Reqall should be helpful when I'm at the dentist's scheduling my next appointment. I just have to remember to check such items. I don't know how difficult it is, to check something six months out. I guess I can search for "dentist" in Google calendar, if Reqall's interface does not suffice.
I love that Reqall and Google calendar keep each other updated.
2) Using Reqall like my voice recorder, where I "note" miscellaneous stuff of greater and lesser urgency, fills up my Reqall daily queue with a lot of detritus that I do not need to do any time soon. I found it necessary to write a little C# code that allows me to copy the Reqall lists of items into the clipboard, then remove all the links and such that I don't want, from the clipboard text -- yielding just the notes and to-do items -- which I then move into their various categories in OneNote -- per usual. Then I need to go back to Reqall to manually remove those items.
Reqall's notification is a strong feature. If I have something scheduled for a given day, my phone will ding, redundantly with an email and SMS (I should eliminate the SMS, it costs) -- and my IM will pop up the message if I'm at work and have forgotten my phone. Reqall will help me most with weekend events, that I can otherwise overlook because I'm not in my calendar consistently on weekends. The 30-minute default notification can be changed to another default -- or the notification time can be changed manually for a given item. Nice.
The shopping list feature seems slick. Given my C# method, though, I don't need to make Costco a known Reqall place, and go through the additional work of associating a Recall voice message with the Costco place (which takes maybe 3 clicks on the iPhone). Instead, I can simply start my note with "Costco" or "CVS" or "Groceries", and when I've cleaned up the resultant text with my C# method, then the Costco items will be sorted together. I have to do that, however, and I have to print out the result... which is not so likely to happen. So maybe applying the official Reqall approach is better. Only, I don't think the Costco items would be available, if I went to another Costco, which is a real possibility; there's one near work, and one in Nashua, where I pick up Nelson.
It's early, yet. I'll figure it out.
It's a bummer that there's no way to remove items from the Reqall lists, en masse. I have to click each one. I wonder if I could write something to accomplish that for me.
Thursday, December 3, 2009
Comment on Fitness Rocks re the Evolution podcast
It was fascinating, but the podcast was light on how evolution relates to our modern health predicaments, and especially how we should be eating.
By coincidence, last week I encountered something new, the Paleo Diet. It's advocates say that we are not evolved to eat grain and dairy products, sugar and salt. Instead, we should be eating like our ancestors did, 10,000 years ago: meat, vegetables, fruit, nuts and roots (?). That's close to your familiar plant-based diet prescription, Monte -- leaving aside the meat. Paleo's hold that the wild game our species ate millenia ago was much leaner (and healthier) than our modern meat. Sounds credible to me: feedlots are all about adding fat, right?
I don't know if these Paleo people are crazy. I chanced on a podcast, featuring a guy with a seemingly strong science background -- a PhD. in biochemistry (maybe?) and a former Olympic class body-builder!! It sounded good, but I haven't read up on it yet.
If you're interested, this page has abstracts of Paleo-related scientific papers, most with links to the journal articles. Dr. Loren Cordain is the main man, according to the podcast, and he's featured on the linked page.
Insulin resistance is a focus of the Paleo crew -- which piques my interest, since I'm a recovering diabetic (my last A1C was 5.6, joy!). The podcaster was adamant about health problems in modern societies, because of a 20-1 ratio of omega-6 to omega-3 fats in the typical American diet -- asserting that it should be closer to 1-to-1. I think the guy dissed flax seed oil -- he definitely was an advocate for fish oil supplementation.
I'll email you if / when I learn more about the Paleo thing.
I am so glad you're back! I'm passing through all the podcasts a second time -- but it's great that there are new 'casts coming. YAY!
- Hoyt
Posted question on StackOverflow about always subclassing controls -- a la PowerBuilder
* NEVER use the native controls!
* Instead, subclass ALL the controls, and ALWAYS use the subclassed version.
Why? Because that gave you a hook... one place to write code and have it applied throughout your application.
For example: Suppose you decide that you want a question mark icon to appear to the right of every TextBox in your webforms app. The icon is rendered, and hovering over it pops up bubble help -- iff there is text in the TextBox.ToolTip property.
How would you accomplish that, if you're using the MS-provided TextBox control?
If you consistently used a subclassed version of TextBox in your application, then you could go to that object, and add the method that renders the icon, stocked with your favorite bubblehelp javascript.
Presto! All of your app's TextBoxes sprout little question mark icons -- or they will, when you set their ToolTip text.
Over time, you can easily adapt and enhance ALL your TextBoxes, because they all have a base class that you can modify. You add a feature where ToolTips are set from a resource file. Next, you add a ShowOnLeft property that presents the icon on the left side of the TextBox. Do you like how the iPhone password control shows the last character you type, obscuring the earlier characters? Override your subclassed TextBox's default behavior for passwords with a method to implement that behavior.
I have never encountered advocates for this practice, in ASP.NET. Have I just missed it? An article describing two dozen ASP.NET design patterns doesn't have anything related. The posts about *how* to subclass server controls describe special-purpose one-offs, like a TextBox that only accepts digits -- but none of them recommend the pervasive "ALWAYS use subclassed controls!" policy that I subscribed to in olden days.
Does it make sense, to apply this ancient wisdom, when working in ASP.NET? To always use the subclassed equivalent of the native server controls?
If not -- why not? Are there other ways to skin this cat? A technique that provides you with just one place where you can augment ALL your application's instances of a given control?
I'd love to hear about that. I *want* my TextBoxQMark control. :-)
TIA - Hoytster
Tuesday, December 1, 2009
Code Generation
T4 is a capability inside Visual Studio, a templated approach to code generation.
My eyes glazed over as I read it. I want code generation to be driven by meta-data. If the STATUS column on a table is a single character, translated at run-time to something readable, then I want to record that fact in a database table, so the translation can be done when the SQL is generated (or when the business object is populated from the SQL). I want to generate SQL by retrieving a table's columns from USER_TAB_COLUMNS and (optionally) joining to related tables as indicated when I detect foreign key relationships. Where does the generated code go? We have multiple targets and each has its own folder structure for the various entities and objects. That's all meta-data. A large part of the app will be making it easy to set that data.
Someone else suggested CodeSmith.
I should look over T4 and CodeSmith enough to have a glimmer about how they work. At worst, that will help inform my own custom coding.
On becoming a stares-at-phone guy
Last night, as I walked three-quarters of a mile to the MS certification meeting, I was using Safari on my iPhone to look at SlickDeals.net. I'm a SAP, Stare-At-Phone guy.
I have something approaching an addiction with the internet. Default activity if I have 10 minutes before bedtime: digg.com. Default activity when eating lunch at my desk: asp.net.
With the iPhone, I have internet access all the time (within the limits of AT&T apparently quite limited 3G network). I hope it isn't a problem.