HNHacker News
TopNewBestAskShowJobs

Anchor

1,507 karma · joined April 5, 2008

submissionscomments
Anchor··on New Warship’s Big Guns Have No Bullets
There's no point in making people just to think more. They have to think very carefully and along a very specific line of though: they have to ask, "Is it really the way you say it is?", every single time something, anything, meaningful is at stake, for the rest of their lives.

People talk endlessly about their values. They talk about self-reliance, decency, honor. But we betray our values if we don't know what really is true. We work against our best interest and our dearest of things when we are mislead the moment we stop asking what really is. No matter what the values.

How about some self-reliance of thought for a change.

Make no mistake, it is a 30-year project to fix peoples. You need to educate a single generation before things start to get better. But then they will. Happens every time and in every country and in every culture. Skip that and no matter what you try, everything falls apart eventually if the people don't want to ask what really is true. Everything else is built on top of that. Nothing else is sufficient anymore, not in this age we now find ourselves in.

PS. I agree - I am greatly in favor of shortening any feedback loops in any system, societal, political, business, software development - it is what makes systems robust against changing environments.

Anchor··on New Warship’s Big Guns Have No Bullets
That's not how it works. They are very well capable of choosing something else and we all know it. They may lack the knowledge to do it - but that is fixable, politicians are not.
Anchor··on New Warship’s Big Guns Have No Bullets
The national security argument only flies if the people buy it. That's the root cause; fix the people.

I deliberately and provocatively overly simplify the issue here, but I claim that every problem we face can be solved by better education that simply requires people to ask "Is that really the way you say it is?" in every single step of every single fact they ever face.

Anchor··on New Warship’s Big Guns Have No Bullets
By the people they chose to make those decisions.
Anchor··on Musk says SpaceX knows what caused the latest rocket failure
True, the trunk needs to be jettisoned from the craft before it lands with parachutes.
Anchor··on Musk says SpaceX knows what caused the latest rocket failure
They could, when Dragon 2 is in use for supplying ISS. But Dragons do not carry the kinds of payloads lost in this case. The satellite is on top of the second stage and covered by fairings. There's no craft on top of second stage, so there is no launch escape system.
Anchor··on SES-10 Launching to Orbit on SpaceX's Flight-Proven Falcon 9 Rocket
More also on LA times http://www.latimes.com/business/la-fi-spacex-rocket-20160829...

It's really exciting to see how this develops going forward. This whole landing rockets thing was deemed not possible (or worth it) only some years ago, and now SpaceX is landing rockets left and right. The next step is to re-fly them - which is still deemed not worth it by most. Let's see if there is a pattern.

Anchor··on Ask HN: Help me see why everyone seems to love TDD?
You don't sell unit tests to management. You don't even tell management. The same way you don't sell using reasonable variable names. You do it because (if!) it makes you and your team more productive. Coverage metrics are internal to the development team - they are not management metrics. Shipped features, open support tickets, velocity, story points, etc. are management metrics; cyclomatic complexity, test coverage, and length of variable names are developer metrics.

That said, there is a fairly large difference in experience and skill required to learn how to write variable names that make you more productive and how to write unit tests that make you more productive.

It all comes down to TCO of the system to users. In many cases, high test coverage does reduce TCO, but this is difficult to see during the first year of the project. And note too that the risk of increasing TCO due to poorly written unit test code is real. You can do more harm than good by creating flaky ad-hoc unit tests that are slow to run, difficult to change, and make refactoring of production code PITA.

The reason we do TDD, is that has some unique benefits. Especially, if you aim to use "full TDD" in the sense that no line production code is written before there is a failing test for that line.

What your life would be like if every time you interrupt a programmer in your team, everything she was working on compiled and passed all its tests less than two minutes ago? And if you'd have an always up-to-date spec that is so precisely written, it executes? And deployment to production would be a business decision instead of technical one as you'd be ready to deploy practically whenever you feel like it? And if you decided to swap MSSQL for PostgreSQL in your production system, you could do it without breaking a sweat?

What would your life be like if you did not have to fear breaking anything when cleaning up code? If you'd be able to keep your system maintainable and you'd know it?

If TDD is so great, why then, it is not used more often? I can only speculate, but I think this comes back to the question of developer skills. I have mentioned some of this before here at HN, but I'll reiterate.

I have noticed that I have to make large refactorings to move things around to arrange the whole system so that each part can be tested without too much effort. To do this I have to view most things in terms of the interfaces they provide. On the test side, I have to write the test code so that the what the test does is strictly separated from how the test does it. This way changing the system causes only minor changes to ripple to the majority of the test code. This is by far the most common paint point of a novice TDD'er.

