Mr. Softwarepants

 
Python/Django/.NET/C#/Database project? Hire me.
25
Nov
2008

The problem with programming (in C#, in 2008)

(This likely also applies to Java, but as I haven't used it in a long time, I won't make any specific claims about it.)

In C# there is one way to create objects: the new operator.

Now, one sentence in and I'm already telling lies. new is only the "normal" way to create objects. You can also call Activator.CreateInstance or use reflection to get a constructor reference and invoke it.

So normally you'll use new and that immediately puts you at odds with "best practices" for developing C# software in 2008. Constructors are bad because they create dependencies, especially when they have lots of arguments that also need to be constructed (creating objects to send into other objects to get a final result is known as "wiring".)

So a ton of Dependency Injection libraries have sprung up, which act as "object factories", creating object graphs for you. These libraries typically use CreateInstance, reflection, or even dynamically generate and cache IL for object creation.

But isn't that a slap in the face? new is pretty fundamental to C# style "object oriented" languages, and yet using it is considered a "code smell" to be worked around.
29
Aug
2008
Bruce F. Webster: Tradeoffs on buy vs. build.

Since I'm a "seasoned developer", I don't have a problem with "buy" when it's the right way to go. We're using a 3rd party Windows control toolkit in our desktop app, for instance.

But these days the question may be better phased, "buy vs. build vs. use a free thing".

We're using Subversion for new source control, for instances, instead of TFS. TFS is a total "buy it" solution, and not particularly cheap for otherwise non-developers. Subversion is free and stable. And in our case, more flexible.
2
Mar
2008

Programming concepts

Every time I try reading about "Dependency Injection" and "Inversion of Control" (two related but separate concepts that are often conflated), I follow a predictable pattern:
* Ah, this makes sense
* Hmm, but why would I do it in this case
* Guh, those diagrams aren't making me care
* Christ, do you really need to use "logging" as your use case?

If I even get that far, by the end I'm all "whatever" and back to whatever I'm supposed to be working on.

The thing that changed on my most recent attempt is that I finally see those places in the project at work where a "cram some services in a container and get them out later" approach makes sense. Mostly because we're already doing that on an ad-hoc basis in at least a couple of places, and wouldn't it make sense formalize that, and use some code that's already been tested?

Of course there's the question of which container to use, but luckily "they're all pretty much the same."
18
Oct
2007
The response to "static typing sucks" is not "look into Haskell instead of using Java as an example." Because last time I checked, the IT world wasn't suffering from a case of too much Haskell.
22
Aug
2007

Tales of automation

Automating things is real work. It's not always just a matter of "putting the manual steps into a script" and running the script. To get this remote executing working properly, I also have to do up some infrastructure.

* I created a new NAnt project that has (A) a task that uses psexec against the build server to call the very same NAnt project using (B) another task that actually writes out the new BuildLabel.txt file.

* I checked the new .build file and psexec.exe into the build support area of source control.

This is the point where "infrastructure" comes into play. Those 2 files won't magically appear on the build server. And it's a bit of a pain to RDC in and use the TFS command-line tools to pull them down, but more importantly, I want any changes to this new script (and any additions to the /tools folder) to come down to the build server automatically.

This means adding a new CCnet project that watches the paths in question in source control, gets them when they change, and then do no actual tasks. The "get latest files" is all the work that needs to happen.

So I edited the master ccnet.config file to add the new project and checked it in. The cool part is that this file already has its own bootstrapping CCnet project; changes to the ccnet.config file are watched by a CCnet project that gets the new config and bounces the server. You have to be a little careful here, because bunging the config file means that CCnet doesn't start back up. Your subsequent edits to fix it won't come down automatically. But another cool part: I already thought of that, and there's already a .bat file in the folder with ccnet.config that tells TFS to do a manual get.

So... well, it seems a little baroque, but it really works, and it makes more sense if you see the files and folders and structure. And as a bonus, all the other non-version-controlled build tools can now be auto-updated by source control check-ins.

At some point I'll write up a "real article" on setting up CCnet bootstrap projects this way.
21
Aug
2007
Gojko Adzic: When windows are not enough.
So, in fact, she spent most of her time logging on to different computers and copying files between them. Although she understood the problem herself, the thought of automating those silly tasks never came to her mind.

I try to keep automation in mind, which is why I spent quite a bit of time at work Q1 going through our build processes. They were working, but there were rough edges, and I think they're a bit more understandable now. It's certainly easier to bootstrap a build server now, at any rate.

But hey, there's always room for improvement!

So with that in mind, tomorrow I'm going to look into using PsExec as part of the QA (or Production) build process. In order to kick off a QA or Production build, there's a text file in the appropriate folder that specifies which source control label to use. Right now you have to RDC to the build server, edit and save the appropriate file, and then you can punch "GO" on the right CCTray task.

I'd like to get out of the RDC game for this, so:
I'm going to add PsExec to the tools folder in source control, then write a nant task that calls it with the specified build label. (The build label usually isn't the most current nightly build, as the nightly build is at least one day ahead of the tested code.)
23
May
2007
Dan Manges: Well Named Methods.

