Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid property recursion

This hit me recently on a project I was working on. Most people are familiar with property recursion:

public int Test  {    get { return this.test; }    set { this.Test = value; } } private int test; 

You accidentally put an upper-case T in this setter, and you've opened yourself up to a StackoverflowException. What's worse is if you've not defined it, often visual studio will auto-correct the casing for you to the invalid state.

I did something similar however in a constructor recently:

public TestClass(int test) {     this.Test = Test; } 

Unfortunately here you don't get a StackOverflowException, now you've got a programming error. In my case this value was passed to a WebService that instead used a default value (which wasn't 0) which caused me to miss the fact I had incorrectly assigned it. Integration tests all passed because this service didn't say

"Hey you forgot this really important field!"

What steps can I take to avoid this sort of behaviour? I've always been advised against defining variables like the following, and I don't like them personally, but I can't think of any other options:

private int _test; private int mTest; 

EDIT

Reasons that the underscore or m prefix are undesirable normally that I can think of are:

  • Readability
  • Slightly more difficult to scroll through members if you're inheriting from 3rd party classes as you get a mix of styles.
like image 846
Ian Avatar asked Oct 30 '13 13:10

Ian


2 Answers

Best way is to use "Auto implemented properties" here.

public int Test { get; set; } 

If not possible to use "Auto implemented properties" for some reason use _ prefix(I don't prefer though).

If you also don't prefer to use some prefixes, then you have other option. You don't have to write the property code by hand. Let the IDE do it for you; that way you can avoid careless mistakes. (I don't know how I missed this in original answer)

Just type

private int test; 

Select the field, Right click Refactor->Encapsulate Field. IDE will generate property snippet for you as below.

public int Test {     get { return test; }     set { test = value; } } 

You don't need to bother clicking the context menu. If you prefer keyboard, shortcut is Ctrl + R + E.

Or get a Resharper, It will point your silly mistake immediately.

like image 124
Sriram Sakthivel Avatar answered Oct 04 '22 21:10

Sriram Sakthivel


Integration tests all passed

Then they weren't exhaustive enough tests. If there's an error that wasn't discovered by the tests, then you've got another test to write.

That's really the only automated solution here. The compiler isn't going to complain, because the code is structurally and syntactically correct. It's just not logically correct at runtime.

You can define naming standards, even use tools like StyleCop to attempt to enforce those standards. That would probably allow you to cover a lot, though it's not an ironclad solution and errors can still get through. Personally I agree with you that decorating variable names is unsightly in the code. Perhaps in some cases it's a valid tradeoff?

Ultimately, automated tests are your defense against these kinds of errors. At its simplest, if an error gets through your tests and into production then the response should be:

  1. Write a test to reproduce the error.
  2. Fix the error.
  3. Use the test to validate the fix.

Granted, that only covers that one case, not every property definition in your code. But if this is happening a lot then you may have a personnel problem and not a technical problem. Somebody on the team is, well, sloppy. The solution to that problem may not be a technical one.

like image 24
David Avatar answered Oct 04 '22 19:10

David