Hacker News new | ask | show | jobs
by pansa2 1877 days ago
> I cannot relate to people who make prototypes to throw away, I've never done it, and I don't know why I'd do it.

When I'm at the prototyping stage, I don't yet know how to solve the problem. That means I need to iterate quickly, which affects my choice of language (Python) and the amount of time I'm willing to spend keeping code clean (very little, because I could hit a dead-end at any point).

But once I have a working prototype of a solution, my users need it in the form of a fast, standalone binary, and my colleagues need code that can be easily understood. This requires using a different language (C++) and more disciplined coding practices. The only way to get this is to rewrite for production, and then "throw away" the prototype.

3 comments

I prototype in C++ all the time. And then refactor it to production code if it makes sense. Switching between languages seems like a waste of time to me.
Only if you don't know any other languages or the domain is well-known. Python is significantly more productive in the short term.
I can program in Assembler, C, Java, C#, JavaScript, Typescript, Ruby, Haskell etc. And there is zero empirical evidence that Python is “significantly” more productive in the short term. My guess is that it is only true if you don’t have much experience in any other languages.
when writing complex algorithms the best approach is usually to write pseudocode, just literally write comments that explain what you are going to do in that particular block of code but not actually code it at all. that lets you build the mental model of how it's all going to work, but without any of the overhead of actually writing code. then write the main algorithm but leave some functions as stubs, just name them and have an idea of what they're going to have to do. then finally you go through and write the low-level details.

using python is both unnecessary and counterproductive. variable names don't take hardly any time at all to type, the logical design is what's actually challenging, and python isn't going to help you understand what needs to be written faster, especially compared to just writing pseudocode.

using python because it's faster for design iteration is a lot like a coder who uses a dvorak keyboard because it lets you type faster. The actual difference between two programmers of equal skill using two different languages is, by and large, nil, because the actual act of typing a program is barely any of the time involved at all.

but on the other hand it does make a massive difference in the long term in code maintainability. having to read someone else's code, especially bad code from someone else, and figure out what goes in, what happens with every variable assignment, and what returns back? Python doesn't give you any hints there, everything is established by programmer convention particular to your specific codebase, it's a mental load on top of the actual programming itself. And sure there's IDEs to help carry some of that burden, but IDEs also make developing statically typed languages a snap, and IDEs for statically typed languages can be even more powerful with their refactoring tools because they can make more assertions about what is going on in the code they're working on.

there's a reason that basically any large codebase that starts out as dynamically typed realizes their mistake and hacks in static types after the fact. Facebook was written in PHP, then realized they were screwed and created a typed dialect of PHP called "hacklang" that they gradually rewrote their codebase into. Microsoft realized their Javascript was turning into a mess and wrote TypeScript to get types into their javascript. Same thing, it's a superset that lets them run their existing codebase while they port but port their existing code and write new code with types as they go.

https://en.wikipedia.org/wiki/Gradual_typing

Once you get a non-trivial codebase, the benefits are just too big to ignore. It's fine when you wrote all the code yourself, and you know how it works and it's all up to your personal quality standards, but once you have to start working with other people's code the regularity imposed by a statically typed language is just too beneficial to ignore. And that's what Microsoft and Facebook and others have all found out in practice. Small, highly skilled teams, sure you can do whatever. Big corporate teams with coders of varying skill? Types help.

Now, what do you do if you're not Facebook or Microsoft and can't afford to implement a whole new programming language/toolchain/etc to fix a bad choice of language? Make better choices up front.

dynamic typing is the dvorak of programming languages. it sounds super cool, and everyone hates verbose java 6 code, but it's just not a productivity boost in practice, in fact in the long term it's the opposite. Best case it improves on something that's not a bottleneck, worst case it actually reduces productivity in a large codebase, and that's the experience from Facebook, Microsoft, and other big companies with good engineering teams.

but the dynamic vs static typing is an age-old slapfight and nobody's mind is going to change.

Python has often been called "executable pseudocode." Avoid it and similar techniques at your detriment.
python still has syntax and still requires you to actually write code. your trite meme aside, python is not actually executable pseudocode, and writing actual pseudocode is still faster and requires less specificity (therefore less mental overhead).

you're welcome to do whatever you want, but I'd rather do a pseudocode outline and then fill it in and have a statically typed program when I'm done, than to do a first-pass python program that is written as I go with no pseudocode.

again, the actual act of typing the code is a pretty insignificant part of development, what really takes the time is debugging all the edge cases and maintaining it for the next few years, and that's where static typing gives you a bit of an advantage. python is very much like the programmer bragging about their dvorak keyboard, it just doesn't improve on a part of the development lifecycle that is a particular bottleneck, and it does pose disadvantages down the road for maintenance and collaboration on a larger codebase. A little mandatory structure (not too much) is indeed a good thing when you have to work with other people's code (including past-you code).

And jeez, "ignore at your own risk!", maybe not intended but you just come off as dismissing a substantiative argument with a meme and a condescending dismissal.

The difference in productivity is substantial. Prototyping in a Python-like language and then porting to a more difficult but safer one has also shown good results as discussed in the rest of the thread.

Any condescension implied is a result of your long-winded rant of inexperience.

Is this stealth promotion for Go?
I wish there were a language that I could use for both prototyping and production, but Go isn't it.

Although I have been considering using it for production, it's not what I need in a prototyping language at all.

Go does not have a REPL with interactive introspection and fiddling capabilities. Such a thing is key for prototyping.
go run main.go works just fine and is blazing fast compared to many compiled langs.

There's also scripted go, which may solve some of what you need.

Print debugging works for 99% of introspection needs. Most times go does just as advertised, though learn of common pitfalls to avoid.

Haskell has REPL and dynamic introspection, but everything takes 4-20 longer times. Maybe it's faster/better with massive practice.

Honestly, most codebases just sucks, including my own, unless you redo alot and put deliberate efforts over time. Which is irrelevant to sales (point in link). Alot of value in battle-tested code turns invisible too, locking knowledge away in obscurity. Go at least is pretty readable and mostly explicit.

REPL with hot-loading is better than print debugging, especially if you work with graphics, but also if you do weird stuff in the memory space than make strings unreadable for human beings.

That said, gdb is probably in the same space as git is: hard to fully use, but the best in its own space.

I envy your use cases, but it's 25 years since I used debuggers. I just didn't have the use case.

With Haskell being a tough nut, maybe it could help though. So may as well try it.

I found git trivial to start using immediately, and almost possible to understand from first principles (ie. almost like versioned subdirs improved). It's a bit more involved, but with right online content, one starts to catch on (leaving magical thinking).