Welcome to DevAuthority.Com Sign in | Join | Help

A lot of people have been asking where I get my architectural insight, how I formulate my designs, and ultimately, how I put projects together. There are a lot of other “manifestos” being tossed about in the wild, so I figured I’d toss my own out there to start to answer the questions. To me, this is the foundation of everything that comes next.

First and foremost, this is an engineering field. As such, decisions are made using engineering principals. Anecdotal “evidence”, as it is, does not factor other than to stimulate hypothesis. Something is never “better” because I think it is; it is “better” because it is measurably superior.

I will always be able to clearly articulate the reasons for a decisions. If I cannot do so, the decision is suspect and cannot be considered defensible. “Because that’s just how it is”, or “That’s just the way we do it here”, or “I just want it that way” is never an answer. There will be clearly stated implications, causes and effects.

The decisions must always have the capability to be expressed in terms of quantitatively and qualitatively measurable metrics. One should always be able to assess Return on Investment and Risk of Investment for any given decision. This allows for alternatives based on what the stakeholders are willing to trade off, and helps to eliminate biased decisions made solely for the purpose of personal preference.

Methodologies are projects too. They are not religions. One should never blindly follow a methodology’s prescriptions “just because that’s how it is”. Methodologies that insist they are a “better way” if you just “trust them” are suspect from the start. Methodologies, just like projects, will have periodic post-mortem assessments. Any part of a methodology that works will be used and improved upon. Any part that does not work will be given equal consideration, and will be thrown out or re-implemented. If re-implementation is necessary, there must be a clear review of why it didn’t work, and a clear identification of the failures, with a clear plan of action that corrects the failures. “It didn’t work because you don’t grok it” is never acceptable. An unbiased review is always necessary. Putting a positive spin on something that sometimes works and sometimes doesn’t because I prefer to do it that way will not make it better, and is never acceptable.

Professionalism will be used at all times. Criticism will always be welcome, but criticism will never be personal. Meltdowns, impatience, and caustic reactions will never be acceptable. I will never blame others to escape my own problems or because I am frustrated or under stress. I will always take the blame on issues for which I am responsible, and I will take steps to ensure I will not repeat those problems. I will always be cognizant that meltdowns or panic on my part will have ripple effects on the team, and are things to be avoided. Conversely, leadership, understanding, patience, and proactive problem-solving will have positive ripple effects on the team. In any type of failure, the immediate action should be to quickly identify and correct the problem, not to invoke blame. Invoking blame is itself a failure.

I will always conduct self-criticism of my decisions. I will never assume them to be correct. I will force myself to prove they are valid.

I will never take the “easy way” because it suits me personally. The decisions must always be accepted as the better option for the team and for the project.

I will accept team members, not minions. I do not want a crowd of groupies who always agree with me. I am not always right. Dissension and alternate viewpoints are not only always tolerated, but welcome provided they are conducted in a professional manner. Yes-men only lead to “group think”, which drastically raises the risk of failure due to suboptimal decisions and incorrect assertions that are never challenged. You are not automatically wrong because you disagree with me.

Disagreements must not hinder the project. In all cases, one should strive for unbiased decisions, because in an optimal situation, disagreements can then be factually discussed and worked out. However, there will always be cases where more than one decision may apply, and where two or more team members disagree on which to take. Team members, myself included, must always be cognizant of the impact an impasse makes on the project, and must work as quickly as possible to choose one of the decisions, compromise, or come to an agreement.

I will always be cognizant that professional pride and project success is at stake for every line of code I write.

Enter CNG, stage left.

In the last epside of this problem, I described how admins can now prevent non-FIPS-compliant crypto code from running, which has the unfortunate side effect of killing ClickOnce deployments since ClickOnce uses .NET hash algorithms that are not FIPS certified.

In the next version of the .NET framework, Microsoft will release built-in support for CNG (Crypto NextGen). CNG supports a very cool new model of exposing cryptographic functionality (compared to the old Win32 Crypto API). Additionally, CNG supports some really nice new algorithms like Elliptical Curve Asymmetric algorithms. But most importantly, CNG is FIPS level 2 certified. The existing .NET algorithms are not FIPS certified at all (and as far as I can tell won't be in the next version either), and any of the wrappers for unmanaged algorithms depend on the underlying unmanaged library being certified. This should allow your .NET code to run on systems where admins turned off non-FIPS-compliant code.

The bigger question is whether or not this fixes ClickOnce. In theory, it could, but it's something I haven't explicitly tried yet. I will post once I figure that part out.

One of the nice features of VSTS is data-driven testing. It’s as easy as hooking up a couple of attributes to the test classes, which then allows tests to be run for multiple sets of input data. The problem is when you want to include data with the test project.

The first thing that came to mind was SQLExpress. It’s free and it allows you to use MDF SQL Server files included in the project, which can be dynamically attached as needed. Unfortunately, there are a number of issues with this approach. The primary two are that you can’t reliably use relative paths or path substitutions without major workarounds, and the way SQLExpress manages users in the database file (primarily when you distribute the file/project to multiple machines with different users). Believe me when I say this option is more trouble than it’s worth. So what then? Use Excel or Access files? Excel has some nasty issues including size of data and data formatting problems (actually, the way the Excel OLEDB provider attempts to identify data types on columns). MDB files work, but can be a bit on the heavy side. More importantly, I’d like to stick to SQL Server syntax and features.


The answer came to me as a new product on the desktop – SQLce. SQL Server Compact Edition 2005 was recently released as a small light-weight file-based database based on SQL Server, which is now available on the desktop (not just mobile devices anymore).


Installation


First thing you need to do is download and install SQLce. You’ll need three components – the database runtime files, the software development kit (for the docs primarily), and the Visual Studio tools.


(runtime) http://www.microsoft.com/downloads/details.aspx?FamilyID=85e0c3ce-3fa1-453a-8ce9-af6ca20946c3&DisplayLang=en


(SDK) http://www.microsoft.com/downloads/details.aspx?familyid=E9AA3F8D-363D-49F3-AE89-64E1D149E09B&displaylang=en


(VS tools with SP1) http://www.microsoft.com/downloads/details.aspx?familyid=877C0ADC-0347-4A47-B842-58FB71D159AC&displaylang=en


If I remember correctly, you’ll have to poke around in the SDK directory to find another installer for the documentation.

Database Creation


SQLce databases are completely self-contained in an SDF file. You can use Server Explorer in VS2005 or SQL Management Studio to create the databases. Unfortunately, there’s no "Add SQLce File" in the VS "Add New Item" dialog, though you could add a template script yourself.


If you decide to use VS2005 Server Explorer, open your test project, and then in Server Explorer, click "Connect to Database".


Change the Data Source to "Microsoft SQL Server 2005 Compact Edition".


Click on the "Create..." button and select your project directory (or sub-directory thereof).


If you don’t include security-sensitive data, there’s no need for a password, and your testing teammates will thank you for not including one :-)


Make sure to change the name of the database file, since by default it’ll be something like "MyDatabase#1.sdf".


Right-click on the project in Project Explorer and select "Add->Existing Item". Select the SDF file you just created. This will include the database in your project.


Adding Tables and Data


Go back to server explorer and expand the entry for your SDF file. Right-click on "Tables" and select "Create Table". You’ll see a somewhat familiar dialog for creating tables.


When you’re done creating the necessary table(s), go back to Server Explorer and right-click on the new table entry, then select "Open". You’ll see a datagrid where you can enter and edit row values.


Wiring Up the Test DataSource(s)


For Unit Tests:
Go to the test method containing the TestMethod attribute.


