Design

Archived Posts from this Category

Untrusted Network shares

Posted by Chris Alcock on 30 Oct 2007 | Tagged as: .NET, C#, Design, Development, Software, SysAdmin

One of my longest standing pet hates with desktop software developed in .NET relates to the almost inevitable security exception that will occur if you attempt to run it from a network share. Its always one of the first things I notice about software, as I often download and unzip software onto my desktop (which on my work machine is located on a network share) and then attempt to run it in place. Many large and quite impressive pieces of software that get distributed as .ZIP files rather than installers suffer this plight, and a lot of them don’t handle the exception well (One that springs to mind was the much heralded release of NDepend 2.0).

The good news is that this anguish may well be about to come to an end, as Brad Abrams requests feedback about the .NET teams possible plan to make network shares trusted. As he mentions, there really is no good reason not to trust a network share for running managed .NET code - there is no such protection for unmanaged code, and there is little or no way a normal user would be aware of which is .a NET EXE and which is unmanaged EXE.

To answer Brad’s Questions:

A) Have you ever run into this limitation (a security exception when running a .NET application from a network file share)?

I frequently experience these issues - I tend to use this problem (and if its been worked round in the application) as a yard stick as to how well written the application is.

B) How often do you use network file shares for deploying applications (managed or otherwise)?

Most of my development is web based, however for utilities written for in house use we tend to distribute them on a network share - being able to run these in place would be a great help, as updating them would be easier.

C) If you think we should make this change, when would be a good time? Is it something we should do sooner in a service pack of the .NET Framework or later in a full release of the framework. Note, we are DONE with .NET Framework 3.5, so there is zero chance it is getting in that release.

From my point of view a patch as soon as possible, and have it included in the next release of the framework - Since this is a relaxation of the current restriction, I can’t see that it would cause any more problems in terms of support of existing application, as a reduction of the support incidents caused by this issue would reduce.

D) Can you ask your local network admin what they think of this issue? Would they be in favor of this sort of change? If so, when?

This change should simplify deployment - allowing Managed EXE to run from shares should mean that local disks can be more locked down as there would be no need to copy programs locally to run them.

All in all, I’m very much in favour of this change - It will level the playing field, give a more consistent user experience, and reduce the problems people have with winforms applications.

Yield to the iterator

Posted by Chris Alcock on 24 Jan 2007 | Tagged as: .NET, C#, Design, Development

I had planned to write a piece about using yield return in c# to allow returning IEnumerable collections in a lazy way, however upon starting up Visual Studio in the news I discovered Bill Wagner’s piece on MSDN entitled ‘Custom Iterators‘ which covers everything I was planning to write about.

On a related note, I happened across a rather old post about the performance of iterating over generic lists - the article compares three ways of iterating the list, with the outcome being (fastest to slowest):

  1. For Statement with cached count
    int iCount = list.Count;
    for (int i = 0; i < iCount; i++)
    {
    //do stuff
    }
  2. ForEach Delegate
    list.ForEach(delegate(ItemType item)
    {
    //do stuff
    }
    );
  3. ForEach Statement
    foreach (ItemType item in list)
    {
    //do stuff
    }

This ordering was pretty much how I expected it to be, but the article has fully example code and some figures to back up the performance difference.

CLS Compliance is good for APIs

Posted by Chris Alcock on 18 Jan 2007 | Tagged as: .NET, Design, Development

CLS, or the Common Language Specification is a set of rules which make up the most basic features of all .NET languages. Many .NET languages exceed these basic requirements and allow for features above and beyond the basics. For instance, C# allows for case sensitive public members, meaning that object.Property is different to object.property.

When developing .NET libraries for use by other developers it is a very good idea to have your library work in a CLS Compliant way, so that you are enabling all .NET languages to leverage your library. It also proves to be a good idea as many of the CLS Rules reflect good design practices.

In order to indicate that your library is CLS Complaint the whole assembly can be marked as such using the System.CLSCompliantAttribute, so in Visual Studio projects using C# this is often placed in AssemblyInfo.cs and looks something like this:

[assembly:CLSCompliantAttribute(true)]

This attribute tells the C# compiler to check the public aspects of whole assembly against the CLS Specification and will report any breaches of these rules as compile errors.

It is also possible to mark individual types, methods, properties, etc, as CLS Compliant by decorating the definition with the same attribute, like so:

[CLSCompliantAttribute(true)]
public class MyType{ ....

[CLSCompliantAttribute(true)]
public string MyFunction() {....

Finally, if you find that you need to exclude something from CLS Compliance, it can be marked as non-compliant by passing a false into the attribute:

//This method can't be CLS compliant as UInt32 is not a CLS type
[CLSCompliantAttribute(false)]
public UInt32 MyFunction() {....

CLS Compliance may seem like an extra complication to development, but it really is a good idea as it forces you to consider the needs of other developers (in other languages) and does enforce a number of good practices via compile time checks.

Further Information:
Cross-Language Interoperability on MSDN

Coding for Coders - Good API Design

Posted by Chris Alcock on 16 Jan 2007 | Tagged as: .NET, Design, Development

As a developer I am most happy writing code for other developers to write code with. I attribute this in part to the fact that I don’t enjoy writing user interface code as much as writing the code that no-one sees. For me, my favourite user interface is an API or even a web service.

One of my favourite books about APIs is Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries by Brad Abrams and Krzysztof Cwalina. I’ve been reading Brad’s Blog for quite some time and today he posted a link to a really good presentation by Joshua Bloch about designing good APIs. The presentation is video with the full slide deck, and covers a range of topics from the initial specification of an API, through implementation considerations with some specific references to good and bad APIs. I found the parts about specification of an API and avoiding implementation details leaking into the published API and controlling the interface of the API.

Things I took away from watching the presentation:

  • Consult people about the specification - get as much input as possible before committing to a design
  • Keep the interface simple - over complication makes using the API confusing - Usability is important for APIs, stick to naming conventions already in use for your platform
  • Control what you expose - don’t let internal implementation escape through your API, control the exceptions and types you expose
  • Documentation is important - make sure all public parts of the API are documented, the level of reuse of your API will be defined by the how good the documentation is
  • Consider performance of your API - make sure its not going to cause any horrid performance characteristics
  • Subclass only when the type is really a sub class of the parent type (Liskov Substitution Principle)
  • Don’t make the client do work if the module can do it for you - avoid the need for boiler plate code to use your API
  • Report errors as early as possible - compile time is best, runtime is worst
  • Be careful about your parameters - use the most appropriate types, keep the number of parameters under control, make sure overloads are obvious
  • When throwing exceptions give as much information about why the error occurred as possible

The list above is not exhaustative, I highly recommend watching the full presentation - its well worth the 68 minutes it will take.