Live data from Hacker News

Be Nice and Write Stable Code

technosophos.com

71–80 of 159 posts

Re: Be Nice and Write Stable Code

#71
post #61
post #42

Earlier quoted context omitted.

In some languages / project structures you need a way for internal components to connect that happens to be "public" but is not meant for public use. I see this a lot in Java libraries, for instance.

C++ and C# have the same kind of problem: except for the iffy freind declaration in C++ there is no way in the language to denote that some method is bot meant for use in other modules. C# has the internal scope for each assembly, but this breaks in combination with unit tests placed in seperate testing assemblies. Generally, proper unit testing is at odds with strict scope restrictions in the tested code. I guess we…

> C# has the internal scope for each assembly, but this breaks in combination with unit tests placed in seperate testing assemblies.

That is what [assembly: InternalsVisibleTo()] is for.

Re: Be Nice and Write Stable Code

#72
post #62
post #43

Earlier quoted context omitted.

No, it isn't computable (that is, correctly determining one of "these functions behave the same" or "these functions behave differently", and not "unknown") in general, as it is equivalent to the halting problem. Consider these two versions of a function, are they API compatible? def foo(): return True def foo(): return halts("some turing machine program") They're only truly API compatible if the program halts, but t…

I wonder if tighter guarantees can be given if tools can work with constructs like D's contracts. These are extra sections in each function that are intended to check invariants. If these invariants change, then they were either broken and needed fixing or the function had a semantic change.

That's an interesting idea. It seems like it would be a way for tools to flag "this function is likely to have changed in an interesting way", but changing invariants doesn't necessarily mean the function breaks semver.

For one, an invariant might be changed syntactically, without actually changing what it is asserting, reducing to exactly my example above: in its simplest form, the contract could go from in(true) to in(halts("...")).

Secondly, an contract could have been made more permissive, e.g. in(x > 1) becoming in(x > 0), or out(y > 0) becoming out(y > 1). Assuming violating a contract is regarded as a programming error (as in, it isn't considered breaking to go from failing an assertion to not failing), these are also non-breaking changes.

Lastly, changing behaviour doesn't necessarily mean changing invariants/contracts.

Re: Be Nice and Write Stable Code

#73

A lot of people are commenting that SemVer doesn't work, because it's still at the mercy of humans choosing good version numbers. Elm's package manager, elm-package, actually tries to remove humans from the equation, by automatically choosing the next version number, based on a diff of the API and the exported types of a package: https://github.com/elm-lang/elm-package#publishing-updates It's not perfect, but it's be…

I think we should stop publishing releases. Writing code is subject to human error and could break somebody else's work.

Re: Be Nice and Write Stable Code

#74
post #47
post #37

Earlier quoted context omitted.

Making an API public means that people can do whatever they want with it. If you are not sure if you want to allow the API in the future it should not be public. People will always look to do the laziest thing possible which might mean hooking into your "public internal API". Then you will never be able to change it and you will have to maintain it forever.

They can do whatever they want with it but you have no obligation to maintain nor support it if it’s not a documented public API, in my opinion. It’s a bit like a house on a corner with a big front yard. People may cut through the grass to save time but you can’t blame the homeowner when he finally puts up a fence.

The question of people using your property falls under the law covering _easements_.

https://en.wikipedia.org/wiki/Easement

It’s unlikely that allowing the public to short-cut across your yard would create a prescriptive easement, but there are certain circumstances where allowing a party or the public to cross a parcel of land for a sufficiently long period of time does prevent the property owner from erecting a fence.

Although it’s not a hard-and-fast rule, in Ontario certain property owners have paths open to the public most of the time, but close them for at least one day of the year, often Christmas or New Year’s Day. The intent is to prevent access for any one or more continuous years, which in turn prevents an easement from being asserted by any party.

Although it’s far from as simple as, “if you allow the public access to your land for one continuous year, you allow it forver,” a certain folklore around this has arisen, and thus the practice.

Re: Be Nice and Write Stable Code

#76
post #14
post #9

Earlier quoted context omitted.

While it's easy to say, how far do you go? Do you test every bit of every upstream library you use? The ideal is probably yes, but the reality is this rarely happens. Even with a test, you may not find this. In the IOException example, the author calls out why: > When we upgraded, all our tests passed (because our test fixtures emulated the old behavior and our network was not unstable enough to trigger bad condition…

> While it's easy to say, how far do you go? Do you test every bit of every upstream library you use? The ideal is probably yes, but the reality is this rarely happens. It depends. I have a friend who used to work on banking systems. They had full test coverage of every dependency. Even standard lib functions and language features. One time they found a bug in the md5 implementation in a minor version of a popular da…

> It depends. I have a friend who used to work on banking systems. They had full test coverage of every dependency. Even standard lib functions and language features.

these are not dependencies anymore then, they are part of your code source and should be vendored with it. I don't know what language your friend is using but I'm pretty sure most std libs and languages already have tests with very good coverage.

> One time they found a bug in the md5 implementation in a minor version of a popular database.

Every piece of code can have bugs. 100% code coverage doesn't eliminate bugs, it just says all code path are tested, an algorithm can still be wrong for some values even if 100% code path are tested.

Re: Be Nice and Write Stable Code

#77

A lot of people are commenting that SemVer doesn't work, because it's still at the mercy of humans choosing good version numbers. Elm's package manager, elm-package, actually tries to remove humans from the equation, by automatically choosing the next version number, based on a diff of the API and the exported types of a package: https://github.com/elm-lang/elm-package#publishing-updates It's not perfect, but it's be…

It litterally changes nothing. I've had to fork a lib to bump a dependency version just recently.

The only things that protect elm from knowing dependency hell are the age of the ecosystem and the fact that there are not that many common package publishers outside of the core team.

Re: Be Nice and Write Stable Code

#78

SemVer is a social construct, not a contract. It's nice when it applies, but you cannot rely on other developers to adhere to it. One man's bugfix is another man's breaking change. If product A implements a workaround for a bug in product B, but the bug gets fixed in a patch version, it could break product A's code, so it becomes a breaking change. The only way to anticipate these changes is reading the change logs/r…

Exactly, every change is breaking for someone: https://xkcd.com/1172/

Re: Be Nice and Write Stable Code

#79
post #50

Earlier quoted context omitted.

The right question is "what's the difference between a bug-fix and a breaking change?"

Irrelevant. If fixing a bug is a breaking change then it is a breaking change. This is the importance of pre-releases/"nightly" branches so that you don't have a mistake of addNumbers(5,5) returning 25 instead of 10 and not being caught and then needing to increment a major number to fix a typo of × to +. A bug fix is a change . A breaking change is a change that breaks the API . Doesn't matter if the previous status…

Irrelevant?? That is the most relevant question that a developer could ask in this situation.

Often, there are ways to work around bugs in an API. And, just as often, those workarounds will break as soon as the bug is fixed. The API developer is in a particularly poor place to judge whether a bug fix is breaking or not. Sometimes, they can talk to users to see if a change will break their code, but other times they can't. Thus, it comes down to how well a developer can predict whether a fix will break projects in the wild.

Re: Be Nice and Write Stable Code

#80
post #14

Earlier quoted context omitted.

> While it's easy to say, how far do you go? Do you test every bit of every upstream library you use? The ideal is probably yes, but the reality is this rarely happens. It depends. I have a friend who used to work on banking systems. They had full test coverage of every dependency. Even standard lib functions and language features. One time they found a bug in the md5 implementation in a minor version of a popular da…

> It depends. I have a friend who used to work on banking systems. They had full test coverage of every dependency. Even standard lib functions and language features. these are not dependencies anymore then, they are part of your code source and should be vendored with it. I don't know what language your friend is using but I'm pretty sure most std libs and languages already have tests with very good coverage. > One…

The lesson learned isn’t about code coverage or oaths tested. It’s to not blindly trust 3rd part anything, even “languages already have test with very good coverage” when the stakes are high.

If billions of dollars are riding on your code, you better be damn sure you trust everything it relies on.

Fun side note: every piece of internal code was always developed in parallel to the same spec by 3+ teams so they could cross validate. If all 3 functions don’t return the same value for the same input, every team gets to build it again until all implementations behave the exact same.

High reliability engineering sounds “fun”

Post reply on HN