Is this violating the DRY principle?
To some degree, yes - and I think it is a little bit astonishing that some commenters here seem to overlook or deny it. Indeed, the consequences are often acceptable in lots of real-world cases, but I think it is worth to take a closer look at the example.
So let us assume for a moment this statement
for(let i=0;i<SharedData.students.length;i++){
SharedData.students[i].something=.....
appears 100 times in a program. Then there are some design decisions which already became harder to change:
the decision to have SharedData
an attribute named students
the decision that students
is an indexable array
the decision that students has a mutable field named something
(Of course, you did not write to repeat the inner part of the loop, but let me put this into this example for the purpose of demonstration)
So how can you mitigate these issues? The first one can be mitigated by avoiding to repeat the explicit expression SharedData.students
more often than necessary. Often, a simple additional local variable can help:
let studentArray = SharedData.students;
for(let i=0;i<studentArray.length;i++){
studentArray.something=.....
Note that this simple change alone divides the number of repetitions of SharedData.students
by two. On a larger scale, you may consider to have several functions implemented in terms of a parameter studentArray
instead of a parameter SharedData
.
Issue #2 can be mitigated, for example, by using a foreach
statement, if your programming language has such a thing:
foreach(student in studentArray){
student.something = ...
Now, it is only necessary to have students
an iterable container, which is a weaker assumption than being an indexable array.
Issue #3 can be attacked by encapsulating the inner part of the for
loop inside a function:
foreach(student in studentArray)
DoSomething(student);
Now, the logic of manipulating or using student
in a specific manner is in one place, not 100 any more.
It maybe also worth to have a look why such a for-head repeats so often inside a program. It may be a sign that the overall code section containing the for
loop can be generalized, maybe by introducing the operation as a parameter itself (I prefer C# syntax, I guess you get the idea):
void DoSomethingForAllStudents(Action<Student> DoSomething)
{
foreach(student in studentArray)
DoSomething(student);
}
But beware, this can already be overengineered, and if the cost of making things less DRY is overengineering you should often better leave those things as they are.
As I wrote at the beginning, in lots of real-world cases the named issues are design decisions which you are not going to change later during the whole lifetime of your program, or where the real number of repetitions is not that high. So even if this literally violating DRY, don't overthink this.
for
loop, assuming there isn't any logical reason not to.map
for streams).