There are also ways to turn runtime contract checks into static verification checks. See my other comment for details/links - https://news.ycombinator.com/item?id=50108112
Again, asserts are just the "mechanism" to express pre/post/inv "policies" in code. Without having an understanding of pre/post/inv from the pov of Hoare Logic, merely using asserts will not give you much benefit. Documentation is quite important here.
Both the above can be seen in the design of the Eiffel Language where they are integrated into proper syntactical mechanisms. Once you understand the concepts here, you can apply them explicitly even if your language does not support the needed syntax (eg. Contracts). See Bertrand Meyer's OOSC2 for details - https://bertrandmeyer.com/oosc2/ Specifically "Design-by-Contract (DbC)" and "Inheritance Techniques" and "Using Inheritance well".
Also relevant is my other comment here - https://news.ycombinator.com/item?id=42788947
> programmers won't write them, or will write them incorrectly.
I think this is a matter of education and discipline and not an argument for not using DbC.
If it is okay with you could you share your dissertation and maybe highlight the key points which led you to your conclusion of "They are generally useless"? I think it would be useful to know.
You should also look into Meyer's "Design By Contract" technique for writing "correct" OO and other-paradigm programs. This is of great value in real-world programming.
PS: You might also find another Meyer's book Agile! The Good, the Hype and the Ugly quite instructive - https://learning.acm.org/techtalks/agile
Also different from assertions in that 'class' invariants applies to every public method of the class.
: All I know about 'Design by Contract' I learned it in the (very good IMHO) book Object Oriented Software Construction by Bertrand Meyer (he made the Eiffel language).