Nov 17

Part of the Story of all of Our Lives

Our lives are complicated. But we all have something in common! We all make mistakes and sometimes fail to learn from them. This is that story, simply yet fully told. May we all eventually find another street.

Autobiography in Five Chapters

by Portia Nelson


I

I walk down the street.
There is a deep hole in the sidewalk
I fall in.
I am lost...
I am hopeless.
It isn't my fault.
It takes forever to find a way out.

II

I walk down the same street.
There is a deep hole in the sidewalk.
I pretend I don't see it.
I fall in again.
I can't believe I'm in the same place.
But it isn't my fault.
It still takes a long time to get out.

III

I walk down the same street.
There is a deep hole in the sidewalk.
I see it is there.
I still fall in...it's a habit
My eyes are open; I know where I am;
It is my fault.
I get out immediately.

IV

I walk down the same street.
There is a deep hole in the sidewalk.
I walk around it.

V

I walk down another street.
Nov 17

Ebooks from Markdown

The last ebook I published was six years ago and a lot about the way I think I would do it has changed. Primarily I think I would change from writing it in word to writing it in Markdown and then converting it to other formats as needed.

Why Markdown? Well there are several reasons why I like the idea of it better.

  1. Plain text editor means write anywhere and still be able to format.
  2. Plain text editor means no dependance on propritary software.
  3. Plain text means easy for using git for version tracking. Big deal here.
  4. Markdown means splitting into multiple files easily – for example by chapter.
  5. Markdown means one master format that can be converted to all the others as needed.

Some sources that seem useful. I will probably convert this to a references section as a fill the body of this article out over time, but for now you’ll have to get there yourself to get the info!

  1. http://www.gabrielgambetta.com/tgl_open_source.html
  2. https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet (Markdown cheetsheat)
  3. https://medium.com/@davidgrophland/making-an-ebook-from-markdown-to-kindle-cf224326b1a2
  4. https://pandoc.org/ (software from converting from Markedown to other formats)
  5. https://ebooks.stackexchange.com/questions/65/is-markdown-a-viable-source-format-for-writing-ebooks
  6. https://garyhall.org.uk/create-ebook-command-line.html
Jul 31

Fix Your Error Messages Before You Fix Your Errors

I work in software development. I’m a “Senior Software Project Engineer” which means that I work with other people to define their needs (and wants) and then lead a team that design, architects, and implements a solution. As I’ve moved up over the years I’ve worked with a bunch of different people many of whom are experts in their area. Recently, I got a little bit of verbal lashing from one of these people who is the head of IT Operations. While the person almost never says anything nicely they do almost always end up being right so I try to ignore almost everything they say and instead try to get the message, because, like I said, they are actually almost always right and they’re really good. So what were they right about this time?

Our logging sucks. We log all kinds of stuff. Some of the errors we log are legit. But many, if not most, are total garbage. Some of the “errors” are not really errors (that’s another blog post). But what about those that are truly errors? What could be wrong with logging them?

Imagine an error that says “Fatal error during processing.”

Ok. Now what in the work does that mean?  And what should I do about it? Can I just rerun processing? Do I have to do some kind of clean up first? Should I report it to someone? Was the problem related to the software logic, to the environement (disk space, network down, etc), to the input? What the hell am I, guy who’s job it is to make sure work gets done, supposed to do with that error? I suppose I’ll probably just try to run it again and cross my fingers, right? Well I’m only doing that until someone’s software doesn’t clean up after itself [that’s also another blog post) and causes havoc by being restarted… then I’m out of the business of trying to be helpful and I’m in the business of complaining.

Let’s re-imagine that same error now says “Fatal error during processing – insufficient disk space available”. That’s better, right?! Sure it is. I’d much rather have that! But I still haven’t answered over half of this operator’s questions. Can I just rerun? Do I have to clean up some runtime data first? I t’s better but not really completely helpful.

Trying again. “Fatal error during processing – insufficient disk space available. Process requires atleast 1GB available disk space on volume /server/vol1 to run. Create necessary disk space and rerun.’

Now we’re cooking! All the information anybody needs to have is there in the log. Happy Ops people! And honestly, if you’re DevOps, you probably care about this even more because it’ll be you trying to figure out what went wrong. Logs are important, good logs are a godsend.

So next time you’re fixing an issue and you’re digging through code to try to find the cause of a problem – that you only know about because of a log – keep in mind that most of that digging could be avoided by better log messages. Take the time to update your log messages while you’re in there rather than just fixing the bug. You’ll be glad you did and you’ll make life better for you and for someone else!

Jul 26

VB enums default to 0 if they are Nothing

I was writing a test case today and when doing the first step – “make a failing test” – I was having problem… the test kept passing even though I knew it shouldn’t. Eventually I figured out the reason is was passing is because I didn’t understand that an Enum will default to 0 if is actually Nothing.

I was testing a factory that had the very simple job of producing a logger depending on the type of logger that was requested. Here’s the factory code:

Public Shared Function MakeLogger(ByVal logmode As LoggingMode) As I_CustomErrorLogger
   If logmode = LoggingMode.DATABASE Then
      Return New CustomLoggerDBEnabled()
   ElseIf logmode = LoggingMode.DEVNULL Then
      Return New CustomLoggerDevNULL()
   ElseIf logmode = LoggingMode.STANDARD_IO Then
      Return New CustomLoggerStandardIO()
   Else
      Return New CustomLoggerStandardIO() ' Assume old way if not told
   End If
End Function

And, as you can see, it takes an object “LoggingMode” which is an enum.

My thought was, for my FAILING test I’ll pass Nothing (this is the vb equivalent of null) as the parameter and I can then check to make sure that the type returned is something OTHER than StandardIO (because the default would be StandardIO). Remember I’m trying to make a failing test so I asserted that the returned logger was of type CustomLoggerDBEnabled.

But it passed! That’s not right I said and reran. Then recompiled. Then restarted visual studio literally thinking something must have gotten cached and the test wasn’t rebuilding or something crazy like that. Then it hit me, maybe null behaves weird with enums. So I debugged it and sure enough the value I passed in as Nothing was being view is 0 in the debugger.

If that’s not bad enough, my enums were “auto enums” (I didn’t define a value for them) and so they started at 0, meaning that the first item in my enum was more or less equal to zero, the next equal to one and so on. As it turns out DATABASE was the first item in my LoggingMode enum and therefore it got the value 0. So in my factory, if it was sent Nothing for the enum it would understand that as 0 and therefore translate it to DATABASE when it came to enum comparisons. All of that happening at the same time, and the fact that I just happened to choose DATABASE  as my FAILING condition made the test pass.

The fix was to update my enums to hardcode the value. so instead of:

Public Enum LoggingMode
   DATABASE
   DEVNULL
   STANDARD_IO
End Enum

I did the following:

Public Enum LoggingMode
   ' Today I learned that sending Nothing as a parameter when an Enum is expected defaults the value to '0'
   ' This means that the first item in the list of enums will be selected.
   ' So If we want to send 'Nothing' and have it not match anything in the enums list then we 
   ' have to specify the enum values. This is poop, but it is what it is.
   DATABASE = 1
   DEVNULL = 2
   STANDARD_IO = 3
End Enum

Now, since I don’t have a value mapped to 0 the Nothing enum will fall all the way to my final else statement and give back the default logger I actually want.

To close this up let me point something not quite so obvious out. Besides the in your face lesson of Enums that are nothing are really 0 there’s something else valuable to take away. Unit Testing works to make better code. You shouldn’t skip it. It finds weird little cases more than I’d like to admit. It just so happens that this one gave me an opportunity to learn a little unrealized nugget about the language rather than the implementation. But it has value! Do it!

Jul 26

Imitation can be Costly Form of Flattery for the Imitated

You may have heard the phrase “Imitation is the sincerest [form] of flattery”. The quote comes from Charles Caleb Colton. And it’s true.  What’s also true is that being imitated online can be costly to those being imitated if they don’t account for it and adjust their way of doing things to minimize its effects.

I recently started a site called Nameinator that was created based on work I’ve done for other sites of my own. I own a bunch of sites about names and I’m working to roll them all into one under that site about name ideas – things from fantasy football team names to boat names.

