@kevlin Oh where to start?
TDD/BDD (obviously-both terms seem to have morphed into “We have some random, impenetrable tests”)
Automated Testing
10 minute build
Continuous Integration (but still using Feature Branches & long lived branches)
Shift left (so many folks assume this means “in the pipeline”)
Build once (most don’t)
Dependency Injection
Single Responsibility
Open Closed
(actually, all of SOLID!)
I'm sure you will find plenty of other material 🙂
+ "refactoring" but where it changes behaviour, too.
@kevlin @xris this has been encouraged by MISRA C. *Much* auto code is marred by it.
@PeterSommerlad took a deep dive on this. IIRC, conclusion was it dates back to pre-structural era: don't jmp into/out of the middle of a procedure. It was then adapted by MISRA as a rule for ensuring mid-function `free`s never got skipped.
SESE stems from a time as a principle of structured programming. all current languages with call-return semantics follow it. so a procedure is already following SESE. That safety guidelines translated SESE to a single return statement is BS from people not knowing its origins. We filed a change request for against one of the ISO safety standards and abandoned single return requirements for MISRA-C++
the source is not MISRA but IEC/EN 61508-3 and ISO 26262 safety standards that mutated SESE to "single return statement per function" without understanding the implications of either. IMHO single return statement makes code more complex and thus more error prone. Therefore we fought to get rid of it.
@kevlin The citation is to the Liskov paper that everybody cites, which I believe is the first one that talks about hierarchy and inheritance:
Liskov, Barbara. Data Abstraction and Hierarchy. ACM SIGPLAN Notices V23N5, October 1987, Addendum to the OOPSLA 1987 Proceedings. https://dl.acm.org/doi/10.1145/62139.62141
For convenience, the oft-quoted section that introduces the notion of substitution is the first paragraph of 3.3, “Type Hierarchy”: (1/6)
«In this case, operations that not all real devices can do must be specified in a general way that allows exceptions to be signalled. For example, ‘get_char’ would signal an exception when called on a printer.»
A printer throwing an exception in response to ‘get_char’ is similar to a Java unmodifiable collection throwing an exception in response to a mutation method. (6/6)
@kevlin
@stuartmarks Ah, OK, I was familiar with this section and conclusion, but I realise now I misread your original post.
I had assumed that you were saying exceptions were unconditionally OK, whereas I now see you carefully stated — and I overlooked — "... when permitted by specification", which naturally leads to covariant exception substitution.
In which case, yes, we are definitely agreed on this interpretation! Thanks for taking the time.
@kevlin the most common I see misunderstood ist, Model-View-Control, although not really a principle, is it?
The confusion stems mostly from the naming convention of naming business logic processing classes as 'controller'. Since most frameworks handle both view and control, and most devs never implemented input devices, 'control' is very unintuitive.
Even big companies confuse this (i.e. Microsoft as documented in their MVVC documentation, for example)
@kevlin
“short functions”: in the original paper it was “not more than 100 lines” which got reduced to “should fit on one screen” (which was 80×25 back then). Ans then suddenly people started to break up 5 line functions.
And everything that is wrong with the clean code book.
I tried to find the original document in a quick search, but did not succeed. If I remember correctly it was some ALGOL or FORTRAN document from the 1960 or something (not a reference manual but a document discussing how to write code). I'd say Bell Labs, but I am not sure at all.