1

The backstory is long but the general idea is that I'm beginning an iterative refactoring process to replace a poorly designed data access layer with a new one under constraints from above. We can't fix everything at once but need to slowly phase in the new changes.

The old DAL contains several classes each containing several data access methods. The new DAL must preserve the method signatures and return types of the old DAL, and the old DAL code must be retained through the refactor. In a way you could say that we're implementing a repository pattern after the fact but also hard coding the dependencies on a method by method basis instead of injecting them at runtime.

A nice way to go about the refactor is with VS Quick Actions. I can easily extract an interface from each of the old classes through the designer and then auto-implement them for the new classes. This creates a new class with the same method signatures of the old class; however the new methods are initially just stubs that throw a NotImplementedException until they are filled with an implementation.

The trouble is that the NotImplementedException is only thrown at runtime whereas I really need it at compile time. Is there a pattern that can be used to allow us to stub out the new DAL methods but raise a compiler error if we attempt to use them before they are in fact implemented?

  • 4
    Can't you just do a search in the code base for NotImplementedException to discover the unimplemented methods? – Robert Harvey Apr 19 at 2:14
  • Quick google shows VS lets you specify pre- and post- build commands/scripts. Create a simple script that simply does a text search for the NotImplementedException string and pops up a warning – ivanivan Apr 19 at 2:48
  • 1
    The pattern would be a "unit testing". Write or generate unit tests for new DAL classes. Then by running the tests you will get a feedback in a few seconds which methods not yet implemented – Fabio Apr 19 at 4:24
  • 1
    @Fabio: It still counts as a runtime failure though. While the testing process itself is automated, it still requires a brute force check of all possible scenarios (testing all possible use cases, including all fringes, for a sufficiently complex codebase, is no simple task). – Flater Apr 19 at 8:49
  • 1
    @Bwmat: It depends on whether the compiler error is thrown when the method is not implemented, or when the method is not implement and called. The question does err towards the latter, but any practical solution would generally err towards for the former, specifically because of the reflection issue you point out: whether a method is called (or not) is not considered to check if the method itself compiles correctly. Because you can't account for reflection (e.g. configurable dependency injection, post-compilation, via a config file) – Flater Apr 19 at 9:03
3

You're looking for the #error directive. Just put it next to the runtime exception.

void LegacyMethodName(string a, int b)
{
    throw NotImplementedException();
    #error Not implemented
}

You can also use #warning, which would allow developers to compile and test as they go while tracking the remaining unimplemented methods.

2

The trouble is that the NotImplementedException is only thrown at runtime whereas I really need it at compile time. Is there a pattern that can be used to allow us to stub out the new DAL methods but raise a compiler error if we attempt to use them before they are in fact implemented?

Yes, it can be done. However, it's not really the best way to approach this problem. You can make your own compiler rules, but this feels disproportionate to what you're actually trying to achieve.

There are much better solution to this problem than you are trying for. I like simplicity, and my suggestion is to use Ctrl + Shift + F to simply ensure that there are no more NotImplementedException instances in the code.

I assume you know Ctrl + F to find something. When there are multiple search results, you jump from one to the other by repeatedly searching.

Ctrl + Shift + F is slightly different in that it doesn't jump to the first search result, but instead gives you a list of search results.

This is exactly what you can use to find all methods that have not yet been implemented. I added some stubs to a test project. These classes are in separate files:

public interface IMyInterface
{
    string TestMethod1();
    string TestMethod2();
}

public class ImplementationOne : IMyInterface
{
    public string TestMethod1()
    {
        throw new NotImplementedException();
    }

    public string TestMethod2()
    {
        throw new NotImplementedException();
    }
}

public class ImplementationTwo : IMyInterface
{
    public string TestMethod1()
    {
        throw new NotImplementedException();
    }

    public string TestMethod2()
    {
        throw new NotImplementedException();
    }
}

So I press Ctrl + Shift + F, enter NotImplementedException and click "Find all":

enter image description here

And at the bottom, VS lists all results. It tells me in what file and on what line the search query has been found.

enter image description here

You can doubleclick any of the results in order jump to the corresponding line of code.


You can achieve a similar result by rightclicking NotImplementedException and selecting "Find all references" (Ctrl + K, R also works). You get a similar result screen:

enter image description here

You can also click on the entries to jump to the code.

However, this requires you to first find an instance of a NotImplementedException, whereas Ctrl + Shift + F does not.

This screen does have a nice set of filtering features (e.g. if you're only looking for references in a subset of projects) which you may want to use in some cases; so you can combine the two approaches: use the normal find (Ctrl + F) to find the first instance, and then rightclick that instance to find all of its references.

  • 1
    Thanks. I probably should have been more clear in my initial post that I'm not able to implement all of the methods at once, so this isn't an issue of needed to find those that aren't implemented. Let's say we have 100 methods that need to be replaced. The idea is that we'd implement 10 for the first release, 10 for the second and so on until they are all done. I don't want to run the risk of accidentally calling an unimplemented method and having the system break at runtime. – christok Apr 19 at 15:10
1

Someone had posted earlier about the Obsolete attribute, which can be configured to throw an compile error when attempting to use a method that is decorated as such. I don't know why that answer got deleted but it works perfectly for my purposes. Thanks, whoever you are!

    [Obsolete("This method has not yet been implemented.", true)]
    public IList<object> MyMethod()
    {
        throw new NotImplementedException();
    }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.