On 08/06/2019 20:31, André Pönitz wrote:
On Sat, Jun 08, 2019 at 06:14:36PM +0200, Giuseppe D'Angelo via Development 
wrote:
On 05/06/2019 23:01, André Pönitz wrote:
As a matter of fact, some of the previous deprecations, e.g. the removal
of qalgorithm, triggered re-implementing the deprecated functionality
downstream, effectively shifting the burden of doing (or, rather,
*keeping*) them once centrally to all users who need it decentrally.

The huge impact that these deprecations have is also due to another reason:
the approach of systematically diverging from "upstream".

Qt really really fails at not over-extending (in the name of convenience, or
compatibility, or whatever). Especially for such low-level facilities there
is a hidden, slow trend at:

1) taking something "upstream" lacks, or is available only in very recent
versions, or is not as widespread as it should be, or similar (limiting
ourselves to "upstream" == Standard Library, that used to be the case with
QtAlgorithms and -no-stl; one could say the same with
QSharedPointer/QWeakPointer, and so on.)

2) reimplementing it so that our users have it (yay!)

3) giving it easier APIs (yay!)

4) *extending* it in incompatible ways with upstream
(QWeakPointer(QObject*); QSharedPointer in QVariants; etc.).

I see that pattern, too. But now, instead putting the break between 3) and 4),
the whole thing is killed, and everybody downstream has to do 1)-3) again,
or put up with what the standard offers.

And could prevent overextension by -x'ing the respective change on gerrit.
So *that* sounds fixable.

It's not *that* simple:

* some of these APIs come from pre-gerrit era (actually, given thread is a QtCore fun fest anyhow, a good 90% of them)

* some of them simply slip in by accident;

* some are just unpredictable at code review time (e.g. suppose we decide to add a QOutcome or QExpected to Qt, based on things which are not standardized yet, what's going to happen when the std:: versions land and supposedly end up with an incompatible design?)


The decision of "killing everything" usually comes from a combination of things:

* lack of manpower to maintain the 1-3 bits;

* very little sense at keeping the 1-3 parts into Qt if they're now widely available by other means, with more features, etc;

* the fact that the 3/4 cut is either going to be an API break (and then, API break for API break, just refactor to use the upstream thing in the first place, so pay the 1-3 anyhow); or a behaviour change, for which the compiler won't warn you, making it even worse. The only way for you to be aware is to force the whole kill.


* We could keep things where they are, supported, thus offering the easier
APIs; but simply reimplement them on top of the "upstream" equivalents.
(Ignore the possible ABI break.)

The last one is the most reasonable.

When doable without API breaks, yes, I'd also agree. What about the NOT doable though?


Here's where the "extension" bites us: if the Qt equivalent offered
something that upstream is not offering, and we can't reimplement it, then
what do we do? Dropping support for it would be, at best, an API break; and
at worst, a _silent_ behavioural change.

Proactively preventing a possible future API break by removing things
immediately is a questionable approach. Taken to the extreme this means
each and every bit of Qt should be removed as otherwise it might break API
at some time.

I'm not sure what you mean by this. When is "immediately" here?


This is exactly the case of what happened with QtAlgorithms. I believe the
culprit back then was the usage of qSwap / qLess or so into the algorithms
themselves (don't remember all the details; also this was pre C++11, and
using detection idioms and SFINAE to work around this would've been another
major fun -- file it under "development investment").

Long story short, making qSort() call std::sort() might not have kept the
behaviour contract with the user.

*shrug*

And what if I, as a user, would not care?

Come on, this is not an excuse. Just because it doesn't break *your* code it doesn't mean it won't break others. (And we KNOW of the behavioural changes involved.)



What about https://valdyas.org/fading/hacking/happy-porting/

    "[...] none, not a single one of all of the reasons you want to deprecate
    Q_FOREACH is a reason I care even a little bit about. It’s going to
    be deprecated? Well, that’s a decision, and a dumb one. It doesn’t
    work on std containers, QVarLengthArray or C arrays? I don’t use
    it on those. It adds 100 bytes of text size? Piffle. It makes it hard
    to reason about the loop for you? I don’t care.

    What I do care is the 1559 places where we use Q_FOREACH in Krita.
    Porting this will take weeks. [...]"

?

Isn't how to cover this kind of cases the whole point of the original post of the thread?

(I won't discuss Q_FOREACH deprecation *itself*; assume it's an API "XYZ" that got deprecated, and of course it's got users who are going to complain, and I keep asking how do we minimize that.)


Is that break acceptable? Is it not acceptable? It's debatable, as usual;
but please don't give me the "who in their minds overloads qSwap / qLess /
qFoobar anyhow?". When it comes to fundamental stuff in QtCore (containers,
algorithms, etc.) I'd like to stay on the conservative side; and therefore
the decision, in the end, was to deprecate QtAlgorithms rather than porting
them over stdlib ones.

(If you want, it's a corollary of Hyrum's law. The lower you are a software
stack, the bigger is your number of users => and Hyrum follows...)


Now, if everyone is unhappy and reimplements QtAlgorithms in their own
projects, I guess that was the wrong decision? Are we committing it all over
again when Qt 6 comes and we drop many deprecated APIs? Should we think
about a Qt5Support module, without API/ABI promises, where to dump things
without deprecation warnings, just a big bold writing on top "no guarantees
are given for these things"?

We won't find consensus here.

... why not? Can at least discuss the preferred options before saying that there isn't a consensus? :)


QT_I_DO_NO_CARE_ABOUT_ABI_BUT_I_CARE_ABOUT_SOURCE_COMPATIBILITY would be a
good starting point for all my personal use cases. For other it isn't.

What I see happening is that projects simply stick for longer with older
versions of Qt the more effort the upgrade is. These are practically
cold forks, fragmenting the ecosystem. Needlessly, if you ask me.

Wait, what? Two seconds before you were advocating for those breaks (as they were not touching YOUR code), now you do care about them?

My 2 c,
--
Giuseppe D'Angelo | giuseppe.dang...@kdab.com | Senior Software Engineer
KDAB (France) S.A.S., a KDAB Group company
Tel. France +33 (0)4 90 84 08 53, http://www.kdab.com
KDAB - The Qt, C++ and OpenGL Experts

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

_______________________________________________
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development

Reply via email to