Developing Application-Wide

Share/Bookmark

What ? Application-Wide ? 

When an application reaches a certain amount of code, the application
code gets usually partitioned amongst several Visual Studio solutions.
Visual Studio hosting some popular addins like Resharper or CodeRush end
up slowing down. Above a certain volume of code in the opened Visual
Studio solution, the IDE becomes quasi-impracticable. The volume
threshold naturally depends on the underlying hardware. For example, on a
modern 3000US$ laptop (32bits dual core + SSD + 8GB RAM + Wnd7) I
experiment 40 seconds to open a 50.000 Lines of Code solution. The
compile-all time mostly depends on how VS projects are organized and
referenced, but if it is more than 10 seconds I consider it as a major
burden.

So code volume can be a reason to split an application
code amongst several VS solutions, but there are several other reasons.
The most common one is certainly the need to separate VS test projects
from VS application projects.

.NET developers typically work with
several VS instances opened at the same time. Developing
Application-Wide means being able to jump from one VS instance to
another. Thus, developing Application-Wide means making several VS
instances smartly collaborate. I am going to elaborate on this feature
proposed by NDepend v3.

Concretely

Concretely the NDepend team is facing the multi VS instances paradigm
as anybody else with a sufficient large code base. Not counting the
test solution, the bulk of the NDepend code is spawned on 2 solutions: NDepend.Framework.sln
and NDepend.UI.sln. These solutions are made of around 50K
logical Lines of Code each. Projects from NDepend.UI.sln depend
on projects in NDepend.Framework.sln.

To make Application-Wide a reality, a NDepend
project must reference all assemblies built by all VS solutions (test
code assemblies can be included or not, here we choosed not).

This NDepend project will constitute the common
base that will make several VS instances aware of each others. The same
NDepend project must be attached to each VS solution.

Now several VS instances are ready to
collaborate. For example if I ask for types that are using the namespace
NDepend.Helpers

…I got some types from several assemblies,
including NDepend.UI. I can now choose to jump to a type source
code declaration by double clicking it in the result. The declaration
will be then opened, in the right VS instance, actually, the one with
the NDepend.UI.sln solution opened. If NDepend.UI.sln was
not currently opened, then the type declaration would be opened in the
current VS instance.

The VS instances collaboration can happen from
CQL query generated from Solution Explorer but also, from source
code editor
directly.

Application-Wide embraces also tier code

Working Application-Wide means also caring for tier code declared in
referenced assemblies. Controlling tier code used by your code is pretty
important. At production time, tier code is loaded and executed the
same way as your own code. From the user perspective, there is no
distinction between a problem coming from tier code and a problem coming
from your code.

In the NDepend Class Browser panel, tier code is
blue. Since the initial NDepend project embraces several VS solutions,
querying tier code will provide a list of code elements browsable across
several VS instances.

Under the hood

I guess that most software developer used to be a kid that destroyed
his toys to see what was the magic inside. So let’s look under the hood
about how the things work.

  • Primary inputs analyzed by NDepend are assemblies themselves, the
    ones referenced by the NDepend project, the NDepend project which is
    common to all VS solutions. (For a more detailed discussion on NDepend
    inputs you can look at this post: NDepend
    Analysis Inputs
    ).
  • From assemblies NDepend tries to find corresponding PDB files. A PDB
    file represent an association between IL code in assemblies and source
    code declarations in textual source files. PDB files are used primarily
    by debuggers.
  • From PDB files NDepend tries to find source files. 
  • From source files NDepend tries to find Visual Studio project files.
  • From Visual Studio project files NDepend tries to complete the
    entire set of source files (because not all source files are referenced
    by PDB files, for example if a file contains only an interface
    declaration it won’t be referenced!).
  • From Visual Studio project files NDepend tries to find Visual Studio
    solution files.
  • And that’s it!

Thus, when the NDepend VS addin is about to open a source file
declaration of a code element, it actually knows which VS solution own
the code element. If the VS solutions is actually loaded in a VS
instance on the machine, NDepend will choose this VS instance. The VS
instances collaboration also works across VS versions (an opening source
file request from a VS 2008 instance can actually open a declaration in
a VS 2010 instance for instance).

We developed several tricky heuristics to recompose all the exposed
file structure from assemblies files themselves. The result is that,
when attaching a common NDepend project file to several Visual Studio
solutions, all living Visual Studio instances becomes aware of each
other and can collaborate.

