CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Patrick Smacchia [MVP C#]

  • An Amazing Introduction to NDepend

    Andre Loker just published an amazing introduction to NDepend on its blog. Most of features are introduced with some methodology reminder about why it is useful. Very nice job!

    Such introduction is welcomed. Indeed, something difficult in promoting a tool such as NDepend is to educate about what it can bring to your development shop in terms of agility. NDepend comes with a set of innovative features currently not supported by any other .NET tool. I like to think that what tools such as ReSharper or CodeRush are doing to your code at micro level (i.e methods' body structuring), NDepend does it at macro level (i.e class, namespace, assembly structuring). Hence, as a developer I personally use both kind of tools to automatically control every aspects of the code base I am working on.

    It seems that the direction taken by NDepend is a promising one since the future Microsoft Oslo will support some similar features such as Architecture Explorer / Dependencies Matrix. Although this could be considered as a threat for the future of NDepend, my opinion is that it is a bless both because the Oslo schedule lets enought time to continue innovating and choose complementary directions, and because this will de-facto educate massively developers/architects about the usefulness of such tooling.

     

     

     
     

     

  • Some RichTextBox tricks

    I have recently been responsible for refactoring the Code Query Language query editor in NDepend to fix some imperfections.

     

     

     

    The CQL query editor implementation is based on a class derived from the System.Windows.Controls.RichTextBox class. It was the opportunity to learn some tricks that I would like to share in the current post.

     

    Text Coloring

    If you google how to color the text displayed in a RichTextBox, you’ll certainly end up using the coloring selection trick, using the RichTextBox method Select() and properties SelectionColor, SelectionBackColor:

     
    Using a search engine is very misleading here. We end up to the conclusion that this approach comes with extremely bad performance, even on short text with just dozens of word to color.

     

    A much better way we found is to use the Rtf / Rich Text Format capabilities of the RichTextBox. You just need to format a rtf string and use this code:

     

    I won’t detail the Rtf format here. The Rtf string for the query above looks like:

     

    Notice that using the SelectedRtf property is also a good way to prevent improper formatted text copy/pasted from Microsoft Word or a Browse for example.

     

    Avoid flickering problem

    When you update the content of your RichTextBox, you’ll certainly notice some pesky flickering. Hopefully, an efficient solution to this problem can be found here. Basically the solution consists in disabling text redrawing by calling some win32 APIs:

     

    Testing for ScrollBars’ visibility

    After looking for a way to test if the RichTextBox’s ScrollBars are visible or not, the only way I found is to infer this information from the delta between this.ClientRectangle and this.Size. This is certainly not the cleanest way but it is working well in every context I tried:

     

    Get/Set the ScrollBars’ positions

    To achieve this I came to the conclusion that it must be done throught the good-old win32. Being able to get and set the ScrollBars’ positions is especially useful to avoid some pesky automatic RichTextBox content re-locating I notice in some circumstances, such as inserting or modifying a long text. Here is the code:

     

    Url Detection

    Something that I wasn’t aware: if you want to display Urls that can be clicked in your text box, just set the RichTextBox.DetectUrls property to true. You can then use the RichTextBox.LinkClicked event to handle the url click.

     

     

  • Simple Core Domain Types and Plain Old .NET Objects

     

    In a recent post about writing Active Conventions with NDepend, Jan Van Ryswyck exposes some great CQL conventions:

    Being the huge DDD adept that I am, I want to enforce that the domain is the core, the centerpiece, the kernel as you may of my application. I don’t want it to have any dependencies to other assemblies in my application, especially not the infrastructure assembly.

    // <Name>Domain is directly using the infrastructure</Name>
    WARN IF Count > 0 IN SELECT METHODS FROM ASSEMBLIES "MyProject.Domain"
    WHERE IsDirectlyUsing "ASSEMBLY:MyProject.Infrastructure"

    It can’t get any easier than this, now doesn’t it? This is actively enforcing Separation of Concerns. Another way to have a convention about this is the following:

    // <Name>Domain-Driven Design convention</Name>
    WARN IF Count > 0 IN SELECT ASSEMBLIES WHERE 
    AssemblyLevel > 1 AND NameIs "MyProject.Domain"

    This means that my domain assembly can only have a reference to the .NET framework assemblies and nothing else. This gets my geek heart pounding. Imagine the possibilities if you incorporate this with your daily and
    continuous integration builds. Pure software quality assurance if you ask me.

     

    Here are some other conventions in the same spirit:

    // <Name>Domain-Driven Design convention</Name>
    WARN IF Count > 0 IN SELECT ASSEMBLIES WHERE 
    IsDirectlyUsedBy "ASSEMBLY:MyProject.Domain" AND !IsFrameworkAssembly
    // Framework or Tier assemblies are those your app is using, 
    // such as .NET Fx assemblies.
    // <Name>Domain-Driven Design convention</Name>
    WARN IF Count > 0 IN SELECT NAMESPACES WHERE 
    IsDirectlyUsedBy "ASSEMBLY:MyProject.Domain" AND !NameIs "System"
    // Domain code can only used System’s types such as
    // string, int, bool…

     

    Personnally I like the following convention that makes sure that domain objects are only made of primitive types, what we could call PONO : Plain Old .NET Object in reference to Java POJO or POCO, Plain Old CLR Object. Such convention garantees that domain object are re-usable accross layers and potentially increase performance since all these primitive types are CLR-optimized. This also helps enforce the currently fashionable concept of persitance ignorance.

    // <Name>Domain-Driven Design convention: PONO</Name>
    WARN IF Count > 0 IN SELECT TYPES WHERE 
    IsDirectlyUsedBy "ASSEMBLY:MyProject.Domain" AND 
    !( FullNameIs "System.String" OR FullNameIs "System.Boolean" OR
       
    FullNameIs "System.SByte" OR FullNameIs "System.Byte" OR
       
    FullNameIs "System.Int16" OR FullNameIs "System.UInt16" OR
       
    FullNameIs "System.Int32" OR FullNameIs "System.UInt32" OR
       
    FullNameIs "System.Int64" OR FullNameIs "System.UInt64" OR
       
    FullNameIs "System.Char" OR FullNameIs "System.Decimal" OR
       
    FullNameIs "System.Double" OR FullNameIs "System.Single")
    // Make sure that my Domain objects are PONO:
    // Plain Old .NET Object.


    The PONO convention could be refined with collection types, diagnostic types such as System.Diagnostics.Debug, some special attributes such as System.ParamArrayAttribute and eventually some serialization infrastructure types System.SerializableAttribute (but then, take care of what you mean by persistance ignorance ?!).

    Notice that all these is easy to adap if your Domain objects are embedded in a namespace instead of an assembly.

  • Declare Active Conventions inside C# or VB.NET Source Code

    With the last version of NDepend, we polished one particular scenario that I would like to describe properly: The possibility to store CQL rules inside source code.

    CQL constraints of an NDepend project are stored as raw text in the XML project file. CQL constraints can also be stored in C# or VB.NET source code. This facility is especially useful when a constraint implies a code element.

    Consider this piece of code:

     

    In the CQL query editor in VisualNDepend.exe, let's write a custom convention that checks that:

    When a method is calling the method Foo1(), it must also call the method Foo2(int).


    Let's declare this constraint in the C# source code. Right click the editor and select: Copy to clipboard to insert this query in C# source code ...



    ... and paste the clipboard content just before the Fct1() method definition. An attribute is now tagging the Fct1() method definition. This attribute contains our CQL constraint as a string.


    It makes sense to declare such constraint near the Foo1() / Foo2(int) methods definitions. This way, during code review or refactoring developers cannot miss it. This is active documentation. The same way the C# compiler checks privacy when finding the private keyword in source code, the NDepend analyzer checks a custom constraint when finding a CQL constraint in source code.


    The attribute class is CQLContraintAttribute declared in the namespace NDepend.CQL declared in the assembly NDepend.CQL.dll. This assembly can be found in $NDepend install dir$/Lib. It is freely redistributable. For conveniency, it is also very small, less than 10KB. Don't forget to reference the assembly NDepend.CQL.dll from your project.


    Each time the project will be analyzed, the CQL constraint is now extraced and included in the list. A dedicated group named Constraints extracted from Source Code is automatically created. This group and its children are read-only.

    Constraints extracted are organized by assemblies / namespaces where they are declared.

    There is also the facility to Go to Constraint Declaration in Source Code:

     

     

     

    Tip 1:

    You can use the tag $FullName$ inside the CQL constraint text. It will be automatically replaced by the full name of the code element tagged. There is also the tag $Name$:

    If an assembly is tagged, $Name$ and $FullName$ will be both replaced with the assembly name (without .dll or .exe extension).


    If a type is tagged, $Name$ is the name of the type without the namespace and $FullName$ include the namespace.


    If a method or a field is tagged, $Name$ is the name of the member (including method signature for method) and $FullName$ includes the namespace and the type name.


    In both C# and VB.NET, a namespace's declaration cannot be tagged with an attribute.



     

    Tip 2:

    It can be tedious to define a constraint for each code element that must satisfy a particular constraint. For example, we want to avoid writing dozens of constraints to check the full test coverage of dozens of types. Such scenario can be handled by defining a dedicated attribute such as the NDepend.CQL.FullCoveredAttribute. Let's tag each class or structure 100% covered by tests with the FullCoveredAttribute...



    Now, the full coverage of classes and structures can be verified with a single CQL constraint:

    The following query can be used to demand for types 100% covered by tests not tagged yet with the FullCoveredAttribute:


    The FullCoveredAttribute and some other attributes are also defined in the NDepend.CQL.dll assembly. This list includes:

    ImmutableAttribute to continuously check that a class or a structure is immutable.


    PureAttribute to continuously check that a method is pure, i.e it doesn't provoke any side effect by modifying some fields states.


    GeneratedAttribute to tag generated code. This way it is easy to differentiate generated code and handcrafted code while writing constraints.


    CouldNotBeInternalAttribute to tag public classes or methods deemed as CoulbBeInternal but that cannot be internal for some reasons (such as some elements must be public for some designer or for tools such as serializer or unit tests runner).


    The default set of CQL constraints contains constraints associated with these attributes.
    It is up to you to define your own attributes classes and your own constraints for your own needs.

     

    Update: Tip 3:  

    The first comment on the present blog post was from Joshua Flanagan that would like not to bind with NDepend.CQL.dll but instead define its own attribute. This is possible by just copy-pasting the following attribute class inside your project. It is working like a charm as long as you don't tinker anything (namespace name, property name...).

     

     

  • Rules on .NET Framework Usage

     
    NDepend v2.9 comes with a set of default CQL rules concerning usage guidelines of the .NET Framework. Some of them are inspired from some FxCop rules while some others are inspired from our development experience. There are significant advantages in the usage of CQL to write such rules:

    The set of rules is straightforward to customize with your own rules or modified rules, more adapted to your code base.

     

    This shows how to use CQL to write rules about usage of any framework, not only the .NET framework.

     

    Using CQL rule naming + comments is a good way to store the convention itself and its name/description at the same place.

     

    Finally, once your application analyzed, NDepend can run dozens of CQL rules per second, even on multi-millions Lines of Code code base (from our tests 7 seconds to run 325 rules on the entire .NET Fx 3.5 code base, WPF/WCF assemblies included, this represent around 1.5M lines of C# code).

     

    We would like to hear from you about any .NET Framework usage rules you learnt the hard way. (support at ndepend dot com)


    Althought CQL rules can be read seamlessly, I take a chance to precise the meaning of the prefix OPTIONAL: found before code elements’ names. When the CQL compiler parses a code element’ name, the default behavior is to emit an error if the code element is not found. Thus to write generic CQL rules applicable to any code base, no matter which .NET framework code element it references, we use the OPTIONAL: prefix to prevent such error on missing code elements.

     

    System

     

    // <Name>Mark ISerializable types with serializable</Name>
    SELECT TYPES WHERE 
     
    IsPublic AND !IsDelegate AND
     
    Implement "OPTIONAL:System.Runtime.Serialization.ISerializable" AND 
     
    !HasAttribute "OPTIONAL:System.SerializableAttribute"

    // To be recognized by the CLR as serializable, types must be marked with the 
    // SerializableAttribute attribute even if the type uses a custom serialization routine 
    // through implementation of the ISerializable interface.


    // <Name>Mark assemblies with assembly version</Name>
    WARN IF Count > 0 IN SELECT ASSEMBLIES WHERE 
      
    !HasAttribute "OPTIONAL:System.Reflection.AssemblyVersionAttribute" AND
      
    !IsFrameworkAssembly 

    // The identity of an assembly is composed of the following information:
    //    - Assembly name
    //    - Version number
    //    - Culture
    //    - Public key (for strong-named assemblies).
    // The .NET Framework uses the version number to uniquely identify an assembly, 
    // and to bind to types in strong-named assemblies. The version number is used 
    // together with version and publisher policy. By default, applications run only 
    // with the assembly version with which they were built.


    // <Name>Mark assemblies with CLSCompliant</Name>
    WARN IF Count > 0 IN SELECT ASSEMBLIES WHERE 
      
    !HasAttribute "OPTIONAL:System.CLSCompliantAttribute" AND
      
    !IsFrameworkAssembly 

    // The Common Language Specification (CLS) defines naming restrictions, data types, 
    // and rules to which assemblies must conform if they are to be used across programming 
    // languages. Good design dictates that all assemblies explicitly indicate 
    // CLS compliance with CLSCompliantAttribute. If the attribute is not present on an 
    // assembly, the assembly is not compliant.


    // <Name>Mark assemblies with ComVisible</Name>
    WARN IF Count > 0 IN SELECT ASSEMBLIES WHERE 
      
    !HasAttribute "OPTIONAL:System.Runtime.InteropServices.ComVisibleAttribute" AND
      
    !IsFrameworkAssembly 

    // The ComVisibleAttribute attribute determines how COM clients access managed code. 
    // Good design dictates that assemblies explicitly indicate COM visibility. 
    // COM visibility can be set for an entire assembly and then overridden for individual 
    // types and type members. If the attribute is not present, the contents of the assembly
    // are visible to COM clients.


    // <Name>Mark attributes with AttributeUsageAttribute</Name>
    WARN IF Count > 0 IN SELECT TYPES WHERE 
    DeriveFrom "OPTIONAL:System.Attribute" AND
    !HasAttribute "OPTIONAL:System.AttributeUsageAttribute" AND
    !IsInFrameworkAssembly 

    // When defining a custom attribute, mark it using AttributeUsageAttribute to 
    // indicate where in the source code the custom attribute can be applied.
    // An attribute's meaning and intended usage will determine its valid locations 
    // in code. For example, if you are defining an attribute that identifies the 
    // person responsible for maintaining and enhancing each type in a library, 
    // and responsibility is always assigned at the type level, compilers should 
    // allow the attribute on classes, enumerations, and interfaces, but should 
    // not allow it on methods, events, or properties. Organizational policies and
    // procedures would dictate whether the attribute should be allowed on assemblies.


    // <Name>Remove calls to GC.Collect()</Name>
    WARN IF Count > 0 IN SELECT METHODS WHERE
      
    IsDirectlyUsing "OPTIONAL:System.GC.Collect()" OR
      
    IsDirectlyUsing "OPTIONAL:System.GC.Collect(Int32)" OR
      
    IsDirectlyUsing "OPTIONAL:System.GC.Collect(Int32,GCCollectionMode)"

    // It is preferrable to avoid calling GC.Collect() explicitely
    // in order to avoid some performance pitfall.
    // More in information on this here:
    // http://blogs.msdn.com/ricom/archive/2004/11/29/271829.aspx


    // <Name>Don't call GC.Collect() without calling GC.WaitForPendingFinalizers()</Name>
    WARN IF Count > 0 IN SELECT METHODS WHERE
      
    (IsDirectlyUsing "OPTIONAL:System.GC.Collect()" OR
       
    IsDirectlyUsing "OPTIONAL:System.GC.Collect(Int32)" OR
       
    IsDirectlyUsing "OPTIONAL:System.GC.Collect(Int32,GCCollectionMode)") 
      
    AND
      
    !IsDirectlyUsing "OPTIONAL:System.GC.WaitForPendingFinalizers()" 

    // It is preferrable to avoid calling GC.Collect() explicitely
    // in order to avoid some performance pitfall.
    // But if you wish to call GC.Collect(), you must do it this way:
    //   GC.Collect();
    //   GC.WaitForPendingFinalizers();
    //   GC.Collect();
    // To make sure that finalizer got executed, and object with finalizer got cleaned properly.


    // <Name>Enum Storage should be Int32</Name>
    WARN IF Count > 0 IN SELECT FIELDS WHERE 
      
    NameIs "value__" AND 
      
    !IsOfType "OPTIONAL:System.Int32" AND
      
    !IsInFrameworkAssembly

    // An enumeration is a value type that defines a set of related named constants. 
    // By default, the System.Int32 data type is used to store the constant value. Even
    // though you can change this underlying type, it is not necessary or recommended
    // for most scenarios. Note that there is no significant performance gain in using
    // a data type smaller than Int32. If you cannot use the default data type, you should 
    // use one of the CLS-compliant integral types, Byte, Int16, Int32, or Int64, to 
    // ensure that all of the enumeration's values are representable in CLS-compliant 
    // programming languages.


    // <Name>Do not raise too general exception types</Name>
    WARN IF Count > 0 IN SELECT METHODS WHERE 
      
    // The following exception types are too general to provide sufficient information 
      // to the user:
      ( ( DepthOfCreateA "OPTIONAL:System.Exception" == 1 OR 
          
    DepthOfCreateA "OPTIONAL:System.ApplicationException" == 1 OR 
          
    DepthOfCreateA "OPTIONAL:System.SystemException" == 1 )
        
    // Test for non-constructor, else this constraint would warn 
        // on ctor of classes that derive from these exception types.
        AND !IsConstructor )


    // <Name>Do not raise reserved exception types</Name>
    WARN IF Count > 0 IN SELECT METHODS WHERE 
      
    // The following exception types are reserved and should be thrown only by the 
      // common language runtime:
      ( DepthOfCreateA "OPTIONAL:System.ExecutionEngineException" == 1 OR 
        
    DepthOfCreateA "OPTIONAL:System.IndexOutOfRangeException" == 1 OR 
        
    DepthOfCreateA "OPTIONAL:System.NullReferenceException" == 1 OR
        
    DepthOfCreateA "OPTIONAL:System.OutOfMemoryException" == 1 )


    // <Name>Use integral or string argument for indexers</Name>
    SELECT METHODS WHERE 
    IsIndexerGetter AND 
     
    !( NameIs "get_Item(String)" OR 
        
    NameLike "get_Item\(Int" OR 
        
    NameLike "get_Item\(Byte" OR
        
    NameLike "get_Item\(SByte" )

    // Indexers, that is, indexed properties, should use integer or string types for the 
    // index. These types are typically used for indexing data structures and increase 
    // the usability of the library. Use of the Object type should be restricted to those 
    // cases where the specific integer or string type cannot be specified at design time. 
    // If the design requires other types for the index, reconsider whether the type 
    // represents a logical data store. If it does not represent a logical data store, 
    // use a method.


    // <Name>Uri fields should be of type System.Uri</Name>
    WARN IF Count > 0 IN SELECT FIELDS WHERE 
      
    (NameLike "Uri$" OR NameLike "Url$") AND !IsOfType "OPTIONAL:System.Uri"

    // A field which name end with 'Uri' is deemed as representing a uri.
    // Such field should be of type System.Uri.


    // <Name>Types should not extend System.ApplicationException</Name>
    WARN IF Count > 0 IN SELECT TYPES WHERE 
      
    DepthOfDeriveFrom "OPTIONAL:System.ApplicationException" == 1

    // For .NET Framework version 1, it was recommended to derive new exceptions from 
    // ApplicationException. The recommendation has changed and new exceptions should 
    // derive from System.Exception or one of its subclasses in the System namespace.


     
    System.Collections
    // <Name>Don't use .NET 1.x HashTable and ArrayList</Name>
    WARN IF Count > 0 IN SELECT TOP 10 METHODS WHERE

     
    // Prefer using the class System.Collections.Generic.Dictionary<K,V> over 
     // System.Collections.HashTable.
     CreateA "OPTIONAL:System.Collections.HashTable" OR

     
    // Prefer using the class System.Collections.Generic.List<T> over 
     // System.Collections.ArrayList.
     CreateA "OPTIONAL:System.Collections.ArrayList"

    // You can be forced to use HashTable or ArrayList 
    // because if you are using tier code that requires working with these classes
    // or because you are coding with .NET 1.x.


    // <Name>Caution with List.Contains()</Name>
    SELECT METHODS WHERE 
    IsDirectlyUsing "OPTIONAL:System.Collections.Generic.List<T>.Contains(T)" OR
    IsDirectlyUsing "OPTIONAL:System.Collections.Generic.IList<T>.Contains(T)" OR
    IsDirectlyUsing "OPTIONAL:System.Collections.ArrayList.Contains(Object)"

    // The cost of checking if a list contains an object is proportional to the size 
    // of the list (O(N) operation). For large lists and/or frequent calls to Contains(), 
    // prefer using the System.Collections.Generic.HashSet<T> class where calls to 
    // Contains() takes a constant time (O(0) operation).


    // <Name>Prefer return collection abstraction instead of implementation</Name>
    SELECT METHODS WHERE 
     
    ReturnTypeIs "OPTIONAL:System.Collections.Generic.List<T>" OR 
     
    ReturnTypeIs "OPTIONAL:System.Collections.Generic.HashSet<T>" OR
     
    ReturnTypeIs "OPTIONAL:System.Collections.Generic.Dictionary<TKey,TValue>"

    // Most of the time, clients of a method doesn't need to know the exact implementation
    // of the collection returned. It is preferrable to return a collection interface such as IList<T>,
    // ICollection<T> or IEnumerable<T>.


     
    System.Runtime.InteropServices
    // <Name>P/Invokes should be static and not be visible</Name>
    WARN IF Count > 0 IN SELECT METHODS WHERE
      
    !IsInFrameworkAssembly AND
      
    (HasAttribute "OPTIONAL:System.Runtime.InteropServices.DllImportAttribute") AND
      
    ( IsPublic OR 
        
    !IsStatic)

    // Methods marked with the DllImportAttribute attribute (or methods defined using the 
    // Declare keyword in Visual Basic) use Platform Invocation Services to access unmanaged 
    // code. Such methods should not be exposed. Keeping these methods private or internal 
    // ensures that your library cannot be used to breach security by allowing callers access 
    // to unmanaged APIs they could not call otherwise.


    // <Name>Move P/Invokes to NativeMethods class</Name>
    WARN IF Count > 0 IN SELECT METHODS WHERE
      
    !IsInFrameworkAssembly AND
      
    HasAttribute "OPTIONAL:System.Runtime.InteropServices.DllImportAttribute" AND
      
    !FullNameLike "NativeMethods."

    // Platform Invocation methods, such as those marked with the 
    // System.Runtime.InteropServices.DllImportAttribute attribute, or methods 
    // defined by using the Declare keyword in Visual Basic, access unmanaged code. 
    // These methods should be in one of the following classes:
    //
    //     - NativeMethods - This class does not suppress stack walks for unmanaged 
    //       code permission. (System.Security.SuppressUnmanagedCodeSecurityAttribute 
    //       must not be applied to this class.) This class is for methods that can 
    //       be used anywhere because a stack walk will be performed.
    //
    //     - SafeNativeMethods - This class suppresses stack walks for unmanaged code 
    //       permission. (System.Security.SuppressUnmanagedCodeSecurityAttribute is 
    //       applied to this class.) This class is for methods that are safe for anyone 
    //       to call. Callers of these methods are not required to do a full security 
    //       review to ensure that the usage is secure because the methods are harmless
    //       for any caller.
    //
    //     - UnsafeNativeMethods - This class suppresses stack walks for unmanaged 
    //       code permission. (System.Security.SuppressUnmanagedCodeSecurityAttribute 
    //       is applied to this class). This class is for methods that are potentially 
    //       dangerous. Any caller of these methods must do a full security review 
    //       to ensure that the usage is secure because no stack walk will be performed.


    // <Name>NativeMethods class should be static and internal</Name>
    WARN IF Count > 0 IN SELECT TYPES WHERE
      
    !IsInFrameworkAssembly AND
      
    ( NameIs "NativeMethods" OR
        
    NameIs "SafeNativeMethods" OR
        
    NameIs "UnsafeNativeMethods") AND
      
    IsPublic OR
      
    !IsStatic 

    // Native Methods' classes are declared as internal (Friend, in Visual Basic) and static.


     
    System.Threading
    // <Name>Method non-synchronized that read mutable states</Name>
    SELECT METHODS WHERE 
     
    (ReadsMutableObjectState OR ReadsMutableTypeState) AND 
     
    !IsDirectlyUsing "OPTIONAL:System.Threading.Monitor" AND 
     
    !IsDirectlyUsing "OPTIONAL:System.Threading.ReaderWriterLock"

    // Mutable object states are instance fields that can be modifed throught 
    // the lifetime of the object. Mutable type states are static fields that 
    // can be modifed throught the lifetime of the program. This query lists 
    // methods that read mutable state without synchronizing access. In the 
    // case of multi-threaded program, doing so can lead to state corruption.


    // <Name>Don't create threads explicitely</Name>
    WARN IF Count > 0 IN SELECT METHODS WHERE 
      
    CreateA "OPTIONAL:System.Threading.Thread"

    // Prefer using the thread pool instead of creating manually your own thread.
    // Threads are costly objects. 
    // They take approximately 200,000 cycles to create and about 100,000 cycles to destroy.  
    // By default they reserve 1 megabyte of virtual memory for its stack and use 
    // 2,000-8,000 cycles for each context switch.
    // As a consequence, it is preferrable to let the thread pool recycle threads.

    // Creating custom thread can also be the sign of flawed design, where tasks and threads 
    // have affinity. It is preferrable to code tasks that can be ran on any thread.


    // <Name>Don't use Thread.Sleep()</Name>
    WARN IF Count > 0 IN SELECT METHODS WHERE 
      
    IsDirectlyUsing  "OPTIONAL:System.Threading.Thread.Sleep(Int32)"

    // Usage of Thread.Sleep() is a sign of flawed design.
    // More information on this here:
    // http://msmvps.com/blogs/peterritchie/archive/2007/04/26/thread-sleep-is-a-sign-of-a-poorly-designed-program.aspx


    // <Name>Don't use Thread.Abort()</Name>
    WARN IF Count > 0 IN SELECT METHODS WHERE 
      
    IsDirectlyUsing  "OPTIONAL:System.Threading.Thread.Abort()" OR
      
    IsDirectlyUsing  "OPTIONAL:System.Threading.Thread.Abort(Object)" 

    // Usage of Thread.Abort() is dangerous.
    // More information on this here:
    // http://www.interact-sw.co.uk/iangblog/2004/11/12/cancellation


    // <Name>Monitor Enter/Exit must be both called within the same method</Name>
    WARN IF Count > 0 IN SELECT METHODS WHERE
     
    IsDirectlyUsing "OPTIONAL:System.Threading.Monitor.Enter(Object)" AND
     
    !IsDirectlyUsing "OPTIONAL:System.Threading.Monitor.Exit(Object)" 


    // <Name>Monitor TryEnter/Exit must be both called within the same method</Name>
    WARN IF Count > 0 IN SELECT METHODS WHERE
     
    ( IsDirectlyUsing "OPTIONAL:System.Threading.Monitor.Enter(Object)" OR
       
    IsDirectlyUsing "OPTIONAL:System.Threading.Monitor.TryEnter(Object,Int32)" OR
       
    IsDirectlyUsing "OPTIONAL:System.Threading.Monitor.TryEnter(Object,TimeSpan)") AND
     
    !IsDirectlyUsing "OPTIONAL:System.Threading.Monitor.Exit(Object)" 


    // <Name>ReaderWriterLock AcquireReaderLock/ReleaseLock must be both called within the same method</Name>
    WARN IF Count > 0 IN SELECT METHODS WHERE
      
    ( IsDirectlyUsing "OPTIONAL:System.Threading.ReaderWriterLock.AcquireReaderLock(Int32)" OR
        
    IsDirectlyUsing "OPTIONAL:System.Threading.ReaderWriterLock.AcquireReaderLock(TimeSpan)" OR
        
    IsDirectlyUsing "OPTIONAL:System.Threading.Monitor.TryEnter(Object,TimeSpan)") 
    AND
     
    !( IsDirectlyUsing "OPTIONAL:System.Threading.ReaderWriterLock.ReleaseReaderLock()" OR 
        
    IsDirectlyUsing "OPTIONAL:System.Threading.ReaderWriterLock.ReleaseLock()") 


    // <Name>ReaderWriterLock AcquireWriterLock/ReleaseLock must be both called within the same method</Name>
    WARN IF Count > 0 IN SELECT METHODS WHERE
      
    ( IsDirectlyUsing "OPTIONAL:System.Threading.ReaderWriterLock.AcquireWriterLock(Int32)" OR
        
    IsDirectlyUsing "OPTIONAL:System.Threading.ReaderWriterLock.AcquireWriterLock(TimeSpan)" OR
        
    IsDirectlyUsing "OPTIONAL:System.Threading.Monitor.TryEnter(Object,TimeSpan)") 
    AND
     
    !( IsDirectlyUsing "OPTIONAL:System.Threading.ReaderWriterLock.ReleaseWriterLock()" OR 
        
    IsDirectlyUsing "OPTIONAL:System.Threading.ReaderWriterLock.ReleaseLock()") 


     
    System.Xml
    // <Name>Method should not return concrete XmlNode</Name>
    WARN IF Count > 0 IN SELECT METHODS WHERE 
    ( ReturnTypeIs "OPTIONAL:System.Xml.XmlDocument" OR 
      
    ReturnTypeIs "OPTIONAL:System.Xml.XmlAttribute" OR 
      
    ReturnTypeIs "OPTIONAL:System.Xml.XmlDocumentFragment" OR 
      
    ReturnTypeIs "OPTIONAL:System.Xml.XmlEntity" OR 
      
    ReturnTypeIs "OPTIONAL:System.Xml.XmlLinkedNode" OR 
      
    ReturnTypeIs "OPTIONAL:System.Xml.XmlNotation" OR
      
    ReturnTypeIs "OPTIONAL:System.Xml.XmlNode" )

    // The class System.Xml.XmlNode implements the interface 
    // System.Xml.Xpath.IXPathNavigable. It is preferrable to return 
    // this interface instead of a concrete class.


    // <Name>Types should not extend System.Xml.XmlDocument</Name>
    WARN IF Count > 0 IN SELECT TYPES WHERE 
      
    DepthOfDeriveFrom "OPTIONAL:System.Xml.XmlDocument" == 1

    // Do not create a subclass of XmlDocument if you want to create 
    // an XML view of an underlying object model or data source.

     

  • BackgroundWorker Closure and Overridable Task

     Clearly, the class System.ComponentModel.BackgroundWorker is a good friend for all Windows Form programmers. Basically, it lets developers delegate a computation intensive task to a non-UI thread in order to get a responsive UI. The BackgroundWorker class lets specify a callback procedure through the event RunWorkerCompleted. The real benefit of the BackgroundWorker class is that this callback procedure is ran by the UI thread once the task done.

     
    The BackgroundWorker class also addresses 2 useful scenario: task cancellation and progression report callback on the UI thread.

     

    The Overridable Task Scenario 

    I found an important scenario that is not addressed by the BackgroundWorker class: overridable task. What I want is to trigger a task and be able to trigger again the same task without waiting for the first occurrence to complete. The first task must be cancelled before the second one being run since a BackgroundWorker object cannot execute 2 tasks at the same time.

     

    I found this scenario useful because it lets refresh a sophisticated UI in real-time on intensive user input, without degrading UI responsiveness. Typically, this happens when you’re implementing some kind of intelligence on mouse move when a non-trivial computation is triggered each time the MouseMove event is raised (typically several dozen times a second). This happens also on some text typing facility such as intellisense, where the user can type several characters a second and the computation might take a second or even more to be computed. In both cases, the UI must remain responsive and the computation has to be re-trigged, each time a new character is inputted or each time the MouseMove event provides new mouse coordinates.

     

    Here is a concrete use of the overridable task pattern in the NDepend UI. When editing a CQL query, both the list of code elements matched by the query (the Query Result panel), and the treemap where matched code elements are painted in blue (the Metric panel) gets updated in real time. The screenshot below shows that the intellisense lets the user modify the threshold on the query: SELECT METHODS WHERE NbParameters > {Threshold}. On large code base with hundreds of thousands of methods, the UI must remain responsive when the user moves the cursor of the intellisense to update the threshold. As a consequence, we needed the overridable task pattern to update matched methods in the Query Result and the Metric panel.

     

     

     

    Implementation of the Overridable Task scenario with BackgroundWorker  timer and closure

    At first glance, the BackgroundWorker comes with 2 convenient members: CancelAsync() and IsBusy(). However, the overridable task can’t be implemented naively by just calling CancelAsync() and then calling IsBusy() in an infinite loop containing a Thread.Sleep( a few microseconds here ).

    • First, this might kill responsiveness since the UI thread is blocked while waiting for the first task to be cancelled.
    • Second, calling Thread.Sleep(...) in an infinite loop is a typical anti-pattern that wastes thread, a proper timer must always be used in such circumstances.
    • And third, even worth, this just doesn’t work: The IsBusy() method will never return false! I am not sure about the implementation of BackgroundWorker but it seems that the internal isBusy state must be reset internally from the UI thread. Thus, you need to release the UI thread and then re-enter one of your procedure before observing IsBusy() returning false.

     

    The only right approach here is to create a System.Window.Forms.Timer object triggered just after calling CancelAsync(). The timer will tick until the method IsBusy() returns false, and then it’ll be time to push the new task. So basically one needs to create a timer field + a timer callback procedure + a state field to store the input data of the new task to trigger. This sort of situation is well handled by closures. Here is the method BeginWork() code with a closure that avoids to create extra fields and extra procedures:

     

     
    Notice that I use here a C#2 anonymous method to implement the closure. A lambda expression can be used also, but in this particular case it is less concise since the 2 tick procedure parameters (sender and arg) would need to be specified.

     

    A bug in the implementation

    While this first implementation seems to me correct at first sight, it contains a subtle bug which effects appear only on certain condition. Imagine that the currently running task takes time to be cancelled. To make things concrete, I provide here a prototype where the task can be cancelled every 500ms only and where the task takes 3s to be computed. What happens if I trigger several time a second the task by clicking quickly the Go! Button? The following screenshot shows that actually, several timers gets created and they are competing to make their tasks run. And we can see that the task#7, the last one triggered, is actually not the one that ends up being executed thoroughly.

     

    Correcting the bug

    There is no way to fix this bug without adding at least one instance field. Indeed, the fact that a new task is waiting to be ran must be stored across each call to BeginWork(). This storage cannot be done with a captured state by a closure because it could then not be read from further calls to BeginWork(). Let’s add m_Argument field. If it is not null, it means that there is a task pending to be ran. Thus a second timer cannot be triggered, but the input argument to the task needs to be updated with the new input.

     

     

    Nothing is obvious with asynchronous programming. Take the time to understand why  the scope (m_Argument != null)  comes before the scope (!m_BackGroundWorker.IsBusy). This lets handle the scenario where a background timer is still waiting for the current task to end up (because it has been cancelled)  and  between 2 ticks, a new task is posted.  Thus m_Argument is updated, and the newer task will be executed as soon as the timer can start it on the BackgroundWorker.


    At first sight, accesses to m_Argument should be synchronized because the field can be written both by entering BeginWork(...) or by a timer tick. One elegant aspect is that these accesses are always done by the same thread, the UI thread. In other words the field m_Argument has an affinity with the UI thread. As a consequence, there is no need for synchronization.

    And here is a screenshot of the prototype in action:

     


  • Book Review: C# in Depth

     

    I just finished my copy of C# in depth by Jon Skeet (published by Manning) and I highly recommend this book to ANY C# professional programmer. Jon is the author of one of the most informative blog on C#. As soon as I realized that he was writing a book on advanced topics of the language, I wanted to read it cover to cover. There are many, many C# books around but with Jon’s one, I was sure that I could polish my knowledge of some aspects of the language. And indeed I haven’t been disappointed.

     

    The book covers sequentially C#2 enhancements and then C#3 enhancements. This provides a unique perspective on the language evolution, from a traditional modern OOP language to a OOP / Functional hybrid one. When programming with C#, this is not a luxury to know how to use functional constructs and especially closures. Since I discover them back in 2004 while being an early adopter of C#2, it definitely changed my coding style. When mixed with advanced language constructs such as generics, type inference, contra/co variance,…closures becomes a dramatic way to enhance your code conciseness and expressiveness. Such power doesn’t come for free and you need first some proper education. IMHO I don’t think that there is any other C# book around that has a better coverage of these aspects. An interesting Jon’s note is that delegates were initially done to implement the concept of event (i.e some kind of command, that perform an action and doesn’t return anything) and become with C#2 first and C#3 after, a premium way to implement computational stuff (i.e function, whose only reason is to return something without any side-effects).

     

    Actually the entire LINQ cathedral sits on closures. But LINQ is not just a C#/VB.NET language artefact and is surrounded by several frameworks. C# in depth is certainly a great introduction to LINQ but to make the most of LINQ I would advise in addition the reading of a pure LINQ book, such as LINQ in Action.

     

    Not only the content is great but also the writing. This is a concise 370 pages software book. Jon doesn’t waste space (and tree!) to explain again and again basic C# construct. Still, you’ll get some refresher on some underlying aspect of the .NET platform such value vs. reference type, with many myths dispelled. I only have 2 minor tacks: First I would have like some decompilation of some IL part with Reflector. This is how I explained some advanced aspects of C# 2 and I still think it is the best way to teach some functional flows to a pure OOP programmer. Using a tool such as Reflector is also a good reflex to have each time you have a doubt about what the compiler spit. Showing this reflex to readers is not a luxury. Second, in a world where a single using clause can thoroughly change the meaning of all code elements, I would have like A to Z code print and not just some excerpt. Here again this is how I used to write book and I still believe programmer needs full C# code file to read printed on the paper. But don’t take me wrong. C# in depth is likely the best book available today to become a better C# programmer (and that’s what you want, else you wouldn’t be on CodeBetter.com!). Go read it!

    Posted