One thing about programming that I realized a long time ago is that it's kind of like voodoo: the true name of a thing matters. Programmers spend a lot of time naming things, and just choosing names that make sense is progress in itself.
26
Apr
2006
Snippy

Snippy is a Greasemonkey script that generates a link to the page you're currently viewing using the page title and selected text. I've had it posted for a while, but this is the first "don't suck so much" release.

I use it here all the time; it's usually what's making those "Site name: Page Name Pull quote" formatted entries.

If you're interested in Greasemonkey coding at all, especially ones which add UI panels (like Snippy and The Movie Dude), there are Panel and Setting libraries hidding out in there. No dev docs for them, but that's coming soon.

When I get those libraries tightened up a bit I'm going to see about migrating The Movie Dude to them. Movie Dude came first, then Snippy, but while pulling code out of MD the libraritization occurred to me.
18
Apr
2006

Factor out the middle

So one of the standard Code Refactorings is Extract Method.

You have some code like:
function Fa(){
  a1 // A bunch of code
  a2 // More code
  a3 // Yet more code
}

function Fb(){
  b1 // A bunch of code
  b2 // More code
  b3 // Yet more code
}

You decide that the code "A2" does some useful self-contained bit of work, so you rewrite to:
function X2(){
  a2 // More code
}

function Fa(){
  a1   // A bunch of code
  X2() // Now a method call
  a3   // Yet more code
}

function Fb(){
  b1 // A bunch of code
  b2 // More code
  b3 // Yet more code
}

It's quite possible that other functions will turn out to have "a2" stuck in them, so you change them to call the new function as well. "a2" and "b2" were equivalent:
function X2(){
  a2 // More code
}

function Fa(){
  a1   // A bunch of code
  X2() // Now a method call
  a3   // Yet more code
}

function Fb(){
  b1   // A bunch of code
  X2() // Now a method call
  b3   // Yet more code
}

Oh boy, duplicate code removed!

Going back to the original two functions, what if "a2" and "b2" are the blocks of code that differ, while "a1"="b1" and "a3"="b3"? Then I guess by the book you factor out the 1s and 3s to two new functions, and end up with a total of four:
function X1(){
  a1 // A bunch of code
}

function X3(){
  a3 // Yet more code
}

function Fa(){
  X1()
  a2 // More code
  X3()
}

function Fb(){
  X1()
  b2 // More code
  X3()
}

But if you have a lot of functions that share X1 and X3, bracketing the "useful work" starts looking weird after a while. At least, to me.

So in pseudo-C# 2.0, with anonymous delegates, I've would rewrite the above to factor out the middle:
delegate void AnOperation();

function TryX(AnOperation operation){
  a1 // A bunch of code
  operation(); // refactored middle
  a3 // Yet more code
}

function Fa(){
  TryX(delegate{
    a2 // More code
  });
}

function Fb(){
  TryX(delegate{
    b2 // More code
  });
}

Is that any cleaner? I don't know yet. It's 3 methods instead of 4. And the delegate signature doesn't have to be empty; it could take parameters that are set up in "a1" and cleaned up in "a3", to enforce some common error handling.

This occurred to me after reading about Python 2.5's with statement; it's certainly not as elegant looking.
5
Jan
2006

Data modeling people names

Well factored objects, via Bill de hÓra

The link goes to a post discussing the complexity of capturing culture-indepedent human names in data models.

The punchline: capture a "display name" and a "sort key". (For normal US names the sort key is approximately "Last, First Middle", while the dipsplay is "First Middle Last". With titles and prefixes and suffixes, of course.)
21
Dec
2005

Windows Vista Task Dialog

IanG on Tap: Windows Vista Task Dialog

IanG is going through the December CTP of Windows Vista and writing about various new UX standards. (UX means "User Experience"; for whatever reason designers at Microsoft started using this term instead of UI for User Interface.)


The post above is about the new TaskDialog API, which seeks to eradicate the MessageBox. And about time, too.