Because of how the test software deploys the individual test runs, you’ll have to deploy the SDF file as well. Add the DeploymentItem attribute to your test method and specify the SDF file. You can also tweak the output directory on the DeploymentItem attribute if you really feel inclined to do so.


Now you need to also add the DataSource attribute to your test method. It should look as follows:


[DataSource("System.Data.OleDb", @"Provider=Microsoft.SQLSERVER.MOBILE.OLEDB.3.0;Data Source=YourDB.sdf;", "YourTestTableName", DataAccessMethod.Sequential)]


Note that the data source is a path to the file itself, but it can be a relative path, unlike SQLExpress MDF attached files.


For Web Tests:
Create a web test as usual and generate the code. Add a DataSource and your attribute should look like:


[DataSource("YourDataSourceName", "Provider=Microsoft.SQLSERVER.MOBILE.OLEDB.3.0;Data Source=YourDB.sdf;", DataBindingAccessMethod.Sequential, "YourTestTableName"]


Now, there are a few caveats with SQLce. First, your data file is limited to 4GB. That shouldn’t be a problem for most unit tests (one would hope!). Also, the SQLce doesn’t support stored procs (yet). This is the first desktop version but this limitation will be addressed soon from what I hear. You can use pretty standard dynamic T-SQL though. The testing framework simply selects the data from the specified table, so having no stored-procs doesn’t impact the unit or web tests. That’s just something you’ll have to think about should you use the database file for other purposes.


Enjoy.

This week I've been inundated under another slew of pattern mumbo-jumbo, so it got me thinking about a long trail of recent issues. This time it's all about MVC and more recently MVP (model-view-controller and model-view-presenter). It's another one of those acronyms you see popping up everywhere. I remember a big emergence of MVC talk around 2000 or 2001, and I remember thinking "why are we going backwards?", because that's how I viewed MVC at the time. Martin Fowler wrote a pretty extensive and insightful history of MVC since then that basically confirms what I was thinking. I remember a post I made back around that time which explained MVC in simple terms and then said in short, "it's a bit of a workaround for SmallTalk-GUI-isms", which, while oversimplified, does get to the heart of the matter. Back in the day, control and widget libraries weren't the norm, so you had to find an (preferably) OOP way of putting data into a view (which could be either graphical or (and) console-based). The controller simply told the view what and how to observe on the model, but it was conceptually and physically more on the "control" level than the "screen" level – and that's really nothing like what most people want when they talk about MVC being so great today.

Apparently, people began to see the picture because you hardly hear about MVC today. Now everyone talks about MVP. However, architecturally speaking, the most important concept with regards to this topic is the notion of separation of presentation, not MVC or MVP. That is to say, you should have a model that represents the data and likely has some business rules attached to it. That object graph representing the model should be separated from the physical UI, most importantly so you can have multiple views showing the same data, and maintain a central location for that data and its associated behaviors. Otherwise, you're stuck having to implement that in each view and then having to coordinate the views – a complete disaster waiting to happen.

Getting back to MVP, it superseded MVC in order to overcome some natural shortcomings of MVC over time as technology progressed. The notion of MVP is that a view was now a standard conglomerate of widgets or controls. The view observed the model though observer synchronization and the view elements (controls/widgets) had the capability of giving out notifications when a user interacted with them. However, these notifications didn't trigger significant code – they were consumed by the presenter, which in turn updated the model as appropriate. The view then resynchronized itself through its existing observance of the model.

So now everyone talks about MVP… but still unaware that it's also a step backwards. Fowler himself wrote this retirement note on MVP (which is well worth the read). Now, he proposes a split into Passive View and Supervising Controller, with several flavors based on how much power the presenter/controller has over the model and how much it interacts with the view itself (with notes about databinding). Again, the important lesson is Separation of Presentation rather than some other buzz-acronym.

I'm about to release a new set of tools and a collegue of mine who was testing it asked how you can localize some of the PropertyGrid aspects. I'm using the PropertyGrid not really because it's a cool interface (in fact, it has less than spectacular user-experience value), but it's easily accessable and fairly universal with regards to development tools and particularly Visual Studio. Moreover, the tools I'm working on will at some point be a VS add-in suite. Getting back to the point, PropertyGrid uses a number of attributes (mostly defined in System.ComponentModel) to drive parts of its display for any given SelectedObject. By applying these properties to the class that will eventually be diplayed in the PropertyGrid, you can drive things like the help text display. The help text display is shown for any given property. You use the DescriptionAttribute on the property to provide the text. Unfortunately, the DescriptionAttribute isn't localizable out-of-the-box. That means whatever text you hard code, is what will show up in the PropertyGrid regardless of the UI culture settings. As it turns out, localizing DescriptionAttribute isn't hard at all - you just have to provide a new class that inherits from DescriptionAttribute and do a little resource manipulation:

using System;

using System.ComponentModel;

using System.Resources;

 

namespace DevPrime.Design

{

    /// <summary>

    ///    Specifies a localized description

    ///    for a property or event.

    /// </summary>

    /// <remarks>

    ///    Unlike the DescriptionAttribute class

    ///    , the Description property of

    ///    ResourceDescriptionAttribute returns

    ///    a description that is set in a

    ///    resource, which can be localized.

    /// </remarks>

    [AttributeUsage(AttributeTargets.All,

        Inherited = true, AllowMultiple = false)]

    public class ResourceDescriptionAttribute

        : DescriptionAttribute

    {

        private Type resourceSourceValue;

        private string descriptionResourceNameValue;

 

        /// <summary>

        ///    Initializes an instance of the

        ///    ResourceDescriptionAttribute class.

        /// </summary>

        /// <param name="descriptionResourceName">

        ///    The name of the resource string

        ///    to use as the description.

        /// </param>

        public ResourceDescriptionAttribute(

            string descriptionResourceName)

        {

            descriptionResourceNameValue

                = descriptionResourceName;

        }

 

        /// <summary>

        ///    Initializes an instance of the

        ///    ResourceDescriptionAttribute class.

        /// </summary>

        /// <param name="descriptionResourceName">

        ///    The name of the resource string to

        ///    use as the description.

        /// </param>

        /// <param name="resourceSource">

        ///    The Type used to initialize the

        ///    ResourceManager for this instance.

        /// </param>

        public ResourceDescriptionAttribute(

            string descriptionResourceName,

            Type resourceSource)

        {

            descriptionResourceNameValue

                = descriptionResourceName;

            resourceSourceValue = resourceSource;

        }

 

        /// <summary>

        ///    Returns the name of the resource

        ///    string to use as the description.

        /// </summary>

        public string DescriptionResourceName

        {

            get { return descriptionResourceNameValue; }

        }

 

        /// <summary>

        ///    Specifies the Type used to initialize

        ///    the ResourceManager for this instance.

        /// </summary>

        /// <remarks>

        ///    The ResourceManager initialized here

        ///    will read the resource inferred by

        ///    the provided type. For example, if

        ///    you provide the type MyNamespace.MyType,

        ///    the ResourceManager will infer the

        ///    assembly of that type and read the

        ///    resource called

        ///    MyNamespace.MyType.[culture-name.]resources.

        /// </remarks>

        public Type ResourceSource

        {

            get { return resourceSourceValue; }

            set { resourceSourceValue = value; }

        }

 

        /// <summary>

        ///    Returns a localized description

        ///    based on the DescriptionResourceName

        ///    provided in the constructor.

        /// </summary>

        public override string Description

        {

            get

            {

                if (string.IsNullOrEmpty(DescriptionValue))

                {

                    ResourceManager resMgr =

                        (resourceSourceValue == null ?

                        Properties.Resources.ResourceManager :

                        new ResourceManager(resourceSourceValue));

                    base.DescriptionValue

                        = resMgr.GetString(

                            descriptionResourceNameValue);

                }

                return base.DescriptionValue;

            }

        }

    }

}

Note that if you don't specify a ResourceSource type, the code here assumes a resource in the assembly where this code is defined. This works only if you have resouces definied in your project properties.

Enjoy.

Normally, I try to keep this blog all about technical issues, but Jay Kimble tagged me, so here goes...

5 Things You Don't Know About Me

* I play guitar and pretend to play keyboard. And just because every other developer does progressive rock, I'll just say that I'm into classical guitar, blues, and Cuban jazz.
* I'm one of those pesky history buffs that actually thinks that stuff old dead people did a long time ago is interesting.
* I entered my first Taekwondo tournament in 1990...
* and won a medal (yeah, I split that one, but I need 5 things and I'm tired)
* I sketch and paint for relaxation.

Now to find some tagging victi... er, friends...

For anyone in the area, I'll be giving a presentation to the SoCal .NET user group on security and cryptography goodies in .NET 2005. The presentation will be on Nov. 1st and will include samples on CD for anyone who wants (while supplies last!).

Hope to see you there!

More info here: http://socaldotnet.org/

So I was in the middle of a build for a rather massive solution in VS2005 when the power went out (the client site doesn't use UPS in the particular building I was in...). Rebooted PC and every time I tried to compile, I'd get the following error:

error MSB3541: Files has invalid value

In addition to being grammatically challenged, the error message doesn't actually help you track down the real problem. One nice thing about MSBuild is the volumes of info you get if you run it in diagnostic mode (Tools->Options->Projects and Solutions->Build and Run : MSBuild output verbosity = Diagnostic). But even that proved somewhat less than useful this time around, although I was able to track down which project it was crashing on. Turns out that MSBuild writes a file list of files that are processed (called <projectname>.FileList.txt in the obj folder), and that file was in the middle of a write when the power went down. Deleted said file, and all is right with the world again.

Don't get me wrong, that's not the only reason for MSB3541 popping up, but since the error message doesn't actually say anything useful, I thought I'd toss this out there as another thing to check before you toss the PC out the window.

If you've worked in a security-conscious government environment, then chances are that you've encountered FIPS (Federal Information Processing Standards). The new 2.0 CLR has a built-in switch that regulates the usage of cryptographic code. The switch can be turned on by an administrator to prevent non-FIPS-compliant cryptographic code from running. Unfortunately, that means ClickOnce too. ClickOnce uses some hash implementations provided by the .NET framework, and these are not FIPS certified. Therefore ClickOnce will fail on any system with these restrictions.

I've been communicating with some internal MS people about the issue, and I've finally gotten the "official" word. It's a known issue and it's been queued for fix (one would hope around the Orcas release time frame, but that's not certain at this point). However, they did state that prioritization for the fix can be bumped up significantly if people post a bug on MSDN and vote. You can do that here: https://connect.microsoft.com/default.aspx

MS just announced two new versions of the .NET framework, and everyone I've talked to is completely confused by what that means. In fact, just about all the MVPs I talked to were similarly confused, so luckily, we got a little clarification. Here is the breakdown as I understand it now:

FX Version Ships with Includes CLR Version
2.0 VS 2005 (uses VB 8, C# 2) What you have today 2.0
3.0 Windows Vista (uses VS2005, VB 8, C# 2) Framework 2.0 + WCF, WPF, WF 2.0
3.5 VS "Orcas" (uses VB 9, C# 3) Framework 2.0 + WCF, WPF, WF + LINQ 2.0

So basically, FX 3.0 will ship with Vista and simply adds WCF (communication foundation/indigo), WPF (presentation foundation/avalon), and WF (workflow). All these components are written using Framework 2.0 and use the CLR 2.0.

FX 3.5 will ship with the next version of Visual Studio, and will (for the most part) add LINQ. It is also uses CLR 2.0.

The confusing part is that unlike 1.0 -> 1.1 -> 2.0, these two new framework versions don't actually change the framework, and the runtime is exactly the same. The team is simply adding new features to the existing framework. And that's perhaps the biggest point of confusion, because in my mind (and the minds of many others), this doesn't warrant a new major version number... made more confusing by the fact that the underlying runtime will continue to be 2.0. If anything, these new versions should be 2.1 and 2.2.

Anyway, hope this helps.

So it seems like all I see as I look around lately is a slew of material about Inversion of Control and (it's more specialized child) Dependancy Injection. You'd think this latest craze was the year's biggest discovery, and somewhere up there with sliced bread (although I have yet to see what makes sliced bread so important... more imporant than, say, the vaccine for polio). In reality, they're just fancy words for patterns called compound patterns. They are nothing more than specialized and formal groupings of more base patterns (factories, builders, adaptors, strategies, etc.), but no less important for a number of reasons. For lack of a simpler term, you can generally think of this as "plug-ins". The end result is that you get blobs of code that are interchangeable and allow a core controller blob of code (which we'll call a framework) to be extensible (particularly after it's released, without recompiling it). We've all seen plug-ins before in tons of software, and even the base Windows OS relies heavily on plug-ins, from device drivers to security libraries (although the physical mechanics of a C PE library export function differs a bit from an OOP-style interface binding, the results are very much the same).

So I'm very much in agreement with Martin Fowler (the guy who is probably the most responsible for coining the term), when he says, "When these containers talk about how they are so useful because they implement Inversion of Control I end up very puzzled. Inversion of control is a common characteristic of frameworks, so saying that these lightweight containers are special because they use inversion of control is like saying my car is special because it has wheels."

All this got me thinking about a more fundamental problem - most modern software is (or rather, should be) molded around some type of framework. Complex systems without frameworks are very difficult to maintain and expand. Complex systems with poorly implmeneted and/or poorly designed frameworks are just as difficult to maintain and expand. And I think that's really the main root problem. As I look back at my teaching stint at USF, I realize that not a single student that went through my programming classes was ever taught the fundamentals of designing and implementing frameworks in the four years they were there. There was no such thing as a "Fundamentals of Frameworks" course. That also explains the seemingly random way people are re-inventing APIs with services.

Sick and tired of the new VS web-site project model? Wish you could get back to the VS2003 web-application model? Well, here it is, complete with Edit-and-Continue debugging: http://weblogs.asp.net/scottgu/archive/2006/05/08/445742.aspx
Well, the blog has certainly been quiet lately. For those of you who don't know me personally, I recently moved cross-country and right into a hectic schedule. And speaking of schedules, I also recently stumbled into something everyone in this field should get their hands on. Some authors (very few as far as I'm concerned) have a consistent record of putting out extraordinary material - like the Pixars of the software book industry. Steve McConnell is one of those guys. There's one thing that CS degree never prepared you for: telling the project stakeholders just how long the project was going to take (and getting that number right). Lots of people have written about project estimation, and most of them, behind the covers, are just guessing (like most developers and managers) and making money off BS arithematic/methedology tricks. Others are just shamelessly pushing methodologies and tools (and speaking gigs) like a street-corner dealer selling crack to the distraught masses. Steve McConnell's new book Software Estimation: Demystifying the Black Art is what they should all have written instead. If you have ever thought to yourself "there's got to be a better way" everytime you give out another project estimate, you need to read this book.

OK, I was doing a security sweep today and found this little gem of an error in two MS' KB articles. The article is about How to Encrypt a File (in both VB and C#), and can be found here: http://support.microsoft.com/default.aspx?scid=kb;EN-US;q301070 (VB) and http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q307010 (C#).

The problem is with the API function ZeroMemory (RtlZeroMemory). This function does just what it sounds like: it takes a chunk of memory and puts zeros in it. The purpose for this is to make sure that sensitive data (like passwords) are only in memory as long as necessary and don't ever get written to the swap file. It takes two parameters: a pointer to the data, and the number of bytes to zero out (starting at that pointer). Typically, strings are supposed to be immutible in .NET, which means that having their contents changed by an API function is taboo. This is the one exception to that rule, where it is in fact necessary. The problem is with the RtlZeroMemory P/Invoke signature at the top of the article. The one in VB is wrong and the one is C# is WORSE :-)

Let's see what's going on in the VB case first. The API function needs a pointer to data. So we're passing a ByVal String. So far so good, because passing a reference type by value passes a pointer (reference) to the data. Here's a quick and dirty illustration - assume we have the following variable defined: Dim X As String = "Hello". Here's what it looks like in memory:

[ x (pointer)] -----------------> ['H'][\0]['E'][\0]['L'][\0]['L'][\0]['O'][\0]

The variable X is just a pointer to a character array (unicode characters in .NET, thus the \0 byte after each letter), so passing X by value passes the pointer value to the API function, which is exactly what we need. Still doing well so far. However, the article doesn't take Interop marshalling defaults into account. By default, P/Invoke assumes that export DLL functions want ANSI strings. So when you pass a string the way the article defines the function, P/Invoke copies the string, but makes the copy ANSI instead of Unicode, then passes a pointer to that ANSI copy instead of the original reference. Because .NET strings are supposed to be immutable, P/Invoke does not copy the results back into the original string. So, the end result is this function zeros out a copy of the string, and the original string (which contains some sensitive data like a password) is still in plain text!!

However, if we tell P/Invoke to send a Unicode string to the API function, then P/Invoke decides that (as an optimization), the string is already Unicode in memory, so it just sends the original reference (X). This will give us the desired result. In order to fix the function definition, we have to write the following:

Private Declare Function ZeroMemory Lib "Kernel32.dll" Alias "RtlZeroMemory" (<MarshalAs(UnmanagedType.LPWStr)> ByVal Destination As String, ByVal Length As Integer) As Boolean

LPWStr means Long-Pointer to Wide String (unicode). Making this change now gives us something that works as desired.

Now let's look at the C# version. It makes the function declaration as follows:

[DllImport("kernel32.dll", EntryPoint="RtlZeroMemory")]
private static extern bool ZeroMemory (ref string destination, int length);

Again, C# is missing the MarshalAs attribute to tell P/Invoke that the destination parameter needs to be sent as a Unicode string. Additionally, this version of the declaration is passing the string by reference! Here's what it's passing:

[parameter reference (pointer)] ----> [X (pointer)] --------> ['H'][\0]['E'][\0]['L'][\0]['L'][\0]['O'][\0]

As you can see, we're now passing a pointer to a pointer to the data. This is horribly wrong. Now the function will wipe the pointer value at X (AND anything next to it, up to the number of bytes specified, thus corrupting memory!!!) and still leave the original string data in memory in plain text. You must remove the "ref" keyword and add the [MarshalAs(UnmanagedType.LPWStr)] attribute to the parameter to fix it.

And here's the ironic part - the article never uses this function! Instead, it redefines the API declaration later in the article to handle arrays. However, anyone looking at how to write the function for strings and stumbles across this article is in for a lot of trouble :-(

Wow, it's been a while since my last post, but to say that work has kept me busy would be the understatement of the year. I just got out of a presentation and for the first time in a while I feel like I can take a small breather. Anyway, here's something interesting I ran into this morning -

If you want to see someone's head explode in a spectacular gush of overpressurized blood, mention the words "design documentation" in the presence of an Agile developer. It's messy (and often loud), but a sure-fire kick (if you're a little sadistic). Before anyone's head really does explode, no, this isn't an anti-Agile post, trust me :-) Now, those of you who know me, know that I've spent years not only on methodology, but actually creating methodology tools. You (the same people) also know that I don't think highly of most methodolgies out there: not because they're worthless, but because they're more religious ritual than pragmatic and useful tool. In some sense, methodologies weren't really invented to make development easier or better, but as a reliable way to throw a couple of knowledgeable people and a small army of dimwits at a project and still end up with reasonable (or least reproduceable) results... or a lot of C.Y.A. paperwork in case of a failure. The backlash to this mountain of paperwork and useless rituals is a slew of new Agile methodologies, all claiming to be a more pragmatic approach to design and development. I happen to think they got a lot of things right, but there's still a lot of religious deadweight ritualization and evangelizing in the Agile community. Personally, I have to view things in a goal-oriented approach, and trust that reason can establish a set of necessary steps to acheive those goals. All this hard-core positioning in one camp or another just wreaks of another cult-based mentality I don't want to deal with. As Mark Twain once said, "Loyalty to petrified opinion never yet broke a chain or freed a human soul." If you believe you've found the ONE way, and that ONE way is superior to everything else, and no other way is worth looking at, congratulations on finding a new religion but you've already lost the battle on the reason front. The Agile approaches do solve a number of nuisances, and work particularly well in the realm of user interfaces, which change as often as the developers refill coffee mugs. They don't work so well with APIs, which need to be designed thoroughly enough to work with clients that don't even exist yet, and cannot, after being put into production, be refactored every time someone sneezes, since that would immediately break everything depending on them. In fact, the very definition of a good API would demolish everything Agile stands for, starting with "don't design what you don't need right now, to solve this one particular problem." The concept of reuse gets very tricky with Agile, despite the fact that most Agile methodologies preach sound practices and patterns, including "avoid coding something more than once."

In a sense, design and development approaches need to be tailored to the environment, the technology, and the team. A change in any one of these factors could render large parts of most methodologies useless. From my experience, there is no one-size-fits-all solution, and the greatest benefit any project can get is good experience leading it. Through experience, people use an observational process to refine what works and what doesn't - patterns by any other name. Methodologies then, are basically attempts to formalize experience and persist it to paper, but unless that experience covers the programming field in general, it's only going to apply to specific cases. The more specialized the methodology, the worse it's going to work in a realistic environment elsewhere. The more generic it is, the more accepted and widely used it can become, but it won't solve as many specific problems.

OK, so after all that rambling, we come full circle back to design docs. Design documents and/or specifications ARE important. You can't just say the code is self-documenting. Reviewing code and even code comments later is like forensic evidence. You may be able to tell what the code is doing, but not WHY someone decided to write it that way. Even tests provide the same limited forensic, post-mortem evidence. I don't mean that to be a blow against tests, because unit testing is one of the most underappreciated and important tools in development. Anything that gets developers to unit test more (including TDD) is a BEAUTIFUL thing. The question then is how do we get design documentation that people can refer to in the future when enhancements and fixes need to be made. More importantly, how do we get it without all the deadweight rituals in traditional waterfall methodologies? Even Agile stories and quickie scibble-diagrams can become woefully inadequate after the first few weeks, when people's brains begin to loose the details.

My suggestion? Video tape (digital if you got it!). Forget long complicated documents. Forget scribbles and shorthand that nobody will understand eight weeks from now, or when the original writer gets run over by a bus. Get all the stakeholders together and have them discuss the problems and the goals, and have the devs subsequently discuss a roadmap for the solution. This always happens to some degree no matter what methodology is used. This time, however, bring a video camera to the meeting. Now you have a great "document" that details not only what was agreed upon, but WHY, complete with details, and no complicated forms required. We've been using this recently for a few projects, and the results are great. Got new people coming in to the project? Got associate level trainee interns trying to fix a bug a year later? No problem - whip out the video tape. You can even index and fast-forward to the relevant parts. Let's at least pretend we don't still live with punch cards :-) Technology... love it.

More Posts Next page »