Skip to content

Conversation

ghost
Copy link

@ghost ghost commented Jan 10, 2018

be warned though, several days ago an account named skylot appeared out of nowhere on my profile stars;
I contacted support, but they couldn't tell me anything but to change my password;
here, have a look: https://github.com/skylot
someone, who has a decompiler as project; oh my god, that's far beyond my skill level

tried to attend to the highlighted items, guided by the IDE
for (DataObject dob:DataObject.getRegistry().getModified()) {
SaveCookie cookie = dob.getCookie(SaveCookie.class);
for (DataObject dataObject : DataObject.getRegistry().getModified()) {
SaveCookie cookie = dataObject.getLookup().lookup(SaveCookie.class);
Copy link

@ghost ghost Jan 11, 2018

Choose a reason for hiding this comment

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

It appears there was a change here:

Before: dataObject.getCookie(SaveCookie.class)

After: dataObject.getLookup().lookup(SaveCookie.class)

Copy link
Contributor

Choose a reason for hiding this comment

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

getLookup().lookup(SaveCookie.class) is the proper way.

Copy link

Choose a reason for hiding this comment

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

Oh, okay. Corroborating, I see that NetBeans provides an automatic fix which rewrites the getCookie() call to getLookup().lookup(SaveCookie.class).

@Override
public void stop(ProgressEvent event) {
// do not rely on plugins;
/* do not rely on plugins; */
Copy link

Choose a reason for hiding this comment

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

Why the change to a multiline comment?

Copy link
Author

Choose a reason for hiding this comment

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

If using the toggle comment feature with a hotkey, it will use single line comments on each line of the whole selected block. So, the thought was, that a multi-line comment would better reflect the true nature of a comment, and not just some blending out.

Copy link

Choose a reason for hiding this comment

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

Line comment was specifically invented for realy short notes and it's faster to type than /* - */ pair. I don't see a point to change it for one-liners. Maybe for long multilines.
It would be more useful to extend the toggle comment feature to:

  • make a block comment (maybe a different hotkey or an additional modifier)
  • turn block of line comments into block comment or vice versa

Whether to use multilines or block comments depend on personal or group development style - it's not a defect to fix.

Copy link
Author

@ghost ghost Jan 12, 2018

Choose a reason for hiding this comment

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

A different hotkey is not a good idea for me. I have reconfigured some actions to use the F1 to F12 keys. And since that is just not enough, I have started to use the Ctrl key in combination with some characters. Just so, that I can easily reach them both, with my left hand only, and without broken fingers. At this side of the keyboard there aren't much unused keys left for reconfiguration. And it would feel unnatural to use two different keystrokes for similar actions. The /**/ commentation mode is already used for documentation. Why not keep it like that, and use // mostly for partial code changes? Since "do not rely on plugins;" can not be evaluated by the compiler, I would recomment using /**/ commentation mode.

if (wrapper != null) {
unsetWrappers(commit, wrapper);
if (undoableWrapper != null) {
undoableWrapper.setActive(false, null);
Copy link

Choose a reason for hiding this comment

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

Should if (undoableWrapper != null) { undoableWrapper.setActive(false, null); } be within a finally block?

Copy link
Contributor

Choose a reason for hiding this comment

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

It's ok as it is.

wrapper.close();
for (Transaction commit : SPIAccessor.DEFAULT.getCommits(bag)) {
SPIAccessor.DEFAULT.sum(commit);
undoableWrapper.setActive(false, null);
Copy link

Choose a reason for hiding this comment

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

Similar to before, should undoableWrapper.setActive(false, null); be within a finally block?

Copy link
Author

Choose a reason for hiding this comment

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

It was not before. Probably it will be of use, if you explain it to me.

Copy link

Choose a reason for hiding this comment

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

Sorry, I was unclear. By "similar to before", I meant "similar to my previous comment up above".

Copy link
Author

Choose a reason for hiding this comment

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

My apologies. I'm not able to answer that question. I would add things without concrete knowledge about what I'm actually doing.

Copy link
Author

Choose a reason for hiding this comment

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

Which is very true.

}

while (it.hasPrevious()) {
undoableWrapper.close();
Copy link

Choose a reason for hiding this comment

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

Should undoableWrapper.close(); be within a finally block?

Copy link
Author

Choose a reason for hiding this comment

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

Probably. Under the circumstance, that the code from within line 228 to 232 throws an unexpected exception. I'm not sure, if that is even possible. But it is a potential pitfall. I like your approach.

}
});
if (undoableWrapper != null) {
undoableWrapper.close();
Copy link

Choose a reason for hiding this comment

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

Should if (undoableWrapper != null) { undoableWrapper.close(); } be within a finally block?

Copy link
Author

Choose a reason for hiding this comment

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

There are several nested try and finally block in the source. I haven't touched the overall structure of it.

long time = System.currentTimeMillis();

final long start = System.currentTimeMillis();
Iterator it = internalList.iterator();
Copy link

Choose a reason for hiding this comment

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

The type of it could be Iterator<RefactoringElementImplementation>.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's ok as it is.

Copy link

Choose a reason for hiding this comment

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

If this PR is to improve readability, it should use type params when possible to eliminate (unnecessary) typecasts. Please add it.

try {
ListIterator it = internalList.listIterator(internalList.size());
fireProgressListenerStart(0, internalList.size()+1);
ListIterator internalListIterator = internalList.listIterator(internalList.size());
Copy link

Choose a reason for hiding this comment

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

The type of internalListIterator could be ListIterator<RefactoringElementImplementation>. This should allow the type cast a few lines down to be removed.

Copy link
Author

Choose a reason for hiding this comment

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

It shall be done. Thank you!

if (element.isEnabled() && !((element.getStatus() == RefactoringElement.GUARDED) || (element.getStatus() == RefactoringElement.READ_ONLY))) {
element.undoChange();
}
RefactoringElementImplementation element = (RefactoringElementImplementation) internalListIterator.previous();
Copy link

@ghost ghost Jan 11, 2018

Choose a reason for hiding this comment

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

The type cast to RefactoringElementImplementation could be removed after parameterizing internalListIterator.

Copy link
Author

Choose a reason for hiding this comment

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

Well spotted. Not bad!

public Iterator<RefactoringElement> iterator() {
return new Iterator() {
//private final Iterator<RefactoringElementImplementation> inner = internalList.iterator();

Copy link

Choose a reason for hiding this comment

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

Maybe delete the trailing spaces as well?

Copy link
Author

Choose a reason for hiding this comment

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

It's a new anonymous inner class implementation, right? The members can be separated by a newline from the enclosing curly braces. But they don't have to?

Copy link

@ghost ghost Jan 12, 2018

Choose a reason for hiding this comment

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

I'm fine with the blank lines. It just looked like you were deleting end-of-line whitespace, so the 16 trailing spaces on the new line 350 could be deleted as well.

boolean enabled = element.isEnabled();
boolean guarded = element.getStatus() == RefactoringElement.GUARDED;
boolean readOnly = element.getStatus() == RefactoringElement.READ_ONLY;
if (enabled && !(guarded || readOnly)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Hi Carsten, this computes "enabled", "guarded" and "readOnly" even when "element.isEnabled()" is false. The original expression
element.isEnabled() && !((element.getStatus() == RefactoringElement.GUARDED) || (element.getStatus() == RefactoringElement.READ_ONLY))
does not, though.

Copy link
Author

Choose a reason for hiding this comment

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

Right, vieiro. I wanted to improve readability, and it resulted in a performance decrease. Haven't even noticed. My bad. Performance is also affected by the added private function call. Before the change, it was done with a redundant inlining of code. Which isn't to bad, but it is not easy to understand.

Copy link

Choose a reason for hiding this comment

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

you can count on private methods calls being inlined by optimizing VM, this is not counted as perf decrease.

You can also can

if (!element.isEnabled()) {
    return;
}
// ....
if (readOnly || guarded) {
    return;
}

or

if (!enabled || guarded || readOnly) {
    return;
}

Which saves you complex conditions and nested blocks.

@vieiro
Copy link
Contributor

vieiro commented Jan 11, 2018

Hi @cp7781. Thanks for the PR. Are these changes related to an issue? if so then would you please add an issue to JIRA?
Thanks,
Antonio

@ghost
Copy link
Author

ghost commented Jan 12, 2018

Thank you for speaking for me, Antonio Vieiro.

Copy link

@svatoun svatoun left a comment

Choose a reason for hiding this comment

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

Overall, I would rather avoid "beautification only" PRs like this. If one examines history later (when analyzing a bug), such "whitespace only" changes add processing time to verify that no semantic change was introduced.

There are only a few changes which in fact improve readability (simple loops onto forEach etc, curly braces in ifs).

boolean enabled = element.isEnabled();
boolean guarded = element.getStatus() == RefactoringElement.GUARDED;
boolean readOnly = element.getStatus() == RefactoringElement.READ_ONLY;
if (enabled && !(guarded || readOnly)) {
Copy link

Choose a reason for hiding this comment

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

you can count on private methods calls being inlined by optimizing VM, this is not counted as perf decrease.

You can also can

if (!element.isEnabled()) {
    return;
}
// ....
if (readOnly || guarded) {
    return;
}

or

if (!enabled || guarded || readOnly) {
    return;
}

Which saves you complex conditions and nested blocks.

UndoableWrapper undoableWrapper = MimeLookup.getLookup("").lookup(UndoableWrapper.class);
commits.forEach(commit -> {
if (undoableWrapper != null) {
undoableWrapper.setActive(true, this);
Copy link

Choose a reason for hiding this comment

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

Is there a reason to inline setWrappers ? Wouldn't it be better the other way around, to move null check into (un)setWrappers ?

long time = System.currentTimeMillis();

final long start = System.currentTimeMillis();
Iterator it = internalList.iterator();
Copy link

Choose a reason for hiding this comment

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

If this PR is to improve readability, it should use type params when possible to eliminate (unnecessary) typecasts. Please add it.

fileChange.performChange();
}
}
SPIAccessor.DEFAULT.getFileChanges(bag).stream().filter(fileChange -> fileChange.isEnabled()).forEachOrdered(fileChange -> fileChange.performChange());
Copy link

Choose a reason for hiding this comment

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

Well, I sort of doubt that this stream syntax improves readability over (more verbose) for or forEach. But please make a breakline between the individual processing steps, like this:

SPIAccessor.DEFAULT.getFileChanges(bag).stream().
    filter(fileChange -> fileChange.isEnabled()).
    forEachOrdered(fileChange -> fileChange.performChange());

Which can be usually scanned faster. Debugging of streamized code is a real pain, BTW.

Copy link
Author

Choose a reason for hiding this comment

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

You are right. Would prefer, if the dot is placed at the new line, in front of the method call.

Copy link

Choose a reason for hiding this comment

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

Right. I think that placing the dot first and indenting twice is more standard:

SPIAccessor.DEFAULT.getFileChanges(bag).stream()
        .filter(fileChange -> fileChange.isEnabled())
        .forEachOrdered(fileChange -> fileChange.performChange());

Copy link
Member

Choose a reason for hiding this comment

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

Yes, thanks. I have bad old habits

time = System.currentTimeMillis() - time;
timer.log(Level.FINE, "refactoringSession.doRefactoring", new Object[] { description, RefactoringSession.this, time } );
final long timeTaken = System.currentTimeMillis() - start;
timer.log(Level.FINE, "refactoringSession.doRefactoring", new Object[]{description, RefactoringSession.this, timeTaken});
Copy link

Choose a reason for hiding this comment

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

Considering most of the PR fixes whitespaces, there should be whitespaces before/after { to separate from type and array content, and before }.

Copy link
Author

Choose a reason for hiding this comment

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

I don't know, what a PR fix is. But to separate things, to get a better overview, seems to be a good idea.

}
UndoableWrapper wrapper = MimeLookup.getLookup("").lookup(UndoableWrapper.class);
SPIAccessor.DEFAULT.getCommits(bag).forEach(commit -> SPIAccessor.DEFAULT.check(commit, true));
UndoableWrapper undoableWrapper = MimeLookup.getLookup("").lookup(UndoableWrapper.class);
Copy link

Choose a reason for hiding this comment

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

// NOI18N marker missing.

Copy link
Author

Choose a reason for hiding this comment

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

There is no string, which needs to be translated. Why adding a comment?

Copy link

Choose a reason for hiding this comment

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

The // NOI18N indicates that the string does not need to be translated.

I believe that some devs have a plugin which places warnings on all strings that are not marked "NOI18N" as a way of verifying that all strings either do not need translation or are localizable.

public RefactoringElement next() {
if (index < internalList.size()) {
return new RefactoringElement(internalList.get(index++));
RefactoringElementImplementation implementation = internalList.get(index);
Copy link

Choose a reason for hiding this comment

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

Coding style in effect does not prohibit pre/postfix increments.

Copy link
Author

Choose a reason for hiding this comment

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

No. That was not the intention. Prefix or postfix operators make loops far more readable in less abstract languages. Java has inherited, adopted and changed the culture, how humans understand code.

Copy link
Member

Choose a reason for hiding this comment

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

OK, then why this change of one-liner return to 3 lines, when the original code did not violate coding conventions ?

Copy link
Author

Choose a reason for hiding this comment

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

I may have seen white rabbits. Changed it back, and no complaints at all. Sometimes, mysterious things happen, and I just try to get used to it, alright? You are right. Thank you for the support.

@geertjanw
Copy link
Member

A lot of people are spending a lot of time reviewing this pull request. It is unclear why this pull request exists. It seems this is a cosmetic refactoring of a random file in the Apache NetBeans Git repo. We do need to set up guidelines for pull requests and surely one of those will be that we need to have an issue number related to a pull request, i.e., an actual problem that we'd like to have fixed, before fixing it.

@ghost
Copy link
Author

ghost commented Jan 12, 2018

The project needs far more developers refactoring their work constantly. Especially at the core product. If the overall structure crumbles and falls, it will be just another waste of time in the history of mankind.

@ghost
Copy link
Author

ghost commented Jan 12, 2018

I think that fixing all of the warnings actually helps. When bug fixing, it is distracting to see all of the yellow warning indicator lines in the sidebar. It makes it more difficult to see what you've changed, as the light green, light blue, and pink added/changed/deleted indicator lines are hidden by the yellow lines. It also makes it more difficult to see the locations of breakpoints that you have set. For example, here is the bar for a file in which I have set two breakpoints and made changes to two parts of the file:
screen shot 2018-01-12 at 8 51 27 am

One other benefit to general cleanup (in particular, supplying type information on generics) is that it cuts down on the voluminous output of build warnings.

I have experimented with submitting the "cleanups" in the same patch as a bug fix (e.g. PR #287), but I don't like this approach. One must be in the mood for examining a lot of small changes that result from cleanup. This work is distracting from reviewing the meat of the patch.

@ghost
Copy link
Author

ghost commented Jan 12, 2018

Sure, cleanup also opens the possibility to oversimplify important parts. Chances are pretty good, that art and skilled craftsmanship end in the trash bin. Lost forever, because the translation of the translation, done by novices like me, without real responsibility, becomes to complicated. That is, what will happen. Either take it for granted, or keep your eyes open the whole night.

the refactoring methods work on three different class member 
collections, which all contain some sort of RefactoringElement;
it is not completely clear, why they are there, and what they are doing;
looks like file changes, commits, and a mysterious inner list;
one of the refactoring method is full of try and finally blocks, but
they don't catch exceptions by itself;
@vieiro
Copy link
Contributor

vieiro commented Jan 13, 2018

Hi,
Thanks for this PR. These changes seem to improve readability and maintainability, and not a real user problem, so I'm adding the "Cosmetics" label.
I'm also adding the "work in progress" label. Please request a review whenever you're done.
Thanks,
Antonio

@ghost
Copy link
Author

ghost commented Jan 13, 2018

Cosmetics sound pretty good. Don't they? It's not just fonts and stuff. Good morning, spain.

@ghost
Copy link
Author

ghost commented Jan 13, 2018

Can anyone tell me, were to get rid of that unit tests? I mean, now it looks like there is a reference somewhere, which needs to be fixed. And actually, I don't want to write unit tests for unit test routines, just because it means business.

@ghost
Copy link
Author

ghost commented Jan 13, 2018

I think 22e386e needs to be reverted, or please explain why you deleted those unit tests.

Also, I think 1ce564b is starting to go overboard. Some thoughts:

  • Changing

    fireProgressListenerStart(0, COMMIT_STEPS + commits.size() * COMMIT_STEPS + 1);

    to:

    {
        int count = COMMIT_STEPS + commits.size() * COMMIT_STEPS + 1;
        fireProgressListenerStart(0, count);
    }

    and the other similar changes are unnecessary, in my opinion. I like the introduction of a variable for the result of DataObject.getRegistry().getModified() because it was unclear that this has type DataObject[] instead of some type of Iterable; but, other introduced variables seem unnecessary.

  • I don't think that reallyDoRefactoring() and reallyUndoRefactoring() should be inlined. Don't get me wrong, I appreciate the reason why you did this. However, I think that the original pattern should be kept, as it is a perfectly acceptable pattern to use.

  • Arrays.asList(...).stream() can be replaced with Stream.of(...).

  • With the exception of the JavaDoc comment on performChange(), I think that the other new comments are unnecessary and should be removed.

One final thought: I think that commit messages should not be cutesy or contain jokes (e.g. "against the order of maw") because the developers working on this project come from different backgrounds and may not get all of the references. I had to search "order of maw" to figure out that it is a Warcraft reference (I think? still not sure...).

@ghost
Copy link
Author

ghost commented Jan 13, 2018

For now, I wouldn't mind those tests, Daniel. There is some package missing, or something. And it turns red, if the plugin is opened. Just want to fix that.

  • This computation of the count variable indeed looks really awkward. What exactly is getting computed?

    {
        int count = COMMIT_STEPS + commits.size() * COMMIT_STEPS + 1;
        fireProgressListenerStart(0, count);
    }

    The fireProgressListenerStep() method is getting called at line 117 and 163. Once in a loop over items in the internalList member variable, and once at the end of a try block. There seems to be no connection to the call of commits.size() in the code listing above. So, this part might be corrupted?

  • Using lambda expressions is an elegant way to streamline code. Before change, there were two private functions in place, which were both called just once. It not only clutters the navigator window, it also distracts attention away from the requirements.

  • Thank you for mentioning Stream.of(...).

  • Doctor, can you please help me? The people say, I'm an idiot, and they are constantly laughing at me.

Order of maw means breakfast. I had toast, honey and milk. And a nice girl was talking to me meanwhile. Life is just to good for waking up early.

@sdedic
Copy link
Member

sdedic commented Jan 13, 2018

Keep in mind that usage of Lambda expression also totally breaks fix-and-continue during debugging. It's a nice syntax suggar but until Hotspot folks fix the VM, class with lambdas does not allow to incrementally fix the code.

As for unit tests: they run on the master. So the only sane approach is to fix the code so that tests run again. But this PR is WIP, so OK. But before the PR is reviewed, I recommend to discard that commit from history.

The PR starts being hard to read, mixing (intentionally just) formatting changes with refactorings which actually have potential to break something. I recommend to separate those two actions into either separate commits, or separate PRs - it's easier to verify that refactoring did not change semantic if 90% of file is not whitespace-changed.

As for commit messages (personal opinion): I will not approve PR with messages like "for the queen", "fixing errors" (which actually deletes test code), or "order of maw". I believe that added confusion which outweights the fun of reading them.

@ghost
Copy link
Author

ghost commented Jan 13, 2018

Debugging, like making use of assert statements, is a relic of the past. Modern software in general has become far way to complex for being used with such features. But take it as my humble opinion. I've almost no idea, how a real project would look like, and what possibly can be done, if used cleverly by a true master.

@ghost
Copy link
Author

ghost commented Jan 14, 2018

So, just to make sure. The tags code-cleanup and work-in-progress seem to mark somewhat suspicious pull requests. You likely want to concentrate on other things; probably more useful stuff, than review and education. I will close this. Good luck!

@ghost ghost closed this Jan 14, 2018
This pull request was closed.
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.

5 participants