Rob Pike's Rules of Programming (1989) - <AUTHOR> http://users.ece.utexas.edu/~adnan/pike.html <comment><USER3> > Rule 1. You can't tell where a program is going to spend its time. > Bottlenecks occur in surprising places, so don't try to second guess and put > in a speed hack until you've proven that's where the bottleneck is.

I wish people would follow this rule and just let stuff work. I recently encountered the most extreme version of this I've ever seen in my career: a design review where a guy proposed a Redis caching layer _and_ a complex custom lookup scheme for a <1GB, moderate read volume, super low write volume MySQL database. And of course he wants to put the bulk of the data in JSON fields and manage any schema evolution in our application code.

Can't we just let stuff work? I'm no fan of MySQL, but can't we admit that a ubiquitous and battle-tested piece of technology, applied to a canonical use case, on tiny data under near-ideal circumstances, is probably going to work just fine? At least give it a chance before you spend days designing and documenting a bunch of fancy tricks to save MySQL from being crushed under a few megabytes of data.

<comment><USER4> This is particularly exasperating for me. I can't tell you how many times in my professional career I've ended up speeding up systems by removing two or three layers of improperly-implemented "caching" and using good ol' MySQL and a basic understanding of algorithmic time complexity to simplify things.

<comment><USER5> Me too. I've seen a few systems that replaced their simple request requiring 10,000 queries "optimized" by requiring 10,000 cache lookups when they should have just added some joins. The bottleneck is the network latency, not the database. The worst I've seen is an nHibernate cache stored in a session variable, half the database was being serialized/deserialized on every http request. Fortunately that was a small database.

Even with in memory caches I've seen systems grind to a halt by death of a thousand cuts, dictionary based entity attribute systems where each attribute is looked up individually. There seems to be a mentality that constant lookup == free lookup and devs don't seem to realize that constant * $bignumber == $biggerNumber. Caching shouldn't be granular.

