Hacker News new | past | comments | ask | show | jobs | submit login
500 Lines or Less (2016) (aosabook.org)
175 points by adarshd 11 months ago | hide | past | favorite | 43 comments



Hmm. I get the sentiment (500, i.e. not too short, not too long), but 500 lines will mean different things for different people and different programming stacks. It literally can mean 50000 vs 500 "lines of knowledge" required. I'm not sure why would you name your book like that.

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 ;)


I must formally disagree: 500 lines is about how you can read and comprehend a program. 500 lines fits in a single file in virtually any programming language (yes, you can put multiple classes in a single *.java file). And if you make use of libraries which allow to write 500 lines of high order instructions steering a vastly complex machinery, even better! This allows the 500 lines to be very expressive. I really like the idea because it puts emphasis onto a well written documentation which explains concepts while the code is very breve. Shorter code can increase the probability that bugs are found because it is probably more frequently read by other people.


> 500 lines is about how you can read and comprehend a program.

(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.)


Remembering that a line of code is a price you pay, and not an accomplishment in and of itself, is a valuable mindset to maintain. And I think that 500 lines is a comparable volume of code to digest across many languages. It may accomplish varying amounts of useful work, but that's beside the point. The purpose of this work is not to engage in an inter-language, inter-domain pissing match; it's to meditate on the human economics of software design. It says as much in the introduction: "500 Lines or Less focuses on the design decisions that programmers make in the small."

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.


That's literally the point of the book. Showing how you can use 500 lines of codes to do a whole lot of things, if you know what you're doing and use the appropriate language, in a way that others can still understand what's going on.

Pick the tool based on your requirements, not the other way around =)


Yeah, working in C and python you definitely have to reinvent the wheel less in Python ;-)

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!


The OCR example uses the full capabilities of the browser environment. A quick scan shows html, canvas, events, XmlHTTPRequest, and JSON.parse on the client side. What the python "server" exactly uses isn't completely clear, but it includes numpy, and probably some ANN library. So yeah, it's a bit of a stretch to compare that to 500 lines of stdlib-only C.


The seemingly arbitrary limit also helps to guide the choice of language: if it's too verbose in one language, it's probably the wrong one for the job! (I.e., reinventing too many wheels, un-ergonomic language patterns vs domain logic, etc.)


Bookmarked! These look like amazing study projects; the kind one can copy and learn from. Quite like how they do it in art school. Each one of them looks like it solves a nontrivial problem, and edifies the reader on the basic contours/tenets of the problem/solution space.

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

  213


I think they're great for study and as art, but I don't really aspire to write programs like that.

In 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.


One of my goals is to rewrite all software for developing software, with each application at about (or less than) this sweet spot.

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 :)

http://github.com/civboot/civlua


Arthur Whitney had a whole operating system, kOS, in a few hundred lines iirc (including bare metal storage drivers, screen drivers, file system and more), with a more-than-sql database in 200 lines and an editor in a few tens.

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.


Totally love the quest for elegant and minimal implementations. But I don't think line-counts are comparable across languages. The APL/K crowd has a very different opinion on the number of statements per line.

To give an impression of the style, this is the C-implementation of a K interpreter. Have fun deciphering that.

https://codeberg.org/ngn/k/src/branch/master/a.c


Yup, I've seen a lot of those. Cool and inspirational stuff.

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 was always disappointed that STEPS was something that produced a few research papers, but didn't produce an ongoing open source project that people could try out and innovate on top of. Seems like a waste of funding.


Re the text editor, when I was writing an editor for my homemade CPU I used the one from this tutorial: https://viewsourcecode.org/snaptoken/kilo/index.html - it is 1000 lines of C. Might be useful to you.

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).


> 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).

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.


Anything that can be shared or tested individually gets moved to a library, no matter how small.

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.


You want to write a serious database in 500 lines. Honestly, I'd be impressed but it's a hell of a target. Err, how long are your lines going to be?


To support the claim that 500 lines might be hard, Berkeley DB and Sqlite about about 200k lines. They are relatively simple databases. Maybe something like LevelDB would be less?


Normal lines (max 80) but I do prefer having each line do "one full thought", like putting `if then ... end` on a single line (if it fits)

I wrote about the database here

https://github.com/civboot/civboot/blob/main/blog/0012-dev-l...


Woof. Man, I really don't think you understand what goes into a DB if you think you can do D in 500 or even 5000 lines, unless maybe, maybe, you're aiming for something so simple it's merely a toy.


To be clear, it would depend on some (equally small) libraries, so it's not like 500 lines of no dependency C or something


I think what you're suggesting it is possible, to get halfway decent database using components, but I think you need to take a very high level view of these components. For a start, a parser. You almost certainly want a parser generator because that can be reused in other places. You need stuff to handle low level disc writes with logging, again, as a pluggable component (or maybe not, if you plan to shovel everything through your database [to clarify, that your DB effectively becomes the usual end to your filesystem, and everyone uses that, which isn't a terrible idea] in which case it's only got to be written once). You need an optimiser for the queries, even 'simple' ones. For this you might need a prolog-like facility, which again would be useful in other places. [to clarify, a prolog-like component system with some constraint+costs solver component built on top]

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!


Thanks, I appreciate the thoughts.

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.


Hi, then a database is not much more than an indexed file system (sort of). I'll check out your link in a bit more detail, thanks.

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.


Ya, basically just a file you dump things at in incrementing indexes and a index file to quickly look up keys.

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 :)


It would be considered a toy by most yes


Glad to see this on here again. This book is what bridged the gap between my undergrad degree and feeling like I could contribute to nontrivial real software projects. I originally found it because of HN


This seems cool and all, and I seldom critique web page design because... hey... I've developed some very crappy looking web pages. But... the designer of this page made it's width wider than a typical desktop browser window and much wider than a typical mobile phone. I turned my 10" tablet into landscape mode and it was still wider than would fit on the screen without scrolling.

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.


All my programs are one-liners.


Nice. I borrowed AOSA Volume 2 from a friend a couple of years back.

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.


Related:

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)


What about useless program ?


I can tell you I wrote many useless things with more than 500 lines, also known as "enterprise software".


I could write a fairly useless program with nearly half the amount of lines!!:

https://github.com/egeozcan/gifDisco

Being able to write silly stuff because you can is immensely satisfying.


For that you can go savor the archives of IOCCC : https://www.ioccc.org/


I can write useless programs in 0 lines!


Well, I have done that in order to see what the compiler creates which isn't your program. Quite useful!


The probability that a program is useful given the number of lines probably peaks in the 10,000’s-100,000’s.


"500 lines" is meaningles without talking into accont its dependencies, that including the SDK.

Corpos will see "500 lines" whatever the dependencies, serious software will embrace the whole software namely with the SDK and dependencies.


Exactly... Given the right library I could write a one line program that does the same as a 500 lines program


Yep, all that "line" thingy is meaningless, and it is even worse when you are serious enough to consider the life cycle of many pieces of software (does not work with all software).

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...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: