Skip to content
This repository has been archived by the owner on Mar 5, 2023. It is now read-only.

PersonListPanel#personListView: revert type change #796 #818

Merged
merged 3 commits into from
Mar 19, 2018

Conversation

Zhiyuan-Amos
Copy link
Contributor

@Zhiyuan-Amos Zhiyuan-Amos commented Feb 4, 2018

Fixes #796.

personListView is of type ListView<PersonCard>. We use EasyBind library
to map the Person objects to PersonCard objects. The mapping / applying
of Function<? super F, ? extends E> occurs only when either get(int) or
getRemoved() methods are called[1]; the creation of PersonCard objects
occur only when either of these methods are called.

The ClearCommand deletes all Person objects. When we have large number
of persons and getRemoved() is called, all the corresponding cards
will be created prior to them being removed. As creation of PersonCard
objects are costly, the app slows down tremendously.

Let's revert ListView<PersonCard> to ListView<Person>.
PersonListViewCell will create the PersonCard object. According to
javadoc for Cell that "it is not feasible to create an actual Cell for
every single item in the control. We represent extremely large data
sets using only very few Cells. Each Cell is "recycled", or reused."[2]
A Cell is created for every row in the ListView that is displayed on
the scene i.e. that is visible to the user, and additional Cells may be
created for efficient scroll handling.[3] This implies that there will
only be about 10 Cells at any point in time since the default screen
size is only large enough to display 10 Cells. Therefore, there will
only be about 10 PersonCard objects at any point. Creation of 10
PersonCard objects is performed in negligible time, thus the app no
longer slows down. This commit is performed by reverting from
75cbfa3.

Also, since PersonCard objects are only created when the card is
displayed on the list view, let's teach
GuiTestAssert#assertListMatching(PersonListPanelHandle, Person...) and
AddressBookSystemTest#assertSelectedCardChange(Index) to navigate to
the card that they are verifying before performing the verification.

[1]: https://github.com/TomasMikula/EasyBind/blob/master/src/main/java/org/fxmisc/easybind/MappedList.java
[2]: https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/Cell.html
[3]: https://stackoverflow.com/questions/18159303/listview-in-javafx-adds-multiple-cells

assertCardDisplaysPerson(expectedPerson, actualCard);
assertEquals(Integer.toString(i + 1) + ". ", actualCard.getId());
assertEquals(expectedPerson, actualPerson);
// Because we do not have the actual card, we cannot compare the index on the card
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a side effect of changing from ListView<PersonCard> to ListView<Person>; we cannot get the actual PersonCard and the corresponding PersonCardHandle :/ Not quite sure how to fix this though. Prior to 75cbfa3, the following code is being used to retrieve the PersonCard nodes.

private Set<Node> getAllCardNodes() {
    return guiRobot.lookup(CARD_PANE_ID).queryAll();
}

However, this code doesn't really get all the card nodes, because the PersonCard objects are only created when required; if we have 9999 PersonCard objects and the ListView currently displays from indices 1 to 5, then only the first 5 PersonCard objects are created. As such, we cannot get the 1000th PersonCard node, for example. So in this case, there's dependency on line 37 (personListPanelHandle.navigateToCard(TYPICAL_PERSONS.get(i))): By navigating to the card, you ensure that the PersonCard object is created, so you are able to find it using getAllCardNodes().

Not sure if there's a better way to do this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@yamgent need your thought on this too :)

Copy link
Member

Choose a reason for hiding this comment

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

As spoken, I guess the dependency is necessary, otherwise the person card verification is nonsense. :P

@CanIHasReview-bot
Copy link

v1

@Zhiyuan-Amos submitted v1 for review.

(📚 Archive)

Checkout this PR version locally
git fetch https://github.com/se-edu/addressbook-level4.git refs/pr/818/1/head:BRANCHNAME

where BRANCHNAME is the name of the local branch you wish to fetch this PR to.

@Zhiyuan-Amos
Copy link
Contributor Author

Ah, forgot to add regression tests.

@CanIHasReview-bot
Copy link

v2

@Zhiyuan-Amos submitted v2 for review.

(📚 Archive) (📈 Interdiff between v1 and v2)

Checkout this PR version locally
git fetch https://github.com/se-edu/addressbook-level4.git refs/pr/818/2/head:BRANCHNAME

where BRANCHNAME is the name of the local branch you wish to fetch this PR to.

@yamgent
Copy link
Member

yamgent commented Feb 5, 2018