Several VS instance collaboration is cool. But another interesting
point in embracing application-wide code through a single shared NDepend
project file, is that the NDepend static analysis results and tools
(CQL rules, dependency matrix/graph, 2 snapshots comparison, code
coverage results…) also work application-wide. As a consequence, you
can harness NDepend static analysis results and tools on the entire
application, in each living VS instance. Concretely you can be informed
on a flaw in VS sln B, from within a VS instance with VS sln A opened.

Finally, let’s notice that the heuristic can be somewhat blurred if
some VS project are shared amongst
several VS solutions. In that case several solutions can own a same code
element. The heuristic will certainly find a VS solution but
at a point in time, this might not be the VS solution you expected when
trying to make several VS instances collaborate.

Share/Bookmark

This entry was posted in Application wide, Visual Studio. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Will

    I too tend to run lots of instances of VS, not to partition a big project but because I tend to be working on several clients/projects at once.

    For me, the biggest problem (and this has been around as long as VS/VC) with running multiple instances is losing VS options if you change anything and then don’t close all the instances in the right order.

    The only reliable way to make settings changes is to open a single instance, and then close it immediately after making the changes.

    Resharper has a similar problem, though it spices it up with a completely inexplicable message box which I’m never sure if I’m supposed to click yes or no on.

  • http://www.czarnovel.com/ home jobs

    Informative post, managed code is really helpful for application.

  • http://codebetter.com/members/Patrick-Smacchia/default.aspx Patrick Smacchia

    Adam, I guess you are talking of 8M physical LoC, which should result in smthing like 2M logical LoC

    See definitions of logical vs. physical LoC here:

    codebetter.com/…/how-do-you-count-your-number-of-lines-of-code-loc.aspx

    With 2M of logical LoC, we are flirting with NDepend upper limit in terms of volume of code analyzed (while VS has an upper limit of 50K to 100K logical LoC). With NDepend, you can still consider some of your low-level assemblies as tier types to greatly reduce the number of LoC analyzed.

    codebetter.com/…/controlling-the-usage-of-libraries.aspx

  • Adam

    Where I work our code base is about 8 million lines of code (and that’s just in the main trunk, there are up to 20 branches at any one time). With that much code we don’t check in solution files at all, rather each developer patches together their own solution files as needed depending on what they are working on.

    I currently have 6 copies of VS sitting open on my desktop.

    So having interoperability between several copies of VS is useful. More useful would be a way to somehow patch several project files together without needing a VS solution at all.

  • Steve Py

    A very handy feature. This goes back a long ways where segmenting an application into assemblies saved considerably on compile and build times. “Core” code that is relatively stable and doesn’t change much can be referenced by assembly rather than having these projects all loaded within a single solution. I remember this becoming a must back dealing with embedded Crystal Reports. (Absolutely hosed compile times)

  • http://codebetter.com/members/Patrick-Smacchia/default.aspx Patrick Smacchia

    Personally, I have the chance to work with a pretty powerful and expensive laptop, but above 50K LoC in a single VS instance hosting R#, VS slows down becomes unacceptable.

    I estimate boosting the machine power to avoid splitting a code base in several VS instances is not the right answer because:

    1) CODE BASE SIZE

    Their will always be a threshold above which VS will slows down unacceptably. I doubt there are affordable machine (say less than 7000 US$) that can host properly a large application (say, 200K logical LoC), in a single VS 2010 instance with R#.

    Moreover code base necessarily grows with time

    2) RESPONSIVE WORK ENVIRONMENT

    It is much more pleasant to work with for example 2 x 50K LoC VS VS instances responsive , than with a single 100K LoC VS instance slow.

    3) TOOLS EVOLUTION

    Future tools version will consume more resource (for example, usage of WPF in VS 2010 slows down compare to usage of win32 in VS 2008)

    Moreover more and more tools are and will be hosted in VS environment (like NDepend, FxCop, Pex …)

    4) POWERFUL MACHINE COST

    The bigger your code base, the higher the number of developers, the higher the cost of powerful and expensive machines your organization should buy for each developer.

  • http://www.integralwebsolutions.co.za/Blog.aspx Robert Bravery

    This seems very cool. But I question the purpose of having to open multiple instances of VS. After all Would that not just take up more memory and resources, bringing you back to square one.

    I can see benefit from different VS versions.