Good abstractions are used often
Good abstractions are referenced at 2 or more places in your software.
Examples:
- Functions with 2+ call sites.
- Abstract class with 2+ concrete classes.
- Interfaces with 2+ implementations.
- Generics with 2+ instantiations
- Libraries with 2+ users.
- etc.
An abstraction that's referenced at 2 or more places helps reducing the code size, by factoring out the common things, and this is a good thing.
But if you have a lot of abstractions that are referenced only a single time, then there
is a good chance that the abstraction is not necessary.
Some examples when unnecessary abstractions come up:
- Writing object happy code (interfaces and abstract classes everywhere having only 1 implementation or concretion). These interfaces and abstract classes are not necessary (at that point of development). YAGNI principle.
- Someone builds a "shiny new" interface upon the old one, where the new functions after some conversion only call the old interface. You can imagine what a big mess is the result, if you repeat this several times. In this case the old functions will have a single call site, so they are not necessary. You need to move the code from the old functions into the new one or don't write a new one and modify the old one.
Some examples of really good abstractions:
- Hardware abstraction layer: provides a single interface to applications so they don't need to develop code for each type of hardware.
- File system: It doesn't matter you use FAT, NTFS, EXT3 whatever. It allows you to use files and directories, the file system driver does the rest.
- C language: You don't need to port your program for each CPU architecture. Just compile it.
So to answer your question pragmatically: Abstractions are bad, when they are referenced from less than 2 places.
With regard to the modularization, its subjective: you can organize your code whatever you want. If your library's source code is in a single source file it doesn't make it worse than if you put explode it several hundreds of files.
When rating your abstractions as good or bad, always consider the big picture: the whole project, the whole product line, etc.