8 ms·
Throw away code
- formerly_proven 6y ago> I’m ashamed to admit that some 1000 lines long shell monster kept running in real production for years ‒ but it did run That's kinda cute.
- Kednicma 6y ago"In the long run every program becomes rococo - then rubble." ~ Alan Perlis
- igor47 6y agoI've been coming at this from the other side and writing typed Python for my little experiments. You can add just enough type hints to make life easier, but not go obsessive over it. Then vim with Python ale tells me if I've done the right thing in a deeply nested loop without having to actually execute it.
- hangonhn 6y agoI've really embraced type annotation and mypy for Python. Partly because it really helps the Python language server in VS Code with autocomplete. It has also saved me a few times in pointing out some type mismatches and forcing me to really think about what I'm returning, etc. It also makes reading the code easier in terms of reasoning about it.
- conradludgate 6y agoI've noticed this similarly switching to using typescript over javascript. I'm not a huge JS dev anyway so I don't use it much, but having type signatures to enforce requirements, but being able to turn them off when they get in the way is great for productivity. Of course in a productive environment I would probably enforce strictness of the types but for my own terrible front ends, I don't care
- SketchySeaBeast 6y ago> It also makes reading the code easier in terms of reasoning about it. For me that's huge. I work in a support role where I pretty much exclusively look after code other people have written. Without type hints when something blows up I need to follow the code all the way back to whenever the variables were initially substantiated so I can know what to expect and what I can do with it. If I have a type I know what I'm looking immediately and start building a model of things without back tracking.
- heavyset_go 6y agoI've been doing this for years, and can't go back. The typing module is pretty comprehensive now, and using pyls-mypy with an editor like Kate that has an LSP client means you can type check as you're writing Python code in your editor.
- dpiepgrass 6y agoThe key argument seems to be "type checking and red squiggly underlines save you time" - I would also attest to that, but isn't there a way to do this in Python now? I would also suggest C#, with its Code Completion, as great at helping you write quick scripts, especially now that it has a REPL with full Code Completion, red-squiggly underlines and syntax highlighting in Visual Studio, plus language features like pattern matching, tuples and LINQ.
- mattmanser 6y agoThe C# REPL's not exactly great though. There's a lag the first time you use it and I regularly forget when you need to put a ; to end a statement or not.
- vonseel 6y agoThat sounds like something a real IDE would help with (forgetting semicolons).
- mattmanser 6y agoNo, it's about being able to do multi-line statements. But you dont always need them, so sometimes leaving them off works, but sometimes nothing happens because it's waiting for the semi-colon.
- 29athrowaway 6y agoMark throw away code with @deprecated or equivalent as soon as you can.
- thinkharderdev 6y agoTo me it's only throw away code if you actually throw it away after using once (or a couple times). If you are checking it into source control (i.e. anyone else will see it) then it's good to assume that it will live forever. I've been burned too many time when my "throwaway code" or "temporary glue script" becomes mission critical infrastructure
- egsmi 6y agoOver the years I’ve learned few things are more permanent than a temporary solution.
- matfil 6y agoOver the years I’ve learned few things are more permanent than a temporary solution. This is something your hear in a lot of places. Often (not always) it seems to be spoken with regret. I think we should be quicker to celebrate than a problem has been solved (and seems to be staying solved!) without worrying so much about whether it was done "properly". Indeed, I think the frequent success of temporary solutions should be seen as a challenge to the prevailing orthodoxy that software developers should be striving towards more discipline and process. Instead, we should be looking seriously at why quick fixes and cowboy coding work so well, and asking whether we can apply these more widely.
- thinkharderdev 6y agoIn my experience, it is not generally a matter of putting some quick and dirty script in the solve a problem and it goes on solving the problem without modification indefinitely. It is more often: 1. Put a quick and dirty script in to quickly solve some immediate problem 2. When that quick and dirty script stops working, instead of putting a proper solution in place you either add another quick and dirty script in to plug the issue or you modify the original quick and dirty script in some ad-hoc way 3. Repeat over and over again And then you end up with some impossibly complex Rube Goldberg machine.
- Havoc 6y agoaka all my code
- millstone 6y agoI could not imagine choosing Rust for the use case described. I think it's one of the worst possible choices! Python has so many advantages for throwaway code with quick iteration. Duck typing. Easy string indexing. Bignum arithmetic by default. Trivial mutable globals. Default parameters. Trivial to make reference cycles. Access variables by name. Exceptions. And the big one is eval().
- procparam 6y agoCan you say more about how you use eval() during prototyping?
- chaps 6y agoIt can be nice when you're working running code in a repl and don't want to maintain state/code between repl sessions. If you just print the data to stdout, you can just eval it and not have to deal with writing one-off cacheing. It's similar to the use case of pdb where you're forcing yourself into the middle of ten different functions. But print statements are easily added, easily removed, and so is eval.
- nicbou 6y agoDon't forget access to a huge range of mature, well-documented libraries and a large standard library.
- dmurray 6y agoThat's what makes the article noteworthy. There are a thousand articles of various quality out there telling you some variation on "dynamic languages are useful for prototyping and scripting, Rust/C/Java really shines in large codebases / when performance or reliability or security is important". It didn't convince me, though. There were a lot of "this tool or library or feature exists in Rust", but no comparative advantage over other languages more compelling than this: > This certainly is in part because I’m more proficient in Rust than in Python. It’s also because the Rust mental model is closer to how my brain works than the Python one.
- nextos 6y ago
- thinkharderdev 6y agoI love writing throwaway code in Python. It is really great for that and there is something about Python and the hassle you have to go through to write safe, well-structured code that makes you wanna say screw it and hack it in there.
- ufmace 6y agoI don't know if I entirely agree with this, but I do think that at the very least Rust is much better for this sort of development then some would have you think. It's strict, yes, but most of that strictness helps with eliminating the types of errors that make your app break over and over again at runtime. Unit tests can help bridge the gap, but who wants to write unit tests for throwaway scripts? When you get to know Rust, it does seem to have plenty of little bits of polish to help you get things going fast. Most of the stuff that the compiler/borrow checker complains about is either easy to fix even if by throwing around clones that might not be the best performing, or represents real issues that are better to think about now than trip over halfway through some processing run.
- identity0 6y ago> It's strict, yes, but most of that strictness helps with eliminating the types of errors that make your app break over and over again at runtime. Really? Most throwaway-script errors I get are simple things like IO mistakes, mistyped URL, or logic errors. The rust borrow checker is not designed to catch simple mistakes, it's designed for massive multi-threaded applications, e.g. making sure threads access data safely, making sure a variable doesn't get unexpectedly modified by some other file, making sure memory is owned by exactly one place, etc. But in a single-threaded garbage collected script that can fit on your monitor, why should you care? The borrow checker does not check for logic errors; it checks for the things you don't care about.
- steveklabnik 6y agoThose kinds of errors are made trivial to handle with ? and anyhow. At least, once you’ve got a bit of practice with it. And it’s barely slower to write out; 1 character in most cases, and “Result<>” on your return type. I ported some random Python to Rust six months ago: https://news.ycombinator.com/item?id=22712441 https://news.ycombinator.com/item?id=22712441 Here's the version I'd write today: use anyhow::Result; use chrono::NaiveDateTime; use serde::Deserialize; use serde_json; #[derive(Deserialize)] struct Person { name: String, age: u32, hired: NaiveDateTime, emails: Vec<String>, } fn main() -> Result<()> { let data = std::fs::read_to_string("agenda.json")?; let mut people: Vec<Person> = serde_json::from_str(&data)?; people.sort_by(|a, b| b.name.cmp(&a.name)); for person in &people { println!("{} ({}) - {}", person.name, person.age, person.hired); for email in &person.emails { println!(" - {}", email); } } Ok(()) } I learned that Chrono supports serde so I can remove my own parsing, and using ? instead of unwrap, because it's not harder and it ends up being nicer overall. (EDIT: Ah actually, it won't recognize this specific format automatically, so I still would write the parsing code. Even then, it's still roughly in the same ballpark.)
- sethammons 6y agoThe last time I prototyped something in python, we ran into issues with gevent while crafting up a multi-tenet mail transfer agent. Spent a couple of days banging heads against it. Then someone on the team did it in Go in like half a day. The language you choose for prototyping depends on the thing you are validating. I'm also partial to prototyping in the language that the real thing will be written in. At the time, we were not a Go shop, but we are now.
- brundolf 6y agoSomething I realized recently is that when I'm hacking on something, I like to brainstorm in terms of data from the very beginning, which means brainstorming in terms of types. Static types aren't just about stability and error-catching, for me. They are their own expressive vocabulary and I feel expressively crippled without them, even when working on a rough draft that will likely get thrown away. That said I tend to prefer TypeScript over Rust for fast iteration, all else being equal, but I agree with the author that Rust can work quite well even for this usecase. And I would never pick Python for anything beyond 100 lines, if I'm being honest.
- jakear 6y agoThis is big! I call it (others might too, idk) “.d.ts driven development”. Where you start the project by writing a .d.ts file and implement it. Similar to starting with a .h in C. Fun fact this is how xterm.js is structured (the terminal emulator used in vscode and hyper, among other things).
- vietjtnguyen 6y agoIf you haven't, you should explore domain-driven design (DDD). It's an explicit idea in that framework that a problem needs a "ubiquitous language" and an identified "bounded context" where the said language is valid. Like you, when approaching a new problem I like to nail down the terms we are discussing, literally scaffolding classes and types (in C++) as the problem is being discussed. It drives the adoption of unambiguous terms. Then as solutions are discussed the "ubiquitous language" helps clearly identify the interactions between types.
- fendy3002 6y agoCan you explain more? For me, DDD is hard if you don't know or inexperienced on the business field.
- brundolf 6y agoOne advantage of using a very open-ended type system like TypeScript's is that you don't have to know as much up-front. I could declare some type Foo, and that type might end up being: - A class - A record type - A union type - An intersection type - A constant or whatever else. But I can go ahead and start referring to that type in terms of function signatures, etc. Particularly for this kind of sketch-coding, it's really nice to be able to declare a concept and start talking about it before you even know what it is.
- asou 6y agoRust is too strict imo. I'm fairly experienced and I still can't throw up an HTTP server in Rust, even with libraries. I almost can do in with NodeJS and Express from memory. Something like app = require('express') app.listen('/', function ( req, res ){ res.send (' Hi Hn') }) ; It's ok for different languages to do different things. I can't imagine anyone being faster with Rust than Python or JS. Of course eventually Rust gets a performance boost, but it's never going to matter unless you're talking about a larger scale project.
- nirui 6y agoI would complaint about Rust as well, but setup a HTTP server in Rust is actually not that hard if you accept the fact that you'll have to use third-party framework. Then, the HTTP server will come to alive in within 20 lines of code. See: https://rocket.rs/ https://rocket.rs/ https://actix.rs/ https://actix.rs/ But, of course, the demo code is always easy. The real nightmare starts as soon as your application became complex enough, that the demo no longer fit and you need to manually spawn something (To handle TCP connection before it hits the framework for example) rather than just "actix_web::main" or "tokio::main".
- asou 6y agoMaybe it's been fixed , but when I tired Rocket last year I couldn't get it to really work. I would like Flutter to take over since it combines the best of Java /C# ( types) with the best of JavaScript/ Python ( dynamic variables which can be any type ).
- gwbas1c 6y agoI wrote this as my first Rust program, ever. It was mostly copy and paste, and involves an https server running on localhost. https://github.com/GWBasic/open_links https://github.com/GWBasic/open_links I spent a few hours reading the book, but it didn't sink in. I will be honest, though: Rust is still very challenging for me. The learning curve is extremely steep. Perhaps it's because Rust makes some things easy, at the expense of what automatic memory management and runtime type metadata make easy?
- rob74 6y agoI'm not sure if the author really meant this phrase the way it sounds, but if he did, it's a bit worrying: > That’s one of the points of Rust. It’ll complain that our code is not production quality and that we need to do better to save on the pain down the line. Ok, Rust will catch a lot of bugs, but assuming that a program is "production quality" once the Rust compiler doesn't complain about it anymore would be really bad - it may still be full of business logic errors...
- davegauer 6y agoI think that's uncharitable. The author is only addressing the inverse: code that is definitely not production quality.
- Miiko 6y agoFrankly, I believe that the criteria for the language selection for throw-away code is just that: > This certainly is in part because I’m more proficient in Rust than in Python. It’s also because the Rust mental model is closer to how my brain works than the Python one. You'll be more productive in writing the quick dirty hacks in language and programming model that you're the most comfortable with. That's it, the rest is IMHO just an attempt to rationalize your intuitive feelings.
- skarap 6y agoPython isn't weakly-typed. > Over the years, I’ve used Perl a lot (that one doesn’t care if it’s int or string… no, correction, in Perl everything is a string, ints just don’t exist. Well, kind of). It’s probably the language designed for throw away coding. I’ve done some Python too (that’s like Perl, but with proper objects in it, and everything is a dictionary there). The author has almost no real programming experience with Python. Perl experience seems to overlap with sysadmin-related work at least partially, where it's usually used as better Bash. All their repositories in GitHub are Rust. So almost all of "real" programming they did used Rust. Why would anyone who know Rust way better than any other language prefer to do their prototypes using anything else?
- acqq 6y agoAnd the claim about how Perl behaves and is to be programmed in is totally, completely wrong. For the start, one couldn't even write a correct "if" condition in Perl without knowing if it's about numbers or strings. Even if the comparison is over the "scalars." Second, the numbers not only exist, one can control which numbers are used when (one can explicitly force integer underlying types for some expressions or code blocks, or keep the floating point calculation, or even turn on infinite integers). Third, Perl has scalars, arrays, hashes, references, which have even different symbols throughout: https://en.wikipedia.org/wiki/Sigil_(computer_programming) https://en.wikipedia.org/wiki/Sigil_(computer_programming) so the types are more obvious when reading the language lines, much more than any language where every use of the variable looks almost the same. That's why it looks "too much like line noise" to those who don't know the meaning of the symbols. But having these symbols makes the code somehow "firmer" -- the programmer must much more often write what is expected from some variable, and the expected behavior is more obvious when reading.
- TobTobXX 6y agoI previously used NodeJS for this, but I missed the system integration you get from python/bash (eg. taking screenshots or playing sounds). Slowly I'm getting faster in Rust (it does require a particular mental model). What really was the gold in this article for me was the useful crates listed. Thank you a lot for that!