In any reasonably large software project, the system will be so large that no one developer will have a good grasp of the details of every function in the codebase.
The tendency is for developers to specialize – that is, developers tend to focus only on certain parts of the codebase and become more familiar with that part, while not having much knowledge about the other parts. This tendency is self-reinforcing – once it becomes known that the developer is an “expert” in the given module, there is a tendency that he will be assigned the most difficult and urgent tasks or fixes related to that module, further cementing his expertise. Thus, the developer becomes a sort of specialist within the system.
In contrast to a specialist, you will also sometimes have developers who prefer to be generalists. That is, they are comfortable working with any part of the system, although their familiarity and knowledge are probably not as deep as the specialist for any given module.
Both generalists and specialists are valuable in different situations. If you need a complicated change done quickly on a particular module with minimum impact, it’s best to have a specialist who is very familiar with how everything works. On the other hand, generalists are very useful from a resource management perspective, since they can jump in to help at any time in any part of the codebase. Say, if your specialist is sick or out of town and you urgently need to do a small change, the generalist can probably take it on no problem.
Ideally, you train more than one specialist per module of interest in your system, through some sort of mentoring or maybe pair programming, but not all dev teams have that luxury (mostly due to schedule or resource constraints). It’s best for software dev teams to find the right mix of generalists and specialists that their particular development process entails.