Live data from Hacker News

Be Nice and Write Stable Code

technosophos.com

51–60 of 159 posts

Re: Be Nice and Write Stable Code

#51

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'm doing this kind of automation with Maven in Java. There is a plugin (build helper I believe is the name) that gives you properties like "next.release.version", "current.release.version", "next.snapshot.version", etc.

So I've setup an infrastructure where you just click a button and it performs a release with _proper_ version number in accordance with semver, simply does the right thing. Works like a charm.

I don't understand complains about human factor when you eliminate it with ease.

Re: Be Nice and Write Stable Code

#52

Argh! I love the deprecation example! How elegant! How did I never think of this (or why did I never think to ask)! edit: pasted here – func ListItems(query Query) Items { ListItemsWithLimit(query, 0, 0) } func ListItemsWithLimit(query Query, limit int, offset int) Items { // ... }

Wouldn't it be easier to write optional variables, allowing you to keep the same method name? This results in cleaner code that doesn't break existing usage. For example: func ListItems(query Query, limit int = 0, offset int = 0) Items { // .... }

It doesn't result in a cleaner interface, which is what matters the most (arguably).

Re: Be Nice and Write Stable Code

#53
post #6

Regarding exception handling, letting internal exceptions define external behavior is perhaps a bad idea. The possible exception types can be wide and change over time as new parts or features are added. Example: // pseudo-code qry = new query(sql=theSql, dbConfig=DB_FOO); if (! qry.Execute()) { errMsg = "Something went wrong during your query. "; if (qry.errorExceptionName=="DB_Busy") { errMsg += "The database appea…

> letting internal exceptions define external behavior is perhaps a bad idea

In practice, I've preferred it for years.

Re: Be Nice and Write Stable Code

#54
post #7

This is all great, but I feel like all these problems could be caught just with properly written tests. If your tests correctly cover the API usage of your code, and I mean both your code complying with the intended API and the API complying with the intended usage, then the implementation behind that API should be totally transparent. No need to check versions, release notes, or any of that, just run the API complia…

Treating the test suite as your contract and having a well structured + documented test suite also makes SemVer considerations a matter of what tests changed and how did they change (new cases, new features, changes to existing features, removed features, etc.)?

Re: Be Nice and Write Stable Code

#55
post #31
post #18

Earlier quoted context omitted.

If the version number is less than 3.1, odds are very good they don’t. And I just described 80% of the node module ecosystem...

Not necessarily. There are plenty of projects in their infancy that follow semver correctly. I'd argue that a project with a high major number is more likely to be indicative of improper usage.

I don’t think high major version number tells you that. Maybe they left 0.x.y (unstable) too early and were just honest with their early churn since which is as semver as you can get.

But one if the main semver violations I see in the wild is a project slotting major changes into the minor version number because they want to avoid high major version numbers for some reason or have some romantic idea of what a major version bump “should be”.

Re: Be Nice and Write Stable Code

#56
Django is my gold standard for this. They have great deprecation policies where they deprecate something in the same release that they add alternatives (allowing for you to fix things up before upgrading Django), they document these changes liberally and offer alternatives, make good use of the warnings system (meaning you can run tests in "deprecated functions not allowed" mode to catch stuff), and generally are careful.

I'm still shocked at the number of projects that make breaking changes without first releasing a "support both versions" release that lets people test their changes easily. Especially frustrating when you have really basic environment variable renames that could support the deprecated name as a one-liner so easily.

Give people the space to upgrade please!

Re: Be Nice and Write Stable Code

#57

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…

> 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. Whats the solution here? Fuck standards? Imagine if we had that same attitude with regards to HTTP.

SemVer is a starting point. If it's a major release you can prepare yourself mentally for a lot of breaking changes. A point release... probably not

In any case you need to read through the changelog or (absent that) the actual code diff and think about how you use the application. It's not 100%, but no versioning system will be able to identify how you use code and how you expect the semantics of an application to be.

Re: Be Nice and Write Stable Code

#58
post #51

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'm doing this kind of automation with Maven in Java. There is a plugin (build helper I believe is the name) that gives you properties like "next.release.version", "current.release.version", "next.snapshot.version", etc. So I've setup an infrastructure where you just click a button and it performs a release with _proper_ version number in accordance with semver, simply does the right thing. Works like a charm. I don'…

And who decides if a change is breaking or not?

Re: Be Nice and Write Stable Code

#59

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…

> 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. Whats the solution here? Fuck standards? Imagine if we had that same attitude with regards to HTTP.

> Imagine if we had that same attitude with regards to HTTP.

Well, many do. You wouldn't believe the number of broken HTTP clients/servers out there.

The difference is that most HTTP clients/servers have to work with some significant subset of the pre-existing HTTP infrastructure (otherwise why would anyone use them?) and so that constrains their implementation to be "mostly correct". It's literally network effects :).

Libraries on the other hand usually start out with a single consumer and have no such constraints on their implementation so you end up with various levels of ossified brokenness or breaking non-ossification.

Re: Be Nice and Write Stable Code

#60

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…

Rich Hickey's take on SemVer makes for a really fantastic talk.

"Change isn't a thing. It's one of two things: Growth or Breakage." Growth means the code requires less, or provides more, or has bug fixes. Breakage is the opposite; the code requires more, provides less, or does something silly like reuse a name for something completely different.

I recommend the whole talk, but the specific beef about SemVer starts here: https://youtu.be/oyLBGkS5ICk?t=1792

Post reply on HN