What is the reasoning in inheriting every class from Initializable? In openzeppelin-eth even interfaces inherit from Initializable. Not to mention classes without the initialize function.
Wouldn’t it be better to remove inheritance from Initializable in these classes?
I’m going to pass the ball to @frangio here, who is the lead of OpenZeppelin, but the reason is basically how Solidity linearizes the inheritance graph. If you didn’t add Initializable to every contract, you may end up in situations (with multiple inheritance involved) where compilation would fail due to being unable to linearize the base classes (see here for an explanation of the problem).
@spalladino is correct, this is related to the linearization of the inheritance graph. But it’s not that if we don’t add Initializable everywhere some contracts may not linearize. It’s that we want the linearization to be exactly the same in openzeppelin-solidity and openzeppelin-eth, not only of the contracts in OpenZeppelin but of any contracts that users build by extending them. This prevents headaches when users adapt a contract to be upgradeable, and guarantees that the tests and analyses performed on openzeppelin-solidity carry over to openzeppelin-eth.
Adding Initializable everywhere guarantees this will happen because of the way C3 linearization works. That is very complex to explain in detail in this post, but essentially if Initializable is first in every list of parent contracts, it will end up first in the resulting linearized list, and the rest of the linearization will proceed as if Initializable wasn’t there.
Compatibility of linearisations between oz-eth and oz-solidity is a nice feature. That explains why it is required in contracts without initialize method. But still why is it required in interfaces?
It may not be required in some places, but we added it everywhere to make it a straightforward mechanical process, to reduce the possibility of human error.