views:

333

answers:

6

Hi,

I sometimes use braces to isolate a block of code to avoid using by mistake a variable later. For example, when I put several SqlCommands in the same method, I frequently copy-paste blocks of code, ending by mixing the names and executing twice some commands. Adding braces helps to avoid this situation, because using a wrong SqlCommand in a wrong place will result in an error. Here's an illustration:

Collection<string> existingCategories = new Collection<string>();

// Here a beginning of a block
{
    SqlCommand getCategories = new SqlCommand("select Title from Movie.Category where SourceId = @sourceId", sqlConnection, sqlTransaction);
    getCategories.Parameters.AddWithValue("@sourceId", sourceId);
    using (SqlDataReader categoriesReader = getCategories.ExecuteReader(System.Data.CommandBehavior.SingleResult))
    {
        while (categoriesReader.Read())
        {
            existingCategories.Add(categoriesReader["Title"].ToString());
        }
    }
}

if (!existingCategories.Contains(newCategory))
{
    SqlCommand addCategory = new SqlCommand("insert into Movie.Category (SourceId, Title) values (@sourceId, @title)", sqlConnection, sqlTransaction);

    // Now try to make a mistake and write/copy-paste getCategories instead of addCategory. It will not compile.
    addCategory.Parameters.AddWithValue("@sourceId", sourceId);
    addCategory.Parameters.AddWithValue("@title", newCategory);
    addCategory.ExecuteNonQuery();
}

Now, StyleCop displays a warning every time a block follows an empty line. On the other hand, not putting an empty line would make the code much harder to understand.

// Something like:
Collection<string> existingCategories = new Collection<string>();
{
    // Code here
}

// can be understood as (is it easy to notice that semicolon is missing?):
Collection<string> existingCategories = new Collection<string>()
{
    // Code here
}

So,

  1. Is there something wrong in using braces to create blocks of code just for variable scope purposes?

  2. If it's all right, how to make it more readable without violating StyleCop rules?

+9  A: 

Use the using statement instead of bare brace blocks.

This will avoid the warnings, and also make your code more efficient in terms of resources.

From a larger perspective, you should consider splitting up this method into smaller methods. Using one SqlCommand followed by another is usually better done by calling one method followed by another. Each method would then use their own local SqlCommand.

Stephen Cleary
I believe using() requires an IDisposable, which he may not have in this context.
Sean Edwards
This applies in this particular scenario (since `SqlCommand` implements `IDisposable`, but wouldn't solve his general case.
Adam Robinson
It's ugly, but couldn't you use `do { ... } while(false);` instead? Turning off the warning would probably be a better solution, though.
Adam Crume
@Sean - SqlCommand implements IDisposable just fine.
Joel Coehoorn
I Agree. Turn these code blocks into their own methods and call them. The blocks as the OP has them looks a little weird and I'd refactor it out if I came across that code.
Chris Lively
@Joel You're right, in this case it would be fine, but as Adam said, it doesn't address the general case, which is what I was referring to.
Sean Edwards
+15  A: 

There's nothing wrong per se with blocking off code, but you need to consider why you're doing it.

If you're copying and pasting code, you're likely in a situation where you should be refactoring the code and producing functions that you call repeatedly rather than executing similar but different blocks of code repeatedly.

Adam Robinson
I agree. There is nothing technically wrong. It's a stylistic complaint, and potentially a warning sign of long functions that really should be split up into smaller and more manageable parts.
Sean Edwards
"you're likely in a situation where you should be refactoring the code": it's not about copy/paste of large blocks of code. The same problem will arise when using Intellisense if two variables have similar names (`sqlGetProductFromTable` vs. `sqlAddProductToTable`). It's easy to mistype the variable name, and since for the compiler, the code is perfectly correct, it will execute, but produce something unexpected.
MainMa
@MainMa: Reusing the blocks is not the only reason to refactor. A method that's just huge can alone be good reason to break it down into smaller pieces.
Adam Robinson
+4  A: 

I think such blocks is good idea, I'm using their often. It is useful when you need to separate blocks of code that are too small to be extracted into method, or when method consists of few code blocks looks like each other, but not with the same logic. It allows to give variables the same names without naming conflicts, and this makes method body more readable.

By the way, my opinion StyleCop has default rule set with more rules which expediency is debatable.

STO
+3  A: 

I'd have to say if I were to work on this code after you I'd be a little offput by your use of scope. Its not, afaik, common practice.

I'd consider it a smell that you'd be doing this. I would think the better practice would be to break off each scope into its own method with fully descriptive names and documentation.

Will
+4  A: 

I don't think there's anything wrong with using braces purely to delimit scope - it can be quite useful at times.

Case in point - I came across a profiling library once that used Profile objects to time sections of code. These worked by measuring the time from their creation to destruction, and therefore worked best by being created on the stack and then being destroyed when they went out of scope, thus measuring the time spent in that particular scope. If you wanted to time something that didn't inherently have its own scope, then adding extra braces to define that scope was probably the best way to go.

As for readability, I can understand why StyleCop doesn't like it, but anyone with any experience in C/C++/Java/C#/... knows that a brace pair defines a scope, and it should be fairly evident that that's what you're trying to do.

Mac
A: 

If you need to use braces to limit the scope of your variables, your methods are probably too long already. Just wanted to emphasize what the others already wrote.

Panagiotis Kanavos