40

TD;DR:

There was some confusion as to what I was asking, so here is the driving idea behind the question:

I always intended the question to be what it is. I may not have articulated it well originally. But intent have always been "is modular, separated, loose coupled, decoupled, refactored code" markedly slower by its own nature than "monolithic single-unit, do-everything in one place, one file, tightly coupled" code. The rest is just details and various manifestations of this that I came across then or now or will later. It is slower for sure on some scale. Like a non-defragged disk, you have to pick up the pieces from everywhere. It's slower. For sure. But should I care?

And the question is not about...

not about micro-optimization, premature optimization, etc. It is not about "optimize this or that part to death".

What is it then?

It is about the overall methodology and techniques and ways of thinking about writing code that emerged over time:

  • "inject this code into your class as a dependency"
  • "write one file per class"
  • "separate your view from your database, controller, domain".
  • don't write spaghetti homogenious single codeblock, but write many separate modular components that work together

It is about the way and the style of code that is currently - within this decade - seen and advocated in most frameworks, advocated at conventions, passed on via the community. It is a shift in thinking from 'monolithic blocks' to 'microservices'. And with that comes the price in terms of machine-level performance and overhead, and some programmer-level overhead as well.

Original Question follows:

In Computer Science field, I have noticed a notable shift in thinking when it comes to programming. I come across the advice quite often that goes like this:

  • write smaller function-wise code (more testable and maintainable this way)
  • refactor existing code into smaller and smaller chunks of code until most of your methods/functions are just a few lines long and it is clear what is their purpose (which creates more functions, compared to a larger monolithic block)
  • write functions that only do one thing - separation of concerns, etc (which usually creates more functions and more frames on a stack)
  • create more files (one class per file, more classes for decomposition purposes, for layer purposes such as MVC, domain architecture, design patterns, OO, etc, which creates more file system calls)

This is a change compared to the "old" or "outdated" or "spaghetti" coding practices where you have methods spanning 2500 lines, and big classes and god objects doing everything.

My question is this:

when it call comes down to machine code, to 1s and 0s, to assembly instructions, to HDD platters, should I be at all concerned that my perfectly class-separated OO code with variety of refactored small-to-tiny functions and methods generates too much extra overhead?

Details

While I am not intimately familiar with how OO code and its method calls are handled in ASM in the end, and how DB calls and compiler calls translate to moving actuator arm on a HDD platter, I do have some idea. I assume that each extra function call, object call, or "#include" call (in some languages), generate an extra set of instructions, thereby increasing code's volume and adding various "code wiring" overheads, without adding actual "useful" code. I also imagine that good optimizations can be done to ASM before it is actually ran on the hardware, but that optimization can only do so much too.

Hence, my question -- how much overhead (in space and speed) does well-separated code (code that is split up across hundreds of files, classes, and design patterns, etc) actually introduce compared to having "one big method that contains everything in one monolithic file", due to this overhead?

UPDATE for clarity:

I am assuming that taking the same code and splitting it, refactoring it out, decoupling it into more and more functions and objects and methods and classes will result in more and more parameter passing between smaller code pieces. Because for sure, refactoring code has to keep the thread going, and that requires parameter passing. More methods or more classes or more Factory Methods design patterns, results in more overhead of passing various bits of information more than it is the case in a single monolithic class or method.

It was said somewhere (quote TBD) that up to 70% of all code is made up of ASM's MOV instruction - loading CPU registers with proper variables, not the actual computation being done. In my case, you load up CPU's time with PUSH/POP instructions to provide linkage and parameter passing between various pieces of code. The smaller you make your pieces of code, the more overhead "linkage" is required. I am concerned that this linkage adds to software bloat and slow-down and I am wondering if I should be concerned about this, and how much, if any at all, because current and future generations of programmers who are building software for the next century, will have to live with and consume software built using these practices.

UPDATE: Multiple files

I am writing new code now that is slowly replacing old code. In particular I've noted that one of the old classes was a ~3000 line file (as mentioned earlier). Now it is becoming a set of 15-20 files located across various directories, including test files and not including PHP framework I am using to bind some things together. More files are coming as well. When it comes to disk I/O, loading multiple files is slower than loading one large file. Of course not all files are loaded, they are loaded as needed, and disk caching and memory caching options exist, and yet still I believe that loading multiple files takes more processing than loading a single file into memory. I am adding that to my concern.

UPDATE: Dependency Inject everything

Coming back to this after a while.. I think my question was misunderstood. Or maybe I chose to misunderstand some answers. I am not talking about micro-optimizing as some answers have singled out, (at least I think calling what I am talking about micro-optimization is a misnomer) but about the movement of "Refactor code to loosen tight coupling", as a whole, at every level of the code. I came from Zend Con just recently where this style of code has been one of the core points and centerpieces of the convention. Decouple logic from view, view from model, model from database, and if you can, decouple data from the database. Dependency-Inject everything, which sometimes means just adding wiring code (functions, classes, boilerplate) that does nothing, but serves as a seam/hook point, easily doubling code size in most cases.

UPDATE 2: Does "separating code into more files" significantly affect performance (at all levels of computing)

How does philosophy of compartmentalize your code into multiple files impact today's computing (performance, disk utilization, memory management, CPU processing tasks)?

I am talking about

Before...

In a hypothetical yet quite real not so distant past, you could easily write one mono-block of a file that does has model and view and controller spaghetti or not-spaghetti-coded, but that runs everything once it is already loaded. Doing some benchmarks in the past using C code I found out that it is MUCH faster to load a single 900Mb file into memory and process it in large chunks than it is to load a bunch of smaller files and process them in a smaller peace-meal chunks doing the same work in the end.

.. And Now*

Today I find myself looking at code that shows a ledger, that has features like .. if an item is an "order", show order HTML block. If a line item can be copied, print HTML block that displays an icon and HTML parameters behind it allowing you to make the copy. If the item can be moved up or down, display the appropriate HTML arrows. Etc. I can, through Zend Framework create partial() calls, which essentially means "call a function that takes your parameters and inserts them into a separate HTML file that it also calls". Depending on how detailed I want to get, I can create separate HTML functions for the tiniest parts of the ledger. One for arrow up, arrow down, one for "can I copy this item", etc. Easily creating several files just to display a small part of the webpage. Taking my code and behind-the-scenes Zend Framework code, the system/stack probably calls close to 20-30 different files.

What?

I am interested in aspects, the wear and tear on the machine that is created by compartmentalizing code into many smaller separate files.

For example, loading more files means having them located in various places of the file system, and in various places of physical HDD, which means more HDD seek and read time.

For CPU it probably means more context switching and loading various registers.

In this sub-block (update #2) I am interested more strictly in how using multiple files to do the same tasks that could be done in a single file, affect system performance.

Using Zend Form API vs simple HTML

I used Zend Form API with latest and greatest modern OO practices, to build an HTML form with validation, transforming POST into domain objects.

It took me 35 files to make it.

35 files = 
    = 10 fieldsets x {programmatic fieldset + fieldset manager + view template} 
    + a few supporting files

All of which could be replaced with a a few simple HTML + PHP + JS + CSS files, perhaps total of 4 light-weight files.

Is it better? Is it worth? ... Imagine loading 35 files + numerous Zend Zramework library files that make them work, vs 4 simple files.

13
  • 1
    Awesome question. I'll do some benchmarking ( take me a day or so in order to find some good cases ). However speed enhancements at this degree come at a huge cost to readability and development costs. My initial guess is the result is negligible performance gains.
    – Dan Sabin
    Feb 25, 2014 at 23:04
  • 7
    @Dan: Can you please put it in you calendar to benchmark the code after 1, 5 and 10 years of maintenance. If I remember I'll check back for the results :)
    – mattnz
    Feb 27, 2014 at 23:49
  • 1
    Yea that's the real kicker. I think we all agree making less lookups and function calls is faster. However i can't imagine a case where that was preferred to things like maintainably and easily training new team members.
    – Dan Sabin
    Feb 28, 2014 at 1:26
  • 2
    To clarify do you have specific speed requirements for your project. Or do you just want your code to "go faster!" If it is the latter I wouldn't worry about it, code that is fast enough but easy to maintain is far far far better than code that is faster than fast enough but is a mess. Mar 3, 2014 at 12:02
  • 4
    The idea of avoiding function calls for performance reasons is exactly the kind of batshit crazy thinking that Dijkstra railed against in his famous quote about pre-mature optimization. Seriously, I can't Mar 4, 2014 at 6:45

12 Answers 12

13

My question is this: when it call comes down to machine code, to 1s and 0s, to assembly instructions, should I be at all concerned that my class-separated code with variety of small-to-tiny functions generates too much extra overhead?

MY answer is yes, you should. Not because you have lots of little functions (once upon a time the overhead of calling functions was reasonably significant and you could slow your program down by making a million little calls in loops, but today compilers will inline them for you and what's left is taken care of by the CPU fancy prediction algorithms, so don't worry about that) but because you will introduce the concept of layering too much into your programs when the functionality is too small to sensibly grok in your head. If you have larger components you can be reasonably sure they are not performing the same work over and over, but you can make your program so minutely granular that you may find yourself unable to really understand the call paths, and in that end up with something that barely works (and is barely maintainable).

For example, I worked at a place that showed me a reference project for a web service with 1 method. The project comprised 32 .cs files - for a single web service! I figured this was way too much complexity, even though each part was tiny and easily understood by itself, when it came to describing the overall system, I quickly found myself having to trace through calls just to see what the hell it was doing (there were also too many abstractions involved,as you'd expect). My replacement webservice was 4 .cs files.

i didn't measure performance as I figure it would have been roughly the same all in all, but I can guarantee mine was significantly cheaper to maintain. When everyone talks of programmer time being more important than CPU time, then create complex monsters that cost lots of programmer time in both dev and maintenance you have to wonder that they are making excuses for bad behaviour.

It was said somewhere (quote TBD) that up to 70% of all code is made up of ASM's MOV instruction - loading CPU registers with proper variables, not the actual computation being done.

That is what CPUs do though, they move bits from memory to registers, add or subtract them, and then put them back into memory. All computing boils down to pretty much that. Mind you, I once had a very multi-threaded program that spent most of its time context switching (ie saving and restoring register state of threads) than it did working on the thread code. A simple lock in the wrong place truly screwed performance there, and it was such an innocuous bit of code too.

So my advice is : find a sensible middle ground between either extreme that make your code look good to other humans, and test the system to see if it performs well. Use the OS features to make sure its running as you'd expect with CPU, memory, disk and network IO.

2
  • I think this speaks the most to me right now. It suggests to me that a good middle ground is to start with mind-mapping concepts to code pieces while following and using certain concepts (like DI), rather than getting tied up with esoteric code decomposition and going nuts (i.e. DI everything whether you need it or not).
    – Dennis
    Nov 5, 2014 at 19:56
  • 1
    Personally, I find that more ""modern"" code is somewhat easier to profile... I guess the more maintainable a piece of code is, it's also easier to profile, but there's a limit, where breaking things into little pieces makes them less maintainable...
    – AK_
    Apr 17, 2015 at 16:01
27

Without extreme care, micro optimization such as these concerns leads to unmaintainable code.

Initially it looks like a good idea, the profiler tells you the code is faster and V&V/Test/QA even says works. Soon bugs are found, requirements change and enhancements that were never considered are asked for.

Over the life of a project code degrades and becomes less efficient. Maintainable code will become more efficient than its unmaintainable counterpart as it will degrade slower. The reason is code builds entropy as it is changed -

Unmaintainable code quickly has more dead code, redundant paths and duplication. This leads to more bugs, creating a cycle of degradation of the code - including its performance. Before long, developers have low confidence that the changes they are making are correct. This slows them down, makes the cautious and generally leads to even more entropy as they address only the detail they can see

Maintainable code, with small modules and unit tests is easier to change, code that is no longer needed is easier to identify and remove. Code that is broken is also easier to identify, can be repaired or replaced with confidence.

SO in the end it comes down to life cycle management and is not as simple as "this is faster so it will always be faster."

Above all, slow correct code is infinitely faster than fast incorrect code.

2
  • Thankx. To drive this a bit towards where I was going, I am not talking about micro-optimization, but a global move towards writing smaller code, incorporating more dependency injection and hence more outside functionality pieces, and more "moving parts" of code in general that all need to be connected together for them to work. I tend to think that this produces more linkage/connector/variable-passing/MOV/PUSH/POP/CALL/JMP fluff at the hardware level. I do also see a value in shift towards code readability, although at the expense of sacrificing hardware-level computing cycles for "fluff".
    – Dennis
    Feb 26, 2014 at 15:13
  • 10
    Avoiding function calls for performance reasons is absolutely a micro-optimization! Seriously. I can't think of a better example of micro-optimization. What evidence do you have that the the performance difference actually matters for the kind of software that you are writing? It sounds like you don't have any. Mar 4, 2014 at 6:44
18

To my understanding, as you point out with inline, on lower level forms of code like C++ it can make a difference but I say CAN lightly.

The website sums it up - there is no easy answer. It depends on the system, it depends on what your application is doing, it depends on the language, it depends on the compiler and optimization.

C++ for example, inline can increase performance. Many times it might not do anything, or possibly decrease performance but I've personally never encountered that myself though have heard of stories. Inline is nothing more than a suggestion to the compiler to optimize, which can be ignored.

Chances are, if you're developing higher level programs, the overhead shouldn't be a concern if there is one at all to begin with. Compilers are extremely smart these days and should handle this stuff anyway. Many programmers have a code-to-live by: don't ever trust the compiler. If this applies to you, then even slight optimizations you feel are important can be. But, keep in mind, every language differs in this regard. Java does inline optimizations automatically at runtime. In Javascript, inline for your webpage (as opposed to seperate files) is a boost and every milisecond for a webpage might count but thats more of an IO issue.

But on lower level programs where the programmer might be doing a lot of machine code work along with something like C++, the overheard might make all the difference. Games are a good example of where CPU pipelining is critical, especially on consoles, and something like inline can add up a little here and there.

A good read on inline specifically: http://www.gotw.ca/gotw/033.htm

4
  • Coming from my question's perspective, I am not as focused on inlining per seh, but on the "codified wiring" that takes up CPU's, bus', and I/O's time process linking various pieces of code. I wonder if there is some point where there is 50% or more of wiring code and 50% of actual code you wanted to run. I imagine there is a lot of fluff even in the tightest code one can write, and it seems to be a fact of life. Much of the actual code that runs on bits and bytes level is logistics - moving values from one place to another, jumping to one place or another, and only sometimes doing adding..
    – Dennis
    Feb 26, 2014 at 15:02
  • ... subtraction or other business-related function. Just like loop unrolling can speed up some loops due to less overhead allocated for incrementing variables, writing larger functions probably can add some speed, provided your use case is set up for it. My concern here is more overall, seeing lots of advice to write smaller code pieces, increases this wiring, while benefiting adding readability (hopefully), and at the expense of bloat at the micro level.
    – Dennis
    Feb 26, 2014 at 15:02
  • 3
    @Dennis - one thing to consider is that in an OO language, there may be VERY little correlation between what the programmer writes (a+b) and what code is generated (a simple add of two registers? Moves from memory first? casting, then function calls into an object's operator+?). So 'small functions' at the level of the programmer may be anything but small once rendered into machine code. Feb 26, 2014 at 17:22
  • 2
    @Dennis I can say that writing ASM code (directly, not compiled) for Windows goes along the lines of "mov, mov, invoke, mov, mov, invoke". With invoke being a macro that does a call wrapped by pushes/pops... Occasionally you'll do function calls in your own code but it's dwarfed by all the OS calls. Mar 5, 2014 at 21:09
14

You need to be careful to listen to experienced programmers as well as current thinking. People who have dealt for years with massive software have something to contribute.

In my experience, here is what leads to slowdowns, and they are not small. They are orders of magnitude:

  • The assumption that any line of code takes roughly as much time as any other. For example cout << endl versus a = b + c. The former takes thousands of times longer than the latter. Stackexchange has a lot of questions of the form "I've tried different ways of optimizing this code, but it doesn't seem to make a difference, why not?" when there's a big-old function call in the middle of it.

  • The assumption that any function or method call, once written, is of course necessary. Functions and methods are easy to call, and the calling is usually pretty efficient. The problem is they are like credit cards. They tempt you to spend more than you really want to, and they tend to hide what you spent. On top of that, large software has layers upon layers of abstraction, so even if there is only 15% waste at each layer, over 5 layers that compounds to a slowdown factor of 2. The answer to this is not to remove functionality or write bigger functions, it is to discipline yourself to be on guard for this problem and be willing and able to root it out.

  • Galloping generality. The value of abstraction is it can let you do more with less code - at least that's the hope. This idea can be pushed to extremes. The problem with too much generality is that every problem is specific, and when you solve it with general abstractions, those abstractions are not necessarily able to exploit the specific properties of your problem. For example, I've seen a situation where a fancy priority queue class, which could be efficient at large sizes, was used when the length never exceeded 3!

  • Galloping data structure. OOP is a very useful paradigm, but it does not encourage one to minimize data structure - rather it encourages one to try to hide the complexity of it. For example, there is the concept of "notification" where if datum A is modified in some way, A issues a notification event so that B and C can also modify themselves so as to keep the whole ensemble consistent. This can propagate over many layers, and magnify the cost of the modification enormously. Then it is entirely possible that the change to A could soon after be undone or changed to yet another modification, meaning that the effort spent on trying to keep the ensemble consistent has to be done yet again. Confounding that is the probability of bugs in all these notification handlers, and circularity, etc. It is far better to try to keep the data structure normalized, so that any change needs to be made in one place only. If non-normalized data cannot be avoided, it is better to have periodic passes to repair the inconsistency, rather than pretending it can be kept consistent with a short leash.

... when I think of more I'll add it.

14

This is a change compared to the "old" or "bad" code practices where you have methods spanning 2500 lines, and big classes doing everything.

I don't think anyone ever thought doing that is a good practice. And I doubt the people that did it did it for performance reasons.

I think the famous quote from Donald Knuth is very relevant here:

We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.

So, in 97 % of your code, just use good practices, write small methods (how small is a matter of opinion, I don't think all methods should be just few lines), etc. For the remaining 3 %, where performance does matter, measure it. And if measurements show that having many small methods actually significantly slows your code down, then you should combine them into bigger methods. But don't write unmaintainable code just because it might be faster.

8

The short answer is "yes". And, generally, the code will be a bit slower.

But sometimes a proper OO-ish refactoring will reveal optimizations that make the code faster. I worked on one project where we made a complex Java algorithm much more OO-ish, with proper data structures, getters, etc. instead of messy nested arrays of objects. But, by better isolating and restricting access to the data structures, we were able to change from giant arrays of Doubles (with nulls for empty results) to more organized arrays of doubles, with NaNs for empty results. This yielded a 10x gain in speed.

Addendum: In general, smaller, better structured code should be more amenable to multi-threading, your best way to get major speedups.

3
  • 2
    I don't see why would switching from Doubles to doubles require better structured code.
    – svick
    Mar 4, 2014 at 12:03
  • Wow, a downvote? Original Client code didn't deal with Double.NaNs, but was checking for nulls to represent empty values. After restructure, we could handle this (via encapsulation) with the getters of the various algorithm results. Sure, we could have rewritten the client code, but this was easier.
    – user949300
    Mar 6, 2014 at 7:42
  • For the record, I wasn't the one who downvoted this answer.
    – svick
    Mar 6, 2014 at 12:51
7

Among other things, programming is about trade-offs. Based on this fact, I incline to answer yes, it could be slower. But think about what you get in return. Getting readable, reusable and easily modifiable code is easily overweighs any possible drawbacks.

As @user949300 mentioned, it is easier to spot areas that can be algorithmically or architecturally improved with such approach; improving those are usually far more beneficial and effective than not having possible OO or function-calling overhead (which is already just a noise, I bet).


I also imagine that good optimizations can be done to ASM before it is actually ran on the hardware.

Whenever something likes this crosses my mind, I remember that decades spent by smartest people working on compilers are probably making tools like GCC far better than me at generating machine code. Unless you are working on some sort of microcontrollers related stuff, I suggest you don't worry about that.

I am assuming that adding more and more functions and more and more objects and classes in a code will result in more and more parameter passing between smaller code pieces.

Assuming anything when optimizing is a waste of time, you need facts about code performance. Find where you program spends most of the time with specialized tools, optimize that, iterate.


To sum it all up; let compiler do its job, focus on important things like improving your algorithms and data structures. All the patterns you mentioned in your question exist to help you with that, use them.

P.S.: These 2 Crockford's talks popped in my head and I think they are somewhat related. First one is super brief CS history (which is always good to know with any exact science); and second one is about why we reject good things.

1
  • I really like this answer the most. Humans are horrible at second-guessing the compiler and taking shots at where the bottlenecks are. of course big-O time complexity is something you should be aware of, but big 100-line spaghetti method vs a factory method invocation + some virtual method dispatching should never even be a discussion. performance isn't at all interesting in that case. also, big plus for noting that "optimizing" without hard facts and measurements is a waste of time.
    – sara
    Apr 13, 2016 at 19:48
4

I believe the trends you identify point at a truth about developing software - programmer time is more expensive that CPU time. Thus far, computers have only gotten faster and cheaper, but a tangled mess of an application can take hundreds if not thousands of man-hours to change. Given the cost of salaries, benefits, office space, etc, etc, it's more cost-effective to have code that might execute a little slower but is quicker and safer to change.

4
  • 1
    I agree, but mobile device are becoming so popular that I think they are a large exception. Although the processing power is increasing, you can't build an iPhone app and expect to be able to add memory like you can on a webserver.
    – JeffO
    Feb 26, 2014 at 16:05
  • 3
    @JeffO : I disagree - Mobile devices with quad core processors is now normal, performance (especially as it impacts battery life), while a concern, is less important than stability. A slow mobile phone or tablet gets poor reviews, one that is unstable gets slaughtered. Mobile apps are very dynamic, changing almost daily - the source has to keep up.
    – mattnz
    Feb 26, 2014 at 23:47
  • 2
    @JeffO: For what it's worth, the virtual machine used on Android is pretty bad. According to benchmarks it might be an order of magnitude slower than native code (while the best of breed is usually just a bit slower). Guess what, nobody cares. Writing the application is fast and the CPU sits there twiddling it's thumbs and waiting for user input 90% of time anyway.
    – Jan Hudec
    Mar 4, 2014 at 7:20
  • 1
    There's more to performance than raw CPU benchmarks. My Android phone works fine, except when the AV is scanning an update and then it appears to just hang for longer than I like, and its a quad-core 2Gb RAM model! Today bandwidth (whether network or memory) is probably the main bottleneck. Your superfast CPU is probably twiddling its thumbs 99% of the time and the overall experience is still poor.
    – gbjbaanb
    Nov 4, 2014 at 16:11
4

Well 20+ years ago, which I am guessing you are not calling new and not "old or bad", the rule was to keep functions small enough to fit on a printed page. We had dot matrix printers then so the number of lines was somewhat fixed generally only one or two choices for number of lines per page...definitely less than 2500 lines.

You are asking many sides of the problem, maintainability, performance, testability, readability. The more you lean toward performance the less maintainable and readable the code will become, so you have to find your comfort level which can and will vary for each individual programmer.

As far as code produced by the compiler (machine code if you will), the larger the function the more opportunity for needing to spill intermediate values in registers to the stack. When stack frames are used the stack consumption is in larger chunks. The smaller the functions the more opportunity for the data staying more in registers and the less dependence on the stack. Smaller chunks of stack needed per function naturally. Stack frames have pros and cons for performance. More smaller functions means more function setup and cleanup. Of course it also depends on how you compile, what opportunities you give the compiler. You may have 250 10 line functions instead of one 2500 line function, the one 2500 line function the compiler is going to get if it can/chooses to optimize across the whole thing. But if you take those 250 10 line functions and spread them across 2, 3, 4, 250 separate files, compile each file separately then the compiler wont be able to optimize out nearly as much dead code as it could have. the bottom line here is there are pros and cons to both and it is not possible to put a general rule on this or that is the best way.

Reasonable sized functions, something a person can see on a screen or page (in a reasonable font), is something they can consume better and understand than code that is quite large. But if it is just a small function with calls to many other small functions that call many other small functions you need several windows or browsers up to understand that code so you didnt buy anything on the readability side.

the unix way is to make using my term, nicely polished lego blocks. Why would you use a tape function this many years after we stopped using tapes? Because the blob did its job very well and on the back side we can replace the tape interface with a file interface and take advantage of the meat of the program. Why re-write cdrom burning software just because scsi went away as the dominant interface replaced by ide (then to come back later). Again take advanatage of the polished sub blocks and replace one end with a new interface block (also understand the hardware designers simply tacked an interface block on the hardware designs to in some cases making a scsi drive have an ide to scsi interface. To shorten this, build reasonable sized polished lego blocks each with a well defined purpose and well defined inputs and outputs. you can wrap tests around those lego blocks and then take the same block and wrap user interface and operating system interfaces around the same block and the block, in theory being well tested and well understood wont need to be debugged, just the additional new blocks added on each end. so long as all of your blocks interfaces are well designed and the functionality well understood you can build a great many things with minimal if any glue. just like with blue and red and black and yellow lego blocks of known sizes and shapes you can make a great many things.

Every individual is different, their definition of polished and well defined and tested and readable vary. It is not unreasonable for example for a professor to dictate programming rules not because they may or may not be bad for you as a professional, but in some cases to make the job of reading and grading your code easier on the professor or grad student assistants...You are equally likely, professionally, to find that each job may have different rules for various reasons, usually one or a few people in power have their opinion on something, right or wrong and with that power they can dictate that you do it there way (or quit, get fired, or somehow come to power). These rules are as often opinion based as they are based in some kind of fact about readability, performance, testability, portability.

2
  • “so you have to find your comfort level which can and will vary for each individual programmer” I think the level of optimization should be decided by the performance requirements of each piece of code, not by what each programmer likes.
    – svick
    Mar 4, 2014 at 12:06
  • The compiler sure, assuming the programmer has told the compiler to optimize the compilers generally default to not optimizing (at the command line the IDE may have a different default if used). But the programmer may not know enough to optimize the size of the function and with as many targets where does it get futile? Hand tuning performance has a tendency to have a negative effect on readability, and maintainability in particular, testability can go either way.
    – old_timer
    Mar 4, 2014 at 14:20
2

Depends how smart your compiler is. Generally, trying to outsmart the optimizer is a bad idea and may actually rob the compiler of opportunities to optimize. For starters, you probably don't have any clue whatsoever what it can do and most of what you do actually influences how well it does that too.

Premature optimization is the notion of programmers trying to do that and ending up with hard to maintain code that wasn't actually on the critical path of what they were trying to do. Trying to squeeze out as much CPU as possible when most of the time your app is actually blocked waiting for IO events, is something I see a lot for example.

The best is to code for correctness and use a profiler to find actual performance bottlenecks, and fix those by analyzing what is on the critical path and whether it can be improved. Often a few simple fixes go a long way.

1

THE ANSWER (in case you missed it)

Yes, you should care, but care about how you write the code, and not about performance.

In short

Do not care about performance

In the context of the question, smarter compilers and interpreters already take care of that

Do care about writing maintainable code

Code where maintenance costs are on the level of reasonable human comprehension. i.e. don't write 1000 smaller functions making code incomprehensible even if you understand each one, and don't write 1 god object function that is too large to understand, but write 10 well-engineered functions that make sense to a human, and are easy to maintain.

0

[computer-time element]

Does Refactoring towards Looser Coupling and Smaller Functions affect Speed of Code?

Yes, it does. But it is up to interpreters, compilers, and JIT-compilers to strip down this "seam/wiring" code, and some do it better than others, but some don't.

Multiple-file concern adds to I/O overhead, so that affects speed quite a bit as well (in computer-time).

[human-speed element]

(And should I care?)

no you shouldn't care. Computers and circuits are plenty fast these days, and other factors take over, such as network latency, database I/O, and caching.

So 2x - 4x slow down in the native code execution itself will often get drowned out by those other factors.

As far as multiple-file loading, that is often being taken care of by various caching solutions. It may take more time to load things up and merge them up the first time, but for every next time, for static files, caching does work as if a single file is being loaded. Caching comes as a solution to multiple-file loading.

Not the answer you're looking for? Browse other questions tagged or ask your own question.