6 ms·
> 90. Consider Static Analysis via typing to Obviate Bugs Personally I wouldn't recommend using typings (we've tried around 1 year ago for multiple greenfield
by matesz 6y ago
> 90. Consider Static Analysis via typing to Obviate Bugs
Personally I wouldn't recommend using typings (we've tried around 1 year ago for multiple greenfield services ~5k LOC each):
- you will be better off investing into proper testing (I mean here code coverage), refactoring and onboarding documentatio/handholding sessions with devs who are on top of the codebase
- in practice annotations make code LESS readible, not more (unless variable names and general code structure and conventions are bad)
- remember most Python devs have little experience with staticly typed langauges, so in practice your team will be skipping annotations - e.g using Dict[str, Any], which defeats the whole purpose of annotations; actually seasoned C++ devs will be skipping it once they will see they can get away with it
Typings are still in 0.x version and are constantly changing - do it for fun or to put typings on your CV, but don't expect it's going to help with readibility, bug prevention, documentation. These are solved with proper structure, conventions, testing and developer prep (readme + pairing).
If you believe bigger projects need annotations tell me why Sentry didn't go with them yet?
- Barrin92 6y agoanother solution yet is going back to one of the fundamental principles of message based OO, leaving interpretation of what objects receive and how to handle them to the object. I've always disliked the idea of using static code-evaluation tools on dynamic object oriented languages, it kind of defeats the point, which is runtime dynamism.
- lmm 6y agoThat's not the solution, it's the problem. A large system is impossible to understand when state could be anywhere and any part could be coupled to any other part. I think you're partly right, but ultimately runtime dynamism has failed; even in Python, the costs of being truly dynamic are higher than the benefits.
- Barrin92 6y agothe intention of that proposed solution is radical decoupling though. Think of objects being used analog to network servers. The internet doesn't go down because someone's server changes (the BEAM VM probably comes closest as far as languages are concerned). Objects communicate messages and status and when something crashes it's up to the object to do something, often restart, but either way it's a matter of interpretation. It's the static typing that couples because it introduces global behaviour through its types, which impose meaning from the top. In a truly dynamic system, nobody needs to understand the entire system. I admit it's a fairly theoritcal point because I don't think many people even embrace this paradigm any more, and ironically if they do it's in functional languages. But to say it's failed I think is not right, because nowadays people write dynamic languages basically like they'd write Java, they don't embrace the dynamic aspects.
- lmm 6y ago> It's the static typing that couples because it introduces global behaviour through its types, which impose meaning from the top. I don't think that's true; static typing on a local scale or at interface boundaries is useful precisely because it enables local reasoning. Without those constraints you have no chance of understanding any part of the system without understanding the whole thing. If you go so far as to expose all state manipulation in the type system then that becomes sort of global, but even then I'd argue what you're actually doing is not introducing global coupling but rather exposing the global coupling that was already there. > But to say it's failed I think is not right, because nowadays people write dynamic languages basically like they'd write Java, they don't embrace the dynamic aspects. I think that very fact is the proof that it has failed; even in languages that were designed for it, people prefer not to follow that paradigm.
- deleted 6y ago[deleted]
- orf 6y ago> in practice annotations make code LESS readible, not more Definitely not true, unless you are writing c++ in Python > so in practice your team will be skipping annotations - e.g using Dict[str, Any], which defeats the whole purpose of annotations Using “Dict[str, Any]” doesn’t defeat the whole point of using annotations at all, and adds useful documentation for callers and IDEs. It can also be gradually improved later. > Typings are still in 0.x version and are constantly changing Typing is part of the standard library. Some new things are added, but the interface is very stable. Mypy is constantly changing. > These are solved with proper structure, conventions, testing and developer prep (readme + pairing). And with some degree of type checking/type annotations. > If you believe bigger projects need annotations tell me why Sentry didn't go with them yet? What an odd point to make.
- CraigJPerry 6y ago>> Using “Dict[str, Any]” doesn’t defeat the whole point I think you’ve misunderstood the parent.
- codethief 6y ago> you will be better off investing into proper testing (I mean here code coverage) Type safety and tests are completely orthogonal issues. Gary Bernhardt explains this really well: https://www.destroyallsoftware.com/talks/ideology https://www.destroyallsoftware.com/talks/ideology
- matesz 6y agoThat is really on point, thanks! ps. watched the presentation - the idea here is that static type checking can eliminate entire category of possibile bugs which are impossible to be eliminated by test - for example enforce variables to be of specific type only. It doesn't work that well where in the most bug prone places typings are made optional.
- antpls 6y agoMy personal anectodal experience : 3 weeks ago, I had a new pet project, and decided to go with Python again, which I left many years ago, before Python typing was a thing. I didn't know where to start, so I started by creating a file with data models I would need. Basically C struct-like / record models. All the classes inherited NamedTuple, and I typed all the attributes. I then created a few pure functions based on those classes. NewType is a great addition. When you work with many int or float variables representing different things in real life (price, amount, quantities, etc), it makes the code cleaner and catch some mistakes when you are tired at the end of the day. I gradually stopped to type things when I introduced pandas into the project and types started to be way more abstract. There is probably a way to make typing work with pandas, but I wanted to learn pandas first and get the project running, so I didn't really try. I expected pandas to do dynamic things under the hood to work, so I didn't bother to understand how types work with it. Of course, being a hobby project, there is no unit test and no documentation, so I may not see all the pros and cons of typing. But I have a feeling gradual typing is an interesting idea that will continue to improve. It's nice to have the support of static typing when you need to, but also be able to "just hack" a solution real quick when needed.
- matesz 6y ago> there is probably a way to make typing work with pandas So we did use a lot of pandas as well. The way to make it work is to create custom types and of course each dataframe will have it's own type which is going to be a total mess.
- lmeyerov 6y agotyping pandas seems like an r&d-level problem as it seems quite close to tricky areas like row types / dependent types that mostly only work in theory attempting manual workarounds like pure nominal typing for it as you describe is against the grain of a type system and pushes a lot of work to the user. We just... don't. We stick with class ('pd DataFrame'), and the one extension we are thinking is Index, while getting into actual columns gets into a mess quite quickly. I tried to engage some PL researchers on this awhile back but no go. IMO would be a great project for most type system research students.
- giantDinosaur 6y agoI'm actually quite curious as to where annotations make things less readable. Do you have any examples? I can imagine if the annotations are wrong and somehow pass checks that this would be true - which is a possibility, I haven't worked with type annotations in Python at all.
- matesz 6y agoIn our case biggest problem arose with Pandas, where each dataframe transform would need to have it's own type. When there are a lot of transforms it is more readable to infer what type variable has just by looking at transforms (more or less) or when needing to be precise step through the code with ipdb/jupyter etc. What about incremental typing? That's what we did, and to be honest I wouldn't do it again. Yes, it's nice to see what type function is returning/arguments it's accepting, but if the name is shit type won't tell you much - you are better off spending more time of figure out better naming convention (prepend dataframes with df_ for example) and keep at it. Another problem with incremental typing is that now of course you will have to decide whether to annotate/not annotate, and when reading code thinking why this is annotated and that is not annotated.
- giantDinosaur 6y agoRight. Similar problem to Typescript - generally its best users are those already sold on static types, for many others the temptation of <any> and friends is too much, and interacting with untyped/poorly typed libraries + poor type inference can be really frustrating. Although in that case it's still a massive gain for new projects, in my experience.
- jgraham 6y agoI recently converted a medium size project from Python 2 to 3 by first adding type annotations to everything, then getting mypy to pass with both versions of Python and then fixing up the remaining issues on the unittests. The functionality of the code depends a lot on external services that are accessed via HTTP/subprocesses. This makes it pretty hard to test well; at best your tests end up exercising an inaccurate partial facsilmile of the external service. Overall I didn't really love mypy; the type system it implements seems relatively simplistic and it was frequently easier to change the code rather than work out how to write working annotations for the existing code. The lack of support for decorated property setters in particular was a big problem; this particular codebase makes extensive use of those to annotate methods that require mutable access to the underlying data. Nevertheless I'm convinced that this approach to the migration was much faster and less painful than it would have been to try and figure out all the string/bytes differences without any tooling support except for the tests. And post migration the code seems overall somewhat higher quality than at the start. On balance, I think the lesson was actually that Python isn't a great choice for this kind of project. When you are depending on external services the ability to unit test everything is greatly diminished, but the ability to make type assertions is not. So for correctness you want the latter to do as much lifting as possible. That suggests that other langauges such as typescript (if you still want a language in vaugely the same category as Python), or Rust (if you don't), which come with more expressive, better integrated, type systems, might be superior options.
- ensignavenger 6y agoWhat version of Py3 were you using? There have been a lot of additions to type annotations in recent releases that have made them better. I'm not sure what you mean by lack of support for decorated property setters? Can't you annotate them like any other method?
- wocram 6y agoMypy doesn't like function attributes, https://github.com/python/mypy/issues/2087 https://github.com/python/mypy/issues/2087
- misnome 6y ago> in practice annotations make code LESS readible, not more Agree, and disagree. I think it depends on lots of things, including how "heavy" you are with type annotations - I think annotating everything, or mandating to, including inline variable definitions - is over-the-top and usually makes the code harder to read. Likewise, chasing down every minor type error for the corner cases can end up wasting loads of time for almost no gain. I also won't argue that sometimes the type definitions are excessively verbose and get in the way of reading code, and your point about less experienced devs is also true - for developers who aren't so familiar with type annotations, at worst, they make it harder to understand. But carefully used, they can really aid understanding a function or codebase. We have a large, somewhat messy codebase open source academic codebase where the input to a function could come from dynamic dispatch some ~5 layers away, and usually the first task of diagnosing a problem is working out what you've actually been passed. Type annotations help solve this problem, as a somewhat statically verifiable documentation of inputs. We've found bugs using them. It's probably not controversial to say that expected types/inputs aren't always obvious from the context of a function, and so need to be documented, to help people using the code. The alternatives to annotations are docstring documenting of types, which is defining types but decoupled and in a non-statically-checkable way - so easy to get them out-of-sync, which is easy when developers are undisciplined; naming (hard, and messy for compound types), pyi files (checkable, keeps them out of the way, but decouples definitions from code), or type comment - which solves some of the readability and checkability, but is still harder to keep up-to-date than inline. So, overall I like them and have seen them bring value to the code I work with, even if that's just documentation, but don't think it's a black-and-white issue. I've certainly eschewed using them when helping less experienced developers write small personal scripts, but use them in my own code or when refactoring something vaguely defined to cross-check my assumptions.
- untitaker_ 6y ago> If you believe bigger projects need annotations tell me why Sentry didn't go with them yet? Because we just came off of Python 2 and typing under Python 2 is awful.
- LockAndLol 6y agoAre there statically typed languages that do support reloading parts of the codebase? Type hints in an interpreted language just don't seem to make much sense to me, as in, why use a dynamically typed language when you actually want a statically typed one? What are the benefits or staying in between the two? Besides of course a legacy code base...
- dragonwriter 6y ago> remember most Python devs have little experience with staticly typed langauges, so in practice your team will be skipping annotations - e.g using Dict[str, Any], which defeats the whole purpose of annotations Using mypy or pylance gives benefits even without annotations, and while you can often do better than Dict[str, Any], rough cut annotations like that often, IME, provide value. (For one, they’ll catch paths that would allow either the dict or a key in it to be None when that isn't expected.)