When I first saw the number of line changes, I had a shock of my life. :P

I am not sure whether we should explore generating 9999persons.xml on the fly locally, rather than uploading the big file to the repository...

@yamgent
Copy link
Member

yamgent commented Feb 6, 2018

Btw is the revert based on a certain commit? (i.e. you did a git revert <sha>)

@yamgent yamgent self-requested a review February 6, 2018 03:03
@Zhiyuan-Amos
Copy link
Contributor Author

When I first saw the number of line changes, I had a shock of my life. :P
I am not sure whether we should explore generating 9999persons.xml on the fly locally, rather than uploading the big file to the repository...

Oh yes you are right. In DeveloperGuide we have this:

Open a console and run the command gradlew processResources (Mac/Linux: ./gradlew processResources). It should finish with the BUILD SUCCESSFUL message.
This will generate all resources required by the application and tests.

So we should generate the .xml file as part of processResources?

Btw is the revert based on a certain commit? (i.e. you did a git revert )

Yup it's based on a certain commit. Do I need to mention it as part of commit message? Cos there were additional changes apart from just reverting.

@yamgent
Copy link
Member

yamgent commented Feb 8, 2018

Yup it's based on a certain commit. Do I need to mention it as part of commit message? Cos there were additional changes apart from just reverting.

As spoken, yes, you might also want to mention the additional changes made after reverting the commit, so that we can verify and understand your flow.

@Zhiyuan-Amos
Copy link
Contributor Author

I am not sure whether we should explore generating 9999persons.xml on the fly locally, rather than uploading the big file to the repository...

Since it's 1MB, I wonder if it's considered as too big and whether we can just upload it to GitHub :P

Copy link
Member

@yamgent yamgent left a comment

Choose a reason for hiding this comment

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

Minor commit message amendements:

[2/3]

PersonCard#person is no longer accessed by the world.
no longer accessed by anyone

[3/3]

Let’s remove it. Also, let’s update README to reflect this change.
... update README**.md**...?

@pyokagan
Copy link
Contributor

pyokagan commented Feb 8, 2018

@yamgent

I am not sure whether we should explore generating 9999persons.xml on the fly locally, rather than uploading the big file to the repository...

Yes, imagine what happens when we add a new field to the Person class and need to update all 9999 entries in the test file. :-)

@Zhiyuan-Amos Zhiyuan-Amos force-pushed the 796-regression branch 2 times, most recently from 57e1668 to 593723c Compare February 8, 2018 13:44
@CanIHasReview-bot
Copy link

v3

@Zhiyuan-Amos submitted v3 for review.

(📚 Archive) (📈 Interdiff between v2 and v3)

Checkout this PR version locally
git fetch https://github.com/se-edu/addressbook-level4.git refs/pr/818/3/head:BRANCHNAME

where BRANCHNAME is the name of the local branch you wish to fetch this PR to.

Copy link
Member

@eugenepeh eugenepeh left a comment

Choose a reason for hiding this comment

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

[2/3]
Commit message nits:

The ClearCommand deletes all Person objects. getRemoved() is called,
and when we have 9999 persons in the addressbook, all the corresponding
cards are created.

When we have large number of persons and getRemoved() is called, all the corresponding cards were created prior to the deletion.
As creation of PersonCard objects are costly, the
app slows down tremendously.

Does this sounds better?

f.write('<email>a@a</email>\n')
f.write('<address>a</address>\n')
f.write('</persons>\n')
f.write('</addressbook>\n')
Copy link
Member

Choose a reason for hiding this comment

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

shouldn't this file deserve its own commit prior to this commit?
That way reviewer can compare to the performance before and after as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh I thought that what was mentioned in the issue is sufficient; the issue describes the problem while the PR resolves the problem? ^^

Copy link
Member

Choose a reason for hiding this comment

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

Hmm okay... then I will have to copy this file to the previous commit to see the improvement >_>

Copy link
Member

@eugenepeh eugenepeh left a comment

Choose a reason for hiding this comment

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

[1/3]

Here I abit don't get it. Doesn't the selection of the card triggers the selected event?

@Zhiyuan-Amos
Copy link
Contributor Author

Here I abit don't get it. Doesn't the selection of the card triggers the selected event?

Yup the selection of the card will automatically post a card selected event. There's a difference between navigate and select: navigation causes your list view to shift to the card, while select... selects the card. XD

@Zhiyuan-Amos
Copy link
Contributor Author

@eugenepeh I edited your commit message suggestion slightly, ok with you?

The ClearCommand deletes all Person objects. When we have large number of persons and getRemoved() is called, all the corresponding cards were will be created prior to them being removed deletion. As creation of PersonCard objects are costly, the app slows down tremendously.

@eugenepeh
Copy link
Member

eugenepeh commented Feb 12, 2018

Yup the selection of the card will automatically post a card selected event. There's a difference between navigate and select: navigation causes your list view to shift to the card, while select... selects the card. XD

In that case, do we still need the selection change event? o_o

@Zhiyuan-Amos
Copy link
Contributor Author

In that case, do we still need the selection change event? o_o

Oh yes, an event is posted when a card is selected is because of this code in PersonListPanel:

private void setEventHandlerForSelectionChangeEvent() {
personListView.getSelectionModel().selectedItemProperty()
.addListener((observable, oldValue, newValue) -> {
if (newValue != null) {
logger.fine("Selection in person list panel changed to : '" + newValue + "'");
raise(new PersonPanelSelectionChangedEvent(newValue));
}
});
}

The reason why I didn't want navigateToCard(Person) to select the card is that in [2/3], this method will be called at the start of the system tests to navigate through all the cards (see paragraph 4 of [2/3]). If I select the card during navigation, then it causes the BrowserPanel to load someone's page, which causes the default state of the app to be modified.

So that's why I need commit [1/3]. However, I chose not to put the above reason as part of commit message in [1/3] because there's no need to do so, since there's sufficient reasons for removing it on its own already.

@eugenepeh
Copy link
Member

The reason why I didn't want navigateToCard(Person) to select the card is that in [2/3], this method will be called at the start of the system tests to navigate through all the cards (see paragraph 4 of [2/3]). If I select the card during navigation, then it causes the BrowserPanel to load someone's page, which causes the default state of the app to be modified.

Hmm okay... but in that case, the selectionchanged will be redundant now isn't it? Is there any other methods that cause selectionchanged other than user click on the card itself?

@Zhiyuan-Amos
Copy link
Contributor Author

Hmm okay... but in that case, the selectionchanged will be redundant now isn't it? Is there any other methods that cause selectionchanged other than user click on the card itself?

As in whether we need this class PersonPanelSelectionChangedEvent? We still need it because BrowserPanel catches this event to load the person :P

The following code is called when user executes SelectCommand :P

private void scrollTo(int index) {
Platform.runLater(() -> {
personListView.scrollTo(index);
personListView.getSelectionModel().clearAndSelect(index);
});
}

@yamgent
Copy link
Member

yamgent commented Feb 13, 2018

Sorry I missed out on this PR, go ahead and make the changes first.

@Zhiyuan-Amos
Copy link
Contributor Author

@eugenepeh

[1/3] Here I abit don't get it. Doesn't the selection of the card triggers the selected event?

Should I still update [1/3] commit message? ^^

@CanIHasReview-bot
Copy link

v11

@Zhiyuan-Amos submitted v11 for review.

(📚 Archive) (📈 Interdiff between v10 and v11)

Checkout this PR version locally
git fetch https://github.com/se-edu/addressbook-level4.git refs/pr/818/11/head:BRANCHNAME

where BRANCHNAME is the name of the local branch you wish to fetch this PR to.

@Zhiyuan-Amos
Copy link
Contributor Author

Zhiyuan-Amos commented Mar 17, 2018

Edit: I increased the test timings as the performance test was sometimes failing on Travis.

@CanIHasReview-bot
Copy link

v12

@Zhiyuan-Amos submitted v12 for review.

(📚 Archive) (📈 Interdiff between v11 and v12)

Checkout this PR version locally
git fetch https://github.com/se-edu/addressbook-level4.git refs/pr/818/12/head:BRANCHNAME

where BRANCHNAME is the name of the local branch you wish to fetch this PR to.

Copy link
Member

@yamgent yamgent left a comment

Choose a reason for hiding this comment

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

No other objections.

@Zhiyuan-Amos
Copy link
Contributor Author

@damithc for your review again as I've made quite a bit of changes since your previous approval.

Copy link
Contributor

@damithc damithc left a comment

Choose a reason for hiding this comment

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

A cosmetic nit. Can merge after that.

* 2. If {@code TestTimedOutException} is thrown after the logs are printed, then the failure occurs during the
* creation and deletion of the person cards.
*/
// Causes test to fail-fast; guiRobot#interact(Runnable) only returns after the Runnable completes execution.
Copy link
Contributor

