500 Lines or Less (2016)(aosabook.org) |
500 Lines or Less (2016)(aosabook.org) |
Consider: 500 lines of defensively written web server C++ code. 500 lines of C driver code. 500 lines of assembly. 500 lines of php script. 500 lines of java server app. 500 lines of c# .net desktop app. 500 lines of electron javacript code.
When I imagine the amount of a "useful program" I can write in 500 lines of C (or other low level statically typed language) while using minimal amounts of library code versus the "useful program" I can write in 500 lines of Javascript while using maximum amounts of Electron library code (i.e. all the functionality of chromium + node + electron), the difference is staggering ( try writing a cross platform video player in C vs Electron.. ). That doesn't mean Electron is better, especially if you need maximum resource budget usage or maximum control.
It's never about the number of lines, it's how you use them ;)
(With the exception of languages that are idiomatically horizontal, such as Forth or APL, where a 500-line program sounds about as reassuring as a 500-line mathematics paper, and is probably about as dense. But none of the programs in that book use one of those.)
Thinking about these things does matter. This past week I refactored a somewhat challenging piece of code my team had been maintaining from several hundred lines of code to about 30, without playing code golf. And I found and removed bugs (and even a little bit of code golf) in the process. Similar to what the book's introduction suggests, a lot of this change was down to rethinking the abstractions and decomposition of the code. The original version apparently tried to force the problem to fit a preselected design pattern. Doing that instead of decomposing the problem according to its own natural structure really does seem to have resulted in a ~10X code bloat factor.
Pick the tool based on your requirements, not the other way around =)
I recently wrote an 8bit style CPU simulator (with it's own simple but perfectly usable instruction set) and assembler, together they fit into 1000 lines of C... To be fair that's a fairly specific case where C works really well though!
I love this kind of stuff, because it shows one _can_ solve a pretty juicy problem with not that much code, honestly. Also because it suggests that the industrial-strength equivalent has a lot more in for use cases, corner cases, and/or optimisations that are not relevant for one's requirements (at least not yet, maybe not ever).
I aspire to write code like that. Useful, concise, but not obtuse. Some of my code is not as significant as those examples, and maybe falls short of my ideals, but it gets a lot done in well under 500 loc. e.g. my website maker in Bash [1] (hot-builds and hot-refreshes without JS), or the JS that drives text art animations for Hanukkah of Data [2].
[1] https://github.com/adityaathalye/shite is about 350 LoC counted this way (excluding the script containing HTML templates).
$ grep -E -v "^$|\\s?#" bin/{events,metadata,templating,utils,hotreload}.sh | wc -l
359
[2] https://www.evalapply.org/posts/animate-text-art-javascript/ the text art animator. $ grep --count -v -E \
-e "^$" -e "//" -e "/|\s+\*.*" \
assets/js/text_artist.js
213In fact most of the time I don't aspire to write anything at all. If I need a feature my first thought is "Does an existing project want this added or a plugin that does it, it does something already have it that just needs cleanup and bugfixes?"
I might not always need the industrial strength equivalent, but analyzing whether I do or not takes time, and using the "just enough" approach can create fragmentation and require learning a new tool for every project, instead of focusing on one that you trust will be maintained for a while.
I do value performance, but sometimes optimization gives better performance than simplicity.
Database, version control, runtime type system (Lua), proto-like serialization, code refactoring, parsing library... The list goes on.
About the only heavy thing will be the text editor, and I'm still keeping that at a few thousand lines (+ a small core data structure library).
When you cut requirements you can make things small and easy to understand. I'm only concerned about big-O and keeping things simple :)
I know all the cool kids are doing this, because it's only old people who care about the ease of reading things on the web. But... please... don't do stupid things like this.
That being said, it's easy enough to open dev tools and unclick the ``width: 68rem;`` clause or open it in lynx which replaces the web designer's styling stupidity with its own, more consistent styling stupidity. The content wasn't that bad.
Too bad the web page performs so poorly on mobile, when two small CSS tweaks would make it fully responsive:
1. Replace `width: 68rem` with `max-width: 68rem` on the body element;
2. Make the flex basis on the table container pixel rather than percentage based.
500 Lines or Less - https://news.ycombinator.com/item?id=12170182 - July 2016 (19 comments)
500 Lines or Less - https://news.ycombinator.com/item?id=11796253 - May 2016 (61 comments)
https://github.com/egeozcan/gifDisco
Being able to write silly stuff because you can is immensely satisfying.
Corpos will see "500 lines" whatever the dependencies, serious software will embrace the whole software namely with the SDK and dependencies.
From a life cycle (and more) perspective, it can be very "better" to write some software with 1000 lines with less deps than 10 with more deps...
The magic — other than Arthur’s genius - was the programming language K (also designed and implemented by Arthur).
And from another direction, the STEPS project from Alan Kay did a metal-to-everything in 20K lines, including IIRC a paint program and word processor. They only counted lines you need to understand - e.g., it parses the TCP spec RFC to get all the structures and constants; the spec parser is included in the 20K count, but the TCP docs and the generated TCP code is not.
To give an impression of the style, this is the C-implementation of a K interpreter. Have fun deciphering that.
My favorite so far has been project Oberon. I've not seen how it's assembler works though. What I want is a full stack (assembly included) self-bootsrapping implementation
I have diverged a bit from the tutorial because I didn't want syntax highlighting, I really wanted vi-style keybindings, and my environment is much more performance-constrained. Mine is at https://github.com/jes/scamp-cpu/blob/master/sys/kilo.sl (in my made-up programming language).
What I found to work really well to trim down my own text-editor was a combination of externalising all menus etc.. E.g. opening files, selecting themes, selecting buffers, all call out to scripts using rofi or similar to do the actual selection, and going client-server so that e.g. I get multiple windows etc. "for free" by just spawning another instance of the frontend which reattaches to the same server.
It's still certainly not 500 lines, but small-ish.
> When you cut requirements you can make things small and easy to understand.
Fully agree with this, and one great way of keeping requirements small like this for me is that I started with the idea that this is my editor. I will only cater to my requirements for the editor itself, but split out shared/reusable functionality in separate libraries so if anyone wants to fork it one day and make their editor we can share much of the code without either of us having to sacrifice.
I think too many people insist that everything they build need to be a "product" that they'll let grow to satisfy as many people as possible even when it'd be better to end up with a dozen smaller, more focused tools.
I'll have an 'ed' library for things like the gap buffer and undo/redo aware buffer (built on gap) as well as the movement logic and stuff like that.
The "editor" will only handle default bindings, the action/draw/paint cycle and an action event loop. These are core to the specific application so they belong to be coupled to it.
I wrote about the database here
https://github.com/civboot/civboot/blob/main/blog/0012-dev-l...
You'll need a lot more than that as well. You will have to take a very high level view of things, ruthlessly componentised.
I understand and endorse what you're trying to do, but a low level infrastructure with a bunch of libraries isn't quite going to cut it.
Just my opinion anyway, take it as you will!
It's for the civboot.org project, so it has VERY constrained requirements. Basically it is just to build things like a VCS and log collector on.
As I outlined in the post I'm only concerned with two requirements: appending mutation quickly and indexing static databases. If I add an in-memory index for recent writes that haven't yet been indexed then it pretty much meets all requirements.
I don't plan on supporting SQL or anything like that -- it's a single-file database that Lua can (indexed) read and write to. Others can also trivially read the index as well, but concurrent writes are probably not going to be possible. Transactions are easy enough I think.
I wasn't expecting it to be multiple user, I assumed single use only which seriously simplifies some aspects (lock the world, do stuff, unlock). To support transactions you'll need a write ahead log and recovery to preserve data through crashes/power loss – that's not trivial. Still, good luck.
Regarding your processor, I like the idea of a very simple process are easy to produce. I haven't looked at what you're suggesting but perhaps instructions on making a full-sized one out of discrete components might be worthwhile? There are a few projects online (I haven't been able to find them but I seem to remember a 6502 made by hand the size of a mattress). While this would only run at a few kilohertz, it's better than no computer at all and useful for bootstrapping to something smaller, and possible if you've got no VLSI or anything similar. An even simpler processor might be possible. Sorry if you've already considered this, it was just a thought.
Your other comments are the kinds of thoughts I approach this with. I'm hoping for the final (simple fab) CPU @100MHz and at least a few MiB of RAM (I think about 1990's tech).
I did the pre-work in thinking about the CPU and hardware to convince myself of what features were needed. Eventually I'll get to building the CPU itself. I first want the OS it will target :)