Obligatory latency numbers every programmer should know: [https://gist.github.com/jboner/2841832](https://gist.github.com/jboner/2841832)

<comment><USER6> Having worked with Hibernate recently on a smallish database (that isn't expected to grow too big), my take away is to minimize the network trips. If you have to check something for a list/set of things and all of that can be done from, say, two not so big tables, fetch the superset of records via a join with as much criteria pushed to predicates as efficiently possible and handle rest of the logic in application code. It is so much more quicker. Of course, like most things in software, conditions apply like network latency/total no. of records being fetched by the query/potential for data to suddenly grow etc.

<comment><USER7> Not to cache simple trips to the database is pretty uncontroversial, the are more controversial cases elsewhere.

Say you consume a Restful API to hidrate order data in another system. Do you fetch orders as:

      /orders?ids=id-1,id-2,id-3

or separate calls to

      /orders/id-x

which can be cached and retrieved by id as a memoized function?

Well if you had to pick only one the second is probably better, but the best would be abstracting away order fetching in application code to always fetch single orders and behind the scenes looking up the cache for singles and pooling all the misses into a single request to the plural endpoint.

<comment><USER5> If this is a common occurrence the former would almost always be better, the second would be absolutely glacial.

> but the best would be abstracting away order fetching in application code to > always fetch single orders and behind the scenes looking up the cache for > singles and pooling all the misses into a single request to the plural > endpoint.

Unless a significant amount of requests have 100% cache hits then I doubt a local cache will make much of a difference at all, all it's saving is a bit of bandwidth.

</comment></comment></comment></comment></comment></comment><comment><USER8> In _The Mythical Man Month_ Fred Brooks said "Show me your flowchart and conceal your tables, and I shall continue to be mystified. Show me your tables, and I won't usually need your flowchart; it'll be obvious."

I first read that on Guy Steele's site: [http://www.dreamsongs.com/ObjectsHaveNotFailedNarr.html](http://www.dreamsongs.com/ObjectsHaveNotFailedNarr.html)

<comment><USER9> > Show me your tables, and I won't usually need your flowchart

A couple of years ago I spent quite some time trying to evaluate the tech stack (and general engineering culture) of merger/acquisition targets of my employer. It was quite a fun exercise, all said and done. I encountered all sorts; from a small team start up who had their tech sorted out more or less to a largish organisation who relied on IBM's ESB which exactly one person in their team knew how it worked!!

I discovered this exact method during the third tech evaluation exercise. When the team began explaining various modules top-down and user-flows etc., I politely interrupted them and asked for DB schema. It was just on a whim because I was bored of typical one way session interrupted by me asking minor questions. Once I had a hang of their schema rest of the session was literally me telling them what their control and user flows were and them validating it.

Since then it's become my magic wand to understand a new company or team. Just go directly to the schema and work backwards.

Conversely, I've begun paying more attention to data modelling. Because once a data model is fixed it's very hard to change and once enough data accumulates the inertia just increases and instead if changing the data model (for the fear of data migration etc.,) the tendency is to beat the use cases to fit the data model. It's not your usual fail-fast-and-iterate thing.

<comment><USER6> I have learned to spend a good chuck on my effort and focus on data model - <USER2> is literally the heart of the application. Once that is done correctly, I've seen that the code almost just falls into place by itself.

</comment></comment></comment><comment><USER10> Rule 5 seems to mirror one of my favorite insights from Alexander Stepanov:

> In 1976, still back in the USSR, I got a very serious case of food poisoning > from eating raw fish. While in the hospital, in the state of delirium, I > suddenly realized that the ability to add numbers in parallel depends on the > fact that addition is associative. (So, putting it simply, STL is the result > of a bacterial infection.) In other words, I realized that a parallel > reduction algorithm is associated with a semigroup structure type. That is > the fundamental point: algorithms are defined on algebraic structures.

This is also exemplified in the analytics infrastructure used at stripe: [https://www.infoq.com/presentations/abstract-algebra- analyti...](https://www.infoq.com/presentations/abstract-algebra-analytics/)

<comment><USER11> But adding floating point numbers _isn 't_ associative, in general. Sometimes you need to do it the right way to avoid catastrophic cancellation.

I guess the key is to know how to deal with things that are only mostly true.

<comment><USER12> That's why in C++ we have traits and overloading.

<comment><USER13> Could you explain where do you see traits and overloading helping you with floating point operations?

</comment></comment></comment></comment><comment><USER14> Everyone building no code tools is learning or will learn that the problem most businesses have is not a lack of coding skill, or the inability to build the algorithm, but rather how to structure and model data in a sensible way in the first place.

<comment><USER15> Modeling the data and structuring the program are indeed the harder tasks, but orgs have lots of smart people who have those skills but not the familiarity with various existing syntaxes and standard libraries and so on that a programmer learns over the decades of their career. Further, those same orgs probably have many people with experience in the latter but without any special ability to think abstractly. This significantly limits the ability to create tools. Further, the no code tools often abstract at a more appropriate level than general purpose programming languages' standard libraries because these tools aren't trying to be general purpose (at least not to the same degree as general purpose programming languages). Lastly, I've seen business people use certain no code tools to build internal solutions quickly that would have taken a programmer considerable (but not crazy) time to crank out, especially considering things like CI/CD pipelines, etc. Nocode won't replace Python, but it serves a valuable niche.

</comment></comment><comment><USER16> > Tony Hoare's famous maxim "Premature optimization is the root of all evil."

Actually that was Donald Knuth - it's an urban legend that it's an urban legend that it was originally Knuth. Hoare was quoting Knuth, but Knuth forgot he said it, and re-mis-attributed the quote to Hoare.

<comment><USER17> And it is usually quoted out of its context.

"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%."

<comment><USER18> It's also often interpreted literally.

Premature _complex_ optimization is a bad idea, but simple (read, cheap to code) optimization for common bottleneck patterns is a perfectly reasonable thing to do.

<comment><USER19> It's also often (ab)used far too often to justify performing no optimisation at all.

<comment><USER20> ...or even _pessimisation_.

<comment><USER21> That is a great word.

</comment></comment></comment></comment></comment></comment><comment><USER22> In long-lived systems (systems that run for many years) it's almost impossible to choose the "right data structures" for the ages. The sources and uses of your data will not last nearly as long as the data itself.

What to do about this? Two things:

STORE YOUR TIMESTAMPS IN UTC. NOT US Pacific or any other local timezone. If you start out with the wrong timezone you'll never be able to fix it. And generations of programmers will curse your name.

Keep your data structures simple enough to adapt to the future. Written another way: respect the programmers who have to use your data when you're not around to explain it.

And, a rule that's like the third law of thermodynamics. You can never know when you're designing data how long it will last. Written another way: your kludges will come back to bite you in the xxx.

<comment><USER23> Sometimes storing in UTC is simply not correct. For example a shop opening time. The shop opens 10am local time, whether DST or not. Their opening time is 10am local time all year but their UTC opening time actually changes depending on the time of year!

<comment><USER24> But a shop opening time is not a timestamp, so I think the original advice is still good. A timestamp is the time at which some event happened, which is different than a date/time used for specifying a schedule.

For example, if you wanted to track the history of when the shop actually opened, it would make sense to store a UTC timestamp.

<comment><USER25> > A timestamp is the time at which some event happened, which is different > than a date/time used for specifying a schedule.

Correct, but that makes this a rule with much more limited applications than many people are going to interpret it as.

</comment></comment></comment></comment><comment><USER26> A quote that combines the rules about optimization with the rules about data structures: "NoSQL databases that only have weak consistency are enforcing a broadly applied premature optimization on the entire system." \--- Alexander Lloyd, Google

Also in support of Rule 5, see Eric Raymond's treatment of Data-Driven Programming:

"Even the simplest procedural logic is hard for humans to verify, but quite complex data structures are fairly easy to model and reason about. To see this, compare the expressiveness and explanatory power of a diagram of (say) a fifty-node pointer tree with a flowchart of a fifty-line program. Or, compare an array initializer expressing a conversion table with an equivalent switch statement. The difference in transparency and clarity is dramatic. See Rob Pike's Rule 5.

"Data is more tractable than program logic. It follows that where you see a choice between complexity in data structures and complexity in code, choose the former. More: in evolving a design, you should actively seek ways to shift complexity from code to data."

[http://www.catb.org/~esr/writings/taoup/html/ch01s06.html#id...](http://www.catb.org/~esr/writings/taoup/html/ch01s06.html#id2878263)

[http://www.catb.org/~esr/writings/taoup/html/generationchapt...](http://www.catb.org/~esr/writings/taoup/html/generationchapter.html)

</comment><comment><USER27> A quote from one of our founders that I've always liked:

If you make an optimization that was not at a bottleneck, you did not make an optimization.

<comment><USER28> Read _The Goal_ by Eliyahu Goldratt. While it's possible your founder came upon the idea independently, this is one of many that are repeated in that book. It's relatively short and entertaining to read and has definitely survived the 36 years since first publishing quite well.

<comment><USER29> This was adapted into a novel about IT/devops called The Phoenix Project. It's an excellent read.

<comment><USER28> I second this. Quite the entertaining read, honestly. I also enjoyed the completely unnecessary transformation of the security dork into a security ubermensch.

<comment><USER30> I've read The Goal and The Phoenix Project. While I did enjoy the stories, I'm uncertain, perhaps due to inexperience, what the main lesson/s are supposed to be.

Anyone want to share their main takeaways from these books?

<comment><USER27> Reduce feedback cycles

</comment></comment></comment></comment></comment></comment><comment><USER31> _> Rule 1. You can't tell where a program is going to spend its time. Bottlenecks occur in surprising places, so don't try to second guess and put in a speed hack until you've proven that's where the bottleneck is._

I agree with the general thrust of this. But it's worth pointing out that often the easiest way to prove where a bottleneck is (or at least) isn't, is to try an optimization and see if it helps. I like profiling tools immensely, and this kind of trial an error optimization doesn't scale well to widespread performance problems. But there's something to be said for doing a couple of quick optimizations as tracer bullets to see if you get lucky and find the problem before bringing in the big guns.

The last three rules bug me. I wish we had a name for aphorisms that perfectly encapsulate an idea _once you already have the wisdom to understand it_ , but that don't actually _teach_ anything. They may help you remember a concept—a sort of aphoristic mnemonic—but don't _illuminate_ it. The problem with these is that espousing them is more a way of bragging ("look how smart I am for understanding this!") than really helping others.

For example:

 _> Rule 5. Data dominates. If you've chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming. _

OK, well what are the "right" data structures? The answer is "the ones that let you perform the operations you need to perform easily or efficiently". So you still need to know what the code is doing too. And the algorithms are only "self-evident" because you chose data structures expressely to give you the luxury of using simple algorithms.

<comment><USER24> I think the point is more to direct how you write/refactor code: focus more on the data structures than on the code. E.g. if you're struggling to write the code, then maybe you need to take a step back and reconsider your data structures.

</comment></comment><comment><USER32> > Rule 5. Data dominates. If you've chosen the right data structures and > organized things well, the algorithms will almost always be self-evident. > Data structures, not algorithms, are central to programming.

Is "data structures" the correct term here? Assuming I'm not misinterpreting, the usage of "data structures" can be misleading - one usually thinks of things like BST's and hash tables, which are inherently tied to algorithms. I feel like "data modeling" better captures the intended meaning here.

<comment><USER33> A custom type is also a data structure and that is usually what I think quotes like these refer to.

</comment></comment><comment><USER34> These rules are good as far as they go. However, they are notably silent on what happens when they stop working.

If you're a celebrity computer scientist and a problem has been 'squashed' to the point where there aren't any more 80-99% "hot spots" I guess you can just parachute out of there and on to a more interesting problem.

However, if you're paid to work on a particular thing, sooner or later, you will fire up a profile and say "oh, great, I don't have a hot spot anymore, just a bunch of 10-30% 'warm spots'". At that point you need to attack problems that aren't traditional bottlenecks if you still want to get speedups.

Moreover, the things that you learn from repeatedly attacking those 10-30% 'warm spots' might be fundamentally different from the learning you get from, I dunno, taking some O(N^2) monstrosity out of the "99% of the profile" and Declaring Victory.

</comment><comment><USER35> Rule 1 and 2 depend on context, whether you're working on an existing program or a new program. They can be true or false. They can really help or they can really hurt. Are you going into an existing system to do performance optimization? Sure, don't guess, measure. Are you designing a new system? Throw out those parroted premature optimization mantras... you are responsible for designing for performance upfront. You will always measure but depending on context you will design for speed first and then test your prototype with measurements. There's no way around an initial hypothesis when you're designing new systems. You have to start somewhere. That's where Jeff Dean's rule always to do back of the envelope guesses will pay off in orders of magnitude, many times over.

Rule 3 and 4 are gold and always true.

Rule 5 is the key to good design.

</comment><comment><USER36> I've always taken a very practical, results-oriented approach to software development.

That makes sense, to me.

One of the first things that we learned, when optimizing our code, was to _use a profiler_.

Bottlenecks could be in very strange places, like breaking L2 caches. That would happen when data was just a bit too big, or a method was called; forcing a stack frame update.

We wouldn't see this kind of thing until we looked at a profiler; sometimes, a rather advanced one, provided by Intel.

</comment><comment><USER37> It turns out rule 5 (Data dominates. If you've chosen the right data structures and organized things well, the algorithms will almost always be self-evident) is both true but also hard.

Eric Evans' Domain Driven Design is a good book on the topic.

<comment><USER38> > If you've chosen the right data structures and organized things well, the > algorithms will almost always be self-evident) is both true but also hard.

The problem is not the self-evident algorithm, but the delicate implementation (or god forbid, at scale).

Take in 1000 web requests per second. The data is all strictly validated and has about 60 fields a record/req plus dealing with errors.

How does that go from webserver to ( _rolls dice_ ) kafka to a ( _rolls dice_ ) cassandra that can be queried accurately and timely? How much does that cost?

Oh, that's not a programmer problem. Except it is. Creating a fantasy niche of describing problems as data vs algorithm is the canonical ivory tower disconnect.

<comment><USER39> It seems you are arguing something different, although I am having a hard time understanding what you have written. I think you are saying algorithms and data structures aren't hard, distributed systems are hard. In my experience choosing the correct data structures and algorithms in your services/programs/whatever can dramatically simplify the design of your systems overall.

<comment><USER38> > It seems you are arguing something different,

I'm making an argument that the stark reality of what's hard in software development is not the simplistic "Rules of programming", which have limited utility.

The reason the "rules" aren't self evident (or followed), is because we live in the reality of disparate functionality paired with an ever-changing technical landscape. You can't just make a DB KISS abstraction and expect it to hold with all the different repository types like ( _rolls dice_ ) Athena after using ( _rolls dice_ ) CockroachDB. There are concerns that are not purely algorithmic vs data structure that are far more influential and important to understand. Even knowing these details and cases, becomes less useful as time goes on and new technologies emerge.

> I am having a hard time understanding what you have written

If you're not interacting with new environments, tooling, and problems, regularly (every year or 2) you don't encounter the real pain which is far more important to your career and your ability to produce functional software. Reading almost every postmortem, the number of lines attributed to "we changed the data structure to O" is dwarfed by "we learned that technology X does Y, so we had to do Z".

This is only incidentally related to distributed systems, which is indicative of a disconnect with the problem described. Of course when you sit around in the same environment for a long time, you can observe and optimize on structure and algorithm, but that's not getting you to market (you're already there) and that's the nature of maintenance...not just being a fire extinguisher who is on call.

<comment><USER40> > we live in the reality of disparate functionality paired with an ever- > changing technical landscape

It is the responsibility of tech leaders to minimize this (accurate) stereotype. Choose boring technology, and only build your own or choose something exotic when it gives you competitive advantage - because the reality I also see is that 99% of devs aren't working on anything new or unseen in the field. Even at the FAMANG companies, most people I know are working on boring problems.

So when your CTO or architect or whomever buys into the hype for X technology, make a good argument against it by proposing a better solution.

</comment></comment></comment></comment></comment><comment><USER41> Modeling the problem domain is so important that I dont know why the first year of every compsci undergrad program isnt entirely dedicated to teaching the idea.

Instead, day 1 is installing python or java, running hello world and talking about pointers, binary, encoding, logic gates, etc.

We should be teaching students on day 1 that code is a liability and to be avoided whenever it is convenient to do so.

<comment> codemonkey-zeta IMO Matthias Felleisen (building on work of Sussman (IIRC) et. al.) gets first-year CS education right with How to Design Programs ([https://htdp.org/2020-5-6/Book/index.html](https://htdp.org/2020-5-6/Book/index.html)). Literally step 1 in the design recipe presented in the preface is:

       "1. From Problem Analysis to Data Definitions
        Identify the information that must be represented and how  it is represented in the chosen programming language.
        Formulate data definitions and illustrate them with examples."

</comment></comment><comment><USER42> All this advice against "premature optimization" has created generations of programmers that don't understand how to use hardware efficiently.

Here's the problem: If you profile software that is 100x slower than it needs to be on every level, _there are no obvious bottlenecks_. Your whole program is just slow across the board, because you used tons of allocations, abstractions and indirections at every step of the way.

Rob Pike probably has never written a program where performance _really_ mattered, because if he did, he would've found that you need to think about performance right from the beginning and all the way during development, because making bad decisions early on can force you to rewrite almost everything.

For instance, if you start writing a Go program with the mindset that you can just heap-allocate all the time, the garbage collector will eventually come back to bite you and the "bottleneck" will be your entire codebase.

<comment><USER43> > Rob Pike probably has never written a program where performance really > mattered

Rob Pike has written window system software which ran in what now would be called a "thin client" over a 9600 baud modem and rendered graphics using a 2MHz CPU. He probably knows a thing or two about performance tuning.

<comment><USER42> By "rendered graphics" you mean "place characters on screen"? If the bottleneck for that is a 9600 baud modem throughput, there's not a lot you need to optimize, even on a 2MHZ CPU.

Also, having programmed more constrained systems decades ago doesn't magically make you knowledgeable on performance on modern hardware with completely different capabilities. In fact, it's probably what causes you to develop a "computers are so fast now, no need to think about performance"-mindset, because everything you want to do could be done in an arbitrarily inefficient way on modern hardware. Performance doesn't matter to you anymore.

<comment><USER44> > By "rendered graphics" you mean "place characters on screen"?

It was a fully graphical 800x1024 (or 1024x1024) system running on 1982 processors.

[https://en.wikipedia.org/wiki/Blit_(computer_terminal)](https://en.wikipedia.org/wiki/Blit_\(computer_terminal\))

> having programmed more constrained systems decades ago doesn't magically > make you knowledgeable on performance

Perhaps not but it does mean you've "written a program where performance really mattered" which I believe was the original claim?

<comment><USER42> > It was a fully graphical 800x1024 (or 1024x1024) system running on 1982 > processors.

I've looked into in that. Blit was monochrome, had an _8Mhz_ processor, and a relatively large 256KB framebuffer which could but directly written to. There were only a handful commands, mostly concerned with copying (blitting) bitmaps around.

Rob Pike only wrote the first version of the graphics routines - the _slowest_ version, in C(!). It was rewritten another four times over, by Locanthi and finally Reiser.

I don't think any credit should go to Pike for implementing the performance- critical parts of that system.

[https://9p.io/cm/cs/doc/87/archtr.ps.gz](https://9p.io/cm/cs/doc/87/archtr.ps.gz)

> Perhaps not but it does mean you've "written a program where performance > really mattered" which I believe was the original claim?

No, it doesn't mean that. You can be wasteful on constrained hardware as well, performance doesn't necessarily matter even on the simplest chips, if what you want to do doesn't need the full capabilities of the system.

However, I am specifically replying to the claim that "Rob Pike probably knows a thing or two about performance". As you can see, Rob Pike handed off performance-critical work to someone else. He probably _didn 't_ know how to write optimal code for that particular platform, but even if he did, most of that knowledge wouldn't transfer over to modern systems.

At the very least, he didn't _care_ about optimizing that stuff, or he wouldn't have handed it off. He would've _enjoyed_ optimizing that stuff. And that's all completely fine, not every programmer needs to care about performance. I just refuse to take advice from these people about performance or "premature optimization", because it is _uninformed_.

<comment><USER43> Writeup of the blit terminal's operating system is here, it consists of a lot more than the bitblt primitive, with many whole-system performance concerns at play:

[http://a.papnet.eu/UNIX/bltj/06771910.pdf](http://a.papnet.eu/UNIX/bltj/06771910.pdf)

Suggest you read this before denigrating Rob Pike's bona fides. Not sure what axe you are trying to grind but it is ugly and unbecoming of a professional.

<comment><USER42> I'm not denigrating his bona fides, I'm questioning his credentials on performance-oriented computing. For all I know, if Rob Pike had been a performance freak, Blit might've never shipped. He may indeed have chosen all the right trade-offs.

Nevertheless, the advice he gives on performance is wrong, plain and simple, for the reason that I gave you: If you have overhead everywhere, there is no bottleneck that you can observe - your software is just slower than it needs to be across the board. If you write software without performance in mind from the very beginning, you can never get all of it back by optimizing later - without major rewrites that is.

How does one give wrong advice? By not having the required experience to give correct advice. I don't care if you're Rob Pike, Dennis Ritchie or Donald Knuth. If you're wrong, you're wrong.

</comment></comment></comment></comment></comment></comment></comment><comment><USER45> > Rule 5. Data dominates. If you've chosen the right data structures and > organized things well, the algorithms will almost always be self-evident. > Data structures, not algorithms, are central to programming.

That one hits me in the feels because I think a lot of folks focus on algorithms (including myself), and code patterns, before their data and as a result a lot of things end up being harder than they need to be. I've always liked this quote from Torvalds on the subject speaking on git's design (first line is for some context):

> … git actually has a simple design, with stable and reasonably well- > documented data structures.

then continues:

> In fact, I'm a huge proponent of designing your code around the data, rather > than the other way around, and I think it's one of the reasons git has been > fairly successful […] I will, in fact, claim that the difference between a > bad programmer and a good one is whether he considers his code or his data > structures more important. Bad programmers worry about the code. Good > programmers worry about data structures and their relationships.

When I have good data structures most things just sort of fall into place. I honestly can't think of a time where I've figuratively (or literally) said "my data structure really whips the llamas ass" and then immediately said "it's going to be horrible to use." On the contrary, I _have_ written code that is both so beautiful and esoteric, its pedantry would be lauded for the ages-- had only I glanced over at my data model during my madness. No, instead, I awaken to find I spent my time quite aptly digging a marvelous hole, filling said hole with shit, and then hopping in hoping to not get shitty.

One thing that really has helped me make better data structures and models is taking advanced courses on things like multivariate linear regression analysis specifically going over identifying things like multicolinearity and heteroskedasticity. Statistical tools are incredibly powerful in this field, even if you aren't doing statistical analysis everyday. Making good data models isn't necessarily easy, nor obvious, and I've watched a lot of experienced folks make silly mistakes simply because they didn't want something asinine like _two_ fields instead of one.

<comment><USER46> The counter argument would be that git is the poster-child of poor UX, which could be blamed on the fact that it exposes too much of its internal data structure and general inner-workings to the user.

I.e. too much focus has been put on data structures and not enough on the rest of the tool.

A less efficient data structure, but more focus on UX could have saved millions of man hours by this point.

<comment><USER24> Or perhaps learning Git just requires a different approach: you understand the model first, not the interface. Once you understand the model (which is quite simple), the interface is easy.

<comment><USER47> People keep repeating this, but it's not true. The interface has so many "this flag in this case" but "this other flag in that case" and "that command doesn't support this flag like that" etc. There's no composability or orthoganality or suggestiveness. It's nonsensical and capricious and unmemorable, even though I understand the "simple" underlying model and have for years.

<comment><USER48> Has anyone attempted to re-engineer a superior UX on top of the git data structure? Would it even be possible?

<comment> codemonkey-zeta Magit with emacs solves git's UX problem IMO. Discoverability is/was git's real problem.

<comment><USER49> This is true, but the trouble is that you need to know what git will do before the magit commands and options make sense.

</comment></comment></comment></comment></comment></comment></comment><comment><USER50> "Write stupid code that uses smart objects"

That's a good one. It's amazing how much complexity can be created by using the wrong abstractions.

<comment><USER51> FWIW I find this is especially important for compilers and interpreters.

It's not an exaggeration to say that such programs are basically big data structures, full of compromises to accomodate the algorithms you need to run on them.

For example LLVM IR is just a big data structure. Lattner has been saying for awhile that a major design mistake in Clang is not to have its own IR (in the talks on the new MLIR project).

SSA is data structure with some invariants that make a bunch of algorithms easier to write (and I think it improves their computational complexity over naive algorithms in several cases)

\----

In Oil I used a DSL to describe an elaborate data structure that describes all of shell:

 _What is Zephyr ASDL?_ [http://www.oilshell.org/blog/2016/12/11.html](http://www.oilshell.org/blog/2016/12/11.html)

[https://www.oilshell.org/release/0.8.pre9/source- code.wwz/fr...](https://www.oilshell.org/release/0.8.pre9/source- code.wwz/frontend/syntax.asdl)

I added some nice properties that algebraic data types in some language don't have, e.g. variants are "first class" unlike in Rust.

Related: I noticed recently that Rust IDE support has a related DSL for its data structure representation: [https://internals.rust- lang.org/t/announcement-simple-produc...](https://internals.rust- lang.org/t/announcement-simple-production-ready-rust-un-grammar/12827)

<comment><USER52> > FWIW I find this is especially important for compilers and interpreters.

Totally. I'm building a relational language and start to get very obvious why RDBMS not fit certain purity ideals of the relational model (like all relations are sets, not bags).

I'm stuck in deciding which structures provide by default. Dancing between flat vectors or ndarrays or split between flat vectors (columns), and HashMaps/BTree with n-values (this is my intuition now).

\--- > I added some nice properties that algebraic data types in some language don't have, e.g. variants are "first class" unlike in Rust.

This sound cool, where I can learn about this?

<comment><USER51> FWIW I found this post thought provoking in thinking about data models of languages.

[https://news.ycombinator.com/item?id=13293290](https://news.ycombinator.com/item?id=13293290)

\---

About first class variants:

[https://lobste.rs/s/77nu3d/oil_s_parser_is_160x_200x_faster_...](https://lobste.rs/s/77nu3d/oil_s_parser_is_160x_200x_faster_than_it_was#c_gu4oaj)

[https://github.com/rust-lang/rfcs/pull/2593](https://github.com/rust- lang/rfcs/pull/2593)

Another way I think of this is "types vs. tags": [https://oilshell.zulipchat.com/#narrow/stream/208950-zephyr-...](https://oilshell.zulipchat.com/#narrow/stream/208950-zephyr- asdl/topic/Better.20solution.3A.20tags.20vs.2E.20types) (Zulip, requires login)

Basically variant can types stand alone, and have a unique tag. Tags are discriminated at RUNTIME with "pattern matching".

But a variant can belong to multiple sum types, and that's checked statically. This is modeled with multiple inheritance in OOP, but there's no implementation inheritance. Related: [https://pling.jondgoodwin.com/post/when- sum-types-inherit/](https://pling.jondgoodwin.com/post/when-sum-types- inherit/)

So basically in the ASDL and C++ and Python type system I can model:

\- a Token type is a leaf in an arithmetic expression

\- a Token type is a leaf in an word expression

But it's not a leaf in say what goes in a[i], or dozens of other sum types. Shell is a big composition of sublanguages, so this is very useful and natural. Another construct that appears in multiple places is ${x}.

So having these invariants modeled by the type system is very useful, and actually C++ and MyPy are surprisingly more expressive than Rust! (due to multiple inheritance)

Search for %Token here, the syntax I made up for including a first class variant into a sum type:

[https://www.oilshell.org/release/0.8.pre9/source- code.wwz/fr...](https://www.oilshell.org/release/0.8.pre9/source- code.wwz/frontend/syntax.asdl)

There is a name for the type, and a name for the tag (and multiple names for the same integer tag). Tags (dynamic) and types (static) are decoupled.

</comment></comment></comment></comment><comment><USER53> Just yesterday I removed an obsolete doxygen tag from some 300 files and my Visual Studio went catatonic.

Well, I suspect it's not about Studio per se but rather the git integration but still. Someone avoided a "fancy algorithm" and wasted both my time and the product reputation with a "small n" workaround. Because, git is about small commits right?

I'd like to restate the first rule as "You can't tell where a program is going to spend its life".

</comment><comment><USER54> "Bad programmers worry about the code. Good programmers worry about data structures and their relationships."

— Linus Torvalds

<comment><USER55> Amateur mathematicians worry about patterns, professionals worry about numbers

<comment> codemonkey-zeta I'm neither an amateur nor professional mathematician, so I can't tell; is this statement tongue-in-cheek? If not, what does it actually mean?

</comment></comment></comment><comment><USER56> If curious see also

2017 [https://news.ycombinator.com/item?id=15265356](https://news.ycombinator.com/item?id=15265356),

[https://news.ycombinator.com/item?id=15776124](https://news.ycombinator.com/item?id=15776124)

2014 [https://news.ycombinator.com/item?id=7994102](https://news.ycombinator.com/item?id=7994102)

Pete_D gets credit for the date: [https://news.ycombinator.com/item?id=15266498](https://news.ycombinator.com/item?id=15266498). These rules come from "Notes on Programming in C" ([http://www.lysator.liu.se/c/pikestyle.html](http://www.lysator.liu.se/c/pikestyle.html)), which has its own sequence of threads:

2017 [https://news.ycombinator.com/item?id=15399028](https://news.ycombinator.com/item?id=15399028),

[https://news.ycombinator.com/item?id=13852734](https://news.ycombinator.com/item?id=13852734)

2014 [https://news.ycombinator.com/item?id=7728084](https://news.ycombinator.com/item?id=7728084)

2011 [https://news.ycombinator.com/item?id=3333044](https://news.ycombinator.com/item?id=3333044)

2010 [https://news.ycombinator.com/item?id=1887442](https://news.ycombinator.com/item?id=1887442)

</comment><comment><USER57> Interesting that the first 3 are all about performance. Which strikes me as a bit ironic given rule #1, which could be summarized as don't worry about performance until you have to.

</comment><comment><USER58> Pike himself says "there's a 6th rule": [https://twitter.com/rob_pike/status/998681790037442561?lang=...](https://twitter.com/rob_pike/status/998681790037442561?lang=en)

(6. There is no Rule 6.)

And points to the best source he finds for it on the web: [http://doc.cat-v.org/bell_labs/pikestyle](http://doc.cat-v.org/bell_labs/pikestyle)

<comment><USER59> dang if this sticks to the frontpage, can you change the title to "Rob Pike's 5 rules of programming _in C_ "? As the title is now it misrepresents Rob Pikes words.

</comment></comment><comment><USER60> > "write stupid code that uses smart objects".

Writing stupid code is actually really difficult.

For me, it takes a little bit of iterating before I know just the right place to insert stupid.

<comment><USER61> Do you use TDD? I'm not religious about it in general, but when I'm lost, confused, and easily distracted, I start with TDD to write the dumbest possible code.

<comment><USER60> No.

It's really an issue of not being sure at first what needs to be flexible & data-driven vs handled in code. If make everything data driven, then it becomes this horrible mess where your input is basically a program and your actual code ends up being a terrible interpreter.

I tend to just build things bottom-up, and start with a small bit of functionality, then when I have enough small bits, I bolt them together and decide what I need to abstract at that point, do refactoring on the smaller bits and provide data to them from the caller. Then repeat that continuously until I have all of the functionality I need.

It might be different for other people, but I need to have working code before I can it abstract.

<comment><USER61> I don't understand. Tdd gets you to working code (if on a subset of all your data) extremely fast. There are both bottom-up and top-down styles, neither of which is particularly wrong.

<comment><USER60> The TDD aspect is not really here nor there.

To provide a more concrete example, say I have a function that performs a transformation on a piece data. From what I _currently know about the data_ , I can parse it using a regex. So I code up the function that accepts data, it runs the regex and provides the transformed result. Great.

Now as I'm continuing my work, I notice that some other data requires a similar, but not exactly the same transformation. It can be done with a slightly different regex. So rather than duplicating functionality, I modify the transform function above to take a regex as input along with the data. Everything works as expected.

I get further along in the project and I realize another piece of data needs a somewhat similar transformation, but this time it's just slightly too complicated for a stand-alone regex, it needs to be a function.

The "smart code" way to handle this would be to create another transformation function and call that instead. The "dumb code" way of handling this is to generalize the transformation function such that I can pass in some descriptor for the transformation, and have the transform function return the correct result.

That's the crux of the issue. I rarely have enough information at the time of writing to know just how generalized to make a function. If I created this hyper-generalized transformation at the beginning, but never needed anything beyond the original simple regex, I would have wasted a bunch of time creating code that's needlessly confusing.

TDD is perfectly applicable for development, and would help tremendously with the refactoring aspect, but what it doesn't help with is information that you don't yet know about.

</comment></comment></comment></comment></comment><comment><USER62> Rule 5 (data dominates) is exactly the same as lie 3 (code is more important than data) of Mike Acton's Three Big Lies ([https://cellperformance.beyond3d.com/articles/2008/03/three-...](https://cellperformance.beyond3d.com/articles/2008/03/three- big-lies.html)). Rob Pike's rule 3 (don't use fancy algorithms) is closely related to Mike Acton's lie 1 (software is a platform) as well.

A part of me wonders if Mike was influenced by Rob Pike's rules directly or indirectly. It's also something that an experienced programmer can discover independently easily enough. Mike Acton was clearly heavily influenced by some of the failures of classic OOP design (lie 2 of Three Big lies).

</comment><comment><USER63> I feel ike #5 is why many people like GraphQL, and #1 - #4 is why many hate it.

It becomes much easier to understand what data exists and build tools on top of it's schema. But the extra cludge it adds to optimise the specific case of returning less data in a field is often counter productive.

<comment><USER64> > _But the extra cludge it adds to optimise the specific case of returning > less data in a field is often counter productive._

Could you elaborate?

</comment></comment><comment><USER65> While the rules make sense, it is often not realistic due to business constraints.

What tends to happen in real life is that the profiling and optimization of bottlenecks is forgotten once the software is "ready".

I would propose Rule 0: Developers are irrelevant, only end users of your software matter.

</comment><comment><USER66> One of the big problems with fancy algorithms is that they either access data out of order and/or do pointer chasing. Simple algorithms tend to access the data in order.

CPU's have a lot of logic for making in order data access very fast.

</comment><comment><USER67> This is even more relevant after 30 years.

The Data Dominates principle is the key, everything else just follow, including n are usually small and preference for simple algorithms.

Nowadays we have exactly the opposite, which is understandable since the field has been invaded by uneducated amateur posers.

[https://karma-engineering.com/lab/blog/NodeModules](https://karma- engineering.com/lab/blog/NodeModules)

</comment><comment> GuB-42 Rule 1. You can't tell where a program is going to spend its time. Bottlenecks occur in surprising places, so don't try to second guess and put in a speed hack until you've proven that's where the bottleneck is.

True, but emphasis on the speed _hack_. It shouldn't stop you from thinking about performance in your design. If it means doing less, do less now. If it means adding a speed hack (usually some sort of cache), don't do it until you are sure that you need it.

Rule 2. Measure. Don't tune for speed until you've measured, and even then don't unless one part of the code overwhelms the rest.

I agree completely. But you have to realize that measuring is as much of an art form as optimization is. Especially on today's ridiculously complex systems, the bottleneck may not be obvious. For example a function may take a long time to run, but the real cause may be another function flushing the cache.

Rule 3. Fancy algorithms are slow when n is small, and n is usually small. Fancy algorithms have big constants. Until you know that n is frequently going to be big, don't get fancy. (Even if n does get big, use Rule 2 first.)

Disagree, unless you can prove that n will stay small. You don't know how your users will abuse your program. For example, you may have designed your program to handle shopping lists of a few dozens of items, and then someone decides to import the entire McMaster-Carr catalogue, which has more than half a million items. It may be a great use case you didn't thought of, and that fancy algorithm permits it by scaling well. There are also vulnerabilities that exploit high algorithmic complexity and worst cases. Don't overdo it, but N^2 is rarely a good idea if you can avoid it.

Rule 4. Fancy algorithms are buggier than simple ones, and they're much harder to implement. Use simple algorithms as well as simple data structures.

True, but with the caveats of Rule 3

Rule 5. Data dominates. If you've chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming.

Agree, for me there is a hierarchy in code. From most important to least important: data (structures), code (algorithms), comments.

The order comes from the fact that if you change your data, you need to change your code too, and if you change your code, you also need to change your comments. Going the other way, you can freely change comments, and changing your code will not require you to change your data. Data is the cornerstone.

</comment><comment><USER68> > Data dominates. If you've chosen the right data structures and organized > things well, the algorithms will almost always be self-evident

What does this have to say about the careers and roles of data scientists vs programmers? A data scientists entire job is to categorize and model data in a useful way. In the future, will they fundamentally more important than coders, or will the two roles just merge?

<comment><USER69> I think you're conflating two things: in my mind, working on the shape of data is different than pulling inferences out of that data.

</comment></comment><comment><USER70> Am I wrong to avoid writing O(n^2) code if at all possible when it is fairly easy to use hash tables for a better time complexity? Sure when n is small the O(n^2) one will be faster but when n is small /anything/ you do is fast in absolute terms so I'm trying to not leave traps in my code just waiting for n to get bigger than initially expected.

<comment><USER71> > Am I wrong to avoid writing O(n^2) code if at all possible when it is fairly > easy to use hash tables for a better time complexity

Are you sure that std::unordered_map is faster than std::vector? Did you measure?

Every time you access an element in std::vector, you also access nearby ones (thanks to L1 cache, as well as CPU-prefetching of in-line data).

In contrast, your std::unordered_map or hash-table has almost no benefits to L1 cache. (It should be noted that linear-probing, despite being a O(N^2) version of hash-tables worst-case, is actually one of the better performers due to L1 cache + prefetching)

<comment><USER72> Worrying about performance of small collections is premature optimization.

Using maps or sets nowadays is mostly for clarity, as they are used to solve certain kind of problems.

<comment><USER71> I agree with you. But what you're talking about is completely different from what I was responding to originally.

If you need a set, use a set. But don't assume that its faster than a std::vector.

Even then, std::vector has set-like operations through binary_search or std::make_heap in C++, so it really isn't that hard using a sorted (or make_heap'd) std::vector in practice.

\</comment></comment></comment></comment><comment>--

Even if you don't plan on doing optimization work, its important to have a proper understanding of a modern CPU. The effects of L1 and prefetching are non-trivial, and make simple arrays and std::vectors extremely fast data structures, far faster than compared to 80s or 90s computers anyway. A lot of optimization advice from the past has become outdated because of the evolution of CPUs.

So its important to bring up these changes in discussion, from time to time, to remind others to restudy computers. Things change.

<comment><USER73> > sorted std::vector

But inserting into sorted std::vector is o(n log n) in worst case right? (As you have to binary search the position and move other elements). But a hash set with linear probing can give O(1) (amortized) access, while usually maintaining an invariant like total_size > 2*n. I don't think that would be such an impact on cache locality. Linear probing doesn't require linked lists.

Of course this is given that you have a data structure in standard library. But at this point I think hash sets are pretty standard.

<comment><USER71> Yeah, linear probing helps hash-sets a lot on modern CPUs.

Perhaps linear probing is a better example of how BigO analysis can go wrong on modern architectures. Inserting into a hashset with linear-probing is O(n) worst-case, while inserting into a linked list is always O(1) (best case, worst case, and average case).

And yet, linear probing seems to work out best in practice (with a bit of rigging. The total_size > 2*n invariant is one, but so does Robin-hood hashing if you want to keep the table small)

Linear probing vs Linked List implementations of hash-sets seems to be a more clear example of an O(1) vs O(n) anomaly, where the O(n) example is superior.

<comment><USER73> I don't think it is the same thing.

Inserting into linked list assumes you have found the node to insert in.

I don't remember exact details but in hash set with linear probing, the worst case happens quite rarely given the hash function is good one (which are quite sophisticated these days). It is O(1) amortized. The same applies for hash table with chaining too, that all of your keys may go to same bucket given a sufficiently bad hash function.

Given the other choices, like (as far as I know) SkipList based or tree based variants, hash sets are obvious choice.

<comment><USER71> I mean "Hash-set with Linked List" vs "Hash-set with linear probing". I realize I was getting lazy with my typing, so lemme try to be more clear this time.

Hash-set with Linked List is O(1) all cases.

Hash-set with linear-probing is O(n) worst-case insertion. But happens to be faster in practice with circa 2020-style CPUs (especially with Robin Hood insertion)

Assume the load-factor to be 90%+, so that we actually get a reasonable difference between the two strategies. We have a situation where O(n) is better than O(1).

</comment></comment></comment></comment></comment><comment><USER74> These resonate, especially #1, but I'm not so sure about #5. Although it makes sense to choose good data structures, I don't think that guarantees a simpler algorithm. For example you can store your data in a heap (tree), and still need to write a tree traversal algorithm to print out the elements in order.

</comment><comment><USER75> Rob Pike's rules of programming simplified :

\- Start with stupid code built on smart data (after Fred Brooks)

\- When in doubt use brute force (Ken Thompson)

\- Premature optimization is the root of all evil (Tony Hoare)

</comment><comment><USER76> Why don't interviewers at tech companies just don't follow these rules while grading candidates?

</comment><comment><USER77> Over time, the rule I've "discovered" is:

"Focus on the Nouns, not the Verbs"

</comment><comment><USER78> Wait, wasn't Knuth that said that premature optimizations are the root of all evil?

</comment><comment><USER79> When people say worry about the data structures, what do they mean?

</comment><comment><USER80> > Data dominates. If you've chosen the right data structures and organized > things well, the algorithms will almost always be self-evident. Data > structures, not algorithms, are central to programming.

:O

Epiphany

</comment><comment><USER81> There are actually six rules!

<comment><USER26> There is no Rule 6 --- [http://doc.cat-v.org/bell_labs/pikestyle](http://doc.cat-v.org/bell_labs/pikestyle)

</comment></comment><comment><USER82> These rules look silly when you know that your tight loop that waits for IO or redundantly computes things needs caching. No, you don't need to measure that, and you know that your tight loop function is going to be the bottleneck. Everyone knows that.

Now it does make sense when you introduce an entire constraint library instead of looping over 3-4 variables with a small search space. But again, you know it is a small search space. You know you don't have to optimize it.

I really don't get these rules.

Edit: Go ahead and roast me, but keep in mind I've probably been there and back.

<comment><USER44> > No, you don't need to measure that

Just this evening I came across some code which pasted an image on top of a blue background (in Go) that set every individual pixel to the background, then got every pixel from the source and set the corresponding pixel of the destination to that colour. I figured it'd be quicker to paste the source onto the destination with `image/draw`.

Turns out, if you're using NRGBA images, it's 40-50% slower. That's definitely an "obvious optimisation" that was proven wrong by measurement.

(If you're using RGBA images, though, the pasting method is 300% faster. Because obviously.)</comment></comment>


Rising Tide: Email startups are hot - <AUTHOR> http://venturebeat.com/2007/10/16/four-startups-ready-to-change-the-face-of-email/

<comment><USER2> Good! It's about time! Gmail has lost its glamour a long time ago (in internet years). I'd like an integrated address book, calendar, rss reader, smarter views (think iTunes), account protection, guaranteed backups + real customer service, search by date, spam filters that can distinguish between my friends are viagra ads, etc, etc.

And I'd pay for it! Actually, I prefer to pay, because paying turns me into a customer instead of a user.

<comment><USER3> Gmail will get a facelift in Nov... along with a ton of other social features.

<comment><AUTHOR> Google is the new Microsoft. They won't really do anything revolutionary anymore. They have become too conservative.

</comment></comment></comment><comment><USER4> The potential problem with web-based email startups is that good AJAX email experience requires fast response times. Google can afford multiple data centers with thousands of servers powering gMail making sure UI response is nearly instantaneous.

A little company with $3-4 million in the bank will most likely feel sluggish. A good example is Plaxo. I like them a lot, always have been. But I simply cannot use it because their UI makes me feel I'm on a dialup.</comment>


Book of Revelation - <AUTHOR> https://www.laphamsquarterly.org/roundtable/book-revelation <comment><USER2> An illuminating Bibliography — the passage:

> "Only a minority of the small minority who were literate were so literate to > the level of being literati."

could be attested in Revelation, by

> "Blessed is he that readeth, and they that hear the words of this prophecy"

which implies that they that hear were not expected to readeth themselves. On the other hand, the license terms of the prophecy are somewhat illiberal:

> "For I testify unto every man that heareth the words of the prophecy of this > book, If any man shall add unto these things, God shall add unto him the > plagues that are written in this book:

> And if any man shall take away from the words of the book of this prophecy, > God shall take away his part out of the book of life, and out of the holy > city, and from the things which are written in this book."

Severe restrictions via Divine Rights Management?

<comment><USER3> Yeah licensing sounds like heavily enforced CC BY-ND</comment></comment>


Reinventing Git interface - <AUTHOR> http://tonsky.me/blog/reinventing-git-interface/ <comment><USER2> Love it, I've always understood the conceptual model (perforce has the same one) but I'm always running afoul on git's "helpful" CLI commands. This would solve almost all the issues and has the promise to educate designers/analysts on how to correctly think of versioning by making it visual.

The project could start out by creating the visual interface (D3,js?) and spitting out the appropriate git CLI commands for whatever was done by dragging and dropping. Phase 2 would be to integrate the web server into the git project.

</comment><comment><USER3> Wow, this is totally the Git Interface of my dreams. Is this just a concept, or do you have a working prototype?

<comment><USER4> Just a concept

</comment></comment><comment><USER5> Love the drag and drop argument. As a matter of facts SmartGit allows several operation via d&d: you can reset, rebase and rebase interactively just using the mouse

</comment><comment><USER6> I just wish people stop calling it GIT instead of git. It's not an abbreviation for anything, it's literally the same as the english insult.

<comment><USER7> And, anyway, abbreviations in general aren't usually all-caps either ( _initialisms_ often are, but that's a very specific subset of abbreviations.)

</comment></comment><comment><USER8> That's great idea. #git

</comment><comment><USER9> Sigh. "grow-only", "rebase is dangerous", "detached head state is dangerous". STOP. Stop it now.

git is a bag of commits organized into a tree (a tree of Merkle hash chains). Branches and tags are symbolic names for these. Think of it this way and there's no danger.

Indeed, _published_ repos/branches must not be rebased. That's what receive hooks are for: to reject non-fast-forward merges. If you don't understand a word of the previous sentence, don't worry: you're just not ready to run a public repo.

What is dangerous is:

\- pruning repositories

\- lack of pushable (and pullable) reflogs

Reflogs are what makes it easy to recover if you lose a symbolic name and you're left with a pile of commits you'd not find your way through: the reflog tells you what you did and gives you the commit hashes you need to find your way home.

I often push from detached head state, and I did so today. Here's what I did:

        $ git remote add contributor https://github.com/contributor/project
        $ git fetch contributor
        $ git checkout contributor/their-branch
        $ git rebase -i origin/master
        <fix up some things>
        $ git push origin HEAD:master
        $ git checkout master
        $ git merge origin/master

Yes, that's advanced usage, and in particular the push command-line can be dangerous, so learn exactly what "git push origin HEAD:master" means before copying that, but compare now to the crutches equivalent of the above:

        $ git remote add contributor https://github.com/contributor/project
        $ git fetch contributor
        $ git checkout contributor/their-branch
        $ git checkout -b their-branch
        $ git rebase -i master
        <fix up some things>
        $ git push origin master
        $ git checkout master

Or, maybe I could have told the contributor to rebase and fix those things. Or maybe I could have merged the contribution and then committed said fixes. But I like clean history -- I've been taught to by the very best.

I didn't need a local branch crutch to find my way around because I know the model: a tree of commits.

Understanding the model is the key.

There are other VCSes that also use Merkle hash trees. Internally they have the power that git has. Mercurial's language for expressing refs is great. Fossil has all the power of SQL, and it shows. But they all try oh so hard to hide the model from me. It's not like hiding what a process is from a non- developer user. SourceTree does a great job allowing non-developers to understand their version trees, so I know this is not too hard on non- developers. Yes, non-developers should mostly never rebase, but detached head state is useful for them: because sometimes they need to "see" old versions, so they end up branching, and so they end up merging, and guess what: merging is what's not easy for them.

If you want to help non-developers use a VCS, give them a better UI for dealing with diffs. Don't punish the rest of us by hiding the wrong thing from everyone.

<comment><USER4> I'm writing exactly about that. GIT model is simple and operable, so UI should not hide it behind "wizards", but incorporate more direct use of it.

<comment><USER6> It's git not GIT. Stop making it an abbreviation.</comment></comment></comment>


The Next Internet: What's Holding Us Back? - <AUTHOR> http://www.readwriteweb.com/enterprise/2011/09/the-next-internet-whats-holdin.php <comment><USER2> I am baffled. He's talking about them trying to settle how companies would bill each other for email, and the complications of interconnected email as if it was a complex subject, in 1990. SMTP was first defined in 1982.

The problem they had was that they were trying to charge for each email sent, and the internet doesn't really support that kind of thing.

The sooner that ISPs realise that they are suppliers of dumb pipes, and charge accordingly, the faster they'll be making money from what is their real business.</comment>


Fermi calc: What percentage of available data does the NSA capture? - <AUTHOR> http://www.bigdatarepublic.com/author.asp?section_id=2817&doc_id=264689&

<comment><AUTHOR> Things actually look at lot worse when you consider the level of data collected in certain countries. For instance, in Jordan 12.7 billion datapoints were collected in one month concerning a population of 6.1 million. 2000 datapoints per person. According to my Fermi calc that's pretty much all the digital metadata generated by an average citizen.</comment>


One-command NORCPU program hacking challenge: analysis and solutions - <AUTHOR> http://meta-coding.blogspot.com/2011/02/one-command-norcpu-program-hacking.html

<comment><USER2> It's headed by PG, no less!</comment>


Clojure Cup 2014 Apps - <AUTHOR> https://clojurecup.com/#/apps

<comment><USER2> I've laughed a lot by looking at the achievements I've unlocked with my Git repos using Acha: [https://clojurecup.com/?#/apps/acha](https://clojurecup.com/?#/apps/acha) ... My submission to ClojureCup was a simple feeds reader: [https://clojurecup.com/?#/apps/friendly](https://clojurecup.com/?#/apps/friendly)

<comment><USER3> Wondeding if Acha will be open sourced :) Only because their platform description sounds tempting. They say no AJAX once it's loaded (isomorphic) but I don't see that on the site, wondering if that's just not live.

<comment><USER4> We're at [https://github.com/clojurecup2014/acha](https://github.com/clojurecup2014/acha)

</comment></comment></comment><comment><USER5> This one is quite fun: [https://clojurecup.com/#/apps/rockets](https://clojurecup.com/#/apps/rockets) And a shameless plug for my entry: [https://clojurecup.com/#/apps/parade- route](https://clojurecup.com/#/apps/parade-route)

</comment><comment><USER6> You can also track current voting here (with history!): [http://voting.playthehat.com](http://voting.playthehat.com)

<comment><USER5> wow very cool

</comment></comment><comment><USER7> That's pretty cool: [http://cloujera.clojurecup.com/](http://cloujera.clojurecup.com/)

</comment><comment><USER8> The voting for the apps has started now - you can vote for multiple apps.

<shameless-plug> Our entry in the competition: [https://clojurecup.com/#/apps/mongrila](https://clojurecup.com/#/apps/mongrila) </shameless-plug>

</comment><comment><USER9> Are these required to be open source and/or is there a way to find them on GitHub?

<comment><USER8> No, there isn't any requirement to make them open source - but most of the apps are and available at [https://github.com/clojurecup2014/](https://github.com/clojurecup2014/)

<comment><USER9> Thank you :)

</comment></comment></comment><comment><USER10> This is a really fun competition and it really highlights how friendly and light hearted the community can be, while showcasing how easy it is to be productive in clojure. Can't wait for next year!

</comment><comment><USER4> Current votes ladder: [http://acha.clojurecup.com/ladder.html](http://acha.clojurecup.com/ladder.html) (updated every 5 minutes)</comment>


Ask HN: Why did delicious.com fail? - <AUTHOR> One day it was popular and then it started going through redesigns and relaunches. For a while, I used it to see what was trending, but then they hid that info from the home page and then brought it back until finally the site appeared to be a broken ghost town.
I'm just trying to construct a narrative to satisfy my curiosity. What exactly happened? Was it death by a thousand cuts (if so, where did it get cut?) or was there one fatal mistake (like Digg).
Discuss. (And feel free to share any links to stories/articles on Delicious' demise.)
EDIT: Typo. I meant "Digg", not "Reddit." <comment><USER3> Acquired in 2005 with 300k users. Had 4m users and maybe 1m MAU in early 2007 before the transition to the v2 site.

Yahoo management did a huge amount of work to kill momentum.

1) We were forced to migrate to PHP. We were not allowed to have ops support until this was complete.

2) We inherited the Yahoo Photos team that brought a backend that they had written for that platform. They estimated it would take six months to migrate delicious to that new platform. It took 2+ years.

3) We were denied having actual access to VESPA and had to reuse MyWeb's backend instead, which was designed for a different feature set.

4) Almost all the staff were placed on Yahoo Answers anyway, which ended up dying of its own accord anyway.

<comment><USER4> That's not likely what caused its decline. I used Delicious for quite a while, and my reduction in use had nothing to do with what it used on the backend. I think it served its purpose as a social bookmarking site pretty well for the time it lasted. But it finally started its decline likely due to old fashioned competition. Google pretty much made the need for personal bookmarks obsolete, and sites like Digg and Reddit were a much better method of sharing links with curated lists and discussions.

<comment><USER3> It lost momentum - no features or anything added for three years.

A large number of people use computers as memory tools. Trello, Evernote, Pinterest, etc. - Google doesn't seem to be particularly relevant. Perhaps you mistake your usage pattern for everyone's?

Neither Digg nor Reddit made a way to share curated lists, so no clue what you are talking about there.

</comment></comment></comment><comment><USER5> I have no specific knowledge here. But I've been a del.icio.us user since I think 2005.

In general, despite great promise and utility (IMHO), curated bookmarking of this sort never really took off. It's always been around, and still is. Why? some guesses:

Not that many people are data-oriented enough to want to use such a service. Same reason RSS is relatively unpopular.

Delicious and related services never generated the sort of social proof / payoff that drove other services. E.g. desire for friends / followers / karma were essential to FB / twitter / HN (since we are here!). Delicious was high on the personal utility, low on the social reward.

I'm not sure this is that related to Delicious' functionality, but might just be a cultural / community function, that never really developed in this case. It's not tech that makes HN awesome, it's people. But given that Digg / Slashdot faded, this may not be as popular a category. Reddit is huge now... but it's more of a forum vs. link sharing.

And these services are so easy to create, who would pay for them? In the absences of hype / popularity, not much of a business there. I switched to raindrop, which is great. But others were close.

It's very sad to me. I think that the ability to socially curate the web, and to vote up/down on such resources, is actually really valuable to the long- term health of the internet.

Maybe we're just not ready yet...

<comment><USER6> * Reddit is a cesspit waiting to fail that encourages abuse as a platform. I am waiting for what replaces them as there is a lot of information people are looking to share without the torrent of garbage that comes with it currently.

* Slashdot faded because new buyers came in who didn't understand the product.

* RSS still exists and is going strong. It just does the job without the flash, the reason content producers don't like it is that you can't monetize it in the same way as email. I personally use TheOldReader for curating this.

* I'm going to add Sourceforge as a site that shot themselves in the face. It seems like it's newest owners have done a lot to try and repair the damage.

Raindrop looks fantastic, I'm glad you brought it up. I'm guessing we few are the kind of people keeping this type of service alive.

<comment><USER7> > Reddit is a cesspit waiting to fail that encourages abuse as a platform.

People mistake reddit for a single bulletin board, because it allows you to aggregate multiple subreddits, and criticize it like it's a single place. In reality it's just a free hosted bulletin board service. As such, it's just a cross-section of the internet, and to criticize reddit is to criticize the abstract concept of internet fora. There are serious places like /AskHistorians in there, along with many others. There are bad neighborhoods/poorly moderated fora in there, but that doesn't make reddit itself a cesspool any more than the existence of Skid Row makes Los Angeles County a cesspool.

</comment></comment></comment><comment><USER8> Because it got bought by Yahoo. They didn't take care of it properly. Then it got bought by Avos systems, who didn't take care of it properly. Then it got bought again by people who didn't take care of it properly.

Now it is finally owned by Pinboard. But most of the users who abandoned del.icio.us had already switched to Pinboard. Now all is well.

<comment><USER9> Some related discussion over at Metafilter during the Pinboard acquisition timeframe:

[http://www.metafilter.com/167340/Pinboard-Acquires- Delicious](http://www.metafilter.com/167340/Pinboard-Acquires-Delicious)

<comment><USER10> Pinboard Acquires Delicious | [https://news.ycombinator.com/item?id=14462384](https://news.ycombinator.com/item?id=14462384) (Jun 2017, 227 comments)

</comment></comment></comment><comment><USER11> For a few years I was the Silicon Valley Necromancer, attempting to reenergize failing businesses with new technology. I was on the Delicious team at AVOS (2012-2013), whom acquired Delicious from Yahoo!. I probably know very little of the whole story...but...I can at least share some of the technical challenges that we faced.

I lead the team on the re-write that brought Delicious into the single page app (SPA) world. Most people wondered why we built the app from scratch again. The python codebase that the Yahoo! team managed, I am not sure if they started their version of the app that way or if the inherited it, but we concluded that it would be quicker to re-write the app as opposed to dissecting the exiting application codebase. This is the primary reason why stacks were canned, regardless of what others might have said. Many times rewrites require reducing features in order to build a new foundation. This is sometimes a good thing, and sometimes not.

A rewrite also gave us the opportunity to build the app as an SPA. While we made an SPA, React, Redux, Webpack, Gulp, etc. did not exist, and we definitely ended up spending more time than expected creating inferior toolsets due to the lack of options at the time.

Another major challenge we faced was that the database was sharded in such a way that if your username was "zebra" the backend would hit MySQL server 1, then 2,3,4,5,6,7,8,9, and finally 10 before returning results. If your username was "apple" you'd get a response quite quickly. I am not sure if we ever completed the migration into new shards/replicas.

There were also some random old API endpoints where we had to double encode periods in the url or the API would throw an exception. Obviously there was no documentation on for our treasure hunt to find which API endpoints had this major issue.

We didn't get any notice at AVOS before the team was moved off of Delicious to work on other projects. Perhaps we took too much time building the rewrite, or perhaps we realized there was no business model worth the time.

AVOS would later make a unilateral decision to move all projects to Angular, which was not a framework I believed would benefit my career development. I left AVOS when StubmleUpon called me and said, "hey if you can make Delicious a SPA, do you think you can make our app an SPA?"

Boy, I sure know how to pick 'em...

P.S. I will say that the Delicious team at AVOS was a very talented team and I am thankful for each day I got to work with them.

[edit] for grammar [edit ii] Since it doesn't seem clear in the comments: I'd build Delicious differently today.

<comment><USER12> I am undoing literally all of your work right now. I curse you daily!

<comment><USER13> OPs story sounded really dangerous - rewriting an existing app that is in scale with unproven tech.

Care to share some fun facts on what you're doing right now? Please?(;

<comment><USER12> I'm just moving it back to flat pages without the javascript cruft.

<comment><USER13> Thx for sharing.

Writing a too complicated front-end is probably one of those situations that I am getting into more often in the last years..

After some 15 years doing web dev, I'm starting to encourage SPAs more and more sparingly - only where they _actually_ improve UX and it's worth the extra work.

</comment></comment></comment></comment></comment><comment><USER12> Current owner of Delicious here.

Here's my understanding of the history (which I hope people like joshu correct if I'm wrong):

The site was awesome and popular pre-Yahoo, but also pretty overwhelming to run. Yahoo brought it with resources, scale, and sweet, sweet promises that they understood Web 2.0. Instead, they quickly moved Joshua to a position where he couldn't really steer the product, and got sidetracked into redesigns and time sinks like integrating Yahoo ID as logins. The original, ambitious plan (integrate Delicious as a signal into Yahoo search, and make it unbeatable in real-time trending topics) was lost to management paralysis.

Yahoo disastrously announced it would 'sunset' the site before actually having a plan for it, so in winter 2010 a large number of people jumped ship. Sites like mine (Pinboard) benefitted a lot, Delicious was crippled.

The new owners at AVOS seem to have had a grandiose idea that they would repeat their YouTube-scale success, and rewrote the site accordingly, to serve billions. The handoff from Yahoo was one of data, not code (since things were written to run on Yahoo's platform) and required users to opt in. This hemmorhaged users further, while AVOS engineers wrote a bloated and ambitious Delicious clone.

But the biggest mistake was when AVOS turned off some features beloved by a core Delicious constituency, fanfic authors. In particular, they made it impossible to search on the "/" character in tags, which instantly rendered a lot of the elaborate fanfic tagging and classification scheme useless. In my mind, that's when Delicious hit the point of no return.

AVOS failed through some combination of founder grandiosity and short attention span. They managed to get the worst of all worlds—high spam, low revenue, and a $40K a month AWS bill. They sold to Science Inc., a bunch of LA tech bros who WROTE EMAIL IN ALL CAPS and owned a bizarre collection of other online apps.

When they tired of it, they sold it to Tony Aly, an SEO specialist who wanted to try his hand on a bigger project, but eventually found himself overwhelmed by the support and operational burden. At that point, he sold it to me, and I parked it on a couple of expensive servers and made it read-only.

To the question "what happened", I think the best answer is that Yahoo killed the site by neglect. AVOS took it past the point of no return by making it bloated, slow, and antagonizing the last remaining group of core users. None of its acquirers ever understood what it was for.

Except me. I understand you, Delicious! But I also compete with you. No more tears now, only dreams.

<comment><USER14> Hello! Can I buy you a coffee in SF? I suppose we're building a competitor to you, but generally think there's room enough for lots of solutions to this space.

<comment><USER14> Also, we are tiny, so 'competitor' is a laughable comparison.

<comment><USER15> I mean, idlewords is just this guy...

<comment><USER16> Well maybe mceoin is a smaller person?

</comment></comment></comment></comment></comment><comment><USER17> My recollection is that it was acquired by Yahoo and promptly stopped receiving any attention. At least one of the founders left Yahoo a few years later. Not unlike what happened to Flickr, except Flickr had enough momentum and traction to not completely die. It wasn't long after all that that Yahoo Brickhouse closed up completely too. I don't think its fate was a result of anything intrinsic, just a byproduct of Yahoo's decline.

<comment><USER12> Flickr negotiated a separate HQ as part of its acquisition, which helped them stay independent for a little while. Delicious had no chance under 39 layers of Sunnyvale management.

</comment></comment><comment><USER18> I may be in the minority here, but I used delicious as a "bookmarking in the cloud" feature because it was around before synced bookmarks were a thing. I was changing machines quite a lot and so didn't want to use the browser's bookmarks.

Now Chrome does this feature pretty well native I don't really need delicious anymore, i never used it much for its social aspect.

</comment><comment><USER19> Yahoo bungled Flickr and Upcoming by neglect - limited resources and demanding integration rather than features. I'd imagine Delicious was the same, but I don't have a link handy.

For Flickr: [https://gizmodo.com/5910223/how-yahoo-killed-flickr-and- lost...](https://gizmodo.com/5910223/how-yahoo-killed-flickr-and-lost-the- internet)

For Upcoming: [https://medium.com/message/diary-of-a-corporate- sellout-5874...](https://medium.com/message/diary-of-a-corporate- sellout-587479c215f4)

</comment><comment><USER20> I was an avid user of del.icio.us in its heyday but I remember these things pushed me away:

* major redesigns (the current Hulu redesign is about as bad)

* competitors, there were a lot of good bookmarking services. I think I went with Evernote

The wikipedia page has a lot of what went wrong [https://en.wikipedia.org/wiki/Delicious_(website)](https://en.wikipedia.org/wiki/Delicious_\(website\))

</comment><comment><USER21> I think it died because bookmarking is a feature, not a company. As so many syncing and social media services gained traction, a pure bookmarking service was always gonna get lost in the noise. I was A Delicious user for a while, but now I use Firefox sync and Evernote for bookmarks. As for exploring others bookmarks, I use Facebook for that.

<comment><USER14> Pinterest is visual bookmarking (though it may be phrased differencly), so a small tweak to the model made all the difference.

<comment><USER22> It feels like Pinterest feels will start declining if they haven't already. Being forced to sign in or download the app kills any openness.

<comment><USER23> They are hugely profitable

</comment></comment></comment></comment><comment><USER24> Delicious - like Mr Wong which I liked - was one of the these social but anonymous services. Some people may have chosen their normal pseudonym of choice and even shared it with friends, others may have not.

IMHO that's also the reason why Facebook was winning above all the other Social Networks, it was "real" and not anonymous (or pseudonymous). Virtually all popular social but (kind of) anonymous services of the past didn't survive or at least not make it to today's mainstream: forums, MySpace, ICQ... Reddit is kind of popular but almost exclusively used by techies or people considering themselves nerdy.

I wonder if one could make a modern Delicious, with mandatory Facebook connect or something. Not sure though if that would still work out of privacy concerns. Actually one might consider Pinterest something quite close to it.

</comment><comment><USER25> Same as the reason for the failure of Upcoming (v1) and underperformance of Flickr: Yahoo & its frothy brew of money plus strategic blindness.

You might also throw the fate of ~pg's Viaweb, once it became Yahoo Stores, into that same class of fumbled opportunities. And so you can read Graham on Yahoo & get a good idea of the issues:

[http://www.paulgraham.com/yahoo.html](http://www.paulgraham.com/yahoo.html)

</comment><comment><USER26> I loved Delicious and I really wanted to stay there, but at some point, the Firefox plugin broke and it wasn't fixed for maybe months. I started using the web interface to save my urls, but it was cumbersome. Then I started looking for alternatives and I paid the lifetime subscription for Pinboard, $9 at the time. Then I switched and I'm a happy Pinboard user since then.

</comment><comment><USER27> Not super familiar with Delicious, but from what I've seen most HN folk seem to use Pinboard ( [http://pinboard.in/](http://pinboard.in/) ) as a bookmarking tool.

</comment><comment><USER28> If I remember correctly the terms of sale required that they get each user's permission to use their links, so the site was vastly diminished.

Again if I remember correctly there was a decent API for del.ico.us but this was not a priority for delicious.com.

The site was premised on the idea of "folksonomy" ie that structure would emerge from the accumulated links. This hypothesis didn't bear out.

<comment><USER3> "folksonomy" was a word created after the fact to describe what I built. Therefore not a premise.

Most users did have structure to their bookmarks. If I had been allowed resources I think we would have built something that lined up similar structures across users and groups of users.

I believe the hypothesis was robustly accurate, especially in the modern world of machine learning.

</comment></comment><comment><USER29> Totally rumor-mill, I had heard that it was, after being acquired by Yahoo, rewritten entirely in PHP, because that's what Yahoo used, and as a result lost all momentum for new features. However, as I said, t his is total rumor mill, and I cannot claim to know if it's true.

<comment><USER12> Delicious was written in Perl (Mason) and ported to PHP at Yahoo. The language change had nothing to do with the horrible management and lack of product vision at Yahoo, though.

<comment><USER3> This is actually pretty accurate. There was a backend written in Erlang and some other bullshit that also delayed things by years.

<comment><USER30> Erlang makes me break out in facial twitches to this day.

</comment></comment></comment></comment><comment><USER31> I stayed away from site for a long time because of the url, del.icio.us. I'm probably just thick headed or something but my mind read that as three words, "Del Icio US," and thought "wtf?"

</comment><comment><USER32> For me, it died the day its popular RSS feed stopped working.

</comment><comment><USER33> Acquisition by Yahoo! Flickr suffered the same fate.

</comment><comment><USER34> I would still be on delicio.us except for the scare that Yahoo was going to shut them down. I moved on to Diigo.com and never looked back.

</comment><comment><USER35> I think Delicious succeed at what it wanted to be (a nerdy bookmarking site that people like myself loved).

What it failed at (under Yahoo) was navigating its product and audience around to the point where it could have become a Pinterest like Behemoth.

Facebook for all it's flaws and my general concerns with them have proven themselves the masters at incorporating and updating both acquisitions and their core product to attract a general audience that they can make money off of.

</comment><comment><USER14> I'm currently building a "social bookmarking" tool, so can't speak to first hand evidence but have looked into this and spoken to people (2nd hand, not 1st hand sources).

[would love to chat over coffee or email with others passionate about this space. @mceoin on twitter]

Why delicious died: \- Yahoo acquisition. Death by a thousand cuts from that day forth. Some things here really pissed off core users include Yahoo sign in and shuttering some core features that power users loved (see exodus to Pinboard).

Landscape: \- The attention economy has definitely shifted. Perhaps delicious could have evolved along with it (we'll never know), but now it is certainly the case that it is more difficult to gain mass adoption for products that will provide you with lists of information, since 'good enough' alternatives exist (notably, these are typically feeds, not lists) \- the world has gone mobile.

Who lives, who dies, who tells their story? \- Most died or were acquired (it turns out if you develop a team of search and indexing experts, you're pretty attractive to big companies). I counted 20+ here, about 50% acquired, the rest: ?? \- Pinterest had the visual twist, and grew to 200m people \- Pinboard generated revenue from Yr1, and has a small but profitable user base (important, because "not dying" is a core piece of the puzzle). \- Kippt had a great product but team was ultimately were acquired by Coinbase, so it would be awesome to hear more about their experience. \- Pocket lives on through Mozilla acquisition. In my experience they never cracked the social piece, although definitely provided the individual utility to be a daily-active- utility. Watch-this-space.

Why is this space difficult, generally? You would think that being able to explore lists of what people find interesting is appealing, and it certainly is (in theory). There's a hierarchy in information discovery for this space where: personal saves > friend saves > followee saves > random people saves. \- social products require high clustering coefficients ( _very important_ ). This seems to be particularly difficult to obtain in social bookmarking space. (I believe, but cannot confirm, that most products went too wide too early, and failed to nail this experience. Facebook's control of launch from college to college is a different but effective strategy that gave them saturation, so I believe a restricted entry via referral is pragmatic approach here.) \- Low virality. This is a hard one to prove since non-success doesn't mean no potential for breakout success. \- Low target market. Same point as above.

Monetization (three options I see): \- advertising: requires mass scale, hence most attempts here die. \- pay to play: Pinboard is doing this. (does this preclude wider adoption? or are other factors at play?) A balance of paying for privacy features might be an option here. \- crowdfunding/non-profit: e.g. wikipedia model. Nobody has tried this yet. Would take a certain kind of team and community, but might position itself well for being a long term human- curated archive of the web.

I have some thoughts on how what this space lacks and what can be done differently that I'm happy to share privately. Suffice to say that we want this, and believe there's an opportunity to build a product that at least a few people love.

Who is taking a crack at at "social bookmarking" today? \- Refind.com. Notably, they're more "show me what my friends are reading right now" and feel like a slimmer, more reading focused, twitter feed. Mobile app is best consumption vehicle. \- Mix.com (from Garret Camp/Expa). Hasn't 'clicked' for me personally, but if might for you. \- Us! We're not ready for a Show HN but if you're in SF and love this space, please do hit me up on twitter for a coffee: @mceoin.

<comment><USER36> > _Facebook 's control of launch from college to college is a different but > effective strategy that gave them saturation, so I believe a restricted > entry via referral is pragmatic approach here._

Off-topic: I wonder who made the call on the next college to move to when Facebook expanded out of Harvard to other colleges.

Was it Zuckerberg? Would love to read about this aspect from Facebook's history as whoever came up with the strategy had a clear understanding of the Economics concept of _artificial scarcity_ [0] and its attendant effects; it was incredibly effective at stirring up _sustained interest_ among college students and the wider population about TheFacebook.com until it was their turn to sign up for an account.

[0] [https://en.wikipedia.org/wiki/Artificial_scarcity](https://en.wikipedia.org/wiki/Artificial_scarcity)

<comment><USER14> Not sure. I studied crowd behavior through sociology when at university and remember looking into the pattern of streaking behavior in the 70s (? - <USER2> have been 60s). Typically started at an elite university, then spread to all the 'lower tier' universities in the same region. Wouldn't be surprised if FB took same approach wrt signaling.

<comment><USER36> Not exactly [0] [1] [2].

They started at Harvard then spread to other elite universities (outside Boston) before slowly opening up access to 'lower tier' universities in the same region as Harvard like you said, then other regions.

[0] _Zuckerberg 's Facebook started off as just a "Harvard thing" until Zuckerberg decided to spread it to other schools, enlisting the help of roommate Dustin Moskovitz. They began with Columbia University, New York University, Stanford, Dartmouth, Cornell, University of Pennsylvania, Brown, and Yale._ From [https://en.wikipedia.org/wiki/Mark_Zuckerberg#Facebook](https://en.wikipedia.org/wiki/Mark_Zuckerberg#Facebook)

[1] _In March 2004, Facebook expanded to Stanford, Columbia, and Yale. This expansion continued when it opened to all Ivy League and Boston-area schools. It gradually reached most universities in the United States and Canada._ From [https://en.wikipedia.org/wiki/History_of_Facebook#FaceMash](https://en.wikipedia.org/wiki/History_of_Facebook#FaceMash)

[2] _Harvard students are no longer the only ones cyber-stalking their classmates and professors on thefacebook.com. With the click of a keyboard and squeak of a mouse, students at Columbia University and Stanford University can now track down that hottie in section or get help with problem sets. Mark E. Zuckerberg '06, the website's creator, opened his online networking service to Columbia last Wednesday and to Stanford the day after._ From [http://www.thecrimson.com/article/2004/3/1/facebook- expands-...](http://www.thecrimson.com/article/2004/3/1/facebook-expands- beyond-harvard-harvard-students/)

</comment></comment></comment></comment><comment><USER37> For me, it was always painfully slow to work with.

</comment><comment> taw-an del.icio.us ?

<comment> taw-an Not sure why I got downvoted. I was the first comment and just trying to clarify which site the submitter was talking about (since he said "delicious.com").

<comment><USER38> I upvoted you because I didn't know that delicious.com was del.icio.us.com until I read the comments.

</comment></comment></comment><comment><USER39> It tried to compete with Pinboard.

<comment><USER40> [https://blog.pinboard.in/2017/06/pinboard_acquires_delicious...](https://blog.pinboard.in/2017/06/pinboard_acquires_delicious/)</comment></comment>


Rocketcharts - Awesome open-source HTML5 financial charts - <AUTHOR> http://www.rocketcharts.com/

<comment><USER2> Is there more than one chart?</comment>


51% Attack at Bitcoin Cash – Here Is What Happened - <AUTHOR> https://medium.com/altcoin-magazine/altcoin-news-51-attack-at-bitcoin-cash-here-is-what-really-happened-66553fefe21c <comment><USER2> As someone not intimately familiar with the field of cryptocurrency research, I wonder if truly decentralized currencies can ever be completely secure? It seems as if one ever became important enough and there was a strongly motivated enough state actor with lots of computing resources, staving off a 50% attack forever would be infeasible, especially if the people using the cryptocurrency day to day weren't mining it actively as well (it superficially seems that more and more people need less and less powerful computers anyway as cloud based services become more popular - it's not infeasable to imagine a world where your average Joe no longer has the computing power to mine ar home because they fully use cloud swrviea). Is this a valid concern, or are there ways to address this?

<comment><USER3> The term you're looking for is finality. Some people are developing consensus algorithms that never reverse transactions but in case of an attack the chain may stop.

BTW, normal people haven't been able to profitably mine any major cryptocurrency for years.</comment></comment>


Atari did not waste any time mourning its departed cousin... - <AUTHOR> http://www.nytimes.com/1985/01/08/science/peripherals-the-plight-of-orphan-computers.html

<comment><USER2> There was this weird Coleco ADAM homebrew scene well into the mid '90s. I used to get this catalog/newsletter called "Adam's House" I think in the mail back then. (I guess they are still around, called EColeco!?!)

They had some crazy custom enhancements for it, including memory expansions that plugged into that internal bay etc.

With that said, I used to goof on my ADAM owning neighbor from my lofty C64 owning perch.

</comment><comment><USER3> The story of the Atari ST and Commodore Amiga is fascinating on many levels. In fact, the Amiga _nearly was_ the Atari ST for a while. For a good morning coffee read, try the link below.

<http://www.amigahistory.co.uk/ahistory.html>

<comment><USER4> Also worth a read, the Ars Technica Amiga history series: [http://arstechnica.com/hardware/news/2007/07/a-history-of- th...](http://arstechnica.com/hardware/news/2007/07/a-history-of-the-amiga- part-1.ars)

Also this interesting analysis : [http://arstechnica.com/gaming/news/2010/06/shadow-of- the-16-...](http://arstechnica.com/gaming/news/2010/06/shadow-of-the-16-bit- beast-an-amiga-gaming-retrospective.ars/)

</comment></comment><comment><USER5> After this, you can understand why people stuck to one platform for the next decade or so.

</comment><comment><USER6> That article was pretty disorienting before I read the date at the top. "Man, I thought I knew most of the players in the industry... wait, joysticks as a standard peripheral?" Guess I missed the 80s mention in the first paragraph. :)</comment>