I'm not against continue and break in principle, but I think they are very low-level constructs that very often can be replaced by something even better.
I'm using C# as an example here, consider the case of wanting to iterate over a collection, but we only want the elements that fulfil some predicate, and we don't want to do any more than a maximum of 100 iterations.
for (var i = 0; i < collection.Count; i++)
{
if (!Predicate(item)) continue;
if (i >= 100) break; // at first I used a > here which is a bug. another good thing about the more declarative style!
DoStuff(item);
}
for (var i = 0; i < collection.Count; i++)
{
if (!Predicate(item)) continue;
if (i >= 100) break; // at first I used a > here which is a bug. another good thing about the more declarative style!
DoStuff(item);
}
This looks REASONABLY clean. It's not very hard to understand. I think it would stand to gain a lot from being more declarative though. Compare it to the following:
foreach (var item in collection.Where(Predicate).Take(100))
DoStuff(item);
foreach (var item in collection.Where(Predicate).Take(100))
DoStuff(item);
Maybe the Where and Take calls shouldn't even be in this method. Maybe this filtering should be done BEFORE the collection is passed to this method. Anyway, by moving away from low-level stuff and focusing more on the actual business logic, it becomes more clear what we're ACTUALLY interested in. It becomes easier to separate our code into cohesive modules that adhere more to good design practices and so on.
Low-level stuff will still exist in some parts of the code, but we want to hide this as much as possible, because it takes mental energy that we could be using to reason about the business problems instead.