The bad side of systemd: two recent systemd failures - <AUTHOR> http://utcc.utoronto.ca/~cks/space/blog/linux/SystemdCrashAndMore <comment><USER2> I'm no fan of systemd, but do we really need to be nitpicking its every failing? The alternatives are certainly not perfect either. If you don't like it, don't use it. Many distros are still committed to supporting other init systems along side systemd and many BSDs have a very good philosophy with things like this and may be worth a look too.

Can we just agree to move on? I'm sick of the endless banter. If you like systemd, use it, if you don't like it, don't. If you think it needs more time to mature, stay away from it for a while and experiment occasionally. That's my plan at least.

<comment><USER3> _if you like systemd, use it, if you don 't like it, don't._

That is so naive. No one chooses to use systemd. People choose a distro. It's being forced on __long time __users of distros without any of the users having a say.

Yeah, I can switch from one distro to another. That's a choice I have. But it's not so simple as you make it sound.

<comment><USER4> > It's being forced on long time users of distros without any of the users > having a say.

It's being adopted by distributions in accordance with the stated and implied wishes of the developers, maintainers, and users of the distributions.

The reason that (e.g.) Arch dropped support for legacy init so quickly was because they literally failed to find anyone who wanted to go through all the work of maintaining the old init system. If none of the users want to do the work, then nothing's being "forced" \- that's the way community-organized FOSS projects work![0]

Same goes for Debian, who made the switch in accordiance with their normal development process (including a general resolution in support of systemd!). Debian has promised to maintain systemd-shim (supporting other init systems) through at least Jessie, and possibly longer, depending on whether there is enough demand for alternative init systems, and support from developers for maintaining it in future releases.

Ironically, the biggest threat to systemd-shim in Jessie's successor are people who claim they want to fork Debian - if all the people who hate systemd leave Debian, then nobody who wants to actually do the work to maintain the alternative init systems will remain with the Debian project[1].