On my previous project, I gave the old college try at doing a better Yes/No/Cancel dialog:


Not bad, if I do say so myself, but not great either. I based it on the XP-ish style "white header, grey body" look, which is just too busy most of the time. And the action buttons aren't as obviously tied to their descriptions as in the new TaskDialog look (though it's still much better than a hunk-a-text with a row-a-buttons underneath.)
28
Nov
2005

API design

IanG on Tap: C# 3.0 - Extension Methods

One of the new C# 3.0 language features is 'extension methods'. The basic idea is that the set of methods available on an instance of a particular type is open to extension. In effect, we can add new methods to existing types.

This is similar to Categories in Objective-C (and related concepts in Smalltalk), and the ability to add methods to prototypes in Javascript, and various other mechanisms in various other languages.

But the problem in comparing features across langauges is that similar things are always different, due to differences in the exact semantics of the rest of the language. Quick! What's an object? Answer: whatever heck your particular language spec says it is.

But I didn't write this to talk about any of the above; I want to comment on this:

Developers new to .NET tend to be surprised that calling ToUpper on a string doesn't convert it to upper case. And I think it's perfectly reasonably to be surprised. ToUpper looks like an imperative operation. Its form actively conceals the fact that it's really a function in the strict functional programming sense - it's has no side effects, it merely takes an input expression returns a result based on that input expression without modifying the input in any way. The input expression is the implicit this reference - the object on which ToUpper is invoked.

I think this form would have been more honest, and less likely to mislead:

String.ToUpper(input)

It's true that this would be more cumbersome, and would require more typing than what we've got today. But misleading code seems like a high price to pay for a little less typing - aren't we always being told that code will be read far more often than it is written? And even if you are convinced by the argument that a core class like String is sufficiently widely used that (a) it's worth the savings in this case because it affects everyone, and (b) everyone knows String so it doesn't matter that it's a special case, it still seems like the wrong thing to do in the general case.

Holy heck GOSH what a bad idea. Cumbersomeness matters, even with IDEs and autocomplete and IntelliSense and what have you.

What language are these programmers coming from that this construct is confusing? I suspect the answer lies here: UCase Function (Visual Basic).

I suppose it helps to have used langauges before where (1) strings are immutable and (2) method call notation is the norm rather than the exception.

14
Nov
2005

C#: Join an array of strings

The built-in method String.Join() let's you join an array of strings with a delimiter. Except that it only lets you join an array of strings. string[]. This is an example of inhumane API design, as it requires gross incantations to get an ArrayList of strings joined.

Here's my method to join together an ICollection of any type of object, which are rendered to strings via ToString().

public static string Concat(ICollection items, string delimiter)
{
  bool first = true;

  StringBuilder sb = new StringBuilder();
  foreach(object item in items)
  {
    if (item == null)
      continue;

    if (!first)
    {
      sb.Append(delimiter);
    }
    else
    {
      first = false;
    }
    sb.Append(item);
  }
  return sb.ToString();
}

Stick this static method wherever you keep your other string utility functions.

11
Nov
2005

Explicit Interfaces in C#

C# lets a class implement an interface in two ways: the normal way, and "explicitly".

Explicit interfaces exist in the language so that a class can implement two separate interfaces even if both interfaces have a method with the same name.

Because of the "same name" issue, you can't call explicitly implemented methods directly on the class; you have to cast the class to the interface first. The manifests in the IDE in IntelliSense as explicitly implemented methods not showing up in the auto-complete list.

The C# langauge has array classes, like "string[]" and "MyClass[]". Behind the scenes these inherit from the .NET array class "Array". Array implements IList, but does so explicitly.

I hadn't made the mental connection until now, so I had been testing membership in an array such as:
string[] things = new string[]{"abc", "def", "ghi", "jkl"};

with code like:
bool found = -1 < Array.IndexOf(things, "abc");

Turns out this works too:
bool found = ((IList)things).Contains("abc");

Too bad it's also ugly, but at least that "-1" isn't hanging around.
8
Oct
2005

More of a guideline than a rule, really

I was going to post about how I wrote the must terrible C# event routing code ever at work Thursday afternoon.

I defined an interface INewContent, which has a single member "event NewContentHandler NewContent".

By implementing this interface, a class signals that it will be providing new content that it wants some control up the chain to process. There are only two ways to process content: display it or pass it on up the chain.

Now, the .NET class library guidelines say to (and the .NET framework does) implement a protected virtual method "OnMyEvenet(MyEventArgs e)" for every public event with signature "MyEventHandler(object sender, MyEventArgs e)".

