Let me try to explain what is over engineering looks like for a following problem statement:
Problem Statement: Print "Hello World" 5 times.
// Technique 1 : Can be written by a naive developer, but that is fine, code is functional
print("Hello World")
print("Hello World")
print("Hello World")
print("Hello World")
print("Hello World")
// Technique 2 : Better, here developer followed DRY principle ie Don't repeat yourself
for (i=1;i<=5;i=i+1) {
print("Hello World")
}
// Technique 3 : Much better, along with DRY developer kept in mind for new changes that should be done easily
#define SIZE 5
for (i=1;i<=SIZE;i=i+1) {
print("Hello World")
}
// Technique 4 : over engineering started, well in this case developer don't need to recompile the code when changes are there for SIZE, just need to update number in the config file
int SIZE = ReadSizeFromAConfigurationFile("config")
for (i=1;i<=SIZE;i=i+1) {
print("Hello World")
}
// Technique 5 : too much over engineering, now developer is reading that SIZE from the backend, again this has great flexibility, but you can see too many things have been involved here
int SIZE = ReadSizeFromTheBackend("some_server_url")
for (i=1;i<=SIZE;i=i+1) {
print("Hello World")
}
// Technique 6 : again too much over engineering, and developer is not following YAGNI principle, that's means requirement was saying print "Hello World", but developer written in a way that he/she can also change the string without any recompilation
int SIZE = ReadSizeFromTheBackend("some_server_url")
String s = ReadStringFromTheBackend("some_server_url")
for (i=1;i<=SIZE;i=i+1) {
print("\(s)")
}
For naive developers technique 6 can be over engineered... but for someone else it can be functional + maintainable code, also there is no standard definition of over engineering code...