Skip to content

Latest commit

 

History

History
159 lines (90 loc) · 13.4 KB

CONTRIBUTING.md

File metadata and controls

159 lines (90 loc) · 13.4 KB

Contributing to WebLaF

First of all, thank you for taking the time to read this and potentially contribute to WebLaF project!

I am developing this project mostly alone and I try to keep releases as polished as they can be, but bugs or other potential problems are unavoidable and the sooner I know about them - the sooner I can deliver a fix and release new update containing it. So any kind of contribution to the project is welcome!

This document contains a set of guidelines that you might find useful. Those are just guidelines, not rules. Use your best judgment and feel free to propose changes to this document if you feel that it can be improved.

Issues

The easiest way to contribute to WebLaF project is opening a new issue which can be a:

  • Question
  • Bug report
  • Feature suggestion
  • Improvement suggestion
  • Wiki article request
  • Wiki article suggestion

And yes, I do consider any questions asked as valuable contribution to the library because if answered and solved - it might help other people to solve similar issue much faster in the future.

Any improvement or feature suggestions are just as I do want to expand WebLaF functionality as much as possible and make it as user-friendly as possible.

Question

If you got any question about WebLaF - I recommend checking wiki section of the project first. It contains multiple helpful articles that might answer your queston right away.

Otherwise - feel free to open new issue and ask about anything related to WebLaF - I'll do my best to answer your question as soon as possible.

Bug report

https://github.com/mgarin/weblaf/issues

If you found a bug and want to report it - I do recommend checking issues project section first to see if someone already submitted a similar request.

In case you are going to report a bug - there are a few things that are crucial for me to know:

  • WebLaF version you found it in
    For example: WebLaF v1.2.11

  • JDK type and version you are using to reproduce the bug
    In case with Open JDK - specify where particular build you are using can be found
    For example: Oracle JDK 14.0.1 or Open JDK 8 u262

  • OS type & version you are running your application on
    For example: Windows 10 or Mac OS X Catalina

Also if bug cannot be reproduced in demo app or on a basic component - please provide a SSCCE that can be used to reproduce it. The harder it is for me to reproduce the issue - the longer it will take to fix it.

Feature suggestion

Something is missing in WebLaF and you would like to see it added? - feel free to open an issue! Just make sure to describe how you would like to see it added into the library.

If it is a new component request -

  • What exactly is it and how should it work?
  • Any examples from other applications or libraries?
  • Anything specific you would like to be added to it?
  • Any particular ideas about the visual style?

If it is a new code feature -

  • What exactly is it and how should it work?
  • Are there any working implementations of that feature that you know of?
  • If yes, is it worth being added instead of using a 3rd-party library?
  • If yes, should it have it's own module or it's a small thing?

These questions should help you to shape your general idea you have into a more detailed issue request.

Improvement suggestion

You found some tangled code, some weirdly behaving component, inconsistent API or something else that you would like to see improved? - feel free to open an issue!

If you want to suggest a behavior/view change - simply describe how you see it and we will discuss it. Image or video examples are also welcome.

If you want to suggest a code change - you can check Pull Requests section below.

Wiki article request

If you want to ask me to write new wiki aricle:

If what you're looking haven't been mentioned/described yet - open an issue.

Wiki article suggestion

If you would like to write a wiki article:

  • Be clear about what feature you are describing and what use cases it has
  • Make sure to separate article into clear sections if it is large
  • Make sure to provide code examples and screenshots if necessary
  • Use GitHub markdown for the article content
  • Specify which WebLaF version this article is written for & modules necessary

Once you're done writing it - you can open an issue with the article content. I will review it, make adjustments if necessary and will add it to the project wiki section.

Pull Requests

Before writing any code please first discuss the changes you wish to make via issue, email, or Gitter with me (Mikle).

Thing is - Swing is simple and at the same time it's not. There are a lot of caveats both in Swing and WebLaF code and there are reasons why some things are made the way they are. Those reasons are not obvious sometimes. I appreciate the time you want to put into the project and don't want it to go to waste. So it is always best to discuss the changes you want to make first, especially considering they might already be in the project plan or even in development.

There are also a few other things you might want to know before writing any additions or improvements for WebLaF.

Code Philosophy

There are a few guidelines I'm trying to follow when writing WebLaF code, some I've "adopted" pretty early on while some other ones I've started following quite late, so library code is certainly not completely streamlined, but I'm working on it.

Note that these are just some basic things, but they can still heavily affect the resulting code and it's quality, so I strongly recommend checking this list:

  • Follow Java naming convetions
    That certainly helps keeping code more clean, streamlined and simply makes it more readable for other Java developers involved in the project. If you aren't sure how something should be named - feel free to ask!

  • Use fail-fast approach
    Do not try to sweep any critical exceptions under the rug. Fail-fast approach helps finding any potential issues early on and keep the code cleaner overall. Any exceptions you can't handle on the spot? - let them loose. There is not much point in ignoring exceptions that will cause UI to halt anyway - it will only make debugging the problem harder.

  • Avoid nulls whenever possible
    Obviously we're talking about Swing and there are countless cases where nulls are used as default values and whatnot, so it is impossible to avoid nulls completely. But whenever I'm writing a new code piece or a feature - I make it null friendly only when it is actually necessary or reasonable in the given context, otherwise I keep it null-less. And if it is hard to manage the amount of possible nulls coming from Swing or 3rd-party library - simply wrap them within your classes and throw appropriate exceptions whenever you encounter one.

  • Don't forget about Event Dispatch Thread
    All UI-related operations should be performed on EDT, no exceptions. That does limit performance, but that also allows you to simplify the code a lot since you can be sure that all UI-related operations are performed on the same thread and should never intersect. Such assumptions are made all across the Swing code and also present in WebLaF code.

  • Avoid unnecessary getters and setters
    Don't return more information from any class than necessary to use it. Even better solution - hide instance class completely behind an interface and provide any public APIs in that interface. Otherwise "everyone" end up having access to "everything" and it is really bad from a design standpoint. It is a bit different for Component classes because they need to provide getters and setters for all component settings, but that is more of an exception.

  • Always use single exit point for methods
    Some methods will get bigger, but it shouldn't matter. Those will still be a lot easier to read than a mess with 10+ return statements and twisted logic behind it. More return statements you have in your method - higher the chance that you or someone else will make a logical error trying to modify that method later on. This includes both - methods that have return value and void methods.

  • Use final for fields and and local variables that can be final
    It makes code a lot easier to read and understand when you don't have a million mutable fields. A good example: if your method must return something - create a final local variable at the start and assign value to it once in every possible conditional branch of the code, then return that variable once at the very end of the method.

  • Always use final for constructor and method arguments
    If you are going to modify value provided in method argument - copy it (or clone it) to local variable first and modify that one instead. This approach helps avoiding various issues and makes code easier to read and understand in the long run.

  • Use @NotNull and @Nullable annotations
    These annotations will make method and field use-cases clear and should also help you to decide when nulls are actually needed for the code itself and when they aren't. And as mentioned before - the less nulls code uses - the better.

  • Getters should return non-null values when possible
    Use getters for returning primarily non-null values and if you recieve a null value internally - simply throw an exception. In case you desperately need null value returned - think about naming method differently. For instance if you have a getValue() - rename it to findValue() or lookupValue() or loadValue() instead and make returned value @Nullable. With this approach you can also have both methods and chain them appropriately to avoid code duplication. Obviously this whole approach only applies to parts of the code that are not dictated by existing Swing or 3rd-party library code.

  • Classes marked as Serializable, Cloneable or Mergeable should actually support it
    Do not slap Serializable marker (or other markers) on everything just because it makes it convenient to use within another Serializable class. Make sure it is reasonable in the given context and that it is actually useful and, most importantly, supported by your class. Provide according method implementations if necessary - read/write for Serializable, clone() for Cloneable and either of the merge options for Mergeable.

  • Write JavaDoc for all parts of code
    Even if something is obvious - still write JavaDoc for it, expand it later if necessary. Other developers might not find it obvious and will thank you later for leaving the life-saving notes. Don't be afraid to explain something more extensively, especially if it is a tricky topic. Add references to GitHub project issues, JDK issues or any online resources if necessary.

  • Write comments only when needed
    Unlike JavaDoc comments will only be visible to people working with source code and are usually only useful for large methods or constructors, but in that case it's usually better to split your code into smaller methods or classes instead and simply have JavaDoc for those. There are some exceptions though: comments about some possible bugs, references to bugs on tracker, todos or comments about some extremely convoluted pieces of code.

Some of these things can be handled by modern IDEs, like final marker, annotations or single exit point methods. IDE can also assist you with formatting your code, writing JavaDoc and checking sanity of the code overall.

There are also some things I haven't tried on the project yet due to some difficulties but might try in the future, so these guidelines will certainly be updated.

Code Formatting

I'm writing WebLaF using IntelliJ IDEA IDE and generally recommend using it due to multiple awesome features it has. Latest code style and inspection settings for IntelliJ IDEA IDE are available in project sources:
https://github.com/mgarin/weblaf/tree/master/ide

You can specify them instead of the default settings in main settings dialog:

Code style settings (ide/intellij-idea-code-style.xml)
Code Style Settings

Inspection settings (ide/intellij-idea-inspections.xml)
Inspection Settings

Once these are set you will be able to safely reformat (Ctrl+Alt+L by default) any project file and you should also get some warnings for the stuff mentioned in Code Philosophy section.