People Are Killing Off Inheritance

by Jon Davis 7. January 2009 11:56

I'm noticing that, more and more lately, people are throwing out inheritance, as is demonstrated by this StackOverflow thread.

I'm still trying to concede my opinion on this. If the proponents of this attitude did not have "use delegation" up their sleeves I would say they are all either nuts or completely clueless about how good OOP can be written.

I think inheritance is a fabulous thing and in well-designed systems is even more important than interfaces, particularly in fundamental, framework scenarios like visual/UI controls, ORM, I/O base classes, and the like. It's also great for application design--three different account types, for example, each with a different subset of behavior but all sharing a lot of commonalities (all being accounts).

I imagine, however, that most of these folks have experienced the real world in team environments wherein bad OOP implementations of inheritence have resulted in unmaintainable code. In such cases, I can certainly see how interfaces, as a compromise, forces team members to stick to the testable specs rather than futz with the legacy. I most definitely cannot fathom how such environments are productive; reimplementing interface behavior everywhere just sounds atrociously bogged down, nothing gets done in such environments.

Delegation as an alternative to inheritance, however, makes sense in the area of code reuse. Compositing behavior services and providers in a composite class that implements multiple interfaces and hands off the implementations of those interfaces' members to the composite members is a great way to reuse code, should inheritence be avoided. 

A sealed composite delegation class does not, however, support is-a relationships, only behaves-like-a relationships via interfaces. Using interfaces alone, we again go back to procedural code and lose the great benefits of OOP and replace it with OBP (objects-based programming), a la COM. VB6 supported polymorphism as such, and its value stopped there. I have hardly used VB6 since C#, the true OOP language, became available to me as a Microsoft tools user.

Actually, a good persuasive article lies over here http://weblog.raganwald.com/2008/04/is-strictly-equivalent-to.html in favor of composition / decorator patterns. It's so persuasive, actually, that I personally think the C# 4.0 team should consider making composition / decorator pattern as easy to implement as inheritance.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

Software Development

Why Windows and IIS Developers Need To Try PHP, Ruby, Python, Pure Javascript, Or Something Else

by Jon Davis 5. January 2009 05:04

I've argued frequently here before that rather than being a master of one thing, it's better to be knowledgeable of many things, expert in a few. This is not the same as being a jack-of-all-trades because one would suck at all those things, but if you're better at some things, rather than a master of one thing, you might actually be better than the master of the one thing, because your experience is diversified.

Perfect analogy...

http://www.candychang.com/design/pages/milk_and_muffin.htm

"[Trying other things makes your specialty] taste better because now you know what makes it special ... and your appeciation of [your specialty] gives you a better understanding of all the other [alternative technologies]."

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Opinion | Software Development | Web Development

New Javascript Library: jqDialogForms

by Jon Davis 5. January 2009 02:52

