Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Components ES6 rewrite with improvements #4550

Draft
wants to merge 15 commits into
base: main
Choose a base branch
from

Conversation

Swiftb0y
Copy link
Member

@Swiftb0y Swiftb0y commented Dec 5, 2021

Reopen #4171 with Be-ing#56 on top.

In the old PR, there is still a review from @Holzhaus which has not been addressed, though I plan to take care when I find the time.

@ywwg
Copy link
Member

ywwg commented Dec 5, 2021

We should really be adding tests to our javascript corpus just like the rest of our codebase. Rather than commit this large PR all at once, I'd prefer to commit this a piece at a time, starting with just the base component class and accompanying tests that demonstrates its correctness, including communication with control objects and midi send/receive. As a side-benefit, the test would also help serve as a way for controller writers to see how the library is supposed to be used.

I had done some minor refactoring to make it easier to write controller tests here, but it was rejected because it was based on the old controller model: #3074. (But it also might be better to do the tests in native javascript, anyway)

@Swiftb0y
Copy link
Member Author

Swiftb0y commented Dec 5, 2021

IMO there are more pressing priorities for the controller right now. Before spending time adding the infrastructure to add tests, we should rather work on a newer mapping engine. Transitioning to QJSEngine was just the first part. Now we desperately need to get rid of the manual handler registration via XML and making ES6 Modules usable. From that point, adding tests is likely a matter of shipping a pre-made established library. However, before spending time on the controller engine, we should rather focus on Qt6 and thus the new QML UI...

So what I'm trying to say is that there are more pressing issues right now and thus I'd like to keep the scope of this PR still as small as possible. This is mostly intended as a follow up PR to the QJSEngine transition which gave us ES7 support, so our APIs should leverage that. The functional changes are very minimal. As a consequence, I'd really like to get this into 2.4 (if I manage to to finish it in time).

@Swiftb0y Swiftb0y marked this pull request as draft December 5, 2021 20:35
@ywwg
Copy link
Member

ywwg commented Dec 5, 2021

Can you at least use git mv so it's clear what is the same as the old file and what's new? As it is now it looks like 1100 lines of new code and it's not really feasible to review that much at once. I can't just assume that it's a noop change without any sort of indication of testing or correctness.

@ywwg
Copy link
Member

ywwg commented Dec 5, 2021

In general I'm not convinced by claims that we have "more important things to do than write tests." Code is code and if we want Mixxx to remain stable, all code needs to be tested. I spend a lot of time fixing regressions, and that all subtracts from whatever new feature work I might want to do. I am all for making ES6 classes usable, but if we're writing a library component that people are going to rely on, it needs some basic test coverage.

@Be-ing
Copy link
Contributor

Be-ing commented Dec 5, 2021

@ywwg Refusing to review code because it's above your arbitrary code size threshold while demanding to drastically expand the scope of PRs is toxic. Likewise, pointing fingers at people for introducing minor regressions while cleaning up old code is toxic and shows a disrespect for the hard work of others. If you think hacking a testing framework into a legacy architecture is more important than moving to Qt6, well, have fun taking care of a dying application that still depends on Qt5 when the world is moving onto Qt7.

@Swiftb0y
Copy link
Member Author

Swiftb0y commented Dec 5, 2021

Can you at least use git mv so it's clear what is the same as the old file and what's new?

We still have to ship the 0.0 version since many existing controller mappings depend on it.
The file here is a new version that got reiterated on (with some breaking changes since the new syntax is already a breaking change). using git mv does not make sense here. If you want to see the differences between the 0.0 and 0.1 version, I advise you to just diff the different files locally.

In general I'm not convinced by claims that we have "more important things to do than write tests." Code is code and if we want Mixxx to remain stable, all code needs to be tested.

I generally agree, please don't get me wrong, I was not arguing against testing. I was saying that introducing the ability to even write tests is not worth the effort right now. Especially considering that most of the code is already "battletested" from the previous iteration.

@Swiftb0y
Copy link
Member Author

Swiftb0y commented Dec 5, 2021

@Be-ing, while I appreciate you are voicing your opinion here, please be more respectful. Owen does not have any obligation to review this PR, if he doesn't want to spend the time on reviewing either someone else will review this or this PR will start rotting like the rest of the 120 PRs.
@ywwg I'd still very much appreciate your input on this though. This is the opportunity for breaking changes so this is where we could start integrating features from your own JS library.

@Be-ing
Copy link
Contributor

Be-ing commented Dec 5, 2021

Of course, nobody has an obligation to review any particular PR. What I am taking issue with is this behavior of commenting on a PR to explicitly refuse to review it while simultaneously demanding to drastically expand its scope. If you don't want to review it, just don't review it and leave it to people who are interested in it.

@Be-ing
Copy link
Contributor

Be-ing commented Dec 5, 2021

The new commits look fine to me. I leave it to @Holzhaus to follow up on his prior review.

@Be-ing
Copy link
Contributor

Be-ing commented Dec 5, 2021

By the way, thank you for the small, easy to review, self-contained commits with clear commit messages.

@ywwg
Copy link
Member

ywwg commented Dec 6, 2021

@Swiftb0y , my worry is that it never seems to be a good time to write tests. I honestly can't think of a better time to do so then when we're rewriting a library -- the workings of the code is in your mind and there is nothing depending on it yet (right?). I know there's a lot more exciting things to do but at some point we need to pay down this technical debt.

As for the library itself, the main reason I wanted to write mine was to separate the action of a button from the midi control it is connected to. A button is two parts: the physical hardware with input and output, and the action that it takes and status that it gives. With my little controller, buttons needed to have up to four different modes for a single piece of hardware. I don't believe the current components library supports that level of indirection. (An example from a non-custom hardware -- the Reloop MIXTOUR has three different shift buttons, and knobs and buttons take different actions depending which one is held).

So in my library, the physical button can have a multitude of modes, and depending which layer is selected, the different modes will be active or ignored. The actual implementation leaves something to be desired, but it's more flexible than the components library.

@ywwg
Copy link
Member

ywwg commented Dec 6, 2021

as for "increasing scope", I'm asking for the scope to be reduced -- Ideally we'd commit this file just starting with the base class and the button class and a few simple tests. then we add a few more subclasses.... and it would get pretty mechanical and move quickly. There is the initial hurdle to write the first test, but that will pay off for all of our js files that need testing

@ywwg
Copy link
Member

ywwg commented Dec 6, 2021

something like https://jestjs.io/

@Swiftb0y
Copy link
Member Author

Swiftb0y commented Dec 6, 2021

my worry is that it never seems to be a good time to write tests.

I can understand that, but now is not only not the time but the arguments for doing it now have decreased weight:

I honestly can't think of a better time to do so then when we're rewriting a library -- the workings of the code is in your mind and there is nothing depending on it yet (right?).

Well this is not a full rewrite (the commit message is misleading). The behavioral aspects are the same (compare existing version with the new one). The main reason for this PR is that we modernize the API to use the new features language available with QJSEngine (replacing prototypical inheritance with class syntax, using arrow functions where applicable, using for...of instead of raw loops, etc). At the moment, there are 0 functional changes compared to the old library.

My point is that I don't want to force creators of new mappings to use old JS patterns because our library mandates it. It raises the barrier to entry for ComponentJS users. That is why I really want this PR to go into 2.4 (so its released together with QJSEngine).

If we change existing code to add new features (rather than just adding a new component or fixing obvious bugs), then I'm also in favor of the gradual, test-centric approach, but making this a requirement for this PR does not make sense.

@Swiftb0y
Copy link
Member Author

Swiftb0y commented Dec 6, 2021

Thanks for your input in regards to what you'd like to see in a newer ComponentsJS version, we will consider them when doing an actual rewrite of the code.

@ywwg
Copy link
Member

ywwg commented Dec 6, 2021

ok, and I appreciate the work. Hopefully there is someone already familiar with this code who can review it.

@uklotzde
Copy link
Contributor

uklotzde commented Dec 6, 2021

I am not a JavaScript developer and do not qualify for reviewing this PR.

If someone is willing to set up tests for the JavaScript parts please do so instead of requesting them from someone else. It is out of scope of this PR.

