Declaring functions in order to avoid explicit nested loops

My programming professor has told me that it is a good programming practice (at least in C/C++) to declare a function with the inner loop when nesting loops (not for loops, since when, i.e. looping through a multidimensional array this is very intuitive). For example, if I write

int main()
{
    while (cond1)
    {
        // ...(1)...
        while (cond2)
        {
            // ...(2)...
        }
    }
}

then it is better:

type inner_loop(param)
{
    // ...(1)...

    while (cond2)
    {
        // ...(2)...
    }
}

int main()
{
    while (cond1)
    {
        inner_loop(param);
    }
}

What improvements do imply this method? Is there any case in which this way of programming nested loops can be counterproductive? Thanks in advance.

1

It adds a lot of readability at the expense of a little function call overhead, assuming you choose a better name than inner_loop. Unless you truly need every ounce of performance, there aren’t many situations where it isn’t advisable.

One thing to take note is that it hides the complexity of your algorithm. In general, this is a good thing. However, I once saw similar nested loops in functions create an O(n^6) function out of what should be O(n) or better, simply because maintainers way down the road didn’t notice the nested loops when they were working on the outer layers.

3

There are advantages and disadvantages to both approaches. Which approach you prefer should depend upon your team’s style and guidelines. For now, since your professor doesn’t like a particular method, you shouldn’t use it for the code you submit.

But don’t get too hung up on either approach.

Calling a function from within the outer loop simplifies the task of analyzing the outer loop. But it also increases the overhead from the stack creation / deletion with a large number of function calls. It can also be more difficult to code since shared variables between the loops will need to be passed and returned with each function call.

Nested loops are a little quicker to write. But they can drag out the length of the function. Longer functions tend to be more brittle, which makes maintenance more difficult. Longer functions are also more difficult to wrap your head around since they’re … longer. It’s a bit obvious, but worth pointing out.

There’s a lot of existing C code written with nested loops without additional function calls. So you’ll see a lot of it in the wild. However, just because “it’s always been done that way” doesn’t necessarily mean it’s the right way.

as I get deeper and deeper into my developent career, I find myself losing interest in the academicians who spout truisms about levels of nesting, anti-patterns and etc.

I’ll share what seems to work well for me in a pragmatic, enterprise-focused development environment:

“…solve for the specific case in front of you, THEN refactor for the general case.”

i.e. write it “all in a row.” Then start extracting things that are obvious function-like constructs. If you’re writing code about the real world and it’s processes, you’ll surely encounter a lot of “function-ish” things that you likely do several times, if not over-and-over…extract them, parameterize them, make them into methods/functions that you can apply across other cases.

Here’s a good way to gauge if you’re “done” refactoring: if your test cases all look very simple, direct. (you ARE writing test cases, right?) If your tests are obvious and simple, chances are your code is structured pretty well.

The advantage is that your main() is now simpler and easier to read (especially if the body of the inner loop is at all complicated).

It would be a disadvantage if the inner loop were very obvious, since it would then take slightly more effort to read something that should take almost no effort.

Do whatever results in more readable code.

The more general advice is: watch out for deep levels of nesting. I’ve heard it called the “arrowhead” or “mountain range” anti-pattern, because that’s what the code starts to look like. If you’re nesting 2 levels for loops, then another level for if…then, and then if..thens inside the if…thens, the level of nesting can make the code really hard to follow.

  • I read an article where a team had huge maintenance problems with their code, so they implemented a policy of a maximum depth of nesting. Their bug rate dropped to almost nothing.

  • Someone famous once said, any code nested more than 3 layers deep is incomprehensible.

Hm. I can’t find that quote now, but I did find a related article about nesting if…thens:

http://www.drdobbs.com/architecture-and-design/refactoring-deeply-nested-code/231500074

EDIT: here it is: “if you need more than 3 levels of indentation, you’re screwed anyway, and should fix your program.”

https://www.kernel.org/doc/Documentation/CodingStyle

Eventually you will learn about refactoring. Refactoring is about changing a program so that its structure is different, while it does exactly the same thing as before. Two refactoring methods that are often used are splitting a function into two functions, and combining two functions into one.

The art is twofold: First, being able to work focused and refactoring code without introducing bugs. Second, to identify which way is better – in this case, whether the nested loop in one function is better, or the loops distributed over two functions.

By claiming that you should always split nested loops into separate functions, your professor isn’t doing you a favour. The split increases total complexity. It’s beneficial if each loop on its own is so complex that nesting makes it too complex (Sometimes each loop is already too complex. Combining them would give you something that is much too complex). It’s negative if the combined loop is simple enough to be left alone. Your job is to decide which one is it.

Modern languages have features that can actually remove boilerplate code and reduce the complexity of nested loops. Learning to use these features will get you a lot further then having complexity in your code and splitting it up.

And where is the split loop counter-productive? Fact is that a modern computer will likely handle anything you throw at it easily – except nested loops. Iterate through 10,000 items, taking 1 microsecond for each – the user doesn’t even notice. Iterate through 10,000 times 10,000 items and it takes 100 seconds. In many cases you must find some better way than a nested loop (if you can’t, ask on stackoverflow).

With your nested loop split over two functions, you have one function that calls a function in a straightforward loop – hard to see how to improve that. And you have a function with a simple loop – hard to see how to improve that. Any improvement must consider the combination of both, and you have broken the connection. That makes it harder to see that improving the efficiency of your code is needed, and that it can be done.

In theory declaring functions for your nested loops may sound good.
In practice you have to be very careful with hiding complexity.

Maybe I can explain better with an example.
Consider you have a list. Now you make an add function, but you don’t want duplicates, so the add function checks all items and only adds an item if there’s no duplicates. Easy enough, computers are fast, it won’t take long in your tests.

Next you start with an empty list and add items one by one. Easy enough, it goes fast in test.

Half a year in you get complaints from your customers that your app is slow, just because well, there’s 10 000 items added to your list and because you hid the complexity, you didn’t see you made an (n^2) situation.

Complexity needs to be clear or otherwise it will bite you.

For different scenarios different approaches are considered. When we want to submit a code which is easy to understand by the teacher or any other friend then we should definitely avoid using nested loops as it becomes difficult for the checker to trace the calls for all the variables one by one. But if there is no such case then there is no harm in using the nested loops as there is not such any change in the complexities. Making additional functional calls just increases the number of the activation records used for different functions and also the memory required for the current activation record pointer and the other pointers that point to the previous records of the functions increases.Thus in both the ways the memory increases but it is up to the programmer which approach to use.But the preferred one is to make functions for different purposes as it becomes easy for the programmer also to understand the code after if he/she reviews it after some time.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật