3

Can I restrict classes from a specific namespace from referencing classes in another specific namespace? Both namespaces exist in the same .NET assembly.

Example:

namespace LegacyCode
{
    class LegacyClass { ... }
}

namespace NewCode
{
    class NewClass {...}
}

I do not want classes from 'NewCode' to be able to reference classes in 'LegacyCode'.

Options:

  1. Have different assemblies (makes deployment harder, build takes longer)
  2. Using a tool like NDetect (costs money!)

Does anyone have any other ideas?

David M
  • 71,481
  • 13
  • 158
  • 186
GarethOwen
  • 6,075
  • 5
  • 39
  • 56

5 Answers5

10

Consider marking the classes with the Obsolete attribute. This will cause any code that isn't itself marked as 'Obsolete' to generate a warning during compilation.

Enable 'Treat warnings as errors' setting on the 'Build' tab of the project file to cause this warning to fail compilation with an error instead.

Edit:

Agree that seperate assemblies is a good strategy to facilitate fading out this code. This won't stop people referring to it though. The obsolete attribute makes it clear that this code is, um, obsolete.

Edit #2:

Thanks to Dan Tao for pointing out the overloaded constructor of the Obsolete attribute. This means you can enforce whether usage of a something should be treated as an error or not, without having to enable treat warnings as errors. There is also usefully the option to specify a message instructing the user of a workaround. This message is displayed during compilation in the error/warning.

Community
  • 1
  • 1
MPritchard
  • 7,031
  • 7
  • 28
  • 40
  • 1
    One of the `ObsoleteAttribute` class's overloaded [constructors](http://msdn.microsoft.com/en-us/library/961hff5d.aspx) takes a `bool` parameter specifying whether references to the marked class should cause compile errors. – Dan Tao Jul 20 '10 at 15:25
  • Thanks Dan - I'd never noticed that before! – MPritchard Jul 20 '10 at 15:29
7

Document the design, talk to people, review code. Don't try to throw technology at people problems. (The review part can become more effective with tools like NDetect, though.)

If you really need the isolation of design changes, go for separate assemblies: that's the intended design mechanism. But be sure you have a reasonable versioning scheme both for the interface and the implementation.

Pontus Gagge
  • 17,166
  • 1
  • 38
  • 51
  • In principle I think you are right - and that is our current solution (to communicate the rule). But in practice this has not worked. An experienced developer checked in a new class that broke the dependancy - and the reviewer missed it too. That is why I want a more strict way of controlling this. – GarethOwen Jul 20 '10 at 13:15
  • 2
    Good to hear! I think you're going to have to bite the bullet and accept costs either in the form of separate assembly management, or in dependency enforcement tools. I'm not aware of any free alternatives to NDepend (and certainly not with its feature set). But dependency breaking is going to cost you money, especially if maintenance goes on for a few years -- an up front investment to stave off later technical debt sounds preferable. – Pontus Gagge Jul 20 '10 at 13:27
3

I think separate assemblies are the only possible solution.

Incognito
  • 16,567
  • 9
  • 52
  • 74
3

MS uses the System.ObsoleteAttribute attribute to mark obsolete/legacy code. This attribute provides an ctor that creates a compiler error. Though, I'd use this if there are not too many legacy classes.

Florian Reischl
  • 3,788
  • 1
  • 24
  • 19
  • I wasn't aware of the Obsolete attribute - it sounds good. But unfortunately we do have a lot of legacy classes :( – GarethOwen Jul 20 '10 at 13:17
  • 2
    Trust me - spending an afternoon copying & pasting [Obsolete] is worth it. If your code is appropriately laid out in folders, so all your obsolete code is in the same folder, try a find & replace using a Regex in Visual Studio. I presume you'll want this applied to classes, enums & structs – MPritchard Jul 20 '10 at 13:21
  • The boss is not too happy about having 90% our code base marked as Obsolete – GarethOwen Jul 20 '10 at 13:30
  • I agree with you MPritch. Maybe I will write my own custom attribute, that does the same as 'Obsolete' but has a friendlier name. – GarethOwen Jul 20 '10 at 15:04
  • Obsolete is just another word for Depreciated, no? – Nate Jul 20 '10 at 15:21
  • 2
    @GarethOwen: Isn't the benefit of using the Obsolete the way the compiler reports a warning/error when it is present on referenced code? If so, then you're out of luck with writing your own I'm afraid: http://stackoverflow.com/questions/154109/custom-compiler-warnings/154254 I'm really struggling to understand what's wrong with marking obsolete code as obsolete.... – MPritchard Jul 20 '10 at 16:08
  • @Nate Bross: I think you mean deprecated.. Deprecated means "express earnest disapproval of" Obsolete means "no longer in general use", or for this purpose "being replaced with something newer". However, with regards to the compiler warnings, there isn't an option for Deprecated so Obsolete is all we have and it's close enough.. – NotMe Jul 20 '10 at 19:03
  • We have no plans to replace the legacy code - which is why 'Obsolete' feels wrong - I just don't want new code to reference it directly. In the few places where I need to reference the Legacy code, I will hide it behind a (non-legacy) interface. – GarethOwen Jul 20 '10 at 19:35
  • Anyone know anything about FxCop? Could I write a custom rule to detect when a class from a 'newCode' namespace references a class in a 'legacy' namespace? – GarethOwen Jul 20 '10 at 20:19
1

As others have said, use the obsolete attribute (Even if you have to rename it).

But go one step further. DELETE ANY Legacy method that is NO longer used as soon as possible. This will prevent someone from using it later. You should start to see the Compiler warnings due to the obsolete attributes to drop over time.

You might even make it a daily one hour long test to eliminate as many compiler warnings as you can... Maybe you pitch in to buy the daily winner a beer (or soft drink..;) after work.

NotMe
  • 87,343
  • 27
  • 171
  • 245
  • 1
    We added it in as a build stat to our TeamCity build. There's something nice about seeing a graph slowly trending to 0 – MPritchard Jul 20 '10 at 15:29