How do inefficient imports affect your project? - objective-c

AppCode has a feature to "Optimise imports".
It will take redundant or unused imports and remove them and reshuffle them etc...
I can see why it can be done... If you have 3 files A, B and C...
A imports B
C import A and B
In this case you can remove the import of B in C.
But what does it do to the project when these redundant imports build up? Can it slow the build? Does it affect the product?

In the case of redundant imports, it's mostly to reduce code noise (i.e. unneeded lines of code). There isn't a dramatic additional cost to importing the same file twice. include does have a non-trivial cost because it has to open and read the file (even if it uses #ifdef guards), but import tries to avoid that. Even so, there's a small cost there.
Importing a file that you don't use can have a large build-time cost. In C-like languages, importing means "read the whole file and all of its included files and parse them right here." That can be very expensive. There are some tricks to avoid it being exactly that bad (particularly precompiled headers), but it's bad. So getting rid of unused imports is definitely good for build times.
Neither should have any impact on the final product. If it did, then AppCode would be removing a header it should not have removed.
Some of this changes with the new #import syntax, which doesn't require reading and parsing all the header files for modules. But you'd still want to avoid importing headers you don't need for tidiness if nothing else.

Related

Should I put all header file into Prefix.pch?

Is it recommended to refer to all my header file in Prefix.pch, and then I do not have to type #import headers during development?
I wouldn't recommend this.
The main reason is, header files can change in the course of your development. If you change one header, it will cause the pch to dirty, have to be rebuilt, and now your entire project will rebuild. That's quite time-consuming, and works counter to the whole reason for pch files.
Same thing if you create a new header file, add it to the pch, and now that triggers and entire rebuild.
But there's no single answer here. You may have a 3rd party library that will never (or rarely) change, is quite header-intensive, and so precompiling it may be a way to reduce build times. Experiment and see.
Pre-compiled header files were brought to serve one purpose: to make compiling faster. It is compiled and stored in cache, and automatically included in every source file during the compilation time. Its like each source file does,
#import "Prefix.h"
This can be handy for project-wide #defines. (FYI, #defines are a code smell)
Xcode quotes:
Precompiling the prefix header will be most effective if the contents
of the prefix header or any file it includes change rarely. If the
contents of the prefix header or any file it includes change
frequently, there may be a negative impact to overall build time.
More clear explanation is here
Please keep this in mind when you #import source file header in .pch. As a tip, you can use Prefix.h for #import of constants and utility source files.
From a standards perspective, your includes should be as minimal as possible. Indeed, you shouldn't include anything you don't require for compilation into any file. So, in each of your .h files you should primarily include the superclass and use #class for all other references, then include only in your .m files. This gives the clearest information about the requirements of each class / file and minimises circularity issues.
You should add header file to Prefix.pch just if you need that file/class in most of your other classes. If you need the header file just in one or two other classes it's not point to add it to .pch because it will takes more time for compiler to compile the files and it will happen every time you want to run your project.
I add all the headers to Prefix.pch, and I have to claim life is much easier since that time. I just do not have to import always headers, believe me, life is much easier. :-)

If UIKit is imported in the PCH file, then why is it imported again in each file?

If #import <UIKit/UIKit.h> and #import <Foundation/Foundation.h> are both found in our `ProjectName.pch' file, making them globally imported, why are they automatically added to the header file when Xcode creates a new class?
The .pch is there as a compile time optimisation, personally I recommend making sure that classes can still build without a pch (so still import into h/m's manually), so that it can A) build without and B) so that if you re-use code, you can easily see its dependencies.
In general, newly-generated iOS projects come with this functionality, which is called a precompiled header or prefix header, and is a file that has the extension .pch.
You can throw all the headers you want in there and Xcode will pre-compile it before it builds anything else, and use it to compile the other compilation units in your project (e.g. .m files).
Using a precompiled header may or may not increase compile time; in general, it reduces compile time, as long as you have a lot of common headers and/or a lot of source files.
However, it's not necessarily good practice to treat the pre-compiled header like a big dumping ground, as your compilation units can form implicit dependencies on all sorts of stuff when you may want to enforce loose coupling between components.
Only Apple knows for sure.
Best guess: Apple can not be sure that the imports are in the pch file for all projects or that there is even a pch file. This by having these implicit imports compiling can be guaranteed.

When should I import a header to Prefix.pch?

I've heard importing a header to Prefix.pch can improve performance as it will load the header once, instead of on each instance. So when is a header imported enough times in a project to warrant being included in the Prefix.pch? A dozen times? Several times? Just twice?
I typically add a header to Prefix.pch if it is being #imported into more than 3 classes. I don't think there's a rule of thumb - it depends on your own standards for what you consider clutter, elegance, how globally the code is used etc. For example, most of my projects have a Utilities.h and Utilities.m where I declare helper functions used in many places. I always add Utilities.h to my .pch.
I tend to avoid the temptation of chucking too much stuff in the .pch. In particular, it obfuscates the dependencies in your code. Suppose you want to see where your code is using AFNetworking lib (for example): You search for the #import statements, and then see that the .pch file imports it, which tells you... nothing.
If when using a module/lib you usually import a number of related header files you can create a new header file that just imports the glob of related headers and then import that instead.

Lots of imports in .pch file

I've started working on a project that has a shed load of imports in the pch file.
Why would someone do this? Lazyness?
I guess if I refactor them out, I could potentially decrease compile times..... is that so?
No, not unless it's importing things that are changing frequently. The point of the precompiled header is that it combines lots of code that changes very infrequently into an intermediate format to decrease compilation times. If you take stuff out, it has to process each of the imports normally instead of using the intermediate format.
Taking things out of the precompiled header generally slows down the compile times. The exception to this is if you are importing stuff that you are changing on a regular basis, as this would defeat the purpose of it by forcing it to compile it each time.

Using MSBuild Import to modularize a project

I have developed a large MSBuild project to build a portion of our solution. There's a lot of things going on-- XML parsing/replacing, Windows services, remote copy, etc. As a result, the file has grown really difficult to manage, despite my best efforts to add decorations in comments.
As a goof, I broke out the main chunks of functionality out into separate files, like "XML.targets", "Services.targets", etc and imported them into the main "Build.proj." The build still worked and I immediately found it to be much more manageable.
However, all the info I have read on the Import feature of MSBuild is that it should be used to import reusable targets, ie those than can be consumed by -any- MSBuild project without any modifications. The separate projects I'm creating here are the opposite-- specific to one project and will break by default if use with anything else unless modified.
So I guess what I'm asking is, even though I can... should I? Is there an inherent danger in using Import strictly for the purpose of organizing a large project? Is there a better way to do this?
Thanks
No, there is no inherent danger. I think it's a good decision to split large project into several .targets files specific to certain operation since it reduces overall complexity. The idea of creating reusable targets means that they should have as little dependencies on the other parts as possible. By analogy you can think of separate .targets files as classes. The less coupled they are - the better. Because modification in one targets file will less likely break the whole process. You can take a peace of paper, draw your targets files as points with your main project in the center and draw all the connections between them. Say if one targets file overrides target from another or expects some properties from it or somehow else depends on it then there is a connection. In the perfect scenario you'll get something like a star.
In short: you should if it reduces complexity.