Live data from Hacker News

Be Nice and Write Stable Code

technosophos.com

101–110 of 159 posts

Re: Be Nice and Write Stable Code

#101
post #58
post #51

Earlier quoted context omitted.

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?

What about basing the decision on the API unit tests ? Combined with API signatures hashes, maybe there would be enough information to deduce minor changes, bug fixes and major changes

Re: Be Nice and Write Stable Code

#102
post #30

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…

Is API compatibility computable in general? My instinct is that it is, but I’ve never seen a theorem.

Type compatibility between two APIs would usually be decidable, because otherwise the type systems would be useless.

But behavior testing is undecidable, easily follows from halting theorem. I doubt it would even be recognizable.

Re: Be Nice and Write Stable Code

#103
post #82
post #41

I'm maintaining an open source project[0] and I'm struggling with using SemVer because my "app" doesn't have a single API but a few: At it's core it's a node app. Though I also include a small web server that wraps around it (and a UI frontend). 1. It allows people to write scripts (js) that receives inputs and passes on events based on an API (the strategy API)[1]. 2. It has extensive configuration[2] that sometimes…

Your project looks cool. Here's some overly harsh criticism from an old dude in no particular order. The problem I see upon an extremely cursory view of your project is that it's trying very, very hard not to be a sellable product. I'm a good programmer. Why do I want to learn your API/library instead of calling the exchange API's directly? Is this saving me time? Is it saving me time long term, even when your code c…

Woah great feedback. This is very much appreciated!

I'm not sure if going specifically into all of your points right here is the best way forward. But suffice to say I am very happen to hear them :)

> the abstractions are wrong and most of the code probably relies on some hidden state that's really hard to debug unless you're the code author.

This is very much spot on, definitely something I want to work on.

-----

The main reason that everything is so spread out (plugins, web API, internal API, etc. etc) is because a ton of people are doing different things with it.

99% of the people only touch the basics, and they don't need to touch any config file, they can go through the UI that handles all of it automatically (Gekko is focused on tech savy but not perse professional programmers). They don't know what (my concept of) a plugin is, and they don't care about any API (nor any version for that matter).

It's about the other 1% who are kind of spread out over:

- people who want to hook into certain lifecycles (to push certain data to google spreadsheets[1] for example)

- people who only use subparts of the app, for example to have something that can fetch normalized market data from a number of different websites - Or people who only want to create their own prediction making logic (with AI or whatever) and use the execution logic of my app. - people building tools on top of the web API that bruteforces a problem space to figure out new solutions[2].

So all the people that care about the versioning (not the 99%) are exactly the hobby DIY hacking people who want to open it up and take it apart. And it feels impossible to steer them into "don't touch this because the interface is not a standardized API".

-----

The main thing I am going to do now is rethink the entire config strategy, because it's a huge mess and I think I am the only one who understands it[3].

[1]: https://github.com/RJPGriffin/google-forms-gekko-plugin

[2]: https://forum.gekko.wizb.it/thread-56589.html

[3]: https://github.com/askmike/gekko/issues/956

Re: Be Nice and Write Stable Code

#104
post #94

Earlier quoted context omitted.

What if: * Function order changes * Prototype goes from int function(char * ); to int function(char * arg); * Typedef is added so instead of int function(char* );, it's typedef char* str; int function(str);

Good points, the second one in particular I don't think could be fixed without a full parser. Function order changes could possibly be worked around by a formatter/linter that can reorder functions, at the risk of creating more issues. The last could be handled be passing the code through the preprocessor (the -E flag in gcc) first. By this point it's probably gone beyond the "perfect is the enemy of good" threshold…

> The last could be handled be passing the code through the preprocessor (the -E flag in gcc) first

Nope, that only handles preprocessor directives (essentially, any line starting with '#'). Typedefs are handled by the parser.

Re: Be Nice and Write Stable Code

#105

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 would; unfortunately Java doesn't support that.

Re: Be Nice and Write Stable Code

#106
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.

D contracts are arbitrary code snippets. So they're Turing-complete, therefore it's still uncomputable.

Re: Be Nice and Write Stable Code

#108
What counts a breaking change? I would say that strictly speaking anything could be a breaking change if an user is crazy enough, so increasing major version all the time is not particularly useful - I mean, you could do that, but what is the purpose of semver then. Consider a following function.

    f(arg: String): Output
Now, let's say that we change it to be generic. Let's assume that `String` implements `SomeInterface`.

    f, U>(arg: T): U
An user is crazy and passed an empty generic type list and their code broke as there are now two generic arguments instead of none.

    f("a")
Or for a different example, let's say that you want to introduce a new function, `g`, but the user does the following.

    import yourlibrary.*
    import otherlibrary.*
An user is using the function `g` from `otherlibrary`, and their code doesn't compile anymore due to an ambiguity.

I would say it's a minor change, but in theory it's possible for it to be a breaking change. I often had situations like this where something could be breaking, but the code had to be really unusual for it to break (and if it would break, it would be a compilation error).

Re: Be Nice and Write Stable Code

#109
post #98
post #58

Earlier quoted context omitted.

And who decides if a change is breaking or not?

It's simple, everything that has existed should behave exactly as it used to before. In order to ensure this people invented lots so technics - code reviews, exploratory testing, integration tests and so on. It's even boring to discuss it, it's just basics.

He means, how can a machine determine it?

Re: Be Nice and Write Stable Code

#110
post #43
post #30

Earlier quoted context omitted.

Is API compatibility computable in general? My instinct is that it is, but I’ve never seen a theorem.

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…

Thanks for that pedantic insight, doc.

It's patently obvious that API compatibility is a computable problem. You are just checking if API1 is a subset of API2.

Even if foo() never returns, the Application Programming Interface is unchanged if the function signature is the same.

Post reply on HN