April 30th, 2008 Rusty
Free: grant freedom to; free from confinement;
Free: dislodge: remove or force out from a position; "The dentist dislodged the piece of food that had been stuck under my gums";
Free: able to act at will; not hampered; not under compulsion or restraint;
Free: complimentary: costing nothing; "complimentary tickets"; "free admission"
I wanted to mention a tool that makes my list of top ten productivity enhancements and tools that make you wonder what you did before them. This one is called FreeMind.
FreeMind
Mind mapping software is something I have read about but not really gotten excited about until now. I had, in the past, produced mind map diagrams on paper and whiteboard with success. However, I thought software would be cumbersome and inefficient at the task. Not so!
MindJet Mind Manager is absolutely fantastic. My boss turned me onto it and we used it to generate our initial website semantics. We were using it for various other purposes and ready to purchase additional licenses. Since the expenditure was going to get a little ugly (though we valued to the tool enough to accept the cost), competitive analysis was in order. I found FreeMind while looking for a way to export MindJet MindManager files. I will point out to anyone doing the same thing that the MindJet files are nothing more than zip files with a mmap extension. The underlying data is in xml. I wasted a lot of time looking for documentation for how to use the com api and VBScript to access the same data. However, along the way, I discovered an open source product that works just as well for my purposes.
FreeMind allows you to work very quickly through ideation. If you are struggling with a complex task, fire up FreeMind and start a new doc. Write > tab > write > Enter > tab > Write > Enter > Write > Enter. This will bring you to an hierarchically structured relationship diagram that takes what is on our mind into a simple drawing.
I used it just now to decide on a Controller naming convention for my MVC meets CMS web application where a duplicative navigation structure may be collapsed into a single controller. Once I had the map, the name presented itself.
Here’s an example of what mind map might look like.
Try it! Its free, you can run it if you have the JVM (which you do), and it is a simple install. I’m running he mac version while my peers have the Windows flavor flav…
Posted in Blogging, Programming | 1 Comment »
April 29th, 2008 Rusty
I recall once that a certain someone built an Enterprise Framework for an organization I worked for and that, during his presentation of our new framework to the rest of the team who would have the honor of using it, he reported that there were over xxx thousands lines of source code. (it may have been over 1 million, I don’t recall the exact number, just that it were an awful lot). It was later coined the "h_________ proprietary code initiative" as it was the HPCi.Enterprise framework.
A few years ago, I had as a goal building bullet-proof and re-purposable code. I sought to think of everything, provide every possible feature, solve every conceivable application of my utility and otherwise make people thankful for and impressed by my thoughtfulness and clairvoyance.
Over the last few years I’ve learned about lean. I learned about KISS. I learned that you should do the simplest thing possible to solve the immediate problem after you write automated unit tests that assert the correct outcome from exercising your logic, and move on! This is easier to state than to practice (unless you write tests religiously, which I strongly recommend).
Today I created a simple rounded corner control that opens and closes the necessary html elements and references the needed images to surround child content with a nice container. I dug up some old source code to remind me how to render child controls inside a webcontrol.
My old rounded corner control was over 1550 lines of C# code. I am just as guilty and our historical benefactor for over-engineering.
The one I wrote today was less than 45 lines. I could write 20 special case controls and still check in well under weight from that old piece of majesty. Stop the madness, write the code you need, not the code someone might someday wish for.
[
PersistChildren(true),
ParseChildren(false),
DefaultProperty( "ImagesDirectoryPath" ),
ToolboxData( "<{0}:CutoutContainer runat=server></{0}:CutoutContainer>" )
]
public class RoundedContainer : WebControl
{
[Bindable( true )]
[Category( "Appearance" )]
[DefaultValue( "" )]
[Localizable( true )]
public string ImagesDirectoryPath { get; set; }
public override void RenderBeginTag( HtmlTextWriter writer )
{
if( string.IsNullOrEmpty( this.ImagesDirectoryPath ) ) this.ImagesDirectoryPath = "/Content/skins/2/cutout/290/";
writer.Write(@"
<div style=""width:290px;"">
<div style=""background:url(" + this.ImagesDirectoryPath + @"top.png) left top no-repeat;height:12px""></div>
<div style=""background:url(" + this.ImagesDirectoryPath + @"tile.png) left top repeat-y;padding:12px;"">"
);
}
public override void RenderEndTag( HtmlTextWriter writer )
{
writer.Write( @"
</div>
<div style=""background:url(" + this.ImagesDirectoryPath + @"btm.png) left top no-repeat;height:12px""></div>"
);
}
}
Posted in Agile, Asp.Net, Programming | No Comments »
April 18th, 2008 Rusty
On many occasions, I’ve met with html that was not compliant. It is really difficult to have excellent html at the same time that you provide non-programmatic updates to web site content. There are a couple of awesome xhtml compliant editors out there for those interested in custom integration but using modern content management systems inevitably means you are bound to either fckEditor or tinyMce. These both produce well-formed html but they tend to add a lot of garbage to html in an effort to format things in a generic and cross-browser way. Pleasing everybody tends to leave me disenchanted with the tools.
Correcting Html following destructive string splits
I can live with the sub-optimal html these editors produce but I had a need to split html into distinct parts. Basically, I had a pseudo-blog. It was a subsonic starter site turned into blogging engine. It worked great for a while. The author would copy the last post, paste it on top, change the date and title, then replace the post body. The old posts moved down the page. Visually, I was able to see a very consistent pattern in the posts and felt confident I could pull the posts apart into an RSS feed. Upon further investigation, however, I found quite a lot of tag artifacts that fckEditor had inserted into the html. The page looked fine as a whole but there was no way to know what each post html would look like when they were separated.
The author had inserted an <hr /> between each post. That was my starting point.
Parse the date
Then, there was always a date and time in the format: MMMM dd, yyyy (April 18, 2008). However, sometimes there were characters inserted in there. Then I discovered that the time was also there but separated with a "|". Like this: April 17, 2008 | 3:50 PM.
I used a regular expression to split the post into parts. Then I replaced the "|" in the dateString and used DateTime.Parse(System.Web.HttpUtility.HtmlDecode(dateString)) to create a DateTime instance.
string dateString = GetDateStringFromPost( html );
string[] parts = post.Split( new string[] { dateString }, StringSplitOptions.None );
public string GetDateStringFromPost( string html )
{
string datePattern = "(?:January|February|March|April|May|June|July|August|September|October|November|December)(?: |\\s)*[0-9]{1,2},(?: |\\s)[0-9]{4}(?:(?: |\\s|\\|)*[0-9]{1,2}:[0-9]{2}(?: |\\s)*(?:AM|PM)?)?";
Regex regex = new Regex( datePattern, RegexOptions.IgnoreCase | RegexOptions.Compiled );
Match match = regex.Match( html );
return match.Value;
}
At this point, I had my post, my date, and the post title happened to be the fragment (parts[0]) before the date.
Clean the title
I just need text for the title so I brute force stripped all html tags (character by character parse) and then used string.Trim() to make that happen. (Caution, not pretty)
public string StripHtml( string html )
{
StringBuilder sb = new StringBuilder();
bool inTag = false;
foreach ( char c in html )
{
if ( c == ‘<’ )
{
inTag = true;
continue;
}
if ( c == ‘>’ && inTag )
{
inTag = false;
continue;
}
if( !inTag ) sb.Append( c );
}
return sb.ToString().Trim();
}
Fixing Html using Tidy.Net
Fixing the now corrupted post body html
Now I had a post body that had any number of invalid html tags because that post may have been in the middle of a table on the page or the post itself may have had numerous formatting containers wrapping the different parts.
The same tool that is used to correct html in wysiwyg editors to the rescue. Html Tidy. I found this post regarding Tidy.Net use and where to find Tidy.Net (Tidy utility in .net).
public string FixHtml( string html )
{
TidyNet.Tidy tidy = new TidyNet.Tidy();
/* Set the options you want */
tidy.Options.DocType = DocType.Strict;
tidy.Options.DropFontTags = true;
tidy.Options.LogicalEmphasis = true;
tidy.Options.Xhtml = true;
tidy.Options.XmlOut = true;
tidy.Options.MakeClean = true;
tidy.Options.TidyMark = false;
/* Tidy will provide messages regarding what it done did */
TidyMessageCollection tmc = new TidyMessageCollection();
MemoryStream input = new MemoryStream();
MemoryStream output = new MemoryStream();
byte[] byteArray = Encoding.UTF8.GetBytes( html );
input.Write( byteArray, 0, byteArray.Length );
input.Position = 0;
tidy.Parse( input, output, tmc );
string result = Encoding.UTF8.GetString( output.ToArray() );
return result;
}
Amazingly, the html is now xhtml compliant! You can throw it at an xml parser and go to town.
Parsing Html with Html Agility Pack
Paring down the html
What I wanted was everything Tidy had tossed into the body tag. I evaluated several options and finally decided I wanted to try HtmlAgilityPack.
The source includes several examples, so check them out. Here is my code…
public string GetHtmlBodyContents( string html )
{
HtmlAgilityPack.HtmlDocument doc = new HtmlDocument();
doc.LoadHtml( html );
HtmlNodeCollection tags = doc.DocumentNode.SelectNodes( "//body" );
if ( tags.Count != 1 ) return html;
return tags[0].InnerHtml;
}
Parse Complete, to RSS with you
I will mention that I used Rss.Net to create my Rss feed. Using it is both easy and outside the scope of this post. I will warn you that they have not converted to using subversion so you’ll have to install a cvs client to get the code. There are no releases. You could, if you desire, pay for their commercial version. However, I feel they are falling into the age old trap of over-thinking their license and making the paid for version inaccessible. I believe you should be able to use the personal version for free and a commercial license should be one, flat fee for single business usage. That would allow a single business to use the product in their web sites. Charging extra for source and then again for redistribution is just confusing. They have 30 something options on their online store. c’mon guys, get it together. When I have more than 10 options, I am pretty much finished wasting my time trying to pay someone for their product when there are free alternatives. Yes, you wrote nifty code, don’t make it so hard to be compensated for it.
Ok, off soapbox, back to coding!
Posted in Blogging | 11 Comments »
April 13th, 2008 Rusty
So I am going to past some code.
1: public class OckhamException : ApplicationException
2: {
3: //
4: // For guidelines regarding the creation of new exception types, see
5: // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp
6: // and
7: // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp
8: //
9:
10: public OckhamException() { }
11: public OckhamException( string message ) : base( message ) { }
12: public OckhamException( string message, Exception inner ) : base( message, inner ) { }
13: protected OckhamException(
14: System.Runtime.Serialization.SerializationInfo info,
15: System.Runtime.Serialization.StreamingContext context )
16: : base( info, context ) { }
17: }
and that’s what it looks like. No work at all. Veeeery nice.
public class OckhamException : ApplicationException
{
//
// For guidelines regarding the creation of new exception types, see
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp
// and
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp
//
public OckhamException() { }
public OckhamException( string message ) : base( message ) { }
public OckhamException( string message, Exception inner ) : base( message, inner ) { }
protected OckhamException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context )
: base( info, context ) { }
}
you can adjust things like line numbers and embedded styles.
Posted in Blogging, Programming | No Comments »
April 12th, 2008 Rusty
I’ve set up PHP and mySQL no less than a dozen times over the last two years for various reasons. Each time, I am astounded by how inconsistent the experience is. Once it works, it works. However, getting there can be a breeze or it can be a pain in the neck. Documentation sucks and troubleshooting is impossible. My hope is to save someone the hours I spent over the last couple of weeks trying to get WordPress and MediaWiki configured on a new Windows Server 2003 machine.
Order of Operations
First, make sure you have IIS installed and configured and that you can serve asp pages through IIS. If you can’t do that, you’re going to have no luck with php.
Next, I recommend installing MySQL and then PHP. No worries if you don’t follow that sequence but it helps you to ensure some details later.
When you install MySQL, make sure you can connect via some non php tool using your expected credentials. I love MySQL Administrator available from the MySQL website.
Installing MySQL
MySQL is pretty straight forward. Just run the latest installer, accept the defaults. Done. Keep in mind that MySQL will require some configuration to expose it outside the local machine, if that’s your infrastructure goal, but local execution is ready out of the box. I usually create users for my PHP apps using MySQL Administrator.
Installing PHP
Do not use the installer. From what I’ve read it tries to configure CGI and CGI is just silly. Isapi is far superior but, as I experienced, has some hidden issues that are difficult to resolve. More on that in a sec. The bottom line, however, is that the installer has never worked for me, not once.
Follow the instructions on the for a manual php install on Windows and enable (at least) mySql and MBString extensions (uncomment the lines referring to them in php.config).
Configure a website to serve php, using isapi, and ensure you can serve a php page. Here’s the most useful thing you can do to prove php execution.
<?php
phpinfo ();
?>
Windows Path Environment Variables
I’m not a fan of throwing anything in System32 so I use the PHPRC environment variable to tell php where to load config from.
More importantly, the PATH environment variable needs to know where php and its extensions are. include both of these directories in the PATH. Make sure PHP comes before MySQL in the list.
PHP / MySQL Access Violation
I experienced "PHP has encountered an Access Violation at 015B73DD" each time any MySQL operation was attempted. There was no Windows event record, no logged issue, no information to the screen and nothing registered with SysInternals FileMon or RegMon. This issue sucked about as hard as any computer frustration could. I finally found a post about Installing PHP on IIS 6 where he referenced someone else’s observation: "Adam Carter worked through this problem …insightful conclusion …problem was caused by his mySQL install’s bin folder being included in the PATH before PHP’s install folder. …mySQL’s libmysql.dll loaded before PHP’s libmysql.dll file …upon loading its mySQL extension [causing access violation]. [fix: ensure php precedes mysql in the path] enabled PHP to find its own libmysql.dll"
The error: "PHP has encountered an Access Violation at xxxxxxx" changes the number but does not provide any other useful information and there is no information on the net regarding fixing this. Well, now there is
Conclusion
I hope I saved someone from this hellishness. There are quite a number of great php apps available and its a shame that its so hard to get through install issues. Now that I am a Mac convert, I believe most of these issues are a result of the way Windows loads and operates rather than some deficiency in the php stack. Its worth noting that php on windows is more of a port form apache than part of a design intent. I am going to load up a Linux WMWare machine and see how that experience works for a Windows guy. For now, I’ve got Windows working and I feel confident the install is reliable. It just required a lot of screwing around to get there. Cheers.
Posted in Programming, Windows | 2 Comments »
April 2nd, 2008 Rusty
I’m presently writing this post using Windows Live Writer, running on Windows Vista, sand-boxed within VMWare fusion, hosted on my MacBook Pro with 4G ram. That may seem like a lot of overhead but rest assured, its screaming fast, stable, reliable and a pleasure to use. First, I can’t say enough about my Mac. After spending ten years learning the intricacies of managing and optimizing a Windows OS, I can honestly say I have had to learn almost nothing about managing or optimizing a Mac OS. I have played in Terminal only because I think its fun. However, the only thing I’ve changed from default is to install the magic SmartSleep preference pane from Patrick Stein. More on that in a sec… My motivation for posting this was what I consider to be complete dribble. Rather than even entertain the moron who posted the article that I found on Digg and wasted my time, I’ll link to the first debunk. The only reason to switch from Mac to PC is that the users of the computer do not justify the added up front expense and their time, and the time of their systems support, is worth less than that difference in cost or they are really, really good at multi-tasking. more on that in a sec…
Volume Might Invalidate my Opinion Entirely
Now… if you are buying twelve laptops for a group of sales people who are somewhat likely to drop their computer and the only app they use is MS Office, buy PC and stop reading.
PC is More Productive than Mac? Nonsense
Perhaps it is an April Fools joke? The reality is that I moved to the mac so I could have a better Windows experience. I was tired of fixing my Windows machines, tired of reinstalling the OS, tired of driver incompatibilities, tired of not being able to print to network attached printers, tired of being "Vista’d", tired of the spinning blue circle and no explanation for WTF it was doing. Tired of everything that Vista brought to my otherwise happy programming world. I now experience none of this. that’s right, none. Twice since I’ve had this device, Vista has crumbled and needed a reboot. I happily rebooted. I’m inside VMWare so this is completely tolerable. I can continue working while I reboot, on the same computer. That is incredible! In fact, I just timed a few things for the record. Vista takes about 90 seconds to boot from powered down in VMWare. When it wakes, it is ready to rock, network available, no spinning mystery cursors. There is absolutely no extra crap loading into memory because Dell wants to remind me to buy ink or some nonsense. OS, necessary drivers, go.
Super Fast Sleep, Super Fast Wake
I set my sleep mode to smartSleep so that, when battery is good, it will not write to disk before allowing itself to be bagged. I can’t tell you how many times I’ve pulled a laptop out of the case only to find the battery dead, fan screaming, case red hot and in a state that is anything but sleeping. This is true of my previous Windows based machines and my Mac. I’ve learned to watch for the blinky light. But not no more! Now, with sleep (rather than hibernate), 6 seconds to bag, 3 seconds to ready. Open the case, count to 3, work, right where you left off. I the battery is below 20% when you close the case, it will write to disk.
Windows CAN be Stable - Vista Suckertude is Dell’s Fault
I keep Windows open all day, usually on my external right monitor. I use Mac for my gmail and general browsing. This set up is rock solid reliable, fast, and highly productive. I can always print (if Vista refuses, I just copy my file to my mac OS and print). I can always work (if Vista dies, I can continue working while I reboot). I never have to install something on my critical OS that I am not 100% certain is not going to cause issues. So far, nothing I’ve tried quite compares to blogging with Windows Live Writer. I am free to use my Windows apps at will. I also get to be part of the exclusive club of geeks who paste apple stickers on the back of their cars.
Mac Productivity Wins
I am significantly more productive with a MacBook Pro than I was with my previous Dell or Lenovo laptops. The cost? Go price a base model MacBook Pro, $40 for VMWare fusion from Amazon, $70 for 4G ram from New Egg, a Vista or XP OS license and then compare that to the price of, say, a Toshiba with similar specs. Its not cheap. If your time is more valuable then the difference in price, pull the trigger and thank me later. I still owe Mark Jones drinks! (thanks dude)
Posted in Mac, Vista | 1 Comment »