(Note: If you link to this blog entry, please use the URL: http://www.jondavis.net/codeprojects/jqDialogForms/ which only temporarily links back to here.)

I'm releasing a v1.0 v1.1 beta build of jqDialogForms, a DHTML-based dialog windows library based on jQuery and jqDnR. This is something I started to build during my free time at my last job (it was never used there) and then continued development and completed it on my own (at home). Since I'm no longer at the job where it would have been useful had it been completed there, I do not have a lot of real-world samples to demonstrate here, but I'm releasing it now in hopes that it can continue to evolve.

There are other libraries out there that produce dialog windows that are completely modal. Modal dialogs are important, but I quickly ran into problems when, for example ...

  • A dialog window spawns a child dialog window
  • I want to see behind the child's parent's window (move the window)
  • I want to open multiple dialog windows at once
  • I'm using any modern browser, including IE 7 in quirks mode
  • Dialog windows are very large, and users are browsing with small monitors or browser windows
  • The user has scrolled down beyond the fold and absolute positioning is used

jqDialogForms has a placeholder for modal dialogs but it's not implemented. The focus instead was on parent disabled+modeless+serializeable windows, meaning the ability to have a child window have a parent window, which forces the child window to retain a top-most z-index over the parent window, while the parent window's form fields are disabled, but you can still access the parent window and even drag it around. None of the windows in this scenario need to be modal; they just retain z-index. You can click on each open window and it acquires "activation", which moves its z-index to the top and then moves all of its child windows above it, and there is also an "active/inactive" titlebar color. It's a Windows 9x multiple app windowing behavior, within the browser. The window is also serializeable, meaning that it is a self-contained <form> with fields that serialize using either jQuery serialize() or using a JSON serialization. It is important to note that I made a point to be ASP.NET Web Forms compatible. jQuery's serialize() function doesn't work well with ASP.NET Web Forms unless the <form>'s are dynamically generated and appended to the body as this library does.

Because it is for dialogs, it assumes Apply and Cancel behavior and the presence of buttons. (OK is Apply+Close. Cancel is Close without Apply.) So there are assignable event handlers for before-show, showApply click, and hide. The default layout implements OK/Cancel and a close box on the top right.

There is a simple test document included with this release that I used to develop the the script, but it is an awful presentation for demoing purposes. The test document and the script itself are complete enough, though, for a knowledgeable Javascript developer to read and understand how it works without documentation. But next on my to-do list is to produce some documentation and samples, but except for modal mode the script itself it pretty much feature-complete, if not quite 100% tested, as a v1.0 beta release.

Features:

  • Modeless+parent disabling+serializeable dialog form windows
  • Reference a DOM element or a string of HTML as the message or form fields to be displayed
  • Automatically switch from fixed positioning to absolute positioning when in quirks mode IE7, and position to the current vertical scroll position
  • jqDnR enabled: Resizeable, Windows 9x style
  • jqDnR enabled: Drag around the screen via the title bar
  • Activateable; show multiple windows, and activate/focus each window as it is clicked on (Windows 9x application windows activation behavior)
  • Lacking CSS conformance of a dialog window container, a prefab one is used that includes a title bar, a close box, and OK/Cancel buttons.
  • OK button invokes Apply event handler and then, if not invalidated, closes the window.
  • Dirty state detection; on editable forms, OK/Apply buttons are disabled unless a field is changed
  • Exposes form serialize functions that outputs name/value HTML/querystring encoding (in the style of jQuery serialize()), or JSON serialization.
  • "Smart" top positioning for oversized dialogs
  • CSS-driven layout

Among the several known issues:

  • Multiple windows do not retain their activation order.
  • No fully modal dialog or truly modeless (non-disabling) support
  • No demo No extensive demos
  • No documentation

A few months back I released a Javascript library called jqAlert. I will probably rewrite jqAlert to use jqDialogForms.

It's NOT perfect, there are a few missing parts and pieces, but as far as I know it's a stable beta and can probably be used in production environments (I think). If you have any comments or suggestions, please use the Comments herein on this blog or e-mail me.

 

Download: 

http://www.jondavis.net/codeprojects/jqDialogForms/ 

 

kick it on DotNetKicks.com

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , ,

Web Development

How to Setup a Dedicated Web Server for Free (Windows version)

by Jon Davis 4. January 2009 16:03

So I clicked on StumbleUpon and came across this:

 http://nettuts.com/articles/news/how-to-setup-a-dedicated-web-server-for-free/

And I kept rolling my eyes because you CANNOT have a dedicated web server for free without a not-free Internet connection with a static IP and port 80 unblocked.

If you've overcome that hurdle, though, such as using unblocked DSL instead of cable modem, for example, then the article is worthwhile. However, by the time I scrolled down to the bottom and got to the end to read "That's it!", I was rolling my eyes again, because the article is about 25 pages long!!

If you have Windows Vista (comes "free" with most commercially built PCs these days, or hey surely you have a Windows XP CD lying around... but be warned, XP and earlier OS's only allow for a single site to be enabled at a time), let me tell you how hard it is to have a complete dedicated web server for free in Windows-land.

Click on this: http://go.microsoft.com/?linkid=958807

(You can read more about it here: http://www.microsoft.com/web/channel/products/WebPlatformInstaller.aspx)

Check off what you want.

That's it!

To be fair, nearly all Linux distros have a "check off what you want" interface, too, but it's still more difficult to set up each component after installation such as mySQL than it is to set up SQL Server Express, IMO.

On a final note, in a word, XAMPP

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Servers and Services

IE8: Performance Problem With This Blog

by Jon Davis 4. January 2009 05:03

I've found with all public betas released so far of IE8 that it cannot handle this blog page (http://www.jondavis.net/techblog/) without locking up for about 15 seconds while waiting on the last few files. I don't know if it's locking up because it's single-threaded and choking on some document.write's, or what. I just know that it locks up. And Firefox, Chrome, et al, don't have a problem--they stall on the document completion, too, but they don't become unresponsive like IE8 does.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

XSLT: With XSLT Extensions, It's Actually Not Bad

by Jon Davis 3. January 2009 05:55

A couple months ago, while picking up and getting certified in SiteCore CMS, which tries very hard to stay true to ASP.NET such that ASP.NET customizations involve as little proprietary knowledge as possible, the training taught me something new about XSLT. I learned that, in an ASP.NET environment, XSLT with XSLT Extensions is actually quite powerful!

In a previous job, I worked a bit with XSLT, and I immediately hated it. I saw that the looping and if..then blocks and otherwise really lightweight business codification in XSLT makes plain-vanilla XSLT completely brain-dead and a nightmare where business rules need to be applied. Computations and processing, instead of being performed inline (which was possible but awfully ugly) was sometimes done ahead of time and passed in as XSLT variables in the header. In cases like that job, I concluded rather quickly that .ascx ASP.NET Controls are FAR more preferable.

However, with .NET XSLT Extensions, one can isolate blocks of business rule driven functionality with identical ease as referencing an ASP.NET control with a referenced control tag. It's still not as versatile as ASP.NET pages with ASP.NET controls, but it comes really close.

Basically, XSLT Extensions are the utilization of XML namespaces to map to a .NET class. When you specify a particular tag with this namespace (once referenced), the .NET class's members are invoked. And yes, you can pass arguments.

Implementation and configuration is also different from ASP.NET Web Forms, but it's not painful. In SiteCore CMS, you drop some XML bits in the web.config and in a special directory; SiteCore has to provide the extensions functionality, as far as I know, but I could be mistaken. I think that they work with built-in .NET XML/XSLT functionality but what I was trained to use in SiteCore may not be available in core ASP.NET without some plumbing code. Again, not sure, and if I find out otherwise soon I'll likely update this post.

However, when working with an XSLT Extensions enabled framework, whatever it may be, the best part about it is that it is an open standards templating language, complete with business logic tagging. Where ASP.NET templating is proprietary to ASP.NET, XSLT is not proprietary to anything. Theoretically, one can take XSLT template markup from an ASP.NET-based web site, and, after migrating whatever extensions were used, reapply the same template markup on a Java-based web architecture, or some other one that supported XSLT w/ Extensions.

Lacking the need or anticipation of such a migration, ASP.NET w/ controls is preferred over XSLT w/ XSLT Extensions. XSLT Extensions are neat, but not quite as easy to work with as ASP.NET controls. One could also argue that XSLT templates are easier for the non-programmer designer to work with since there is less to learn; personally, while I agree to an extent, I'm still somewhat doubtful that it matters much, because one can simply apply strict rules of simplicity in ASP.NET control implementation and thereby still be far easier to work with. In my opinion, of course.

For more information, here's a Google search: XSLT Extensions

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

Web Development

LINQ Didn't Replace SQL Queries

by Jon Davis 3. January 2009 04:17

Just observing the obvious here, but about three and a half or so years ago when I heard about C-Omega, which later became LINQ, which then later became a part of C# 3.0, I got the impression that LINQ would perform SQL querying on the fly with integrated SQL-like syntax directly inline with C#, with strong typing and everything. In other words, I thought the language would inherently know ADO.NET/SQL semantics.

It does, but well, no, it doesn't. LINQ isn't an inline SQL translator at all. It is only syntactical sugar for a set of interfaces to a neutral provider to different sources of data. Once the provider is set, LINQ is still not translating SQL inline.

LINQ-to-SQL, LINQ-to-Entities, LINQ-to-NHibernate, LINQ-to-YoMamasDB, all of these use ORM templating and database boilerplating with class-specific generated code to match up the generated SQL.

I'm not against ORM, but it's still too much for smaller (read: tiny) quick-and-dirty hacks. In these cases LINQ (-to-anything) would be overkill galore in the database context. I do say this as a complaint: I still have to use plain old ADO.NET for quick-and-dirty SQL invocation additions, there's no way around it without making it not-so-quick-and-dirty.

Meanwhile, LINQ-to-Objects and LINQ-to-XML are legit. No boilerplating / generated code there. Very sweet.

Tags: , , ,

C#

BlogEngine: Ban Users and Block Ratings Per Articles

by Jon Davis 3. January 2009 03:28

A reader (or two or three etc?) of my blog here makes the occasional one-star rating without sharing a comment. Sometimes this is fair and deserved.

Sometimes, however, I don't care what the heck you guys think of a few of my posts, because these occasional posts might be very personal, UNLESS you share your thoughts in comments. Thumbs-down is generally rude unless you post a comment with constructive criticism. I can take constructive criticism far better than I can take "this post sucks".

So I decided I wanted to be able to both ban visitors by IP address and disable ratings per post. The ban list can be maintained in SQL, and by the way the solution here is usable anywhere, not just BlogEngine.net (although it has no effect for FeedBurner RSS/Atom subscribers), but the other feature of per-post ratings disablement I felt should complement the "Enable Comments" feature in the post editor. These were two easy changes, so I'll make this quick.

Banning Users (Usable On Any ASP.NET Web Site)

 

Add a SQL table (IPAddress column is nullable so that other types of bans can be added later):

/****** Object:  Table [dbo].[Bans] ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[Bans](
	[id] [int] IDENTITY(1,1) NOT NULL,
	[IPAddress] [varchar](15) NULL,
 CONSTRAINT [PK_Bans] PRIMARY KEY CLUSTERED 
(
	[id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

Add a new class file in the App_Code directory:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net;
using System.Data.SqlClient;
using System.Configuration;

public class SiteUtil
{
    public static bool IPIsBanned
    {
        get
        {
            try {
                IPAddress remoteIP = IPAddress.Parse(HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]);
                return BannedIPs.Find(addr => addr.ToString() == remoteIP.ToString()) != null;
            } catch {
                return false;
            }
        }
    }

    private static List<IPAddress> _BannedIPs = null;
    private static DateTime? _BannedIPs_TimeStamp = null;
    public static List<IPAddress> BannedIPs
    {
        get
        {
            if (_BannedIPs == null || (_BannedIPs_TimeStamp != null && 
                ((TimeSpan)(DateTime.Now - _BannedIPs_TimeStamp.Value)).Ticks > TimeSpan.TicksPerHour))
            {
                _BannedIPs = new List<IPAddress>();
                using (SqlConnection conn = new SqlConnection(
                    ConfigurationManager.ConnectionStrings["BlogEngine"].ConnectionString))
                {
                    conn.Open();
                    string ssql = "SELECT IPAddress FROM Bans WHERE IPAddress IS NOT NULL";
                    using (SqlCommand cmd = new SqlCommand(ssql, conn))
                    {
                        using (SqlDataReader dr = cmd.ExecuteReader())
                        {
                            while (dr.Read())
                            {
                                _BannedIPs.Add(IPAddress.Parse((string)dr["IPAddress"]));
                            }
                            _BannedIPs_TimeStamp = DateTime.Now;
                        }
                    }
                }
            }

            return _BannedIPs;
        }
    }
}

Add to global.asax:

  protected void Application_BeginRequest(object sender, EventArgs e)
  {
      if (SiteUtil.IPIsBanned) Response.Redirect("http://www.albinoblacksheep.com/flash/youare");
  }

Per-Article Ratings

 

Add SQL column:

BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
ALTER TABLE dbo.be_Posts ADD
	IsRatingEnabled bit NOT NULL CONSTRAINT DF_be_Posts_IsRatingEnabled DEFAULT 1
GO
COMMIT

Create ~/themes/{theme}/MyPostView.aspx.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.SqlClient;
using System.Configuration;

public partial class MyPostView : BlogEngine.Core.Web.Controls.PostViewBase
{
    protected override string Rating
    {
        get
        {
            return this.IsRatable ? base.Rating : "";
        }
    }

    protected bool IsRatable
    {
        get
        {
            return BlogEngine.Core.BlogSettings.Instance.EnableRating
                && !RatingDisabled(this.Post.Id);
        }
    }

    protected List<Guid> _RatingDisabledPosts = null;
    protected DateTime? _RatingDisabledPosts_TimeStamp = null;
    protected bool RatingDisabled(Guid postId)
    {
        if (_RatingDisabledPosts == null || (_RatingDisabledPosts_TimeStamp.HasValue &&
            (DateTime.Now - _RatingDisabledPosts_TimeStamp.Value).Ticks > TimeSpan.TicksPerHour))
        {
            using (SqlConnection conn = new SqlConnection(
                ConfigurationManager.ConnectionStrings["BlogEngine"].ConnectionString))
            {
                conn.Open();
                string ssql = "SELECT PostID FROM be_Posts WHERE IsRatingEnabled = 0";
                using (SqlCommand cmd = new SqlCommand(ssql, conn))
                {
                    using (SqlDataReader dr = cmd.ExecuteReader())
                    {
                        _RatingDisabledPosts = new List<Guid>();
                        while (dr.Read())
                        {
                            _RatingDisabledPosts.Add((Guid)dr["PostID"]);
                        }
                        _RatingDisabledPosts_TimeStamp = DateTime.Now;
                    }
                }
            }
        }
        return _RatingDisabledPosts.Contains(postId);
    }

}

Modify header line of ~/themes/{theme}/PostView.ascx:

<%@ Control Language="C#" AutoEventWireup="true" EnableViewState="false" Inherits="MyPostView" 
    CodeFile="~/themes/Standard/MyPostView.aspx.cs" %>

Modify ~/admin/Pages/Add_entry.aspx (add cbEnableRating between the two other checkboxes):

<asp:CheckBox runat="server" ID="cbEnableComments" Text="<%$ Resources:labels, enableComments %>" Checked="true" TabIndex="14" />
<asp:CheckBox runat="server" ID="cbEnableRating" Text="<%$ Resources:labels, enableRating %>" Checked="true" TabIndex="15" />
<asp:CheckBox runat="server" ID="cbPublish" Text="<%$ Resources:labels, publish %>" Checked="true" TabIndex="16" />

Modify ~/admin/Pages/Add_entry.aspx.cs:

// cbEnableRating: generally follow cbEnableComments

protected void Page_Load(object sender, EventArgs e)
{
    ...
	if (!String.IsNullOrEmpty(Request.QueryString["id"]) && Request.QueryString["id"].Length == 36)
	{
		...
	}
	else
	{
		... 
        cbEnableRating.Checked = BlogSettings.Instance.EnableRating;
        ...
    }
    ...
    cbEnableRating.Enabled = BlogSettings.Instance.EnableRating;
}

private void btnSave_Click(object sender, EventArgs e)
{
    ...
	post.Save();

    using (SqlConnection conn = new SqlConnection(
        ConfigurationManager.ConnectionStrings["BlogEngine"].ConnectionString))
    {
        conn.Open();
        string ssql = "UPDATE be_Posts SET IsRatingEnabled = @enabled WHERE PostID = @PostID";
        using (SqlCommand cmd = new SqlCommand(ssql, conn))
        {
            cmd.Parameters.Add("@enabled", System.Data.SqlDbType.Bit).Value 
                = cbEnableRating.Checked;
            cmd.Parameters.Add("@PostID", System.Data.SqlDbType.UniqueIdentifier).Value
                = post.Id;
            cmd.ExecuteNonQuery();
        }
    }

    ...
}

private void BindPost(Guid postId)
{
    ...
    using (SqlConnection conn = new SqlConnection(
        ConfigurationManager.ConnectionStrings["BlogEngine"].ConnectionString))
    {
        conn.Open();
        string ssql = "SELECT IsRatingEnabled FROM be_Posts WHERE PostID = @PostID";
        using (SqlCommand cmd = new SqlCommand(ssql, conn))
        {
            cmd.Parameters.Add("@PostID", System.Data.SqlDbType.UniqueIdentifier).Value =
                post.Id;
            using (SqlDataReader dr = cmd.ExecuteReader())
            {
                dr.Read();
                cbEnableRating.Checked = (bool)dr["IsRatingEnabled"];
            }
        }
    }
}

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Blog | Web Development

Merry Christmas, Screwed New Guy, Here's Your Pink Slip

by Jon Davis 1. January 2009 15:11

Happy new year and stuff.

I got a wonderful Christmas present a week or two ago. After accepting a job where my responsibilities, I was told, were to be trained for a certain very cool and expensive ASP.NET 3.5 based CMS and to generally do ASP.NET 3.5 work while helping to migrate from ASP Classic, instead upon arrival at the new job I discovered that all the CMS migration work was already outsourced to an outside consulting company, my employment was only to secure post-migration support and maintenance, and in the mean time I’d be spoon-fed ASP Classic and .NET 1.1 tasks one at a time for the next six to 24 months. On top of that, they didn't isolate their databases for development (development and testing was performed on production databases), and they didn't do localhost testing. Apparently my “bad attitude” (about being lied to? being suckered in? having to work with such unprofessional standards as developing against production databases?) showed itself to be a “bad fit” and the “contract was cancelled”, even though I kicked butt, performing tasks in a fraction of the time planned, like replicating and fully testing CAPTCHA across 20 web sites in 3 hours (and spitting razzberries after I was done? .. no, not really, just popping my head in and saying “it’s done, my plate’s clean again”). To whatever extent I might have had an "attitude", it wasn't just regretting having to work again with antiquated technology (which I managed to convince myself to enjoy), it was also being tasked with work different from what was in the job description.

Truth be told, no one said anything about an "attitude". It was about "personality conflict". But honestly I think that my personality came out a lot differently because I *did* have an attitude. For the first time in my career, at my last two contracts I was forced to work no more than eight hours a day (even if I didn't invoice for extra hours), I *had* to leave the building at 5 and I wasn't allowed to come in early, I had no co-workers to discuss the work (only one fellow developer, and we never had anything to do with each other), and absolutely no inspiration from the employer to stay on top of current technology. It was lonely and would have been depressing; I was grateful for a paycheck, though, and I kept coming home saying how strange this is, that I am neither loving nor hating my job, as it is the most perfect and ideal environment for absolute complacency. But that honestly had me kicking and screaming inside. I'm a driven worker, and I tend not to be happy if I can't throw in an extra hour of discovery and a few minutes a day (even five would suffice) discussing projects and/or technology with a peer. And no, study at home wasn't much of an option anymore; I may be single with no kids, but this job was almost two hours' drive round trip, I'm NOT a morning person and the drive home in stop-and-go traffic every day wore me out.

This is a really awful economy to be back on the job hunt, as anyone who hasn’t been living in a cave knows. But being that now is within the first few hours of 2009, I guess I want to get an early start at initial attempts to pursue my 2009 New Year’s resolutions. I need a job.

Tags:


 

Powered by BlogEngine.NET 1.4.5.0
Theme by Mads Kristensen

About the author

Jon Davis (aka "stimpy77") has been a programmer, developer, and consultant for web and Windows software solutions professionally since 1997, with experience ranging from OS and hardware support to DHTML programming to IIS/ASP web apps to Java network programming to Visual Basic applications to C# desktop apps.
 
Software in all forms is also his sole hobby, whether playing PC games or tinkering with programming them. "I was playing Defender on the Commodore 64," he reminisces, "when I decided at the age of 12 or so that I want to be a computer programmer when I grow up."

Jon was previously employed as a senior .NET developer at a very well-known Internet services company whom you're more likely than not to have directly done business with. However, this blog and all of jondavis.net have no affiliation with, and are not representative of, his former employer in any way.

Contact Me 


Tag cloud

Calendar

<<  August 2020  >>
MoTuWeThFrSaSu
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456

View posts in large calendar

RecentPosts