Contrary to what one may think at first, a good program will usually be less complex than a bad program. Many people think that the best programmer is the one who writes the most difficult and counterintuitive code.
In fact, the good programmer is what solves complex problems in the simplest way possible. This is because when the developer is more experienced, he learns to solve the problem directly, without giving unnecessary "laps".
Another factor of maturity of a developer is the question of first solving the problem, then implementing the solution. The younger ones usually go out scheduling without knowing very well where they will arrive. The code ends up "working", but with gambiarras and parts completely unnecessary.
Suggested Reading: Good programmers write complex code?
Of course, some algorithms are inherently complex, but the truth is that in general we never come up with an optimal solution.
There is a whole theory about the complexity of algorithms, but what usually affects even the complexity is the amount of loops and comparisons made.
Memory Vs. Performance
Memory and performance are generally not proportional.
A good program can use more memory for cache and fine optimizations, a more elaborate class structure, and more. A bad program can do all the operations on disk or directly in database and contain less classes, but without separation of responsibilities.
So I think it's better to look at these items separately ...
Except in the cases I've cited, where we purposely use more memory, a well-done program will occupy less memory when the developer correctly uses the data structures and language APIs.
In languages that have garbage collector it is essential to look at memory leaks in static attributes, such as maps that never have their items removed.
Another problem is reading too many data in memory without need. Some people read database and file all in memory to then process the information, being that you could do this record the record or line by line.
Performance can also be greatly affected by how a system is implemented.
This can begin with how the database is modeled, the way the system reads and writes data, and implemented algorithms.
Reading and writing to databases should be carefully thought out, avoiding
select * and bulk when possible instead of updating records one by one.
For files it is interesting to use streams for reading and writing, as opposed to the usual practice of loading everything to a String in memory.
Performance, memory, and complexity
Decreasing the complexity of a program can help you decrease memory usage and improve performance.
The amount of loops and comparisons can be reduced by using appropriate data structures. For example, in many situations we can use a * hash map to retrieve elements based on a key instead of using
indexOf in lists and vectors. In the best case, a map allows you to retrieve an item without iterations, in a single step, while in the lists you may need to scan all the elements to find an object inside.
You can also save memory by avoiding unnecessary variables and data structures. Or even avoid creating unnecessary values in memory, using
StringBuffer s or equivalent instead of string concatenation, for example.
Readable code and optimizations
In general, a programmer tries to write simple and readable code, after all maintenance is a very important factor in most systems.
However, in specific cases, it is possible for it to "break" certain rules by prioritizing some other quality issue: performance, availability, efficient memory usage, or some other resource.
An example of this is in "real-time" systems, where you have to extract maximum performance at the cost of having a hard-to-read code.
Or when deciding to use UDP socket communication with a proprietary protocol instead of a REST web service because of the data volume.
Anyway, it was all to say that, yes, complex code often hurts performance and memory usage.
I have tried in the above topics to consider some rather generic points, but that are relevant to the discussion.