> >> it's the type system that ultimately underpins the kind > > >> of tooling you get with things like IDEA > ... > >> So I concur with Michele - "the larger the code base, > >> the smaller the relevance of the language on the > >> productivity.". The problems I've found are to do with > > >> structural complexity and behavioural unpredictability > - > >> things like non-locality of change, mind-numbing > >> logic, lack of cohesion, monolithic codebases, > >> unexplained wtfs, bad abstractions, the absence of a > >> coherent "physics" for the system of the code. Plus the > > >> overall entropy and drag of poorly written code. > > > Well, if the type system is static, you have tooling, > otherwise you pretty much don't.
So that's incorrect; at best I have better tooling. But imo most of what you say I need is achieved by typing function arguments, which strikes a good balance between extremes. This is one reason I find Scala interesting and sometimes wish Python would support type declarations on functions/methods.
> For instance, all the problems you mention: structural > complexity, etc. are all reasons we have static analysis > tools. Most of your examples scream "refactor" e.g., > extract interface, extract method, rename, modify > signature, introduce variable, replace inheritance with > delegation, etc. etc.
They scream redesign that impact contracts/interfaces and changes to classes that cause further changes across system boundaries. If it was just refactoring, it would be internal details at least according to classic definition, no? How does a static type system find all callers for published interfaces? Or is the assumption that the entire codebase is monolithic/closed?
> While refactoring you need to find > usages of types, methods, properties, etc. And you need to > look for types, declarations, etc. Even if the large > system is "perfect", you can't keep it all in your head, > so you need code completion.
I can get that kind of information from indexing code (eg akin to python tools such as pydev). Not being able to keep a system in my head goes well beyond the type system of a programming language.
> And all these features must > be reasonably deterministic in order for them to be > reliable.
"Reasonably" being the important word. But look, it's either deterministic or it's not, right?
So here's the question - do I *require* said determinism to maintain a system?
> You simply cannot achieve this level of > sophistication with a dynamically typed language; by > definition it's not possible.
I think you need to back this claim up. I am not saying static typing will not help, I am saying it does not seem to me to be an absolute requirement.
> The truth is there aren't any "perfect" large systems; > none that stay perfect anyway. And, as it happens, > successful software is often the least "perfect". To the > uninitiated it evolves in "peculiar" ways, usually under > pressures of competition and deadlines.
I know all this, but now I'm confused. On the one hand you seem to be saying I simply cannot achieve anything without a static type system as the codebase grows - on the other it's all commercial tradeoffs and contingencies - so which is it?
> The real issue was the business logic, which was very tricky > to understand and to get right (it even contained bugs > in the first place). The issues with tools very nothing > compared to that.
The absence of types makes everybody's life hard: the developer trying to use or understand the code and the IDE.
All these tools you list are useful and are certainly better than a dumb text editor, but refactorings such as "replace inheritance with delegation" or "extract method" are an absolute nightmare to do in a dynamically typed language.
The fact that these refactorings come for free and are automatic with statically typed languages guarantees that the code rot can be kept in check, and as such, I find that they are a vital tool when you are dealing with massive amounts of code.
>> They scream redesign that impact contracts/interfaces >> and changes to classes that cause further changes >> across system boundaries. If it was just refactoring, >> it would be internal details at least according to >> classic definition, no? How does a static type system >> find all callers for published interfaces? Or is the >> assumption that the entire codebase is >> monolithic/closed?
Regardless of published interfaces, redesigning involves heavy internal code changes between dependent modules. Making changes like that invariably involve refactoring and lots of it (if you have the tools).
Considering published interfaces, you're not any better off with a dynamic language. In fact you are probably worse off. At least with a static language like Java you have a proper contract in terms of an interface. If the API changes users of the old API can deterministically search and fix their *usage* of it (with refactoring). Not so with dynamic languages.
>> I can get that kind of information from indexing code >> (eg akin to python tools such as pydev). Not being able >> to keep a system in my head goes well beyond the type >> system of a programming language.
Pydev is not in the same league as IntelliJ IDEA, not even remotely close. If code indexing were the answer, we would have dynamic language IDEs on par with Java's by now.
>> > And all these features must >> > be reasonably deterministic in order for them to be >> > reliable. >> >> "Reasonably" being the important word. But look, it's >> either deterministic or it's not, right? >> >> So here's the question - do I *require* said >> determinism to maintain a system?
Do I *require* electricity in my house?
I'll say this: Dependable tools require reasonable determinism. The necessity of dependable tools grows with the size of the system. Thus a large system loses vitality without reasonable determinism.
>> > You simply cannot achieve this level of >> > sophistication with a dynamically typed language; by >> > definition it's not possible. >> >> I think you need to back this claim up.
How about this. Show me an IDE for a dynamic language that approaches IntelliJ's level of completeness regarding refactoring, code completion, usage searching, etc. If it were possible, I would not have to ask.
>> > The truth is there aren't any "perfect" large systems; >> > none that stay perfect anyway. And, as it happens, >> > successful software is often the least "perfect". To >> > the uninitiated it evolves in "peculiar" ways, >> > usually under pressures of competition and deadlines. >> >> I know all this, but now I'm confused. On the one hand >> you seem to be saying I simply cannot achieve anything >> without a static type system as the codebase grows - on >> the other it's all commercial tradeoffs and >> contingencies - so which is it?
Hey now, I didn't say that. I said that without static typing you can't the build tools required to evolve a large system and remain competitive. So it's both. We can't absorb the engineering tradeoffs we make today unless we have solid tools to help navigate, understand, and eventually change them tomorrow.