views:

151

answers:

5

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?

+7  A: 

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
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
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
+3  A: 

I think separate assemblies are the only possible solution.

Incognito
+3  A: 

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
I wasn't aware of the Obsolete attribute - it sounds good. But unfortunately we do have a lot of legacy classes :(
GarethOwen
MPritch
The boss is not too happy about having 90% our code base marked as Obsolete
GarethOwen
But surely if it is Legacy code as you say....
MPritch
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
Obsolete is just another word for Depreciated, no?
Nate Bross
@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/154254I'm really struggling to understand what's wrong with marking obsolete code as obsolete....
MPritch
@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..
Chris Lively
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
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
+10  A: 

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.

MPritch
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
Thanks Dan - I'd never noticed that before!
MPritch
+1  A: 

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.

Chris Lively
We added it in as a build stat to our TeamCity build. There's something nice about seeing a graph slowly trending to 0
MPritch