In a previous job, I wrote an autotrader which by now I believe will have handled hundreds of millions of pounds in untyped Python 2. Certainly tens of millions.
There were a number of approaches I used. This is a few years back now, so apologies if anything is unclear.
You can fake a type system to some extent in py2 by using methods and copious 'isinstance' checking.
For example, Money<EUR> + Money<GBP> can be made illegal by overloading addition operators. Strings which require some sort of meaning can be given classes and functions which use them can use isinstance and friends to perform runtime type checks.
Another is indeed the use of 'raw_whatever' and 'whatever' in identifiers, what I now know to be "apps hungarian" notation. 'raw_whatever' would have a similar definition to Joel's unsafe user input. It might come from an API of some sorts that you don't truly "trust".
Similarly, that sort of variable naming approach applied to function parameters. Passing a 'dog_id' to a 'cat_id' function _may_, in certain cases, be possible if both were flat strings (and not objects that could be isinstance checked), but I favoured a variable naming approach (along with calling functions by keyword argument) that would result in this at least being visible after problems came up (e.g. you'd see myfn(dog_id=cat_id) and feel an urge to hold your nose).
There were tons of these sorts of things all over the codebase, tests, etc, and the system outperformed the previous ones by a significant margin. My understanding is that it still hasn't suffered any significant losses; only some minor API issues that were outside of our control.
Super fun project. Nowadays I'd just use a typed language for it and interface with the py2 stuff via an API. Or at least make use of mypy. But that autotrader was what the company needed at the time.
Details are in my bio if anyone has further interest.
There were a number of approaches I used. This is a few years back now, so apologies if anything is unclear.
You can fake a type system to some extent in py2 by using methods and copious 'isinstance' checking.
For example, Money<EUR> + Money<GBP> can be made illegal by overloading addition operators. Strings which require some sort of meaning can be given classes and functions which use them can use isinstance and friends to perform runtime type checks.
Another is indeed the use of 'raw_whatever' and 'whatever' in identifiers, what I now know to be "apps hungarian" notation. 'raw_whatever' would have a similar definition to Joel's unsafe user input. It might come from an API of some sorts that you don't truly "trust".
Similarly, that sort of variable naming approach applied to function parameters. Passing a 'dog_id' to a 'cat_id' function _may_, in certain cases, be possible if both were flat strings (and not objects that could be isinstance checked), but I favoured a variable naming approach (along with calling functions by keyword argument) that would result in this at least being visible after problems came up (e.g. you'd see myfn(dog_id=cat_id) and feel an urge to hold your nose).
There were tons of these sorts of things all over the codebase, tests, etc, and the system outperformed the previous ones by a significant margin. My understanding is that it still hasn't suffered any significant losses; only some minor API issues that were outside of our control.
Super fun project. Nowadays I'd just use a typed language for it and interface with the py2 stuff via an API. Or at least make use of mypy. But that autotrader was what the company needed at the time.
Details are in my bio if anyone has further interest.