[0] Even then, you _can_ still find an AUR package for it ([https://aur.archlinux.org/packages/initscripts- fork/](https://aur.archlinux.org/packages/initscripts-fork/)), though as with everything in the AUR, it's subject to much less testing. Note that the package has only 27 votes - this means that only 27 people actually said that they care about moving this package back into the main distro.

[1] This may be a bad or a good thing, depending on who you ask.

<comment><USER5> >The reason that (e.g.) Arch dropped support for legacy init so quickly was because they literally failed to find anyone who wanted to go through all the work of maintaining the old init system. If none of the users want to do the work, then nothing's being "forced" \- that's the way community-organized FOSS projects work![0]

Users != developers

I am not a developer. I'm an administrator. I know enough C to be able to poke around source code and understand what is happening when I get an error, but not enough of it or anything else to maintain an init system. A lot of admins don't know this much. A lot of desktop users don't know this much.

I'm not disagreeing with your overall sentiment here - but it's not so simple as "If the users of the product liked it, they'd maintain it" \- sometimes they don't have the skills required to. Not everyone who drives is a mechanic, etc.

<comment><USER6> > Not everyone who drives is a mechanic, etc.

If you car requires more knowledge to maintain than you have, you can get a different car, pay someone to maintain it or get a bike. Those are the only options I see. I don't see how init is any different than a car. You have those same options. I'm sure someone somewhere is paying RH or canonical or in house devs/admins to maintain init scripts for their application stacks.

<comment><USER5> I hesitated to make the analogy because I expected a response like this, stretching the analogy too far.

It isn't a matter of managing init scripts - that's easy. Continually updating a distro to use your init system of choice is a wholly different matter. I can change the oil in my car. I can't replace the transmission.

</comment></comment></comment></comment></comment></comment><comment><USER7> I can't speak to the first problem, but the second is more of "this is strange and I don't care to learn how it works".

journalctl --no-pager

Problem solved. I mean, you have the command, it's right there in the usage text. Which, awesomely, does invoke a pager when you do journalctl --help so if you're stuck on a 80x25 console (as you might be on a broken system) you can easily actually read the help options.

<comment><USER8> While I agree with your first paragraph,

> if you're stuck on a 80x25 console

What's wrong with `journalctl | less` in this case? The only command I use regularly which invokes a pager _by default_ is `man`, and that seems like an actual special case.

Edit: FTR, I agree with your assessment in the first paragraph, but not the judgement I infer you passing. IMO, things should avoid being strange.

<comment><USER9> > The only command I use regularly which invokes a pager by default is `man`

Git also invokes a pager by default. And it also sets $LESS when doing so. In fact, it wouldn't surprise me if systemd's automatic use of a pager was based on git; IIRC, it used to set $LESS to the exact same value git used (I believe systemd has changed it since then).

<comment><USER10> I super dislike this btw. If I want a pager I'll use a pager. I'm using Git, I can handle `| less`.

</comment></comment></comment></comment><comment><USER11> How much of the blame should systemd be taking for these bugs? Unless the same segfault is happening on other distros, this seems like a problem in Fedora rather than systemd.

I suppose this does give some substance to the systemd criticisms that it is too system-critical for a process that is technically outside of the Linux kernel.

<comment><USER12> If you're saying, a bug should always be investigated downstream before reporting it upstream, then I agree.

If you're saying, there are scenarios where segfaults caused by upstream code are not upstream bugs, then I disagree.

</comment></comment><comment><USER13> The first problem, PID 1 crashing, is certainly worth complaining about.

The rest seems mostly nitpicking. I wouldn't work myself up about the pager issue as discussed elsewhere here. I do somewhat agree with a rather useless default for the range of things to show (i.e. I'd prefer -b [1] to be implied unless specified otherwise, for example).

1: -b means 'since the last boot' for people not using journalctl. The default is instead to show the full journal from its beginning, as stated in the article.

</comment><comment><USER14> Regarding the first problem, as someone else said, 'Remember how awesome PulseAudio was? Imagine that for PID 1!'

<comment><USER15> PulseAudio gives me a better out-of-the-box experience than any other sound system, bar none.

<comment><USER16> Guess I'm the only one who had a cron job restarting the PulseAudio process regularly.

<comment><USER17>
      # keep systemd happy
      0 * * * * /bin/shutdown -r now

<comment><USER18> You know you are old when the first thing that comes to mind is a User Friendly strip...

[http://ars.userfriendly.org/cartoons/?id=19990302](http://ars.userfriendly.org/cartoons/?id=19990302)

</comment></comment></comment></comment></comment><comment><USER19> Guys, the `less -S` problem is bunk, because you can easily change it at runtime. From the OPTIONS section of `man less`:

 _Most options may be changed while less is running, via the "-" command._

So, just start `journalctl -l` as you would, then type in `-S` and scroll the screen in any direction to force it to re-draw.

Discussing it any further is bikeshedding, and distracts from the much more interesting segfault discussion.

<comment><USER20> To which I would say that you are completely missing the point of the complaint levelled here - that you can work around a stupid design decision does not negate the stupidity of that design decision. Personally I think the default of show all logs ever is worse but both mean that what should be an integral and useful tool is initially off putting at best and constantly irritating at worst. I say this as an arch linux user for the past three years.

</comment></comment><comment><USER21> It's interesting to see examples of where systemd falls down, though I'd be interested to hear what the actual problem is. The Fedora bug report and linked page basically say "systemd fell over during an upgrade", but is this really a systemd problem or is it a Fedora problem?

<comment><USER22> Almost any time PID 1 segfaults, it's PID 1's fault. With PID 1 being systemd, that makes it systemd's fault here. Based on gdb stack backtraces in the Fedora bug report and looking at the systemd code, it seems like some sort of memory corruption or overwrite, perhaps a use after free issue. The segfault itself comes from dereferencing a clearly invalid pointer and said pointer was obtained by dereferencing a structure field through another pointer, so you'd get exactly this result if the structure was overwritten with other data at some point.

(In my grumpy sysadmin view, it is PID 1's fault even if the distribution is doing odd things around PID 1. Init processes need to be absolutely rock solid and extremely defensively coded, precisely because the world basically dies if they ever fall over.)

(I am the author of the original post.)

<comment><USER18> What i find interesting is that it is the traditional sysadmins that find fault after fault with systemd.

On the other hand those that embrace it come from web/cloud development, with an eye towards virtualization and containerization.

I think someone somewhere once compared it to pets vs cattle.

Traditional servers are the pets of sysadmins. Groomed and cared for to make sure they never keel over unexpectedly.

To the cloud "admins" (or maybe i should call them devops?) servers are cattle. they have X of them living in some cloud "farm" somewhere, and can order any number of them to be slaughtered and replace at the drop of a pin.

</comment></comment></comment><comment><USER23> " Oh, the full message is available, all right, but journalctl specifically and deliberately invokes the pager in a mode where you have to scroll sideways to see long lines. Under no circumstance is all of a long line visible on screen at once so that you may, for example, copy it into a bug report."

Well, that's what you get by supporting a system built by obnoxious incompetents that think they can replace the most important process in the machine

"(Oh, and journalctl goes out of its way to set up this behavior. Not by passing command line arguments to less, because that would be too obvious (you might spot it in a ps listing, for example); instead it mangles $LESS to effectively add the '-S' option, among other things.)"

Yes, of course.

</comment><comment><USER24> Man, anybody else remember being able to use tail and grep to decode system logs?

 _And not having the init process crash_?

Seriously, this is clownshoes. Their developers and evangelists should get hit by a SIGBUS.

</comment><comment><USER25> I felt dirty, but this made me laugh out loud:

>While I'm here, let me mention that journalctl's default behavior of 'show all messages since the beginning of time in forward chronological order' is about the most useless default I can imagine.

<comment><USER9> Yeah, that's an annoying default. At least it also uses a pager by default, so it stops after the first screenful.

On the other hand, "journalctl -b" (show all messages since the machine has been last powered on, in forward chronological order) is quite useful.

<comment><USER26> Yep... even better is that it takes an index, so you can "journalctl --list- boots" to look up boot by timestamp and "journalctl -b -2" to look at the log of the second-to-last boot to copy and report the kernel oops in there.

</comment></comment></comment><comment><USER27> With apologies for drifting off topic:

I love less's command line interface for some of this stuff.

The command line switch to chop long lines: -S The in-app command to toggle chop lines: -S

The reverse is almost true for things like /search, F (follow) or G (go to end). They can be used from the command line with +/search, +F or +G

</comment><comment><USER28> Looks like there is another bug open already with a similar backtrace, also triggered by an upgrade:

[https://bugzilla.redhat.com/show_bug.cgi?id=1130633](https://bugzilla.redhat.com/show_bug.cgi?id=1130633)

</comment><comment><USER29> All I've been seeing lately are posts very critical of systemd. I really don't know much about it, and I would love to hear the other side of the story. Why is it so popular lately?</comment>


How Apple Card Works - <AUTHOR> https://techcrunch.com/2019/03/28/how-apple-card-works/ <comment><USER2> What's TechCrunch's source on all of this info? Or is it just pure speculation/reasoning?

\---

I was talking with a friend a few days ago about how the physical Apple Card would work in reality. During that conversion, I came up with the idea that maybe the physical card contains a custom chip on it that an iPhone can communicate with via NFC. That NFC chip would be able to rewrite the card info (i.e. card number, exp. date, and CVV) at will to the physical chip on the card (the one that talks to the actual payment terminals) and that's how Apple is going to issue cards that never technically expire. Perhaps they'll do something similar with the mag stripe (their promo videos pretty clearly show that the physical card does indeed have a mag stripe)?

<comment><USER3> The chip on the card is an entire computer running a Java program every time it's activated by the terminal. What it communicates via that terminal can vary, the same way the NFC tap-to-pay terminals can vary. There's no need for it to carry a conventional card number or expiration or anything.

<comment><USER4> Why on earth would it run java?

<comment><USER5> It is nothing like the real Java. Almost no regular data type is supported and there are severe limitations. [1]

You should view it as using a safe language instead of something like C. If Rust had been invented 20 years ago, it might have been Rust instead.

[1] [https://en.wikipedia.org/wiki/Java_Card](https://en.wikipedia.org/wiki/Java_Card)

<comment><USER4> fascinating. thanks!

</comment></comment></comment></comment></comment><comment><USER6> Why couldn't they have dropped the magstripe completely and forced the card to use online chip mode only and then declined all transactions unless temporarily unlocked within app? Would be a lot simpler than pairing card to phone.

<comment><USER7> Presumably because there are still a lot of transactions out there requiring a magstrip.

<comment><USER8> You are correct. Lots of places still don't take chips. Pei Wei for one.

At Lowes last month I noticed that chip is only accepted for credit transactions; debit has to be swiped. Or the other way around.

<comment><USER9> In the USA, pay at the pump transactions for fuel are still 100% mag strip as far as I've seen. The POS terminal inside can typically do chip transactions, but not the pumps.

<comment><USER10> I've used Apple Pay at a few Sheetz stations along I-95, but the vast majority of stations are still swipe-only.

</comment></comment></comment></comment></comment><comment><USER11> This is a nice card for beginners to credit cards but I don't anticipate a lot of uptake by consumers familiar with the Uber Barclays or Chase 2% cards.

<comment><USER12> Can you elaborate? I'm not familiar with these. What are the pros/cons?

As for the Apple Card, I've been fairly dismissive of most of Apple's recent products, but this is the most interested I've been in an Apple product since the iPhone. It feels like a similar situation: a "device" that seems simpler to use than existing offerings leveraged off of a partnership with a company that has nothing to lose by playing along with Apple's game. It might not be the best card offering in terms of features, but it seems like a solid choice for the masses.

<comment><USER2> Apple is acting as though their rewards is the most generous reward system ever, period. In reality, it is not even close. For instance, you can trivially get 2% cashback on all purchases (regardless of whether you're using Apple Pay or not) without annual fees:

\- Citi Double Cash: unlimited 2% back on everything; regardless of payment method; no annual fee

\- Fidelity Rewards: unlimited 2% back on everything; regardless of payment method; no annual fee

\---

2% is the minimum you should earn on any credit card purchase. There are a bunch of generous rewards cards that offer special cashback rates on certain categories. For instance, the US Bank Cash+ card [0] lets you pick two categories to get 5% cashback on, albeit you're limited to $2,000 in spending per quarter. After that $2,000, you only accrue 1% back. One of the categories is 'Electronics Stores', which includes Apple. In other words, you can get 5% back on Apple purchases (on up to $2,000/quarter in purchases) while the Apple Card offers unlimited 3% back on Apple purchases. There is no annual fee for this card.

The Uber Visa card [1] gets you 4% back on dining and 3% back on hotels/flights with no annual fee.

The Chase Freedom and Discover it cards both have rotating 5% categories (subject to a $1,500 per quarter maximum spend) without annual fees. Meaning, you get 5% back on specific categories on each card which change every quarter. In 2018, the Chase Freedom card had gas stations, internet/cable/phone, Google/Apple Pay, grocery stores, PayPal, gas stations, Lyft, Walgreens, department stores, and wholesale clubs as some of their rotating categories [2]. Also in 2018, Discover had gas stations, wholesale clubs, grocery stores, restaurants, and Amazon as their categories [3].

Admittedly, I believe most of the banks named above charge the "normal" fees that Apple has stated they will not be charging (i.e. penalty APR rates, late fees, etc.). But in reality, responsible users of credit cards were never going to pay those kinds of fees anyway.

[0]: [https://cashplus.usbank.com/merchants/index](https://cashplus.usbank.com/merchants/index)

[1]: [https://www.uber.com/c/uber-credit-card/](https://www.uber.com/c/uber- credit-card/)

[2]: [https://thetravelsisters.com/chase-freedom- categories-2018-c...](https://thetravelsisters.com/chase-freedom- categories-2018-calendar/)

[3]: [https://awardwallet.com/blog/discover-5-categories- calendar-...](https://awardwallet.com/blog/discover-5-categories- calendar-2018/)

<comment><USER8> _Apple is acting as though their rewards is the most generous reward system ever, period_

Is it? I don't think Apple is pretending to be the most generous. I think it's trying to be the easiest/most friendly.

There are a lot of ways the Apple card is better than those you list, especially when it comes to fees. But your post is too long for me to bother going through it.

I picked your Uber example randomly.

4% back is great on dining. But it's only on dining. 3% on travel matches Apple. The rest of Uber is 2%, except for some exclusions, which is less than Apple.

Buy music and videos online? With Uber you're capped at $50 cashback per year. And you only get that after you spend $5,000 within 12 months. And then the clock resets.

Too many games. Apple's whole point is to simplify.

Personally, I don't even like the whole cashback thing, but I accept that other people do. I'd rather they just lower my interest rate instead.

Uber's rate is 17.24-25.99%. We'll have to see what Apple comes up with.

<comment><USER13> If one is borrowing money at credit card level interest rates, the last thing they should be worry about is rewards, and the first thing is figuring out how to fix their cash flow so that they're not paying credit card level interest rates.

</comment></comment></comment></comment></comment><comment><USER14> A bit off topic, and I may be (most likely) wrong... but isn't Apple Card a good way for apple to dodge tax in some countries? Like if I'm in Australia and I pay using Apple Card then pay my apple bill, apple gets 100% of the bill paid with no sale so the money is in the country of their choosing paying the minimal amount of tax.

</comment><comment><USER15> > _Using Apple Card on Android is pointless... you could continue using your > physical card... but without the majority of the cash back or security > benefits why would you?_

I'm mainly interested in the card for the privacy benefits, but would love to get rid of my iPhone (and wouldn't want to use a card dependent on carrying one).

Does anyone familiar enough with transactions know if the physical card would still be generating virtual numbers for each transaction if you're not carrying an iPhone?

</comment><comment><USER16> I think the no-fees is partly a reflection of the reality of what it costs a financier when you are late with a payment and partly a means of standing out in a field where everyone else is lining up to kick you when you are down. I use the "Don't Fuck With Paste" browser extension on CapitalOne's sites more then anyone else's - why don't they want me to cut and paste into their web forms? Because the small percentage of typeos that occur due to manual data entry translate into millions in fee income - and of course it's your fault you got fined because it's your mistake.

Probably the worst industry for this is car rentals - I have often wished Amazon or some disruptive entity would get into car rentals. The entire industry exists to just to shake you down when your at your most vulnerable - far from home, unfamiliar territory, limited options. Is there any reason why they can't accept an alternate credit card from the one that secured a reservation? No. Is there any reason the slightest change to a reservation requires the previous reservation to be completely destroyed and renogiated at a new price? No. Is there any reason that cash can not be accepted? No. I live in a state that forces the rental car companies to accept cash and they do just fine.

<comment><USER17> > Is there any reason why they can't accept an alternate credit card from the > one that secured a reservation?

I did just that 3 weeks ago. Someone made a reservation for me, I used a different card to pick up the car.

</comment></comment><comment><USER3> I'll be honest, I want this because it's a cool looking metal card. I already use Apple Pay for the majority of my regular in-person spending, and don't carry balances on (normal) credit cards so, it would just be a bump in my available credit and a cool widget fitting right in with my minimalist wallet. It would be a perfect white balance for my black Tesla key card.

</comment><comment><USER18> I can't lie, I was thinking of switching to the Apple card when it's released. Unfortunately, it's a mastercard :( so no costco gas or shopping and I only carry one credit card in my wallet..

<comment><USER19> Why not just use the digital form via the Wallet app?

<comment> frosted-flakes What if he/she does not have an Apple phone?

</comment></comment></comment><comment><USER20> I don't get the "no late fees" feature. I suppose they'll still make plenty of money with the interest charges, and they'll probably freeze the card for new charges at some point.

</comment><comment><USER21> The post title gave me the slightest pang of hope that HyperCard was revived, until I remembered the credit card. This is cool too, but not as much as I hoped.

</comment><comment><USER22> I'm still floored when I read those interest rates. You guys got a Visa Debit? It's a visa, that uses the money you have... Clever isn't it?

When will people understand that buying something now without the money is not freedom? It's not, it's shackles.

<comment><USER23> For all your moralizing, you're suggesting people forgo the sizeable benefits of using a credit card for day-to-day purchases because some people are foolish enough to use it as a long-term loan?

> When will people understand that buying something now without the money is > not freedom

I would imagine the vast majority of people worldwide who have a mortgage are happy with the end-result of that leverage.

<comment><USER22> No they're not. No one is happy with a mortgage. The very simple fact that mortages exist is the reason why housing prices have multiplied over the years.

<comment><USER24> I'm happy with my mortgage(s); they allow me control of real estate it would've otherwise would've taken me 10-30 years to obtain.

Cheap capital can of course create asset bubbles, but nevertheless, debt is one of the most useful tools you can use for wealth creation, innovation, and economic growth.</comment></comment></comment></comment>


Why I think we're not souls but just matter. - <AUTHOR> https://medium.com/@utkarsh_sinha/why-i-think-were-not-souls-but-just-matter-3cf424994a95 <comment><USER2> Materialists fear the unknown. That's one reason they adhere to materialism and refuse to consider God, the existence of a soul or supernatural forces. They're afraid and prefer to avoid facts, details and truth in favor of their own indoctrinated perspective.

<comment><AUTHOR> "They're afraid and prefer to avoid facts, details and truth in favor of their own indoctrinated perspective." \- This quite easily could also be the definition of someone who believes in God, souls and supernatural forces. Anyway, I respect your opinion.

I just believe that individuals are born with unique intellects. Each one thinks differently. Each brain, is creative and is entitled to believe in their own ideas first. However, one thing that lies undeterred which is, our ability to question things and ideas. Question our own ideas for that matter. Questioning things makes us wiser undoubtedly.

Questioning things has brought us to all the technological & scientific advancements that we enjoy today. Unfortunately, I do feel, that believers in the God/souls/supernatural, question much less, almost never. Therefore, while the field of science, has seen multiple iterations of ideas - One scientist comes up with an idea, it's accepted and then another scientist comes up with a better idea which gets accepted. Scientists keep debunking their own ideas from time to time, thus unravelling the truth further. Whereas, this rarely seems to be the case in the field of religion.</comment></comment>


A First Excercise in Natural Language Processing with Python: Counting Hapaxes - <AUTHOR> http://catswhisker.xyz/log/2017/9/7/a_first_excercise_in_natural_language_processing_with_python_counting_hapaxes/ <comment><USER2> I get that the point is to be an introduction to the libraries and whatnot, but was I the only one who immediately thought of just using Counter?

        from collections import Counter
        import re

        [word for word, count in Counter(re.findall('\w*', text.lower())).items() if count == 1]

<comment><USER3> As the article states in the introductory paragraph, this problem encompasses more than just counting strings. It also involves _" some fundamental tasks of natural language processing (NLP): tokenization (dividing a text into words), stemming, and part-of-speech tagging for lemmatization"_, so a little more work is required here.

</comment></comment><comment><USER4> for anyone interested in more good beginner resources, I really enjoyed this youtube playlist on python NLTK [https://www.youtube.com/watch?v=OGxgnH8y2NM&list=PLQVvvaa0Qu...](https://www.youtube.com/watch?v=OGxgnH8y2NM&list=PLQVvvaa0QuDfKTOs3Keq_kaG2P55YRn5v)

edit* I accidentally linked to another good playlist, but here's the first vid of the NLTK list from the same user [https://www.youtube.com/watch?v=FLZvOKSCkxY](https://www.youtube.com/watch?v=FLZvOKSCkxY)

</comment><comment><USER5> Hapax Legomenon is such a satisfying phrase to say. Even the opportunity to look at it makes my eyes happy.

</comment><comment><USER6> I counted word n-grams up to length 6 in a corpus of 6 billion words with Madoka, a Count-Min sketch algorithm.

[https://pypi.python.org/pypi/madoka](https://pypi.python.org/pypi/madoka)

</comment><comment><AUTHOR> Author here. The misspelling in the title is embarrassing, but luckily not very noticeable (I've fixed it on the site).

<comment><USER7> It's so beautifully put together and made so easy to understand, I thank you very much, it helped greately in my learning.</comment></comment>


Hackers and Caffeine - <AUTHOR> http://www.whattofix.com/blog/archives/2009/09/hackers-and-caf.php

<comment><USER2> 3D graphs, oy vey.

Author needs to adjust for the number of respondents in each group. Giving us just the mean for each group would convey more information.

If the histogram thing is just too appealing to ditch, they should make two: avg. # of cups by age group and # of voters by age group.

edit: I'm not saying that the 3D graph is missing some information--humans are just terrible at extracting meaningful data from this sort of presentation.

<comment><AUTHOR> Fixed

<comment><USER2> Thanks for the fast fix! And check out the reversal in apparent trend: the 36-50 group has higher average consumption in your sample.

<comment><AUTHOR> Yes. Although the 21-35 group _responded_ the most, the 36-50 group had a higher relative usage of caffeine.

I think the 35-50 group has the highest 7+ usage, although that's hard to tell from the graph. Maybe if I kick out another...

<comment><AUTHOR> Actually I'm wrong again -- as it turns out, the group with the highest percentage of 7+ cup-chuggers is the 50+ group. It looks like caffeine consumption, overall, steadily increases with age.

<comment><USER3> Must be the addictiveness of caffeine creeping in :-(

<comment><USER4> No, that happens in about a week or so.

It is probably more like more responsibility = less sleep = more coffee. I am 24, and my obligations to the world mostly consist of 8 hours of work and a few hours of "chores" (cleaning, grocery shopping, etc.) a week. This leaves plenty of time for sleep.

As you get older, you have more job responsibility, you have a bigger house, you have kids, etc. All these things take time, and probably reduce the amount of time you have for sleep. Caffeine must give people enough energy to get it all done.

(Personally, I use caffeine to supplement my wakefulness. It doesn't really help me not be sleepy if I need to sleep.)

</comment></comment></comment></comment></comment></comment></comment><comment><USER5> I wonder if smoking prevalence among "hackers" is higher than in general population (about 20% aggregate in the US) and over standard deviation over the mean.

Anecdotally and completely unscientifically, my experiences suggest yes, first and foremost as a former smoker who tended to take notice of the distribution of professionals who also took smoke breaks in the half a dozen or so places I worked in three years. Seems like the same sorts of tendencies that make nerds responsive to caffeine probably apply to stimulants in general, especially noting the long-held poetic association between creative, focus-based tasks and tobacco. I also know more than my fair share of ADD types (in a noticeably classical kind of way) who sincerely regard it as a form of viable self- medication.

<comment><USER6> I started smoking because of the boredom and frustration of high school. After that nightmare ended i had to re-rationalize smoking and i ended up doing that by telling myself that it has a positive effect on my concentration in a combo with caffeine. Im not sure if it really is so, or is it me just trying to rationalize my stupid addictions.

</comment></comment><comment><USER7> Has anyone else here switched to caffeine pills? I used to do several cups of coffee a day but I decided I could control my dosage better using pill form. Not to mention avoid staining my teeth.

<comment><USER8> I pulled an all nighter in EE lab once with caffeine pills.

This is for the good of everyone reading this: _do not overdose on caffeine pills_. Fucking unpleasant is what it is.

</comment></comment><comment><USER9> What kind of caffeinated drink does each cup represent?

A cup of coffee has 2-3x times the amount of caffeine a cup of tea has.

<comment><AUTHOR> It was self-reported.

It'd be much better to convert to mgs of caffeine, but that seemed a little much to ask HN.

</comment></comment><comment><USER10> Basically, it turns out there's more 21-35 year olds on the internet who are hopped up enough on caffeine to answer the survey they ran into while browsing the internet. Consequently, I feel almost any survey done on the internet in this fashion will include this distribution of respondents.

</comment><comment><USER11> The sample size is unfortunately woefully small.</comment>


Show HN: Peeshkot - automatically make cookie warnings go away - <AUTHOR> http://swizec.com/blog/peeshkot-cookie-warnings-go-away/swizec/6242

<comment><USER2> Those cookie law popups are even worse than ads. And what's even worse they don't really do anything - a lot of Slovenian websites just added the popup, but the use of cookies hasn't changed.

I do have to hand it to the people who run [https://slo- tech.com/](https://slo-tech.com/) . There is no cookie banner there, because they decided to simply remove all the cookies, awesome job!</comment>


Garry Kasparov arrested outside Moscow court - <AUTHOR> http://www.bbc.co.uk/news/world-africa-19300149 <comment><USER2> That was almost civil.

USA will give them a lesson in abusive police power at the end of the month at RNC convention and then again at the DNC next month.</comment>


Not Lisp again (2009) - <AUTHOR> https://funcall.blogspot.com/2009/03/not-lisp-again.html <comment><USER2> If this presentation of Lisp and model of computation clicks with you, you owe it to yourself to read Structures and Interpretations of Computer Programs (SICP).

The Abelson from the OP's lecture is the co-author, and the presentation described exactly follows the structure of the book (including the derivative example).

It opened my eyes to a new way of thinking about coding when I first read it (and worked through the exercises) many years ago.

<comment><USER3> I've always wondered if recommending SICP would also be applicable to a person who has never programmed before.

Perhaps pragmatism aside, would you?

<comment><USER4> SICP is literally a textbook for programming 101 class. It's whole purpose is to teach programming to people who might have never programmed before.

<comment><USER5> One potential downside for novice programmers is that some of the examples are a bit deeper than what you find in most beginning programming books. For example (as exhibited in the blog post topping this thread), writing programs pertaining to differential calculus. Obviously, lots of non-programmers have studied calculus, but lots haven't, as well. To the extent a reader might stumble on some example programs, SICP could be challenging, even if the programming content itself starts at zero and builds up.

<comment><USER6> It's supposed to be a rigorous and challenging introductory course for first- year MIT students 40 years ago who had no previous computer programming background.

For someone who is not as well prepared as a typical first-year MIT student, something else might be better, but it's reasonably accessible in my opinion. I would have loved to have a course like SICP as a high school student.

<comment><USER7> The target audience for SICP seems to be basically a freshman Gerry Sussman. There's no doubt it's reasonably accessible to people with a suitable combination of background and aptitude, but the historical evidence seems to be that it's not accessible to the typical CS undergraduate: according to [https://www2.ccs.neu.edu/racket/pubs/jfp2004-fffk.pdf](https://www2.ccs.neu.edu/racket/pubs/jfp2004-fffk.pdf) it had a wave of adoption as a CS 101 text but enthusiasm soon soured. In my experience, even _The Little Schemer_ , which covers much of the same material, from a similar perspective on computing, but in a much more streamlined and learning-friendly form, isn't close to being universally accessible for _unsupervised_ learning.

<comment><USER6> My quick take is that the authors of the linked essay have a circumscribed and very industry-focused view of what an introductory CS course should teach and what kind of things a student should be expected to learn. Their primary goal seems to be preparing students for a follow-up Java course (of the early 2000s style of Java), but without dropping all of the incidental complexity of Java/C++ on the students right away. To that effect they have pared down most of the "computer science" content of a SICP type course, and focused heavily on the computer programming process, analogous to the way middle school English classes teach about writing.

(Disclaimer: I have not directly evaluated their curriculum/textbook.)

This differs markedly from my own opinion about the proper goals of a 'computer science' course at the undergraduate level, which is to teach timeless principles and flexible thinking without bending to fashion (especially fashion which is now a decade out of date), and to prepare students for follow-up computer science courses such as data structures / algorithms, theory of computation, programming languages, or in a more applied direction databases, networking, graphics, operating systems, numerical analysis, machine learning, and so on. A lot of these follow-up courses will be substantially mathematical and will rely heavily on analytical skills developed in in introductory CS course and in mathematics courses (not just on programming skills per se).

But if updated for 2018 the authors' curriculum would be appropriate as a course titled "introduction to programming" or the like. I agree it sounds like an improvement vs. first courses that start students out on C++ or Java (their main comparison in the linked paper).

YMMV.

<comment><USER7> The authors are Matthias Felleisen and other core PLT Scheme/Racket guys. They're hardcore members of the academic Scheme community, absolutely not very industry-focussed guys, and the real industry-friendly contingent apparently doesn't much like HtDP either: [http://www.ccs.neu.edu/home/matthias/Thoughts/colleagues.htm...](http://www.ccs.neu.edu/home/matthias/Thoughts/colleagues.html) . HtDP is often described as a bit of a grey slog (I've dipped into it but haven't done it or read it cover to cover yet), but the authors absolutely haven't given up on the ideal of teaching timeless principles and modes of thinking, they're just more realistic about how the material has to be paced and prepared to get a normal body of first-year undergraduates through it successfully.

</comment></comment></comment></comment></comment></comment></comment></comment><comment><USER8> Lisp is a fun language to program in. I learned Lisp after already being familiar with Java / Python and some other languages, which maybe made it even more beautiful.

One of my favourite pieces of code is a Lisp REPL in Lisp:

        (defun repl()
                (loop (print (eval (read)))))

<comment><USER9> looks even better with threading in imaginary lisp dialect:

        (-> read eval print loop)

<comment><USER10> I think clojure has that; I could be wrong, though, I've never used clojure.

<comment><USER11> Clojure does indeed have -> (thread-first), ->> (thread-last), some->, some->>, cond->, and as->. [0]

(->) inserts each form's value between the function name & the first argument in the next form.

(->>) inserts each form's value as the last argument in the next form.

The latter forms are much more niche and I haven't found need for them yet.

[0]: [https://clojure.org/guides/threading_macros](https://clojure.org/guides/threading_macros)

<comment><USER12> as-> is great for when you have to mix thread-first and thread-last.

cond-> is great for building maps where some keys might not be needed:

        (cond-> {:k1 v1}
          v2 (assoc :k2 v2)
          ...)

some-> and some->> I don't use as often, but when mixing in some java code that could throw an NPE, these will avoid that and just return nil early (they short-circuit when getting a nil value).

<comment><USER13> You can next ->> inside ->, took far too many years for me to realize:

        @(-> ctx
            :hypercrud.browser/fiddle
            (reactive/cursor [:fiddle/ident])
            (->> (reactive/fmap name)))

another

        (-> [10 11]
            (conj 12)
            (as-> xs (map - xs [3 2 1]))
            (reverse))

</comment></comment></comment></comment></comment></comment><comment><USER14> My previous, somewhat-cranky comment got downvoted away, but I do think Lisp's "higher-order magic" and "ability to do calculus" is being a bit exaggerated here. From below - evaluating an Nth derivative in 80s-era C is not so atrocious:

        #define DX 0.0001
        typedef double (*func)(double);

        double NthDeriv(int n, func f, double x) {
            if (n == 1) {
                return (f(x + DX) - f(x)) / DX;
            }
            else {
                return (NthDeriv(n - 1, f, x + DX) - NthDeriv(n - 1, f, x)) / DX;
            }
        }

        double Cube(double x) { return x * x * x; }

        double result = NthDeriv(3, &Cube, 5.0);

As mentioned in previous discussions of this article, the equivalent in Python is pretty elegant:

        >>> def deriv(f):
        ...   dx = 0.0001
        ...   def fp(x):
        ...     return (f(x + dx) - f(x)) / dx
        ...   return fp
        ...
        >>> cube = lambda x: x**3
        >>> deriv(cube)(2.0)
        12.000600010022566

<comment><USER15> I think the thing that impressed the author at the time was more the fact that functions, being first-class values, can be introduced at runtime in a REPL, rather than having to be "planned" at compile time. So the C code isn't really analogous, but the Python code is.

But re: the Python code—I would say that, from the perspective of the 1960s, all modern "dynamic" languages that have REPLs (like Python) _are_ Lisps in essential character.

"Lisp", back then, referred less to "a language that uses a lot of parentheses", and more to things like:

• runtime sum-typing using implicit tagged unions;

• parameterization of functions using linked lists (or hash-maps) of paired interned-string "keys" and arbitrary product-typed values, rather than parameterization using bitflags or product-types of optional positional parameters;

• heap allocation and garbage-collection;

• a compiler accessible by the runtime;

• "symbolic linkage" of functions and global variables, such that a named function or variable "slot" can be redefined (even to a new type!) at runtime, and its call-sites will then use the new version.

We only notice the parens as the differentiating feature of Lisps nowadays, because everything else has become widely disseminated. Perl and Python and PHP and Ruby (and even Bash) are fundamentally Lisps, in all of the above ways. Lisp "won."

<comment><USER16> However, PHP, Python, Ruby, JS, etc aren't homioconic, which would disqualify them as "lisps" in the minds of most Lispers, including its creator.

<comment><USER15> One might say that they're all implementations of [https://en.wikipedia.org/wiki/M-expression](https://en.wikipedia.org/wiki/M-expression) s.

My point, though, was that while the _proponents_ of Lisp define Lisp one way (by the things _only_ Lisp can do due to e.g. homoiconicity), the _opponents_ of Lisp (like the author was, coming into the course) define Lisp by the set of features that make Lisp "not a Real Programmer†'s programming language"—i.e. the set of things that make them not want to use it.

† [http://www.catb.org/jargon/html/R/Real- Programmer.html](http://www.catb.org/jargon/html/R/Real-Programmer.html)

My assertion was, from these opponents' perspectives, there are very few languages left for "Real Programmers"; most modern languages have inherited nearly all of those horribly convenient Lisp-isms. Heck—modern CPUs are so good at pointer-chasing, they may as well be Lisp Machines!

</comment></comment></comment></comment><comment><USER17> Previous discussions:

2017: [https://news.ycombinator.com/item?id=14247269](https://news.ycombinator.com/item?id=14247269) (261 comments)

2013: [https://news.ycombinator.com/item?id=5375735](https://news.ycombinator.com/item?id=5375735) (176 comments)

2009: [https://news.ycombinator.com/item?id=504667](https://news.ycombinator.com/item?id=504667) (39 comments)

<comment><USER18> Its a matter of time before there is a "bot" that auto-posts this kind response for historical reference.

<comment><USER19> There is a link at the top called "past" that does exactly what all these "helpful" posts do. And it's been there for a long time.

</comment></comment></comment><comment><USER20> This isn't identical, but I remember when I first learned first-class functions and partial application in Haskell about ten years ago, it was a "the world is different now" moment. I had reinvented partial-application approximately thirty billion times by using overloading or with elaborate if- elseif-else chains. When I learned Haskell, and saw that I could magically make my non-lists function automatically lift across a list, and how I could _define things like this myself_ , I was immediately convinced that I would never go back to C again (I didn't know about function pointers).

I learned Clojure about a year ago (which was my first introduction to Lisp outside of reading SICP), and it gave me a similar feeling. I felt like Clojure was a "better Java than Java", and now its my go-to JVM language. I think McCarthy was really onto something with Lisp :).

<comment><USER21> Could you give an example of partial application with Haskell in the way you mention? I've had similar feelings with Clojure.

</comment></comment><comment> phoe-krk _I was impressed first by the fact that whoever designed this particular Lisp system cared about efficiency._

This isn't a particularly unusual approach. Common Lisp, a contemporary Lisp dialect, was designed with efficiency in mind. The approach of "Lisp = slow + inefficient + spending 80% of time on garbage collection" is a myth.

<comment><USER22> This article is set about 20 years prior to common lisp's standardization. It was a reasonable belief then.

<comment><USER23> It's set in 1983. "Common LISP The Language" was published in 1984.

(The ANSI standard was 1994. Still nowhere near 20 years).

<comment><USER24> Well, 10 years is the same order of magnitude as 20.

</comment></comment></comment></comment><comment><USER25> Isn't the derivate relatively easy in C?

        #include <stdio.h>

        const double delta = 1.0e-6;
        double cube(double x) { return x * x * x; }
        double deriv(double (*f)(double), double x) { return (f(x+delta) - f(x)) / delta; }

        int main()
        {
            printf("%f", deriv(&cube, 2));
            return 0;
        }

Am I missing something?

<comment><USER26> I think it's that you can calculate the value, but you can't (or can't as easily) create a new function that is the derivative of another function, and pass that around.

<comment><USER27> yeah you can return a new function, but it is less easy than in lisp, or F#

but in general a lot of that stuff in the article seems mundane today, you have to imagine seeing it in 1983

<comment><USER28> > yeah you can return a new function

How?

<comment><USER29> You could do it with JIT compilation or self-modifying code. I'm not sure if there's a simpler way in C

<comment><USER30> You can exec a C compiler and use dlopen on the generated object file, or use libtcc[1].

[https://www.bellard.org/tcc/](https://www.bellard.org/tcc/)

</comment></comment></comment></comment></comment></comment><comment><USER31> I thought it would be a down with Lisp article, but it was like my experience with the language, omg, how cool. From that ancient introduction to Lisp all I learned was that Lisp was as close to perfection and beauty as I would get in a programming language.

<comment><USER32> Serious question: what is it about the "beauty" of Lisp that the HN community seems to like so much? To me, how Lisp looks is its worst quality--the number of parentheses is just mind boggling. I want to understand why it is so loved.

<comment><USER33> > the number of parentheses is just mind boggling

There aren't actually more parens in a Lisp program than a program written in a C-like syntax (which is really an algol-like syntax). They just stand out more for two reasons:

1\. There is less punctuation in general, so the parens are more obvious. Instead of f(x, y, z) you write (f x y z). Without the commas, the parens stand out because that's all that is left.

2\. There is only one kind of parens in Lisp whereas C-like languages use at least three: (), [], and {}, so that makes any particular kind of paren less prominent.

<comment><USER34> I believe it's purely seeing lines that end with )))))))) that leads the OP's observation ("To me, how Lisp looks is its worst quality--the number of parentheses is just mind boggling"). You don't get that in a C-like syntax. In practice you don't read each individual closing paren to understand the code so it doesn't matter. But it sure looks "scary."

<comment><USER33> > You don't get that in a C-like syntax.

No, instead you get something like );}]);) except that that's usually split up over several lines.

BTW, it's pretty easy to tweak Lisp's syntax so that your parens don't get so deeply nested. See

[https://github.com/rongarret/tweetnacl/blob/master/ratchet.l...](https://github.com/rongarret/tweetnacl/blob/master/ratchet.lisp)

for an example.

</comment></comment></comment></comment></comment><comment><USER35> When I was in high school I had access to three programming tools: Commodore BASIC, 6502 assembly, and Turbo Pascal. I spent years hand coding 6502 assembly because BASIC was clearly for amateurs and I could only get at the Pascal system at school.

At one point I wrote my own Pascal interpreter for the C64. In BASIC, because I wasn't good enough to do it in assembly. It was a little slow.

I desperately wish someone had introduced me to lisp. The entire course of my life would have been different. The most frustrating thing is that I probably could have written a naive lisp interpreter in assembly.

<comment><USER36> I got a Forth for my C64, and it was the PERFECT language for the machine: fast, compact, structured, extensible. Generally much easier to understand the code than C64 Basic, but you could also easily call into assembly language if you needed a bit more speed.

</comment></comment><comment><USER37> I'm too young (or studied in the wrong time or place) so my CS teachers failed to impress me to such an extent.

However, I very well remember reading the Compilerbau book by N. Wirth and the awe I felt. It's just a few pages but it was a revelation.

<comment><USER38> Can you share the name of the book? Is it "Compiler Construction" by Niklaus Wirth?

<comment><USER39> Check also his other books: Algorithms and Data Structures, Programming in Oberon, Project Oberon, etc.

They are all available on the ETH website and his homepage (in various revisions). Basically everything you need to know about imperative programming on CS bachelor level for free.

<comment><USER37> Indeed, a small search yields: [https://www.inf.ethz.ch/personal/wirth/](https://www.inf.ethz.ch/personal/wirth/)

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

</comment></comment></comment></comment><comment><USER40> Any computer scientist worth his salt has read SICP. I had similar reactions as the author of the post to the expressiveness of Lisp, and it set me on a journey towards functional programming that has been so rewarding to my career. I also got a chance to meet some of the people who worked on Lisp machines at MIT, who interacted with Stallman back in the day. The Lisp machines were truly ahead of their time, and Lisp is still as beautiful in its homoiconic glory today as it was back in the 60s.

I now focus primarily on Rust, which has given me a lot of the same feelings as when I first encountered Lisp. It's truly a language ahead of its time, and I hope it will continue to grow beyond what even Lisp was able to accomplish.

</comment><comment><USER41> For anyone who wants to feel what this might have felt like (and you've yet to watch them), MIT posted videos of Abelson and Sussman presenting the course on YouTube [0]. I felt a similar sense of magic the first time I saw the derivative section.

[0] [https://www.youtube.com/watch?v=2Op3QLzMgSY](https://www.youtube.com/watch?v=2Op3QLzMgSY)

</comment><comment><USER42> Differentiation/Integration implementation in Clojure:

[https://gist.github.com/divs1210/4ca74577711eb996a89a36d86a3...](https://gist.github.com/divs1210/4ca74577711eb996a89a36d86a38ea78)

</comment><comment><USER43> Scheme was my favorite language in school back in 2006, but the only class I ever used it in was a class where we learned search algorithms and the like (it was either AI or Robotics). I was dismayed to find out there isn't a lot of software written in LISP dialects, because I would love to write LISP code all day, it's so much fun.

</comment><comment><USER44> > Hal went on to explain how the substitution model of evaluation worked in > this example and I carefully watched. It seemed simple. It couldn't be that > simple, though, could it? Something must be missing. I had to find out.

Well, not that simple... as the author hasn't taken the potential problem of free variable capture into account.

</comment><comment><USER45> I was working on a webpage for translating SICP lecture, it is always something worth to split out. [https://learningsicp.github.io](https://learningsicp.github.io)

</comment><comment><USER46> I wish so much that I had known about lisp in college. I only knew Java, C++, Javascript, and Python.

</comment><comment><USER47> I feel like I am missing something here but are the things mentioned in the article (tail call recursion, first class functions) unique to LISP?

They seem available in other functional languages.

I was under the impression LISP was unique due to its macros.

<comment><USER48> Where do you think those languages got those features from? This story appears to take place in the 80s, incidentally.

</comment></comment><comment><USER49> my question is yes, lisp.. but what is beyond lisp?

<comment><USER50> LISP is more akin to a class of languages rather than a single language in isolation, so it is kind of trick to ask what's "beyond" LISP.

<comment><USER49> if we can solidly say what lisp is, then i'd assume there's beyond the horizon...if we can't say what lisp is.. then whats the point? is it just anything?

i mean, if i have a lisp with static types vs not static types, why is the lisp part important at all? and you just have two different languages one with static types and one without?

seems very unimportant? i dunno could someone enlighten me

</comment></comment></comment><comment><USER51> So the author was excited about the concept of function composition? I'm a fan of lisp but I'm not seeing what's particularly novel about lisp here.

<comment><USER52> Context is also helpful. "I'm not sure what's novel about function composition" is a little bit of a smug take on a language and concept that was pretty cutting edge back in the early 80s. Now we Meat-and-Potatoes Programmers know the composition is useful, but I'd be hard pressed to find first-class composition in 1980 in any popular language that wasn't {academic, Lisp}.

<comment><USER53> Was it, though? If I remember correctly, Algol 68 had facilities sufficient to do everything the author describes, and just as neatly.

</comment></comment></comment><comment><USER54> Lisp: gnosticism for programmers.

</comment><comment><USER14> All this could be done easily in C (function pointers, factorial for loop etc.). And sampling a function twice at 0.0001 dx's apart and calling it "doing calculus" is a stretch.

The author seems to be making the case that, contrary to his original skepticism, Lisp is indeed some magical higher-order language, but I honestly don't see it. Lisp's ratio of philosophizing to noteworthy projects seems to tend toward infinity.

<comment><USER55> How could you create the equivalent semantics without closures and higher level functions in C? For example, if you wanted to take the second derivative of f

(deriv (deriv f))

or if you wanted to take the nth derivative

(define (nth-derivative f n)

        (if (= n 0)

            f

            (deriv (nth-derivative f (- n 1))))

You could do it with some data structures, which you'd then have to interpret, but not as nicely or easily.

<comment><USER14>
        #define DX 0.0001
        typedef double (*func)(double);

        double NthDeriv(int n, func f, double x) {
            if (n == 1) {
                return (f(x + DX) - f(x)) / DX;
            }
            else {
                return (NthDeriv(n - 1, f, x + DX) - NthDeriv(n - 1, f, x)) / DX;
            }
        }

        double Cube(double x) { return x * x * x; }

        double result = NthDeriv(3, &Cube, 5.0);

<comment><USER55> Touche. It's not as general as the lisp example though.</comment></comment></comment></comment>


My startup story: from big idea to thriving business in 8 short years - <AUTHOR> http://blog.traysoft.com/2011/04/my_startup_story/

<comment><USER2> Great post. I'd much rather read this type of success story than all the get rich quick examples given in mainstream media. You overcame obstacles and willed yourself to succeed.

One theme in your post I find really interesting. You talk about how your next move always came to you over time. That's really interesting, because you give the impression that the solution was not immediately apparent, and only after years of sales and feedback you realized how to evolve the business. Even if the data had been in front of you for quite some time, it seems that at some point a light bulb went on about how to expand, and from that moment it was obvious.

<comment><USER3> I didn't think of it this way but yes, some of the ways to expand were in front of me and were really obvious in retrospect. I can't believe I didn't think about selling to ISPs sooner. It was definitely the biggest blunder I made.

</comment></comment><comment><USER4> This startup story emanates the true hacker spirit. Some good lessons in here as well.

1) You continuously provided something of value to your users.

2) You listened to what your users had to say and iterated accordingly.

3) You pivoted sensibly when your prime market was diminishing.

A good example of some basic startup rules that we often read about on HN, put into practice.

</comment><comment><USER5> Great story! Sure, creating the next world changing product and making millions would be awesome, but when it comes down to it, what I really want is to work on interesting challenges, make my own decisions, and support my family.

</comment><comment><USER6> Great story. It just goes to show you that you are better off being close to your customers and carefully listening to them than dreaming up revolutionary products in your imagination. It is a bit unfortunate for those of us with overactive imaginations, but it is the truth.

<comment><USER7> Point taken, but:

      "If I had asked my customers what they wanted, they would have said a faster horse." - Henry Ford

_Someone_ has gotta be innovative.

<comment><USER8> I've seen this quotes many times, and it's only today that it occurred to me that it's being incorrectly applied

hristov is talking about customers Traysoft already has and who are using his product. Henry Ford is talking about _potential_ customers who aren't using his product, who've never seen his product and who don't know anything about his product (or anything like it). Big difference

<comment><USER7> True, but this wasn't made clear, so I felt the need to "debunk". "Ask your customers what they want" is a common startup catch phrase, and while it does apply in many situations, it isn't as clear-cut and true as many seem to think.

It belongs in the same bin as "execution is everything," "ideas are meaningless" and "you need a cofounder to succeed." Useful and oftentimes true, but by no means a universal truth.

<comment><USER9> The problem with Ford's quote is that the customer offers a solution. In such a case you need to ask further questions to find out the problem he wants to solve. Had Henry Ford realized that, he would have found out customers wanted to get from A to B faster and he wouldn't have quipped this silly 'they want a faster Horse'. They didn't actually want a faster horse. As soon as you understand the problem, you're free to come up with innovative solutions.

There are still a few exceptions though: you can create a new market by appealing to a need people didn't have until you offered a solution. Fashion, fads (including fads for children), arguably Twitter,...

</comment></comment></comment></comment></comment><comment><USER10> Great log about how you - dare I say it - pivoted and build a business out of something you did as an aside!

<comment><USER3> It's more of a U-turn than a pivot, at least that's how it felt for me.

</comment></comment><comment><USER11> Very cool stuff. Also that library looks pretty sweet. I'll keep it in mind if I ever find myself needing something like it. Congrats!

</comment><comment><USER12> Great post! Lesson: build multiple MVPs, quickly ship and see which stick, then let the market forces be your compass.

</comment><comment><USER13> Brilliant. Thanks for taking hte time to share your story!

</comment><comment><USER14> Good story.

</comment><comment><USER15> Please get your website redesigned...current UI sucks=)

<comment><USER16> I guess this shows that you don't need fancy HTML5/CSS/rounded borders/custom fonts/etc. etc. to actually build a business. As much as I love eye candy and love spending hours tweaking my projects to get them to look "just right," this is something I have to always remember. Shipping and getting customers is what ultimately matters.

(One pet peeve though: many of the recent HN posts linking to company blogs don't include a link back to the homepage. Everyone, please have a link! The standard top-left logo works really well for this. Immediately after reading your blog, my first intention is to see your product. Don't make me edit out "blog." from the URL by hand.)

<comment><USER17> > many of the recent HN posts linking to company blogs don't include a link > back to the homepage. [...] Don't make me edit out "blog." from the URL by > hand.

I'm glad I'm not the only person who has noted this lately. :)

Listen to this advice and follow it!</comment></comment></comment>


What's in a Parser Combinator? (2016) - <AUTHOR> https://remusao.github.io/posts/whats-in-a-parser-combinator.html <comment><USER2> Every few years I look at the latest parser combinators, parser generators, compiler compilers. And every time they seem to lack in some huge vital way (not always all of them, but always at least 1):

* Error handling always ends up being non-existent or of the quality of "begin, for, if, while, repeat, identifier, number, float expected" with no good way to override what happens

* Recovery is usually impossible

* Parser generator generates a full model that doesn't match what we need

* Working around the quirks of the input language ends up being more tricky than hand writing (almost every language has some ambigiuty)

* Slow: With ANTLR it's _really_ easy to make it do gigantic amount of look aheads in complex languages, which isn't even really needed

I always end up going back to a simple hand crafted parser which is easier to read and write.

<comment><USER3> By curiosity, did you try Lezer?

[https://marijnhaverbeke.nl/blog/lezer.html](https://marijnhaverbeke.nl/blog/lezer.html)

<comment><USER4> That is keen!

</comment></comment></comment><comment><USER5> Graham Hutton recently did a tutorial via Computerphile YT channel on functional parsing [0].

Where he starts from the scratch and explains the process of creating your own library for parsing.

The YT video description has the link to the full version of the library that he starts creating in his tutorial. It's kind of an elegant Haskell programing that I don't think I'll ever achieve. [1]

[0][https://www.youtube.com/watch?v=dDtZLm7HIJs](https://www.youtube.com/watch?v=dDtZLm7HIJs)

[1][http://www.cs.nott.ac.uk/~pszgmh/Parsing.hs](http://www.cs.nott.ac.uk/~pszgmh/Parsing.hs)

<comment><USER6> If you want more such elegant Haskell/math check out Conal Eliott( conal.net )

</comment></comment><comment><USER7> Parsing from first principles by Saša Jurić [0] is a good video on writing parser combinator in Elixir.

[0] [https://youtu.be/xNzoerDljjo](https://youtu.be/xNzoerDljjo)

</comment><comment><USER8> Parser combinators are just recursive descent. That's it. They're just recursive descent - an idea that's been around since the 1960's.

A parser combinator library is just fancy marketing speak for "recursive descent utility functions". All it is is a a bag of commonly used patterns wrapped up in generic functions.

The hoopla is overblown.

<comment><USER9> And Pratt parsers are just precedence climbing, but I've rewritten unifdef's precedence climbing expression evaluator in Pratt style and it has turned out much better, because of the way Pratt structures the technique so neatly. So the key feature of parser combinators is a neat and tidy way to structure a recursive descent parser, and the key feature of monadic parser combinators is to get extra neatness from Haskell's categorical types.

<comment><USER8> I wish more tutorials started with "Parser combinators is a neat and tidy way to structure a recursive descent parser" because I 100% agree. Mostly, my disagreements are how parser combinators presented and taught, obscuring the core ideas with a focus on language features and trivialities.

To me, the monad/applicate stuff is a red herring. It's mostly used to simulate imperative sequencing. e.g. the Haskell code `Person <$> parseName <*> parseAddress` would be `return Person { parseName(), parseAddress() };` in C. There's a few tricks but it's not crucial to the parser combinator idea and doesn't help readability.

</comment></comment></comment><comment><USER10> gracefully handling errors and giving useful output is the hardest part of writing parsers, why does everybody skip over that part?? :)

<comment><USER11> You can get parsing stacktraces by changing the definition of Parser to

        data Parser a c = Parser { runParser :: String -> Either [c] (a, String) }

and adding a combinator

        withContext c p = Parser \s -> case runParser p of
          Left stackTrace = Left (c:stackTrace)
          Right x = Right x

This allows you to write stuff like

        number = withContext "parsing a number" $ ...
        addition = withContext "parsing addition expression" $ ...
        expr = withContext "parsing a mathematical expression" $ ...

and combine that with a technique that keeps track of where you are in the string when failure occurs, you can pretty print that to something like:

Failed to parse!

        2 + 34.0O4
                ^

While: parsing a number

While: parsing addition expression

While: parsing a mathematical expression

<comment><USER12> So, one of the key things that I see is that the constructed abstract syntax tree must have the raw tokens within it so all other layers have full awareness.

I feel the criticism is valid because most parsers in production are done via hand without tooling or fancy techniques.

<comment><USER13> > most parsers in production are done via hand without tooling or fancy > techniques.

What? Do you have any data you'd like to share?

I'm given to understand that e.g. the C++ compilers usually have a hand-coded, but AFAIUI that's mostly due to the complexity of actually parsing it (and fitting that into anything other than just raw code).

<comment><USER12> only anecdotal and observations over the years

[https://www.drdobbs.com/architecture-and-design/so-you- want-...](https://www.drdobbs.com/architecture-and-design/so-you-want-to- write-your-own-language/240165488)

A common theme is that the parser generator does not provide you the tools to write the high quality error messages. Having used ANTLR and other tools, I believe it now that I'm trying to ship a real language.

<comment><USER13> You're talking about parser _generators_... the article is about parser _combinators_. Fully agreed that parser generators are often very limited and often require hacks to do anything non-trivial.

(IME MegaParsec basically solves most of the issues.)</comment></comment></comment></comment></comment></comment>


Consultants Ate My Unit Tests - <AUTHOR> http://metroize.com/consultants-ate-my-unit-tests/ <comment><USER2> Ah, the sadness of seeing your code again after somebody else has had it for a couple years. I feel the author's pain.

I had a company license the source code from one of my old projects to use as the basis for a new site they were building. I built out the bits they needed on a consulting basis and got them launched. Then they started thinking about how expensive I was, and how much they would save if they moved the development overseas.

Fair enough. My philosophy on such matters is that it's best to let a client learn this lesson through painful experience. All the best, guys.

They made it about a year before the site stopped working completely. Reading this article reminded me of the first time I opened the source that came back. You just wouldn't believe that you could do that much damage in such a short time.

I quoted them double my old bill rate and got them back up and running, with all the new functionality they had been wanting, and re-launched. They brought in a new guy to run things, and he started making comments about expenses, and how surely there must be a way to do this cheaper. He even found a local kid who knew some C# and would be willing to help out for a lot less than I was billing.

No problem. All the best.

I took a quick look at the codebase when they got back in touch a few months later and politely declined to come back on board.

<comment><USER3> It's sad how often this scenario comes up :/ get what you pay for, plus another, larger bill later. The technical debt collector will find you.

<comment><USER4> yes he will find you and he holds a mighty ransom!

</comment></comment></comment><comment><USER5> I've seen this with my own two eyes. When asked why they removed the unit test they said after they made some rather extensive code changes the tests were failing so they deleted them. Nor was there any trace of irony in their response. When asked didn't they realize that was the whole point of having unit tests they replied that they knew, but they had deadlines to meet and there wasn't enough time. Since controls had been put in place to not ship with failing unit tests but not to check for test coverage they took the easy way out and deleted the tests. I informed management what they had done and thankfully they were relieved of their contract and their consulting company was informed what they had done. I don't know what happened to them after that.

Thing is, once the PM was informed what they had done we did a couple of sprints where we restored the unit tests (which we still had in our history) and got them passing. They had no idea the consultants were doing such shoddy work in order to meet deadlines. The upside of all this is to this day that PM now actively checks the Jenkins dashboard to see the current state of tests and that no tests have been deleted - and that's for all his projects not just that one particular projects. Now that the story is part of our IT lore the new consultants get the message loud and clear we're not afraid to send them packing.

In the end this turned out to be a good story for us - but wow.

<comment><USER6> Always assume that consultants will never perform any task that isn't required for milestone sign off.

<comment><USER7> I'm a consultant; this is good advise.

It's not laziness or apathy. It's just that we're only paid to do a task.

<comment><USER8> Good luck explaining the point of unit tests to technology illiterate managers - they don't understand and really they shouldn't have to.

<comment><USER9> I always use double accounting from finances to explain tests. You don't do logic changes in one places, but in a second to double check it actually works out.

<comment><USER10> Sounds good, if only I understood double accounting :-)

<comment><USER11> The principle is simple. Basically your entire accounting log is always a balanced equation: sum(assets) = sum(liabilities) + sum(owner's equity). Every transaction gets recorded on both sides of this equation, so you can check for (certain kinds of) mistakes by adding up everything on both sides and seeing if it matches. This is a vast oversimplification, and possibly slightly wrong, but hopefully illuminates the connection with unit testing. :)

</comment></comment></comment></comment></comment></comment></comment><comment><USER12> I don't agree with the implicit premise that if the cheaper consultants had been required to maintain the tests and provide coverage for what they wrote, the code quality would have stayed high. In my experience, it would have turned into just as much of a mess, except would have taken three times as much work to maintain all the tests in the process.

Maybe the tests would have had some benefits, but would they have enough to justify all the extra time to write/maintain them? Certainly not.

In my experience, good programmers write good code, tests or not, and bad programmers write bad code, tests or not. I'm not against testing altogether, it makes sense in some contexts (like very widely used libraries). It's also useful for beginners who aren't sure "where to start" with a project. But even in cases where people swear that their tests are invaluable because it's tricky code that breaks often, that's a sign to me that that code needs to be made less fragile, not more well tested. TDD is a cargo cult.

<comment><USER13> I couldn't agree more. Almost every other form of testing, automated or manual, is more effective at catching bugs than unit testing in my experience. I rarely find unit tests catch any actual bugs (two I can remember in two years in two major codebases) and they are actually a liability rather than an asset because of that in many cases due to the time it takes to create and maintain them.

Often, tests are so far removed from their actual run context with mocks and stubs that they're only testing the functionality of the mock/stub framework itself. OOP code is hardly ever unit test friendly by definition and a lot of bugs are at integration points and due to app state that won't show up in unit tests. There are few places, in other words, where they are useful outside known algorithms with expected outputs in OOP. For one bug prevented per application per year, it's easy to see why spending weeks a year on preventing said bug might not be worth it. I'd rather use them sparingly and test in other ways that are more effective at catching bugs.

<comment><USER14> > I rarely find unit tests catch any actual bugs

What kind of code are you writing? Sure, a Spring service that just integrates a bunch of other services is hard to test due to mocks galore, but any dense logic blocks should be moved to standalone, testable classes.

For my math libraries, Fibonacci compression algos, etc, I find the hundreds of unit tests invaluable. Add to that, in tools like SBT, "sbt ~testOnly com.MyTest" will rerun tests on every change, giving me feedback in under a second, rather than the whole dev/test cycle of save/restart_server/click_on_UI. Write unit tests for the tricky bits that will benefit from them.

<comment><USER13> These are known algorithms you're talking about, the one place where unit tests actually consistently make sense. I'm not writing a math library, however. I'm writing APIs and web GUIs. We have an immense amount of business logic and we do unit test a lot of it, but as I mentioned above, those unit tests hardly ever catch any bugs and they take a lot of time to maintain. Every time there's a change in the logic, the tests have to be updated. 999/1000 times, when a unit test fails after a chance it's because it needs to be updated, not because there is a bug. Keeping up with those updates is simply not worth the time to catch one bug per year. Neither is writing new unit tests in these areas. Writing them for well-defined algorithms with a limited (or at least definable) set of known inputs and outputs, as I mentioned in my original reply, is still useful. Other types of testing that our developers could do to make sure the code is high quality are much more useful of course and therefore preferred because they actually help make the codebase better rather than creating the illusion of doing so as unit tests often do.

<comment><USER15> I don't use tests, and I find that when I need to make a change to some code that has, say, four or five different paths through the logic, a lot of times one of the paths will break. Testing all of the paths manually each time there is a change is incredibly tedious and time-consuming. I feel like if I had unit tests I would be able to just see instantly if anything was broken. But, I never can seem to find the time to write them...

</comment></comment></comment></comment></comment><comment><USER16> I've been on the other side of this as a consultant. I once was consulting for a place where I asked if I could run the existing tests to confirm I hadn't broken anything when adding in some new functionality. The owner of the project yelled (actually, really yelled) at me to never run the tests, ever. Apparently they deleted production data.

I didn't spend much time consulting for them.

<comment><USER17> I would have given them a bid for fixing that problem...

<comment><USER18> The yelling problem?

<comment><USER17> The "can't run tests without deleting production data" problem.

The yelling problem, I'd be tempted to fix for free...

<comment><USER19> > The yelling problem, I'd be tempted to fix for free...

So, run the tests?

<comment><USER17> My temptation was more toward a knuckle sandwich. Not a productive response, and probably death for a consultant's business, but I would be tempted...

</comment></comment></comment></comment></comment></comment><comment><USER20> Some of the reasons why I delete unit tests from time to time:

\- Often the quality of unit test code is a lot worse than the production code.

\- Some times people test too much in a single test (ie. more than one unit) making it very hard to change the design of the application.

\- Some times a unit test misunderstands how the application is supposed to work or the requirements change.

\- Some times a unit test tests something too little or too trivial.

\- Some other test is already covering the case.

I personally don't weight 100% test coverage as critical. Often other aspects of QA in application development are more important (i.e. integration test or documentation).

<comment><USER21> I don't know why you were down-voted. TDD fanatics?

</comment></comment><comment><USER22> I, very recently, began writing a suite of tests to go along-side a complex mobile app. During a stand-up meeting I (somewhat) proudly announced that for a particularly onerous piece of business logic, I had 100% coverage with tests that run in less than a second.

The project manager in the room was worried about the time it was going to take. All the developers in the room piped up to say "oh, no, this actually saves time"

The next day, I found myself in a private meeting room with the project manager and my line manager.

Both were trying to tell me that unit tests are not part of the scope of the project, not were they approved and, that I was to stop writing them.

Manual QA was the way to go at the end of the project.

Yesterday, I was in the office from 10am to 2am on a national holiday addressing issues arising from QA.

It was unproductive to spend the day wondering how many of those defects I'd have been able to catch months ago if I'd been writing tests all along.

When you're the only one on your team who respects the tests, the world feels like a very bleak place.

<comment><USER23> It does suck how much of the time you wind up in the situation that, to make any progress, you have to work in secret behind some smokescreen of other less useful work, to keep the micromanaging and the hemming and hawing from consuming any improvements.

It's not uncommon that orders of magnitude more time wasted in debate and FUD'ing round on things than it takes to actually do them.

</comment></comment><comment><USER24> I'm going to be a contrarian here and say that if unit tests, in most cases, made economic sense they'd be a given in almost all software development.

But they're not. Do we assume business owners are dumb? Do we assume managers are dumb? That's a popular position for technical people. "Oh, you just don't understand how valuable those unit tests are!"

But the cost of maintaining unit test vs. the cost of fixing bugs later might favor just fixing the bugs later. Maybe it doesn't sometimes - but one is an upfront cost you know about, and one is a nebulous cost that you might or might not have to pay later.

Given that, I know what most people paying the bills are going to choose.

<comment><USER25> It's a question of incentive alignment. Managers are not dumb, their incentives are aligned to short-term success rather than long term. Consider the difference in scenarios between producing ok code very quickly and good code more slowly. The manager will immediately feel the negative consequences of taking the second decision, if their incentives are badly designed. Meanwhile they may never feel the negative consequences of the first decision. When bad code breaks down, how likely is the manager of three years prior the one to take the blame or heat for it, let alone face real consequences? Often they won't.

</comment></comment><comment><USER26> I had a different experience with tests. 18 years ago at one company I laid out a test plan. Some of it was automated, the majority of it was manual. It applied specifically to a large custom built application.

2 years ago, I was at an entirely different company. They handed me their test plan documentation. Lo and behold, it was my document, now laden with another consulting company's logo. It was missing a few tests, but there was nothing new.

I was angry for a solid 4 hours. Then I had to laugh about it. I would be flattered that my 18 year old work was still being used, but it was quite simply dated. If a big company was being cheap and getting things built by offshore resources who had no better way to accomplish it than by stealing my work, then they got what they deserved.

</comment><comment><USER27> I have this same underlying feeling every place I work. Maybe it's because I'm not in the Valley, but in the last several jobs I've had, I was the only person advocating for things like unit tests, release pipelines, or even VCS(!). And each time I get a new job, team members and bosses from the old one inevitably call with similar self-inflicted crisis like this.

<comment><USER28> I don't think it's because you're not in the valley. I think it's because only a few percent of developers in the world care enough to become leads and make this stuff happen across the team.

</comment></comment><comment><USER29> Man, this makes me sad. Not about the atrophied codebase, but about the inevitably extreme difficulty of keeping one properly maintained.

Expertise in software maintenance isn't common and it isn't cheap. Every greenfield dev is going to eventually see his project handed off to people who won't understand or respect his conventions and methods. That mostly destroys it, but business requirements can put it on chemo and a food tube and keep it alive against its will for a long, long time, and it's not a pretty sight.

It's practically impossible to. I've been maintaining an ancient Rails codebase for the last two and a half years. I'm perhaps the fourth or fifth such guy to do so since it was built. The project was never updated past a certain point release and it's more work than it would be economical to do to do that now. I'm experienced enough now to take it on, but both me and the company have better things to do with our time and resources.

It is so ridiculously easy to make a bad decision that seems like a good decision that instead ultimately dooms the project. Software is like this weird life-form from another part of the galaxy whose motives are so alien to us that we can't even begin to come to grips with it. We know it's not actively plotting against us, well, pretty sure, but more than that? All you can do is shrug your shoulders and hope it doesn't consider you a threat today.

</comment><comment><USER30> I don't think this should be surprising to anyone.

Outside developers don't have any real ownership of their work product. Even if they know better in principle (and many do), they don't have any incentive to practice good stewardship. And bargain-basement outside developers aren't magical productivity pixies; the reason they are able to charge lower prices because they don't need to charge you for all the things they aren't taking the time to do.

</comment><comment><USER31> Moral of the story: Great developers are profit centers, bad developers are cost centers.

Unfortunately, many execs without development experience neglect to see it this way.

They see "expensive cost center" that can easily replaced with cheaper labor. Cool thing is, as others (like the author) have said, they tend to get burned and end up re-hiring you on even better-than-original terms.

Kudos to the author for doing good work!

</comment><comment><USER32> FWIW I've been eating my own unit tests these days. I find they slow me down and distract me from what I'm doing.

You've got the "large scope" unit tests that test functions that take lots of dependencies, via mocking. These often end up being so mocked, that you're testing the mocks more than the function itself. You feel smart when you write it, but a week afterwards you can't even remember what it's testing.

You've got the "small scope" tests that test small pure logic functions. Great, but these hardly ever change. It doesn't seem worth the overhead to maintain a test for unchanging code.

There's a "fuzzy middle" that _could_ be reasonably worth unit testing, but these are the functions that are most likely to get completely ripped up during refactoring and new feature dev.

To me, a sound architecture (no global variables, a minimum of mutation[1], etc) and a sound type system means things generally work the first time anyway, without the need to maintain a big honking test suite and everything required to run it.

I'm finding it's much quicker to get things out the door without this overhead, the architecture ends up being simpler ( _far_ simpler in some cases) because I don't have to put test hooks in for everything, I can refactor without the worry of how many unit tests will break, and I've experienced no downturn in quality.

Of course there are cases (public core libraries, large distributed dev teams, really complex pure logic) where unit tests are absolutely necessary, but for _most_ of my projects these days I'm finding them to be redundant.

[1] In fact, one could argue that the greatest benefit from the TDD phase was that TDD is harder with globals and mutation, so it reduced incidences thereof.

</comment><comment><USER33> _maybe the more disorganized the code, the more "less expensive" consultant work there is to do (charge)?_

I know of one consulting shop that had a dependable stream of income from a major European bank, because that bank had a project that didn't use source control, so they got to be the periodic hero and get paid for it.

</comment><comment><USER34> That's normal. Any non-essential complexity gets dropped. Accidental complexity accumulates.

In one project next developer ate my build script. Why bother with compiling less to css if you can just edit css and forget the less files and build script. Same went for r.js bundler.

In other project I participated angular got dropped because people couldn't be bothered with it.

</comment><comment><USER35> The bulk of the first comment of the article was as good as the article IMO. Quoting here:

>> But maybe the more disorganized the code, the more "less expensive" consultant work there is to do (charge)?

> This is implying maybe they intentionally disorganize the code so they'll > get more billable hours?

> I seriously seriously doubt it.

> Rather, it's as simple as: If you want to add features or make changes > paying the cheapest possible amount, you simply aren't paying for well- > organized code.

> It's not just less experienced programmers, it's less experienced > programmers trying to get you the feature in the least possible hours. They > aren't doing artificial things to bill you more hours, it's in fact quite > the reverse -- they really are trying to get the feature done in as few > hours as possible, to bill you as few hours as possible.

> And when you do that, you simply don't have time to organize the code well, > or keep the tests working. You're shoving it out the door as quick as you > can. Of course it takes more time to keep the code well-organized than to > just hack it until the feature works as quickly as possible. Of course it > takes more time to maintain the tests -- over the short term, and all you > ever have is the short term when you're paying and getting paid little by > little feature by feature.

> They have other customers, they don't need to bill you artificial hours. > They really are billing you as few hours as they possibly can -- because > that's how they get customers, being the cheapest. That's exactly what the > client asked for, it to be done as cheaply as possible.

> You get what you pay for.

I have only recently started working for a consultant that bills hourly. It's an eye opener. We are a small shop of experienced developers, we work for people that do want us to produce quality, and we do, we do good work, and we do write tests and maintain our tests. But it is a still a constant struggle inside my head between doing it as right as I really want to, and not charging the client more hours than the feature seems 'worth'.

> If you as a client prioritizes price even higher over quality (and you have > no way to judge internal quality anyway, not being a coder, so why wouldn't > you? It looks nice and works, what else can you judge?), if you're hiring > less expensive developers to save money... they might be skilled devs in > fact, but if you are trying to get it done as cheaply as possible, you are > not going to get well-organized code. And you as a client don't care, what > do you care about well-organized code? Until it reaches a breaking point > where your technical debt is so high you can't get any more features at all, > and you realize, oops... and probably still don't understand what you did > wrong or could have done differently.

> Good software is expensive. Too expensive. More expensive than most people > who need good software can afford. Which is why we have so much shitty > software.

</comment><comment><USER36> Cheap labor != consultant. In fact, real consultants tend to be expensive. A real consultant is an expert in a field, not an asterisk or wildcard for anything.

</comment><comment><USER37> Of course, then when the OP was asked back for one particular thing, he didn't go and setup the unit tests again, either. He did the same exact thing as the consultants.

<comment><USER38> He was contracted to fix one thing, not to rewrite the unit tests. At the end of the day, he can't change what the company does or doesn't value.

<comment><USER37> Yes, as are the consultants. Why put them down when they are doing exactly what was asked of them?

Of course they don't bother with unit tests when asked to change thing A that breaks a bunch of them.

</comment></comment></comment><comment><USER39> The format of this article was downright annoying.

<comment><USER40> yes. i don't understand the trend of duplicating quotes from the article inline in a larger font.

<comment><USER30> It's mimicking something many print magazines do. But without any apparent understanding of why or how print magazines do it.

<comment><USER41> > But without any apparent understanding of why or how print magazines do it

I have honestly never had any idea why print magazines do that. Maybe I've never seen a print magazine do it "right", but I think it seems just as pointless and annoying in print or online.

<comment><USER42> A common way of consuming magazines is to flip through them looking for something interesting, and a good pull quote will intrigue you and make you want to read the surrounding article.</comment></comment></comment></comment></comment>


A genius tool for finding relevant long tail keywords - <AUTHOR> http://answerthepublic.com/ <comment><USER2> The kind of tool I would love to keep only to myself. Loved it :D

<comment><AUTHOR> Exactly! :-D I cannot believe it took me two years to find this gem.</comment></comment>


UML is rarely used in the industry (2013, PDF) - <AUTHOR> http://oro.open.ac.uk/35805/8/UML%20in%20practice%208.pdf <comment><USER2> The only people who read UML diagrams are those that make them.

And there are about 12 of those people in the world.

</comment><comment><USER3> lol big surprise.</comment>


How do I take my iOS app from $1.5k/mth currently to $10k/mth? - <AUTHOR>

We've been working at developing and supporting this iOS app for 14 months now.
http://itunes.apple.com/us/app/dvd-player-for-ipad/id376493632?mt=8
We've tried everything in the book including: 1) free version + paid version 2) permanent money back guarantee 3) extensive SEO, we occupy almost all of the first page of "DVD" and "iPad" 4) extensive support, we use Fogbugz and track every single ticket and give refunds immediately.
Questions being: 1) Is the market too small and should we move into adjacent markets? 2) If so, how about the Air Video space? Though they really have a great product that I love to use...
Otherwise, should I just scrap support and keep the app on life support given that it cant feed the Support and Dev teams...
Much appreciated! <comment><USER2> I wouldn't buy that because I'd either use a VNC, or rip the DVD. I also wouldn't buy anything with such reasonable negative reviews. Air Video is for videos in general, so it is what people will look for. I'd suggest moving on.

</comment><comment><USER3> Fix the bugs - 1 star reviews aren't helping you.

<comment><USER4> On the flip side, also ask happy users to post reviews.

</comment></comment><comment><USER5> Have you asked existing users what they like / dislike?</comment>