Historically, what I’ve done was added names to the list and after a certain number were added I’d write a rundown list article of the newest items. But due to imitators (maybe better said thieves), I’m planning to move towards publishing our name ideas articles a little more often instead of adding them straight to one of our lists and then later writing a rundown article that includes them. It seems that doing it the old way we managed to see our names in other peoples articles before we even got to publish an article containing the name ourselves. People were reviewing our lists and taking the names and not linking back – as if the names were their ideas. So we’ve got to do what we can to minimize the effect this can have on us.

For the reader it’s no big deal. Basically we’ll be creating a new type of article that will be less lengthy but very fresh. We’ll still do longer rundown types of articles and we’ll still do articles highlighting user added items. This new way of doing things we hope will allow us to rank on the search engines for our own content before other sites copy it. We want to get our own fresh content straight to you from us rather than someone else giving your their take on our ideas without attribution.

If you’re someone who creates a lot of content you may want to consider posting more often in smaller bits rather than saving up to publish some huge item. Especially if you’re putting the little bits out there in pieces for the convenience of the end reader. Take a little more time and do both so you’ll get ranking for all your hard work.

Feb 06

550.50 On Images in Windows IIS in WordPress

I was having a problem where uploaded images were causing a 550.50 error when users clicked on them to see the original image. That is, images showed up in articles fine, but when the user tried to view the full size version it errored. I was able to fix the problem by setting the permissions of the temp directory that my php.ini file points to such that they matched what wordpress needed. Here’s the two best sources I found on the subject. After the links I’ll post the contents of the archive.org page including all the info you need.

So here’s an attempt at answering the question that did pretty well. It didn’t work for me exactly (I think they got IUSR and IUSRS backwards), but it’s pretty much right. Either way I found this other page that was referenced on that one even more useful.

Here’s that page quoted in it’s entirety because archive.org can have pages dropped and I’m going to want this info later. It’s original location was at the following url. I’m not linking to it because it’s a dead link, but I will link to the primary page for that site.

http://www.digitalpimple.com/tutorials/windows-tutorials/fix-550-rewrite-error

Begin Quote:

While creating this blog I ran into a rather interesting problem that took me all of a half day to figure out. If you installed WordPress on a Windows IIS7 Server using the URL Rewrite Module 1.1, you may receive a HTTP 550 error when clicking on an inserted image.

Well that shouldn’t happen now should it.

After much agonizing I concluded the problem lies in the images’ permissions that seem to get set when first uploading them to/from WordPress. The permissions of the original uploaded image seem to NOT inherit the correct WP upload folder permissions; This in-turn, blocks access to the original file on the server. When the original file is called from the blog/internet, the server throws a 550.50 URL Rewrite Error. The same error that you see in the above image.

Now time for the strange part. Thumbnails of the original are created by WordPress using this same original uploaded image. They display just fine when inserted and called. These thumbnails inherit the correct permissions of the Windows/WP  folder where they are stored. So the question: Why does the original uploaded image that is stored in the exact same location as the thumbnails not inherit the same permissions? Checking the original image directly on the server against the thumbnails that were created from it confirmed my theory. Hum… perplexing. Is this really a URL Rewrite Error or not?

So what causes the original uploaded image from inheriting the correct permissions? The answer is incredibly simple but also incredibly annoying.

The Setup:

For the record, I’m running WordPress 2.8.4 on an IIS7 Windows server 2008 platform using FAST-CGI with PHP, MY-SQL & URL Rewrite module 1.1. I’m using a custom permalinks structure of “/%category%/%postname%/”. The following is the web.config code I’m using along with the same file for download:

<?xml version=”1.0″ encoding=”UTF-8″?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name=”wordpress” patternSyntax=”Wildcard” stopProcessing=”true”>
<match url=”*” />
<conditions logicalGrouping=”MatchAll”>
<add input=”{REQUEST_FILENAME}” matchType=”IsDirectory” negate=”true” />
<add input=”{REQUEST_FILENAME}” matchType=”IsFile” negate=”true” />
</conditions>
<action type=”Rewrite” url=”index.php” appendQueryString=”true” />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>

Download: web.config file-1.0

The Solution:

PHP is the issue, not WordPress. The problem only happens when you use PHP to upload a file.  When you upload a file, PHP sends the file to a temporary directory on the hard drive (for me it’s C:\Windows\Temp) and then copies it over to it’s intended directory.  Once the file has landed in the temporary directory, it is assigned the permissions of that directory.  The problem is when Windows copies that file, it keeps the temporary directory’s permissions and doesn’t inherit that of your web directory’s.  Bingo!!

The easiest way to fix this problem is to add to the temporary directory your intended web directory’s permissions.  In other words, don’t erase the permissions already in the temporary directory, just add the web directory’s permissions to them.  In Windows Server 2008 the two user groups you must add are: “IUSR” & “IIS_IUSRS”.

If you want to change your temporary upload directory, find the “upload_tmp_dir” in your php.ini file and set it to the directory of your choosing (outside your web folders of course), and then add the proper permissions.

So, just create a new folder named “PHP_uploads” in  “c:\<YOUR_PHP_DIRECTORY>\PHP_uploads\”. Now go to your PHP.ini file and  change it to the new location.

After adding the new folder location to your PHP.ini file add the IUSR & IIS_IUSRS permissions to the new upload folder you just created.

After your all done, delete the previous uploaded images from your WordPress admin console and reinsert them as normal.

Your 550.50 error is now no more!

Feb 06

Programming Languages Popularity Surprising to Me

I came across the TIOBE Programming Community index a few minutes ago and was a little surprised by what I saw. As developers we all know that there’s much more work being done in different programming languages than what we are exposed to each day. But checking out the TIOBE indicator gives a pretty amazing look at what’s popular and what’s being used in the industry.

The TIOBE indicator is an indicator of the popularity of programming languages. The index is updated once a month. The ratings are based on the number of skilled engineers world-wide, courses and third party vendors. Popular search engines such as Google, Bing, Yahoo!, Wikipedia, Amazon, YouTube and Baidu are used to calculate the ratings. It is important to note that the TIOBE index is not about the best programming language or the language in which most lines of code have been written. – TIOBE.com

 

TIOBE2015jan

Think about it for a moment. Think about which languages you think are the most popular and then click on the link. How did you do? Are the ones that you use on a regular basis the ones that you thought were more popular (they were for me) and were you right (not really for me)? I think it demonstrates a certain level of bias that many programmers have that what we use is probably the best available – unless we’re forced by someone else to use their own favorite choice. It’s important that we be aware of those bias and what’s going on in the rest of the industry so we can grow as developers and remain up to date on our skill sets.

Feb 02

DOMCOP – A Tool for Domainers Looking to Catch High Quality Dropping Domains

I don’t remember exactly how it started, but over the last few years I’ve acquired a little over 400 domains. I bought a domain about 10 years ago and carefully built a nice site. It climbed in the ranks over the years, but considering that the domain name was cool only to me and I didn’t already have a lot SEO expertise it just never really had a chance. I diligently worked on the site for 8 years making no more than $1000 per year. I experimented with different revenue streams and models (affiliates, subscription, membership, even pay what you can!), but nothing turned it around because the traffic simply wasn’t there.

Finally I “gave up on it” and decided to move on to another project. It was in the same niche, but just not exactly the same. And it required maybe 1% as much work. It was just much smaller.  I was able to buy some exact match domains to match the concept (mind you at this point I’ve got something like 10 domains) and I coded up the project. I’ll be damned if in the first month I didn’t make what I had made the entire previous year. So I started to see if it was repeatable and bought more domains. BAM by the end of the first year I made 5x what I had made in the previous 8 years combined! Nice. So now I had it all figured out – or so I thought. I basically reinvested most of the earnings and I ended up spending tons of money (tens of thousands of dollars) to buy domains that would fit what I was trying to do. The idea was right, the execution was horrible.

If I could do it all again I’d do it differently. I would not buy from third parties near as much, and I’d buy pre-releases of dropped domains more often. Something I didn’t know when I bought from third parties was that I was buying domains that they’d simply bought off the drop. That means I could have had just as much a chance paying a service to try buying them for $69 rather than several hundred or up to $2000 dollars. It probably cost me $10000 to learn that little lesson.

So I could wait until they dropped if I could spot them before hand, but there is a problem with buying dropped domains. A domain’s age resets to 0 when it deletes / drops. If you can manage to get these domains before they drop you can keep the age bonus that many search engines grant. Basically an older domain has a little more street cred as far as the search engines are concerned. If you want to rank quickly in the search engines then having an aged domain will only help.

If you can get aged domains with a lot of clout (page rank) to point to a site that you want to rank high then you can help that site rank well quickly. The problem is that it’s darn near impossible to find sites with a lot of legitimate link juice and to get them to point to your site. You can (and should) reach out to other sites and share your site with them to get them to see the value you provide, but you can also jumpstart the process yourself if you’re willing to do a little extra work. It’s actually a LOT of extra work unless you know the right tools. That’s where DomCop.com comes in.

DomCop is basically a search engine for expired domains. You can use it to find domains that match all kinds of metrics (Page rank, age, number of links, types of links [gov, edu, etc], alexa rank, and much more). Then, once you’ve found a domain you can try to buy those domains BEFORE they are deleted. Or you can stand ready to snatch them up when they actually are deleted. Their tool makes it so easy to find domains that will help you in your SEO efforts. They’ve even got a pretty great tour to show you how to use their site for maximum benefit.

domcop-screenshot

[Click on the above screen shot for a large clear view]

As you can see from that screen shot it’s a very informative and useful tool. Whether you want to utilize the purchased domain for your main site or you want to build a set of quality links to your main site from high link powered domains DomCop can help you find the domains that will give you the most value for the least effort. I’ve bought a few domains that I found using their engine and I’ll even be using it to enable me to continue to trim my domain holdings. By identifying and buying a few strong domains and letting quite a few weaker ones go I’ll lower my renewal fees (less domains) and have stronger sites helping improve the ranking of those I do maintain.

If you decide to use DomCop let me know how it works for you in the comments section below. Maybe you’ll use it some way I’ve never thought of before and you can help me get even more value from it!

Jan 27

Copy Text from Label – Winforms – DotNet

A customer asked that some of the data on one of their windows forms screens be copy / paste friendly. “Easy enough” you’d think, but on closer inspection I found that the data was being displayed in labels – not text boxes. Nothing wrong with that, but there is no built in way to be able to click on a label and drag your mouse to select the contents of the label so I was tasked with either rewriting the screen to use some sort of disabled textboxes trick or making it possible to click on a label and copy the text of the label to the clipboard.

I chose the copy/paste label route. Here’s what I did. Code follows the steps.

  1. I added a formwide variable that would hold the value to be placed in the clipboard (the value of the label that had been chosen).
  2. Then I added a contextmenustrip to the form and wired up each label to use that contextmenustrip.
  3. When the context menu opens I get the label that launched the context menu and I store the value of that label to that formwide “ToCopy” variable. I also set the text of the context menu option to say both “Copy” and also the value that will be copied to the clipboard.
  4. Finally, I set the ItemClicked method of the ContextMenuStrip to copy the value from the formwide variable (which we set when the context menu opened) to the clipboard.
  5. Consume Beverage of Choice


Dim valueToCopyToClipBoard As String = ""

Private Sub ContextMenuForCopyLabelData_Opening(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles ContextMenuForCopyLabelData.Opening
ContextMenuForCopyLabelData.Items.Clear()
Dim lbl As Label = ContextMenuForCopyLabelData.SourceControl
valueToCopyToClipBoard = lbl.Text
ContextMenuForCopyLabelData.Items.Add(String.Format("Copy - {0}", lbl.Text))
End Sub

Private Sub ContextMenuForCopyLabelData_ItemClicked(sender As Object, e As ToolStripItemClickedEventArgs) Handles ContextMenuForCopyLabelData.ItemClicked
Clipboard.SetDataObject(valueToCopyToClipBoard, True)
End Sub

Modifying the data to be displayed in textboxes would not have been a huge task, but it would be boring and required doing the same exact action a lot of times. Not hard, just a lot of work for a little gain. Plus, textboxes don’t autogrow so longer data would have to be handled some way making it even more tedious. The nice thing about textboxes is that it would have “just worked” without have to handle any special events. My plan if I went the text box route was basically to create a custom textbox control that matched the form, but was readonly, had no border, etc.

Default values would be something like this:

.ReadOnly = true;
.BorderStyle = 0;
.BackColor = this.BackColor;
.TabStop = false;

Then for each textbox that you wanted to hold readonly data and look like a label you’d just use that bad boy.

Each solution is good for a particular situation. If you have data of different lengths going into to your controls then labels are probably the way to go. But in the end it’s up to you.

Hope you find it useful!

The research I did consisted covered essentially these 2 pages:
https://msdn.microsoft.com/en-us/library/system.windows.forms.contextmenu.sourcecontrol%28v=vs.110%29.aspx
(Just a little documentation on how to find out which control actually launched the ContextMenu)

http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_21693232.html
It turns out my solution looked a lot like theirs in the end, but in my solution we never talk about a specific control so it can be attached to any label (and any number of labels) and just work being written one time.

Have you encountered the same problem and found this useful? Or maybe attacked it a better way. Let me know in the comments below!

Nov 18

Roger Goodell Does The Impossible – Proves that Unions Are Necessary

I’m an NFL football fan. But I don’t have to be, and at this moment I’m not sure I want to be due to Roger Goodell’s handling of Adrian Peterson. If you read my post on the recent announcement of Apple’s CEO then you’ll know I don’t like to support companies who have leaders who do pretty major things that make me sad. Whether they make me sad by being unfair to those under their power or by being blatantly dishonest about important matters – either way they’ve broken a trust. It’s my money and my time, so why use it to support something that makes me sad?

Roger Goodell has managed to do something nobody else has been able to do. Something I never thought was even possible. Something that the party that leans more to the left hasn’t been able to do in my 35+ years. Something my college professors couldn’t do. Something my wife’s dad who was vice president in the fire fighter union couldn’t do. Goodell’s actions have convinced me of something probably every conservative would agree is a terrible idea, which is funny because I’m pretty sure that Goodell walks on the conservative side of the political line. In any case, his decisions and actions have managed to convince me of something conservatives have fought hard to discredit. He’s convinced me that unions are still important and necessary.

Now, to be honest, all this has done it upgrade unions in my mind from “completely unnecessary and counterproductive” to a slightly more elevated state of “needed and a necessary evil“, but I honestly never thought I’d see the day that such a thought would even enter my mind. What Goodell has done to Adrian Peterson is reprehensible and inexcusable. The arbitrary punishments doled out in the face of pressure from some fans and some advertisers are understandable, but still show signs of weakness on the commissioners part. I’ve yet to see him make a proactive move in any of his dealings, and his reactive ones have only come after he’s been forced into a corner. Now he’s managed to back someone else into a corner, and even though I didn’t think I’d ever say it, I’m glad there’s a union there to back up his victim. As USA Today’s Nancy Armour put it Goodell hasn’t done anything here other than try to protect what he considers to be his turf and ended up just picking a fight with the union.

If the union really wanted to impress they’d convince players to hold out on the Thanksgiving day games coming up next week. Hell, I bet the union has enough in the coffers to write a game check to every player for that missed week. That would be glorious! I could live
with it and it would probably further strengthen my new found slightly positive opinion toward unions. Of course, they might not have to. The union might win it’s grievance hearing and Peterson will be allowed to play sooner than next year. Maybe that’s Goodell’s plan anyway. This way he can act like he tried to get rid of Peterson but the arbitrator was convinced by the big, mean union and forced his hand to let
Peterson play again this year. Maybe that’s the plan. But it shouldn’t have come to that and it frustrates me that, if that is his plan, he simply proved that unions are necessary in order to protect individuals from weak leaders.

Roger Goodell has made me sad today, but maybe I should thank him (and the other owners for continuing to support him) for opening my eyes to the truth. As long as there are leaders like Goodell, there will be a need for organized protection of workers rights. I’d still rather just get rid of the bad leaders, but even if that were the plan there would need to be some mechanism for raising awareness about bad leaders when they slip through the cracks, and I’m not sure I can think of another more functional mechanism for that very task than a union…

I guess unions are probably a little bit like firearms. They can be used wrong and can cause all kinds of damage if whoever is controlling them doesn’t make good decisions and doesn’t pay close attention to where they’re pointing their power. It’s best to not wield the power at all if possible. But in the end, it’s probably better to have one and not need it than it is to need one and not have one.