The deal is, subclasses can override this method to do special case event raising. This is sometimes better than a class listening to its own events, as you can gaurantee the order in which your handling happens in relation to any other objects that have hooked the event.

Now, all the classes I have that implement INewContent had an OnNewContent, usually defined in a common base class. In most cases, I want an object that is listening to other objects' NewContent events to reraise the event as their own NewContent event.

The problem is, the event signature has an "object sender" parameter, but the event raising method doesn't (almost always, the event raising method sets itself as the sender.)

So I came up with some rigamarole in a static utility class to translate between the two kinds of methods.

Then the next morning I realized that I had been a slave to orthodoxy.

I took out OnNewContent(MyEventArgs e) from the base class and replaced it with HandleNewContent(object sender, MyEventArgs e).

Now when an object A listens to content from object B, it hooks the object B's NewContent event to its own HandleNewContent, which by default just reraises the event for whoever is listening to object A.

Still wonky, but much less so than having a separate static class that does event routing.

The moral of the story is, know when to ignore the guidelines.
6
Oct
2005

Using Back/Forward mouse buttons in .NET

The Code Project: Using Hooks from C#.

Sample code that shows how to process the Back and Forward mouse buttons in a .NET application, using the "Local Windows Hook." Also includes an IComponent that wraps up the hook and translates Windows Messages into useful .NET events.

It's all rather more complicated than it seems it ought to be, considering how long five button mice have been around now.
19
Sep
2005

Now that RSS is "pervasive..."

Seems that Microsoft is embracing RSS feeds in a big way in its new projects, though it remains to be seen what that actually means.

As a developer, here's what I want from Visual Studio v.Something and Team Foundation Server:
* Subscribable personalized "My Bugs" feeds out of whatever TF's task tracking system is.
* Subscribable "latest check-ins" feeds out of whatever TF's source control system is.
* RSS feed subscriptions from within Visual Studio, tied to Solutions.

The subscriptions would be shown in an add-in pane. And throw an icon in the statusbar when there's new stuff to look at.

The final piece of that puzzle is turning off email notifications for those things.

Email notification on bug changes sounds like a good idea, vs. people forgetting to check their bugs regularly in the client, but using feeds is much better. It's less of a zone-breaker.

HowTo: Mark an event as "NonSerialized" in C#

This may be common knowledge, but took far too long to figure out (as nothing helpful came up on a Google search.)

When using object serialization in .NET, the default serialization behavior is to serialize event handlers (and the objects which are listening) which leads to a couple of problems.

1) You're serializing out a larger object graph than you potentially need, since (in our case) we don't want events on the other side of the wire, just the object data.

2) Chances are the objects handling events aren't serializable, or have members which aren't serializable.

You can't mark a public Event as [NonSerialized] because there's some compiler magic going on behind the scenes, but you can mark a private Event, and provide a public event with add/remove accessors:

[NonSerialized]
private EventHandler myEvent;
public event EventHandler MyEvent
{
	add { myEvent+= value; }
	remove { myEvent-= value; }
}
Gross and non-obvious; the compiler should be smart enough to do this for you, but I guess I'll just have to see what C# 2.0 lets you do.
9
Sep
2005
SQL Server 2005 Books Online: Transact-SQL Reserved Keywords
Use a naming convention that avoids using reserved keywords. Consonants or vowels can be removed if an object name must resemble a reserved keyword. For example, a procedure named bckup that performs BACKUP statements for all user-defined databases.
Yeah, that's a great idea.

Yes, yes, having the source is good.

Debugging WinForms that use validation or databinding is hard.

The framework handles validation events and databinding behind or back, as it were, and when something goes wrong inside the methods you genreally end up with an exception in "non-user code" with the cursor pointing to your Application.Run() method in your main function.

Not the most helpful place to be when debugging. If .NET shipped with the full source to itself, at least you could see a useful stack-trace that was inside some internal DoValidation() method or somesuch.

I suppose it's possible to set up debug symbols, so I should check if that is a remote possibility at all. After all, we have these MSDN Hella Platinum subscriptions. Might as well use them.

(A long time ago, I was getting paid to use the TurboVision framework, which at the time shipped with Borland's C++ compiler with full source. It was also unsupported by that time. I actually did find a bug deep inside the valdation code, where they were setting a field to null instead of going through the ClearSomething method.)
Back
 
View my:
Reads
Links
Photos
Website
LinkedIn
Last.fm
GM scripts
Twits
Google Code
GitHub
Wiki

Back

The Piehead News
(C) 2003-2008
Adam Vandenberg