Based on this, it seems that programming with TDD is a distinct skill-set that requires significant effort to get reasonably good at, i.e., to be more productive than without TDD. I have given it a try on medium-size projects and it does pay off in terms of simplicity of the design (I have to manage dependencies and decouple external systems and components quite heavily), low defect rates in production/QA, way less time spent in debugger, and relatively high velocity (this is notoriously hard to measure cross projects/teams, but at least this was true based on customer and product owner feedback).

However, the problem with TDD is that all of the above (tests decoupled from interface, interface decoupled from implementation, system decoupled from external systems, components decoupled from each other, design skills to recognize this, and refactoring skills to do this fast enough to remain productive) need to be done well enough at the same time. Otherwise the approach falls into pieces at some point.

To paraphrase Uncle Bob from some years ago: "I have only been doing TDD for five years, so I am fairly new to it..." Half of the programmers have that much experience in programming in general, so the amount of time required to hone TDD and refactoring skills may not be there yet.

TDD'ing requires months or years of practice to get really productive with, and has a fairly large set of prerequisites that one has to know in order to remain sane. It took me several years of experimenting (especially with different techniques of writing unit tests) before I found a way to be productive with TDD. I also drew the connection between testability and program architecture (aggressive decoupling) fairly recently (some four years ago), and that was one of the last pieces of the puzzle that made everything work. The system structure is especially crucial for writing fast unit tests. You really want the dependencies to external systems (DB, UI, Network, MQ, OS, Library, Framework, or the like) injected and abstracted behind and an interface.

If your system's design results in your unit tests depend on volatile components, your system becomes unnecessarily complex. This is because volatile components change often and these changes ripple to your units tests effectively rendering them volatile too. Avoiding this problem has been captured, among others, by the Stable Dependencies Principle (http://c2.com/cgi/wiki?StableDependenciesPrinciple), which states that the dependencies should be in the direction of the stability. A related one is the Stable Abstractions Principle (http://c2.com/cgi/wiki?StableAbstractionsPrinciple), which states that components should be as abstract as they are stable.

When I started with TDD, my productivity plummeted initially, but the benefits were too good, and I slowly found the techniques needed to keep up with my old self in terms of produced features. I dread to think the pieces of code that send me deep down into debugging sessions due to non-existent test coverage.

Part of the problem is that there are not that many TDD codebases or TDD'ers around. Also, this is probably not something you can pick up while doing toy projects or school assignments. The benefits start to show in the 100 kloc and above magnitudes, and as there are so many ways to paint yourself into a corner with bad overall design, coupling, unmaintainable (or, my pet peeve, slow) tests, chances are, you don't figure out all the necessary things yourself. On top of that, there is no time to learn this much in most dev jobs, so you are left to learn with hobby projects (which do not usually grow big enough).

Most TDD experiments result in failures for the reasons listed. This is why you read so many comments on TDD being useless, wrong, a religion, or Uncle Bob cult. However, it seems that people who keep practicing TDD have been programming for more years than people who have not tried it, or have abandoned the practice. I have yet to meet a TDD practitioner who started programming that way and has not considered any alternatives. The ideas have born out of really bad - serious - experiences with existing approaches.

Anchor··on Apollo 11 Guidance Computer source code
And this:

  GAINBRAK,1        # NUMERO MYSTERIOSO
https://github.com/chrislgarry/Apollo-11/blob/master/LUNAR_L...
Anchor··on Lawmakers Say Redacted Pages of 9/11 Report Show Saudi Official Met Hijackers
Assuming you are not aware of this already, you may want to check HN classic https://news.ycombinator.com/classic which only displays posts from people with sufficiently old accounts, IIRC. The Blackwater and NPR post seem to be on that list, though.
Anchor··on SpaceX Launch Livestream: CRS-8 Dragon Hosted Webcast
Successful landing on the autonomous drone ship. Awesome to be witnessing the amazing progress.
Anchor··on Left-pad as a service
How about adding a line that alters the output randomly every 1000th second. Is your UI testing strategy good enough to pick that up? Or do you code review all your dependencies on version changes?

I was bitten by a JS function change in a package that has been named also in this thread. It was an "oh, we moved that functionality to a new function, but reused the old name for a new function that does nothing like the old". And no semantic versioning.

Slipped through UI testing and broke production functionality. I did not like dependencies before, and I like them even less now.

And people keep wondering why everyone's software is so ridiculously bad.

Anchor··on Giving Up on TDD
In general it seems that people who keep practicing TDD have been programming for more years than people who have not tried it, or have abandoned the practice. I have yet to meet a TDD practitioner who started programming that way and has not considered any alternatives. The ideas have born out of bad - serious - experiences with existing approaches.

As I said in the previous thread yesterday, TDD'ing requires months or years of practice to get really productive with, and has a fairly large set of prerequisites that one has to know in order to remain sane. It took me several years of experimenting (especially with different techniques of writing unit tests) before I found a way to be productive with TDD. I also drew the connection between testability and program architecture (decoupling etc.) fairly recently (some four years ago), and that was one of the last pieces of the puzzle that made everything work.

Yes, my productivity plummeted too, but the benefits were too good, and I slowly found the techniques needed to keep up with my old self in terms of produced features. I dread to think the pieces of code that send me deep down into debugging sessions due to non-existent test coverage.

Anchor··on Giving Up on TDD
If I read this sentiment correctly, this means that any attempt to improve anything ("provide benefit") usually results in net negative. But I cannot imagine that this is the case. Can you elaborate?

For example, let's say I want to improve my car factory efficiency. I introduce a way to keep things running without delays on the production line. Would you say that this plan is futile too? Toyota might disagree.

Would you also say that accountants waste half of their time doing double-entry bookkeeping? Half of the transactions are extra in the same sense.

I mean, I understand your argument on the imperfection of any improvement plan, but this does not say much on the actual topic on hand. Should we discuss concrete trade-offs instead of general sentiments?

Anchor··on Giving Up on TDD
> But he doesn't. Because the benefits aren't higher, in fact they are lower

I am genuinely curious, what do you mean with this claim? I mean, yes the costs are high [1], but when properly paid, do the benefits still end up smaller than without practicing TDD? Which concrete benefits we miss when doing TDD?

Uncle Bob has stated many of benefits of TDD elsewhere and did not mention them in this post. Many of his public talks on the subject are available online.

[1] https://news.ycombinator.com/item?id=11311646

Edit: link to my previous comment from yesterday elaborating on the costs

Anchor··on Giving up on test-first development
Part of the problem is that there are not that many TDD codebases or TDD'ers around. Also, this is probably not something you can pick up while doing toy projects or school assignments. The benefits start to show in the 100 kloc and above magnitudes, and as there are so many ways to paint yourself into a corner with bad overall design, coupling, unmaintainable (or slow!) tests, chances are, you don't figure out all the necessary things yourself. On top of that, there is no time to learn this much in most dev jobs, so you are left to learn with hobby projects (which do not usually grow big enough).
Anchor··on Giving up on test-first development
[TDD] encourages a focus on sorting out detail to pass tests rather than looking at the program as a whole.

I have actually found the opposite to be true.

I have to make large refactorings to move things around to arrange the whole system so that each part can be tested without too much effort. To do this I have to view most things in terms of the interfaces they provide. On the test side, I have to write the test code so that the what the test does is strictly separated from the how the test does it, so that changing the system causes only minor changes to ripple to majority of the test code.

Based on this, it seems that programming with TDD is a distinct skill-set that requires significant effort to get reasonably good at, i.e., to be more productive than without TDD. I also have given it a try on medium-size projects and it does pay off in terms of simplicity of the design (I have to manage dependencies and decouple external systems and components quite heavily), low defect rates in production/qa, waaay less time spent in debugger, and high velocity (based on customer and product owner feedback at least).

However, the problem with TDD is that all of the above (tests decoupled from interface, interface decoupled from implementation, system decoupled from external systems, components decoupled from each other, design skills to recognize this, and refactoring skills to do this fast enough to remain productive) need to be done well enough at the same time. Otherwise the approach falls into pieces at some point.

To paraphrase Uncle Bob from some years ago: I have only been doing TDD for five years, so I am fairly new to it.. Half of the programmers have that much experience in programming in general, so the amount of time required to hone TDD and refactoring skills may not be there yet.

So maybe I am saying that you are not doing it right, but I don't really know. Maybe I am wasting my time writing tests, but anecdotally, I seem to enjoy extending and maintaining the TDD-based pieces of code more than the non-TDD pieces in our codebase.

Anchor··on The Wrong Abstraction
Maybe I am being idealistic, but I think the sentiment in the discussion concerns not only the ideal coding techniques themselves, but also the bigger picture of business needs. That is, if we took the approach of keeping code in somewhat decent shape, we would end up, in the long run, producing the whole system more efficiently, and reducing the TCO of the system for the user and the business.

I certainly hope that the discussion is not only about making the lives of the programmers easier.

Anchor··on The Wrong Abstraction
In case of a UI, the trick is not so much to write an abstraction for this, but to write the application logic such a way that it does not depend on the UI framework.

Your own UI code should be limited to displaying the data with the help of the framework. This minimal UI code should depend on the application code and that should be the only dependency between the two.

There are simple techniques to keep view logic and application logic decoupled, for example by introducing a separate data structures prepared and optimized for view components to consume. An added bonus of this is testability of both application and UI logic without opening a browser.

Anchor··on The Wrong Abstraction
I'd say this is sound advice for core components of the system, but we may want also to consider the types of the dependencies. For example, I would not wait for three times if the dependency is some kind of external system (DB, UI, Network, MQ, OS, Library, Framework, or the like) which is volatile in one of the worst ways - not directly under your control, unlike your own source code.
Anchor··on The Wrong Abstraction
I think those four criteria beautifully capture many goals of software design. And for example, we could say that we reduce system state with a functional approach, make component coupling looser by indirection with object orientation, and decrease code complexity by structured programming.
Anchor··on The Wrong Abstraction
If your system's design results in your stable components depend on the non-stable (volatile) components, your system is complex. This is because volatile components change often and these changes ripple to your stable components effectively rendering them volatile. Now the whole system becomes volatile, and the changes to it become very hard to reason about - hence complex.

Avoiding this problem has been captured, among others, by the Stable Dependencies Principle (http://c2.com/cgi/wiki?StableDependenciesPrinciple), which states that the dependencies should be in the direction of the stability. A related one is the Stable Abstractions Principle (http://c2.com/cgi/wiki?StableAbstractionsPrinciple), which states that components should be as abstract as they are stable.

Anchor··on The Wrong Abstraction
I think the right approach is not to avoid dependencies, but to manage them.

Let's say you are unsure of the correct UI framework just. React, Knockout or Angular? React native? Maybe you don't yet know which database best suits your usage and scaling needs. Should you avoid committing to those dependencies? For how long? Doesn't this slow you down?

A good way to approach this is to isolate the dependencies so that you don't have to commit to the actual implementations (React, Mongo, PostgreSQL, Angular, ZeroMQ, whatever it is you need) early. Of course you start the work with some set of frameworks and libraries, but so that no other part (the parts that does all the important stuff that it unique to your application) of the system knows of the implementations. This way, if the need arises, changing the implementation details will not be expensive.

Isolating the implementation behind an abstraction sometimes introduces boilerplate and duplication, but as the article mentions, the dependency is usually more costly.

Anchor··on The Wrong Abstraction
> The real offense when we factor duplicated code is the new dependency that is added to the system.

A slight tangent on that note, but I think many of the problems with current web development result from the same root cause: adding yet another dependency to solve an almost trivial problem. Sometimes going to the extreme of for the sake of saving few keystrokes. Need one function to find an item in a collection? Reference Lodash. And then drop references all over the place.

Yes some dependencies are useful, but they all need to be handled with care. Wrap that search operation to an internal utility function and inject Lodash as its implementation if you don't want to reinvent the wheel. This is what DI is for (and nothing more).

Maybe the feedback of exploding the compile times as a result of a complex dependency graph would make people more sensitive to the issue. But then again, that did not prevent it from happening either. Oh well, it's not my codebase (yet).

Anchor··on Open-source infrastructure is not venture-backable
Maybe if VCs do not see a way to make a decent return on their investments on common infrastructure (as seems to be the case also with physical infrastructure), we should consider funding that work through taxes. The article refers to Mark Suster's comment that "[OSS projects] directly caused tech’s rapid rise". This work benefits many, and we rely on it to exist - and function (Heartbleed), so there are similarities to physical infrastructure.

How about a new civil servant job: OSS maintainer.

Anchor··on Starship Robots – Small robots that travel sidewalks for local delivery
There's a team building, it seems, the same thing in partnership with DHL: http://www.sidewalkdelivery.co
Anchor··on FBI director calls lack of data on police shootings "ridiculous," "embarrassing"
Here's another tangentially relevant data point http://yle.fi/uutiset/finnish_police_fired_guns_only_six_tim...

Population: 5.5 Million

Anchor··on A General Theory of Reactivity
Previous discussion https://news.ycombinator.com/item?id=9244005
Anchor··on SpaceX – Launch Vehicle Failure
"more than 150,000 annually, which kill some 209 civilians every year" http://www.businessinsider.com/17-cars-catch-on-fire-every-h...
Anchor··on Readability, hackability, and abstraction
The problem you are referring to is called the expression problem [0]. There are solutions, such as the Visitor Pattern, but these tend to increase complexity substantially. Functional programming has approached this from the other side by introducing something called protocols [1].

[0] http://c2.com/cgi/wiki?ExpressionProblem

[1] http://www.ibm.com/developerworks/library/j-clojure-protocol...

← PreviousPage 2 of 3Next →