@ywwg
Copy link
Member

ywwg commented Dec 15, 2021

Given the lack of anyone else being able to review this... I will give it a try. When it's ready for review please mark it Ready For Review and I'll do my best. thank you.

@Be-ing
Copy link
Contributor

Be-ing commented Dec 16, 2021

So I guess my review doesn't count? Nor does @Holzhaus' review? @ywwg you have a history of belittling others' reviews. It's not okay. Writing "thank you" immediately after pretending like others' work doesn't exist comes across really badly.

@Holzhaus
Copy link
Member

So I guess my review doesn't count? Nor does @Holzhaus' review? @ywwg you have a history of belittling others' reviews. It's not okay. Writing "thank you" immediately after pretending like others' work doesn't exist comes across really badly.

9 days ago, @ywwg said that he hopes someone finds the time to review this. The only reaction to that was @uklotzde who said he doesn't feel qualified to review it. Nobody reviewed it since then, and there is still 0 formal reviews on this PR.

So I agree with him that there currently is a "lack of people being able to review this", probably due to unfamiliarity with JS, time constraints, lack of motivation or other factors.

I appreciate that @ywwg wants to help to finish this PR and I don't feel belittled at all. His message sounded friendly to me.

Besides: 10 days ago you attacked @ywwg and said "Refusing to review code [...] is toxic" (which implies that you agree that another review makes sense btw). Now he agrees to review and you also attack him. I don't understand what you want.

@Be-ing
Copy link
Contributor

Be-ing commented Dec 16, 2021

I did review this yet @ywwg just posted "Given the lack of anyone else being able to review this". This is disrespectful.

I don't understand what you want.

I want @ywwg to stop insulting, gatekeeping, ignoring, and taking for granted others' work.

which implies that you agree that another review makes sense btw

Sure, another review could help if it is done respectfully, remains on topic/within scope, and makes an effort to understand context before passing judgement.

@Swiftb0y
Copy link
Member Author

Since the majority of the code is from you @Be-ing, merging this PR on the basis that you reviewed it is almost equivalent to merging your own PR.
Thank you @ywwg for offering to review this. I guess its reviewable in its current state. Any change can be added in separate PRs before the 2.4 release.

@Swiftb0y Swiftb0y marked this pull request as ready for review December 16, 2021 10:36
@Be-ing
Copy link
Contributor

Be-ing commented Dec 16, 2021

Since the majority of the code is from you @Be-ing, merging this PR on the basis that you reviewed it is almost equivalent to merging your own PR.

Not really, since you've reviewed it too. Not every PR needs 3-5 people picking it apart.

@Swiftb0y
Copy link
Member Author

I guess this is a gray area to be clarified in our contribution guidelines.

@ywwg
Copy link
Member

ywwg commented Dec 16, 2021

ok I'll take a look!

Copy link
Member

@ywwg ywwg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the type of review I would like to write... is this helpful? If this is a library we hope more people are going to use then I think we should work to make it friendlier. I find it hard to follow right now and I think some basic rearrangement, comment documentation, and renaming of some things will make it better.

res/controllers/midi-components-0.1.js Show resolved Hide resolved
res/controllers/midi-components-0.1.js Show resolved Hide resolved
res/controllers/midi-components-0.1.js Show resolved Hide resolved
res/controllers/midi-components-0.1.js Show resolved Hide resolved
};
Component.prototype.max = 127;
Component.prototype.shiftOffset = 0;
Component.prototype.sendShifted = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is where we should define this.midi so it's more clear how to use it, but perhaps this whole block should move to the top of the class. Again, my thinking is that we want to have the parts the programmer is most likely to change at the top of the file, and the internal guts at the bottom.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue is that there aren't really sensible default values for this.midi. Components might be used without outputting anything just to track some state or just for input handling (in the case for pots).
We could make this.midi explicit by Component.prototype.midi = [undefined, undefined] (essentially just declaring the property)?