Choose a reason for hiding this comment

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

The comment can be clearer: what causes test to fail fast? the timeout? e.g.,

The timeout makes the test fail fast. Without it, the test can stall for a long time because ...

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, I'm not sure if javadoc tools allows normal comments between javadoc and the method.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, I'm not sure if javadoc tools allows normal comments between javadoc and the method.

Yup, verified that having normal comments between javadoc and the method won't interfere with the generation of the javadoc.

image

Also, @damithc I've updated the header comments with the html tags to format it to look as above, otherwise it will be in a single paragraph. Is it ok?

Edit: ignore the double 1. 1. and 2. 2., I've fixed the header comments to display only a single 1. and 2..

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks good 👍

* <li>
* If {@code TestTimedOutException} is thrown before the logs are printed, then the failure occurs during
* the preparation of the test (creating the xml file containing the large number of persons).
* </li>
Copy link
Contributor

Choose a reason for hiding this comment

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

Like this will work too (fewer lines needed):

*     <li>If {@code TestTimedOutException} is thrown before the logs are printed, then the failure occurs during
*         the preparation of the test (creating the xml file containing the large number of persons).</li>

@CanIHasReview-bot
Copy link

v13

@Zhiyuan-Amos submitted v13 for review.

(📚 Archive) (📈 Interdiff between v12 and v13)

Checkout this PR version locally
git fetch https://github.com/se-edu/addressbook-level4.git refs/pr/818/13/head:BRANCHNAME

where BRANCHNAME is the name of the local branch you wish to fetch this PR to.

navigateToCard(Person) navigates to the card containing the person
passed in as parameter, and selects the card.

The selection of the card is an unexpected behaviour as it is not
clear from the naming of the method. Also, there’s no need for this
method to select the card.

Let’s update this method to no longer select the card that it navigates
to.
personListView is of type ListView<PersonCard>. We use EasyBind library
to map the Person objects to PersonCard objects. The mapping / applying
of Function<? super F, ? extends E> occurs only when either get(int) or
getRemoved() methods are called[1]; the creation of PersonCard objects
occur only when either of these methods are called.

The ClearCommand deletes all Person objects. When we have large number
of persons and getRemoved() is called, all the corresponding cards
will be created prior to them being removed. As creation of PersonCard
objects are costly, the app slows down tremendously.

Let's revert ListView<PersonCard> to ListView<Person>.
PersonListViewCell will create the PersonCard object. According to
javadoc for Cell that "it is not feasible to create an actual Cell for
every single item in the control. We represent extremely large data
sets using only very few Cells. Each Cell is "recycled", or reused."[2]
A Cell is created for every row in the ListView that is displayed on
the scene i.e. that is visible to the user, and additional Cells may be
created for efficient scroll handling.[3] This implies that there will
only be about 10 Cells at any point in time since the default screen
size is only large enough to display 10 Cells. Therefore, there will
only be about 10 PersonCard objects at any point. Creation of 10
PersonCard objects is performed in negligible time, thus the app no
longer slows down. This commit is performed by reverting from
75cbfa3.

Also, since PersonCard objects are only created when the card is
displayed on the list view, let's teach
GuiTestAssert#assertListMatching(PersonListPanelHandle, Person...) and
AddressBookSystemTest#assertSelectedCardChange(Index) to navigate to
the card that they are verifying before performing the verification.

[1]: https://github.com/TomasMikula/EasyBind/blob/master/src/main/java/org/fxmisc/easybind/MappedList.java
[2]: https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/Cell.html
[3]: https://stackoverflow.com/questions/18159303/listview-in-javafx-adds-multiple-cells
EasyBind is no longer used in our code base.

Let’s remove it. Also, let’s update README.md to reflect this change.
@CanIHasReview-bot
Copy link

v14

@Zhiyuan-Amos submitted v14 for review.

(📚 Archive) (📈 Interdiff between v13 and v14)

Checkout this PR version locally
git fetch https://github.com/se-edu/addressbook-level4.git refs/pr/818/14/head:BRANCHNAME

where BRANCHNAME is the name of the local branch you wish to fetch this PR to.

@Zhiyuan-Amos
Copy link
Contributor Author

Changelog: Rebased off master after merging #837, otherwise Travis fails.

@Zhiyuan-Amos Zhiyuan-Amos merged commit a4ef522 into se-edu:master Mar 19, 2018
@Zhiyuan-Amos Zhiyuan-Amos deleted the 796-regression branch March 19, 2018 13:32
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants