Hacker News new | comments | show | ask | jobs | submit login

I've started to come around on a similar thought recently, after a few years avoiding static typing in python. I've been toying with C# specifically.

C# with visual studio is, I think, the most productive environment I've come across in programming. It's ergonomically sound, straightforward, and the IDE protects me from all sorts of relevant errors. Steve mentioned Intellij is a bit slower than he'd hope typing sometimes. I totally agree with that. I think Visual Studio doesn't quite suffer from that (though I haven't worked on huge projects, and that may well affect it). My main problems with IDEs are twofold: for non-static languages like Python, they're just not very good. Sometimes they do exactly what you need, and 70% of the time they're just totally useless (which is a knock on the programming languages more than the IDEs). The zippiness on reaction to my typing is another huge deal. If it's anything other than instantaneous, then I notice my editor in a negative light. When you pair a tremendous IDE with a good language though, the productivity loss of typing becomes pretty much negligible, and the gains for all the other reasons start to become apparent.

Changing one parameter or type on a class or function to refactor, and then just following the chain of compiler errors, reaching the end, and seeing that everything just works exactly how you want it to was a big eye opener to me.

Definitely going to give kotlin a go some time as well.




> Changing one parameter or type on a class or function to refactor, and then just following the chain of compiler errors, reaching the end, and seeing that everything just works exactly how you want it to was a big eye opener to me.

Yup, "following the chain of compiler errors" mostly makes refactoring straightforward. Dynamic typing is fine when the codebase is small enough to keep it all in your head so you know what the impact of a change is. Once you've got enough code or you're not completely familiar with it, the cycle of changing the code, running it, diagnosing errors, changing the code some more while hoping you caught everything etc. becomes tedious and impractical. Simple renaming a field in JavaScript, Python or PHP is a nightmare if you want to guarantee nothing broke so I can't relate to how people don't appreciate strong typing. You're basically badly doing the job of the compiler manually by trying out all code paths yourself looking for errors.


We tend to use tests for just this case. You change anything you want, then see which tests break, and fix all the places.

I definitely agree that dynamic typing doesn't scale as well as static typing, though.


> We tend to use tests for just this case. You change anything you want, then see which tests break, and fix all the places.

Why not tests + static typing? Getting tests to point out breakages is attempting to do job the compiler can do for you but not as well. If you renamed a field in some places but not others for example, you'd have to rely on good enough code coverage to catch this plus deciphering a failing test is nowhere near as easy as a compiler error that pinpoints the exact line causing the problem. Tests take time to write and static typing is giving you many tests for free. You also miss out on automatic refactoring tools and autocomplete.


> rely on good enough code coverage to catch this

Wait, you don't enforce 100% coverage? (Sorry, couldn't resist ;))

I actually mostly agree, static typing is a huge boon for productivity, and certainly allows for less experienced (both new programmers, and new to the project) developers to become productive on a new codebase faster.

However, I think dynamic typing forces a certain familiarity with the codebase that can prove really useful. Yes, it slows learning down, yes it rules the lower end of the spectrum of developers out, but there are still benefits to this required familiarity.

Obviously, when codebases reach a certain size, this falls over. And even before they do, the drawbacks may be more than the benefits, but it's still something to consider.

My personal opinion right now is that these benefits don't exceed the drawbacks, that static languages are better, however I tend to flip flop back and forth on this every other month (or project).


> However, I think dynamic typing forces a certain familiarity with the codebase that can prove really useful. Yes, it slows learning down, yes it rules the lower end of the spectrum of developers out, but there are still benefits to this required familiarity.

Useful in what way? I don't see how static typing is going to make you less familiar with a codebase. Good use of types provides a certain amount of documentation for free as well.


> Wait, you don't enforce 100% coverage? (Sorry, couldn't resist ;))

I know this was a joke, but 100% coverage only means you've covered every code path, not that you've tested every case. Static types allow you to prove the absence of certain classes of errors. Of course, you still need tests for all of the classes of errors that your type system doesn't cover.


My intuition would stay that static typing would rule the lowest end of the spectrum of developers out, and that dynamic typing would allow that lower end to get started coding much more quickly, until reaching the scale at which the false economy becomes apparent.


But if you're writing tests (and writing documentation that documents the expected return type of methods, etc.) you're doing an error-prone replacement of work the compiler can be doing for you.


While I've always preferred static over dynamic, Powershell is what finally got me to actively disliking dynamic languages. Not strongly disliking, but enough that I'll put up with a bit of pain in order to use a static language over a dynamic language.

I made the mistake of trying to build a system in Powershell because the ability to remote into windows boxes was core to it. That was a mistake I didn't see coming.


I developed at a Windows-centric shop for several years using C# and Visual Studio, and I can personally attest, at least in 2013, that stock Visual Studio is pretty far behind Java IDEs in its capabilities. At the time everyone I talked to recommended I get my manager to get me a copy of ReSharper, but it wasn't in our team's budget. At least in 2013, here's where I remember C# IDE support was lacking:

* No automatic incremental compilation. It turns out, this feature is specific to Eclipse alone. In my current job I'm forced to use Intellij and cannot figure out for the life of me why people think Intellij is better. Automatic incremental compilation is a game changer and only Eclipse has it.

* Limited Code analysis and search. For instance checkout this SO: http://stackoverflow.com/questions/282377/visual-studio-how-.... This kind of symbolic analysis and code search feels essential to me in an IDE, and stock Visual studio just didn't seem to have it beyond the basics.

* Weak refactoring and code generation support. ReSharper might bridge the gap a little here, but stock Visual Studio felt way behind.

* Weak ecosystem for plugins and tool integration. With Java IDEs I have excellent integration with unit test frameworks, code coverage tools, checkstyle, my command-line build tool, etc. I remember it taking a fair bit of effort just to be able to run NUnit tests in Visual Studio. Why NUnit? Well, our software needed to build on Linux with Mono so we needed to use a cross-platform unit testing framework instead of the one built into visual studio.

As a side note, I think the plugins ecosystem is another area where Eclipse has an edge over Intellij. For instance, when I tried Intellij's code coverage tool I eventually gave up on it because it had a critical bug I couldn't diagnose that resulted in incorrect code coverage being displayed.


Kotlin has incremental compilation since 1.0.2 last year, both in IntelliJ and Gradle: https://blog.jetbrains.com/kotlin/2016/05/kotlin-1-0-2-is-he...

...and in Maven since 1.1.2: https://blog.jetbrains.com/kotlin/2017/04/kotlin-1-1-2-is-ou...


A lot of this has been at least partially addressed since VS2015. There is built-in code search (ie, "find me any language construct with these letters in it"), there's support for basic refactorings (rename, extract method, extract interface, etc). I got used to all the built-in stuff before someone talked my into Resharper, and found most of the built-in stuff is actually better these days. Faster, anyway.

There's always been codegen support with snippets, although I never found too much need for it, personally.

The tools ecosystem is pretty weak though. I always found TestDriven.NET to be the best test runner, although Resharper's is OK if slow. I actually like NUnit a lot better than JUnit, but YMMV.


My bosses never understood ReSharper so I bought it myself. Worth it just to reduce my frustration at work.


I know that Roslyn the C# compiler visual studio taps into defiantly does support incremental compilation.


> Sometimes they do exactly what you need, and 70% of the time they're just totally useless.

I thought that but PyCharm scores way better than 70%. I even trust it to do automatic refactors. Sometimes...

> The zippiness on reaction to my typing is another huge deal. If it's anything other than instantaneous, then I notice my editor in a negative light.

Maybe I grew up on IDE's but I type stuff in full only if autocomplete fails me. Maybe I have an appalling memory. Or maybe I'm really slow at typing. Or maybe my variable and method names are too short.


I think I'm pretty sensitive to even a minor typing delay. That's not necessarily true for everybody, but it irks me.

> I even trust it to do automatic refactors. Sometimes.

Function extract refactors and the like are definitely within the realm of possibility. Once you want to refactor code across many files it becomes a lot harder in dynamically typed code, for sure.

I guess for a long time I sort of had this view of "ooh I have this awesome expressive language that won't get in my way and I can just power through it all". Don't get me wrong, I totally love python as a language. But I think languages like C# have started to make typing feel like it's more out of your way with type inference, etc.

I mean, this is the sort of code you can write in C# these days (to take a super trivial example):

  var somestuff = someList.Where(x => x.Id > 7)
    .Select(x => x.Name)
Typing in this case is 100% out of your way, but you get all the benefits regardless, and you get all those sort of nice functional-style list operations you expect in other languages.


More often snippets like this can be even more straightforward:

  var somestuff = from x in someList
                  where x.Id > 7
                  select x.Name


Except when you have to wrap it in parentheses and tack a .ToList() onto the end of it, or use something outside the subset that the query syntax supports, it starts looking considerably more ugly than chaining the functions together.


The obvious answer is don't wrap a good query in parentheses, use a second line:

    var somestuff = from x in someList
                    where x.Id > 7
                    select x.Name;

    var somestuffList = somestuff.ToList();
For what it is worth, I personally consider ToList() harmful. I've done a lot of LINQ performance work and the first place I start is with a project-wide search for ToList and start to delete and/or replace calls to ToList to things more appropriate. List is more often than not the wrong data structure for a query result and I've seen too many people use ToList as a debugging crutch without understanding its performance impact.


They're different ways of programming -- it's where you spend your brain power. You can see codebases that weren't built in IDEs: they generally don't have strong naming conventions in their classes/structures/functions.

One of my hobby projects is in C, and I prefer using an editor to an IDE. Because of an accident of history, public methods tend to be named like `P_PlayerCommandRead`, where `P` means (generally) "physics", and `Player` and `Command` are essentially nested namespaces. I specifically name things this way so that I can type them quickly without spending a lot of brain cycles on figuring out the scopes.

I'm not saying code bases built with IDEs don't have consistent naming, or that code bases built without IDEs have hellish homegrown naming. But it's kind of a "how you grew up" thing, and it latches onto a lot of underlying feelings you have about coding in general.


More recently I've come to the conclusion that most of naming must be influenced by "how you grew up". As someone who has mostly touched the Java and Python ecosystems while learning to program, I frequently run into names that seem "weird" to me, because they replace often-used technical words (from those ecosystems) through more obscure synonyms.

C++ also often had that (replacing 'map' through 'transform' and so on) - but since it's a standard, at least it is usually more consistent in its own internal logic. Same goes e.g. for LINQ, which was influenced by SQL instead of LISP-like collection transformation functions.


It definitely is. I started with C++, and at some point I found my way to Common Lisp. At first I was surprised at how many weird names the latter has... and then I got used to them, started to like them, and now I shake my head when I see new languages inventing new names for things that had a perfectly good Lisp name already, probably because they didn't know the concept had already existed for 50+ years...


> Same goes e.g. for LINQ, which was influenced by SQL instead of LISP-like collection transformation functions.

This was an explicit decision to make functional programming more palatable to mainstream developers.

Have you read the paper from Erik Meijer?


It's pretty obvious that this was a conscious decision. And it makes a lot of sense too, if you think of Microsoft's target audience.

But still - if you're used to the functional "default" naming schema (which mostly comes from math, anyway), it's nontheless something that can be a bit irritating (especially since there's also the "inline SQL syntax" you could use alternatively).


I think part of that is that PyCharm is a JetBrains product. Those guys are the preeminent IDE makers out there at this point. Even Visual Studio is playing catchup to the stuff that they've been offering for years with ReSharper, and Rider is making a compelling case at becoming the best C# editor out there.

I cringe when I have to deal with one big legacy product of ours that still hasn't been converted from a Eclipse project to IntelliJ; it's an order of magnitude more painful to work with.


> Sometimes they do exactly what you need, and 70% of the time they're just totally useless (which is a knock on the programming languages more than the IDEs)

See, that makes a lot of sense on the surface... And I find it playing out across a lot of the modern IDEs like PyCharm...

But I don't think it actually has to be that way.

DrRacket blew most of what I knew out of the water. It could refactor for me, trace functions and calls to definitions through multiple libraries, which included argument arities. I could write code in the REPL and push it back up into the editor, or vice versa.


I just disable automatic autocomplete in IDEA and use ctrl+space explicitly when I need it. You still have all the smart functionality of the IDE, but you also get zippy typing.


If you know C# you don't really need Kotlin. You can write windows, windows universal, web, linux console, Android and iOS apps, all native, and all in C#.


I don't think that's necessarily true. Dotnet is still just getting started on Linux, meanwhile the Java ecosystem is insanely mature on Linux. Fwiw, I have been writing dotnetcore lately, and enjoying it, but it definitely doesn't match the java ecosystem in terms of library maturity. Because of Google/Netflix/etc, Java on Linux is a really interesting beast

Not to mention that toying with another language is not such a complicated endeavor once you're 5-10 languages in. The great thing about C# and Kotlin is they've been good at adopting features from other languages that are already good and familiar, so picking them up is generally super easy.


The Mono runtime is quite mature and capable on Linux as the Java ecosystem. Many very good GTK/Gnome apps have been written in C# over the years (Banshee, F-Spot, etc).

.NET Core is awesome, but don't forget that it's not the first time .NET has been available to Linux developers.


Some of us still develop desktop applications on Linux in Java SE. Kotlin is a godsend.


> for non-static languages like Python, they're just not very good

Yup. Because they can't.

Without type annotations, IDE's are pretty much incapable of offering automated refactorings without human supervision (and yes, that includes Smalltalk IDE's).

They can give you some primitive auto completion and navigation, but that's pretty much it.


> Yup. Because they can't.

Actually they can.

> incapable of offering automated refactorings without human supervision

> (and yes, that includes Smalltalk IDE's)

Patently false. Everyone repeat after me: automated refactoring was invented on Smalltalk with the Refactoring Browser. Again. Automated refactoring was invented on Smalltalk with the Refactoring Browser.

The lack of static type information was considered a major potential problem by the authors when they started the project. They later reported how they were surprised when it turned out it wasn't.

So please stop spreading misinformation.

'This is absolutely the greatest piece of programming software to come out since the original Smalltalk browser. It completely changes the way you think about programming. All those niggling little "well, I should change this name but..." thoughts go away, because you just change the name because there is always a single menu item to just change the name. When I started using it, I spent about two hours refactoring at my old pace. I would do a refactoring, then just kind of stare off into space for the five minutes it would have taken me to do the refactoring by hand, then do another, stare into space again. After a while, I caught myself and realized that I had to learn to think BiggerRefactoringThoughts, and think them faster. Now I use probably half and half refactoring and entering new code, all at the same speed (I should instrument to measure this). -- KentBeck'

http://wiki.c2.com/?RefactoringBrowser

http://www.refactory.com/tools/refactoring-browser

https://link.springer.com/chapter/10.1007/3-540-49255-0_180


Here's the thing: guided, interactive refactoring is not the same as automatic refactoring. If I can hit a button to inline all usages of a method (as in IntelliJ), that's not the same as using a tool that can point out candidate locations for inlining what might be the method.

Furthermore, the reason Smalltalk pulled all this off is because it is/was metadata-heavy. Every object could be interrogated about its shape and capabilities (in the form of asking about its "slots"), even though there were no static type annotations. It's sorta like the runtime-typing stuff done by Dialyzer in the Erlang/Elixir world nowadays, and the tooling and code all ran together in the same runtime/VM instance.

Clearly this is not the case for Python, Ruby, or Javascript, where the tooling runs in a separate process from the code, and there's very little metadata that tooling can query without just up and executing the whole program. In fact, this particular lack of metadata is why PEP-484 exists (https://www.python.org/dev/peps/pep-0484/) adding "type annotations" that are really just runtime metadata hints.

So no, a language without static typing or metadata is not as tooling-friendly as a language with such requisite available analyzable information, and certain categories of refactoring cannot confidently be done automatically.

Smalltalk was not as "loose" as Javascript or Python, not by a long ways. The level of metaprogramming it was capable of was only enabled by the level of metadata it made available to its hybrid, in-process runtime/design-time tooling.


> Clearly this is not the case for Python, Ruby, or Javascript,

Javascript objects are inspectable and modifiable in exactly the same way as Smalltalk objects are. All browsers support this today.

This inspection capability has nothing to do with static/dynamic typing.

> So no, a language without static typing or metadata is not as tooling-friendly as a language with such requisite available analyzable information, and certain categories of refactoring cannot confidently be done automatically.

Yes, they are. You can do anything with IDEA/Eclipse + Java that you could do in Smalltalk + IDE.


> > (and yes, that includes Smalltalk IDE's)

> Patently false.

It's a mathematical fact.

Without type annotations, refactorings are never safe and need supervision from a human.

Did you notice that the "Refactoring Browser" calls itself just that, not "Automatic"?

Because it can't provide that guarantee. Even renaming a function is dangerous and can break a program when you don't have type annotations.

I have a lot of respect for Smalltalk and the pioneering work it accomplished, but the refactoring browser was just a powerful string replacement engine, nothing more. Which is not a knock on the engineers and scientists who invented it: it simply, mathematically, could not do more than that.


> Without type annotations, refactorings are never safe

There is a difference between "I can prove this is safe" and "this is safe". You guys need to start figuring out the difference between theory and practice.


In practice, "this is safe" often transforms to "I thought this was safe" at the most inopportune moment.


Nope, your theory says it should. In practice it doesn't.


Please. With all due respect towards Smalltalk and all the pioneering work it did, stop it with the Refactoring Browser as a shining example for automated refactoring.

No, it really can't, not with the correctness guarantees of a statically typed language.

If you are required to run tests to do refactoring, you're simply not on the same level.

The last paragraphs in this link for an example (Ironic title, I know. :) ):

http://wiki.c2.com/?DynamicTypesEaseRefactoring


Automatic refactoring in dynamic languages are nowhere need to those in java. Just rename method - with static typing you know it was changed correctly everywhere, full stop. Implementation of refactoring code is easy. With javascript, you just don't know what can potentially come in as argument of function, so you don't know whether object function call can or can not be renamed.

Smalltalk authors seeing static typing as major potential problem when started years ago does not make it actual problem today.


Please: re-read the comment and preferably the links as well. Once again: automatic refactoring tools were invented on Smalltalk.

> Smalltalk authors seeing static typing as major potential problem

Authors saw lack of static typing as a major potential problem. It just wasn't. Again: reading helps. A lot.


This may depend a lot on coding style and uniformity of coding conventions, something likely to be the case on the Smalltalk system (as it was designed by a small and focussed team) and less likely to be the case on a system using many different libraries, some of which might have names conflicting with names you use.

Even then you still need manual supervision in that it may work in 99% of the cases, but for a particular method it is more difficult to automate (because it's meaning is more overloaded).

And of course just because the authors foresaw problems and decided that it was fine doesn't mean someone used to refactoring in static type system can't have more stringent norms.


Yours is first and foremost a theoretical argument. The authors of the Refactoring Browser and I understand these theoretical concerns (about not having static type safety). However, there is theory and there is practice. The two are not identical, and practice trumps theory (see also: science). And in practice, that theoretical concern appears to not have been an issue.

You also argue with hypotheticals (may...depend, likely be the case etc.). Why is that so? Is it because you can't accept that reality doesn't conform to your theory?

Once again: the argument was "you can't". That is as patently false as can be, in reality is it not just "you most definitely can", but "this system is extremely well suited for building this type of tool and in fact the whole category was invented on that system".

And your theoretical concerns notwithstanding, people who have actually used the system consider it best-of-breed.

A scientific approach adapts theory to observation. Theology adapts observation to theory.


> You also argue with hypotheticals (may...depend, likely be the case etc.). Why is that so?

Partly because my experience with Smalltalk has always been that my experience is less positive than what others claim to encounter (this is not just about refactoring, where at least once I wanted to rename a method, but this method name was also used in a different context where it shouldn't be renamed, typing would have made this irrelevant; but also about things like Monticello where I got far more conflicts and things that didn't work out of the box than I consider reasonable or knew how to handle). This may have been the way I got introduced to the platform, but it colors my skepticism about the generality of the observations.


Well, he/she isn't saying anything about smalltalk, but talking about python. Are you sure these two pose the same problems when it comes to automated refactoring? Apart from just lack of static typing, these languages could be miles apart when it comes to how dynamic they are and what problems this poses to automated refactoring. For example, the fact that attribute access in python can be delegated to a function that will receive the attribute name as an argument and decide whether that object has this attribute or not and what it is, or the fact that you can dynamically generate a new class whose attribute names and implementation come from outside as function arguments. How would you deal with automating the renaming of such an attribute when it is defined and used across wildly varying circumstances. I have no idea if smalltalk can do this, or even if my examples are good examples of showcasing the automated refactoring problem, but just raising a point.


> I have no idea if smalltalk can do this,

It can.

> if my examples are good examples of showcasing the automated refactoring problem

They're not.

More to the point: Smalltalk is as dynamic a language as practically possible and was like that for two decades before Python existed. The `__getattr__` from Python, `method_missing` from Ruby, and `__index` from Lua are all inspired by Smalltalk's `doesNotUnderstand`. The concepts of metaclasses and first-class message sends was invented in Smalltalk. The idea of inspecting code using a GUI instead of flat text files also originates with Smalltalk. Refactoring, as noted by GP, also came out of Smalltalk-land. Smalltalk gives you all that without any static typing in sight.

How? Smalltalk is special. Normally, you have your code: a static blueprint of what's going to happen; and a program: part of computer memory which your code gets loaded into and gets executed. This is true for both statically and dynamically typed languages: the familiar type something -> hit "Run" -> see if it worked cycle works equally well in Java and in Python.

Smalltalk is not like this. With Smalltalk, all you have is a program. It's always running. You hand it the code and it patches itself dynamically in memory. The classes are live objects you can query. Metaclasses are, too, objects you can query. They implement methods for refactoring. It's easy, because there's no need for any parsing, statical analysis of any kind: you just iterate over all the classes in your system and ask them one by one: "do you call such-and-such method?" And the classes inspect themselves and say: "why, yes, I call it when handling such-and-such messages, here's the list".

Really, Smalltalk is special. It's not unique: Forth and Common Lisp come to mind, Self, Lua and Io too. But it's special and very few modern languages come close to its capabilities.


> isn't saying anything about smalltalk

Very specifically was: "(and yes, that includes Smalltalk IDE's)"


I often use WebStorm (Intellij variant), and I am continually annoyed by its inability to keep up with my typing. I do like the IDE, but I do wish it was more responsive. It often feels like a heavyweight, taking long to do any operation, especially starting up.


I've never seen anything that tried to do intellisense in JavaScript that wasn't slower than molasses. The quickest way for me to get Visual Studio to crash is to open two or three small .js files, watch the memory usage skyrocket, and the editor speed grind to a halt.


Webstorm is significantly better than VS for JS, or at least it was with VS2013.


I use it for dart


Once you manage to get the shortcuts, create a few "Views" it gets even better.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact

Search: