This is just my opinion, but if you can design a project that only takes a few activities, it will be more readable in terms of clutter. Like if you need to search through a long list of activities and into multiple sequences inside each other, then it becomes less readable.
But, like there needs to be a balance also, and it’s something I’m still working at myself. You don’t want many giant blocks of query functions or long dictionary references because then debugging becomes more tiresome. While, you also don’t want to break your logic up into every little activity (ie creating an If activity for every single condition needed)
If you can present a project in a small flowchart built by small sequence boxes that describes the process to a non-programmer then that’s good. If they need to migrate through many embeded For Eaches and If clusterbleeps, then that is bad
An example of efficient processing, I believe, would be something like this:
—assuming you are wanting to compare tables and perform actions
For each block (For each row in dt1.AsEnumerable.Where(Function(r1) If(IsNumeric(r1(0).ToString.Trim), CDbl(r1(2).ToString.Trim)>0, False) ).ToArray)
If activity (condition: dt2.AsEnumerable.Where(Function(r2) If(IsNumeric(r2(0).ToString.Trim), CDbl(r2(2).ToString.Trim)=CDbl(row(2).ToString.Trim, False) ).ToArray.Count>0
.... and so on
So in that example, I could have run dt2 through another For each, but when dealing with thousands of lines of data this can use up memory and take a long time.
EDIT: Also, I could have assigned the datatable array before it, but I didn’t see a point in this case (not all cases) and it would be more confusing to have to look for what that array of rows represents. But on the other hand, if there is a coding error, you could check the array before the for each, so there are some disadvantages also. You would not want to assign each item from the row, though, because it’s unnecessary and adds bulkiness/clutter to the For each block.
Just my 2 cents