Reorderings in general should be fine, sure.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this.midi can't be defined on the prototype. It is unique to each instance of Component.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be defined there, but each instance needs to overwrite it regardless, so defining it there does not make a whole lot of sense as already pointed out.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I once tried to move a property onto a prototype and have each instance override it, but that did not work because each instance was actually sharing the same data.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm ok. This may just be a limitation of javascript then?

Copy link
Member Author

@Swiftb0y Swiftb0y Dec 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I once tried to move a property onto a prototype and have each instance override it, but that did not work because each instance was actually sharing the same data.

Thanks for the insight. This seems rather strange and conflicts with some of my JS understanding, so I'll try to recreate the issue and look into what exactly is wrong here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't say that's a limitation. That's just how prototypes work. If you don't want that, just set a normal property, not the prototype's property, which is what the code already does.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say only spend a little time trying to make it work. We can work on it more later if needed. My goal with this review is to make this library a little more organized and comprehensible to someone who is new to it (me), not make it perfect.

Copy link
Member

@ywwg ywwg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK I've finished going through the file. The effect section is particularly complex and it's hard to know what's going on, so I'd like to flag that for eventual cleanup and testing. But mostly I think it shouldn't be too much work to make some noticeable improvements.

thanks again for working on this.

res/controllers/midi-components-0.1.js Show resolved Hide resolved
res/controllers/midi-components-0.1.js Show resolved Hide resolved
res/controllers/midi-components-0.1.js Show resolved Hide resolved
};
Component.prototype.max = 127;
Component.prototype.shiftOffset = 0;
Component.prototype.sendShifted = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say only spend a little time trying to make it work. We can work on it more later if needed. My goal with this review is to make this library a little more organized and comprehensible to someone who is new to it (me), not make it perfect.

return value > 0;
}
input(channel, control, value, status, _group) {
if (this.type === undefined || this.type === Button.types.push) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this be done with a switch statement? I think that would be more readable.

res/controllers/midi-components-0.1.js Show resolved Hide resolved
this.toggle = function() {
// cycle through unitNumbers array
let index = this.unitNumbers.indexOf(this.currentUnitNumber);
if (index === (this.unitNumbers.length - 1)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mod trick again

res/controllers/midi-components-0.1.js Show resolved Hide resolved
if (colors !== undefined) {
this.color = colors.unfocused;
}
this.group = "[EffectRack1_EffectUnit" +
Copy link
Member

@ywwg ywwg Dec 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we see this building of the group name a few times -- can we factor that out into a function effectGroupName() or some sort?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the last bit of low-hanging fruit we can do now. Does that seem reasonable?

}
this.pressedWhenParametersHidden = true;
}
} else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the nesting gets very deep here. Where possible, can you do

if { 
  ... 
  return;  
 }
...

instead of:

if {
...
} else {
...
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I'm also favoring early returns, this was just not my code to begin with, but I can change it now surely.

@Swiftb0y Swiftb0y requested a review from ywwg December 22, 2021 20:54
Copy link
Member

@ywwg ywwg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for discussing these issues with me. I resolved most of the issues and there's just a couple more things we talked about that should be easy to do. It's good to have a more solid idea of where we need to take this library to make it better!

super.connect();
if (this.group !== undefined && this.colorKey !== undefined) {
// TODO (Swiftb0y): replace with arrow function once https://bugreports.qt.io/browse/QTBUG-95677 got fixed
this.connections[1] = engine.makeConnection(this.group, this.colorKey, function(color) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am ok with making this a TODO as well -- we should come up with some way of handling connections that doesn't rely so much on callers doing the right thing.

if (colors !== undefined) {
this.color = colors.unfocused;
}
this.group = "[EffectRack1_EffectUnit" +
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the last bit of low-hanging fruit we can do now. Does that seem reasonable?

@github-actions
Copy link

This PR is marked as stale because it has been open 90 days with no activity.

@github-actions github-actions bot added the stale Stale issues that haven't been updated for a long time. label Mar 27, 2022
@github-actions github-actions bot removed the stale Stale issues that haven't been updated for a long time. label Sep 1, 2023
@christophehenry
Copy link
Contributor

This looks abandonned. Is there a reason?

@Swiftb0y
Copy link
Member Author

no time / interested from me atm. you're welcome to pick this up if you'd like.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants