Due to that, I write my first line of code as if it's going to be on production forever, because it will.
Due to that, I write my first line of code as if it's going to be on production forever, because it will.
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.
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.
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.
Any condescension implied is a result of your long-winded rant of inexperience.
Although I have been considering using it for production, it's not what I need in a prototyping language at all.
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.
That said, gdb is probably in the same space as git is: hard to fully use, but the best in its own space.
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).
I did it a lot through university. If you have no experience tackling a certain type of problem, your perception of it tends to change significantly as you build the solution and become familiar with the problem space. It makes sense to throw away what you've written, because most of it was based on assumptions that were wrong.
Other companies take ideas, consider them long and hard - and usually follow other orgs doing something similar who have already proven something works. They do a lot of planning and tend to put much more funding in up-front.
Both approaches suit different businesses. The former being startups and SME's, the latter where market share is already won and now they just acquire other businesses that develop the former way.
If we're considering what people develop at home however.. 99.9% of the stuff I write is never publicly visible, and it's terrible because I'm not a great developer. But I'm not a regular open-source contributor. I issue the occasional patch for shit that's broken for me.
The original waterfall paper[1] advocated for doing an initial version, by which point you'll have understood the problem domain (in miniature) enough to make a better attempt by throwing it all away and reassessing what tradeoffs make sense.
> Without this simulation the project manager is at the mercy of human judgment. With the simulation he can at least perform experimental tests of some key hypotheses and scope down what remains for human judgment, which in the area of computer program design (as in the estimation of takeoff gross weight, costs to complete, or the daily double) is invariably and seriously optimistic. [2]
The myth goes that someone in the Department of Defense looked at the first diagram (which the author claims right underneath is flawed), copied it in a rush for a diagram and that became enshrined in history as "How best to develop software" until agile and what not
[1]: http://www-scf.usc.edu/~csci201/lectures/Lecture11/royce1970... [2]: Page 7 of the above PDF
To me, "I write my first line of code as if it's going to be on production forever" means setting up a testing infrastructure, a reproducible build that can be automated, a CI that runs my tests. An auto-commit system where I can create a PR and submit it to the CI and if it passes it will automatically get merged to main, etc...
Instead of my lamp project taking 1-3 hrs it would have been a week of setting all this up before I was ready to write my first line of actual code.
Are you saying you'd actually take that week? Would you therefore never write something on shadertoy because it's missing all that infrastructure and you can't write code as if it's going to be in production forever?
All of the worst production systems I've worked with are systems where people are running code from many many years ago because they don't know what it does and are scared to touch it.
Write one to throw away, even - perhaps especially - if it goes into production. Write production to throw away.
Then if the code / project / product refuses to die (success!), I can come back some day and refactor without being scared to dig in again.
So even though my original code is a bit messy, I’m not scared to change it a couple years later.
Have you ever had that moment when you say: "Oh damn, now I got it! I should do it entirely differently!" — and then you code up a different approach, the approach that works well enough.
If you had this moment, it was the moment of throwing away the prototype.
I've never written a prototype, nor seen one written, in actual businesses. I've never had an employer with the patience to let me play with a prototype either.
Maybe, but then the previous one was version 1, not a prototype. I've never seen people actually write prototypes, nor management accept time invested on writing prototypes, in any job I've had.
Prototypes always directly become version 1 on production, unless of course the whole project gets canceled mid-development.
Rewrite is always a business decision and need legitimate reasons. You rarely have those reasons, knowledge and time between projects.
Not because the previous version was wrong, but because it became inadequate as business grew and requirements changed.
Convincing management to refactor your code is another thing entirely.
It's not worth doing things "the right way" right off the bat because you might not know what that is. My first version was literally a linear file of statements and console output.
Once I got something working and understood the problem space then I could back and fix it up. The final code looks like nothing like the original prototype although at no point did I actually throw it away -- I just transformed it heavily -- but the theory is the same. It started as a console app even though the final product was not one.
Occasionally I will code that way when I'm fairly certain of what I'm doing but you have to be very careful that you're not painting yourself into a corner.
In my experience, new programmers tend to build a lot of structure for their code that it's not clear they even need yet or will ever need and then often end up solving a problem with much more code than was necessary. It's usually my advice to get something (anything) working end-to-end first and then expand on that rather than the more linear approach.
It's not the holy grail of software development but it ain't shitty code either. Also I tend to use only one web framework - FastAPI, one database - mostly Redis or MySQL and one front end React. Saves a ton of time as I can reuse a most parts of the code.
I do think there is a lot of merit in using something like GAE. Saves a boat load of time but comes at a cost and I am willing to bear the cost to save time.
The people I know who regularly take this approach end up with a really fantastic code architecture in the end, and avoid a lot of pitfalls from their first naïve attempts.
When dissatisfied with an approach I'll often copy a class/function or three into new versions. I'll append the names of the old with 0. Then I start writing new ones with the new approach. In effect throwing the old ones away, even if sometimes it is a gradual process.
This happens frequently in a new project, less frequently in a maturing project, to never in a maintenance project.
However, it has a lot in common with (a severe) refactoring. Generally you're keeping the "overhead" docs, code, and even files, so it is not a complete rebirth, perhaps ~30% of the core code.