How can I create an advanced addon with a GUI and multiple settings for Blender 2.8x?
Here is how to create addons with an interface in Blender 2.8x. I share here minimalist scripts snippets.


If the addon has multiple files compress it to a .zip.
To enable the addon go in Edit > Preferences..., in the Addon section and type "Minimalist Addon". I suggest you to name your main file __init__.py, it's a convention between every addons. Make sure to use the extension .py for all your files.
To edit your addon you don't need to reimport it each time, you can find it here on Windows: C:\Users\NAME\AppData\Roaming\Blender Foundation\Blender\2.8x\scripts\addons
And here on Linux: /home/NAME/.config/blender/2.8x/scripts/addons/
You will need to reopen Blender to see the changes. If the addon doesn't appear it means you have made a mistake somewhere, if it is still visible in the Preferences try to re-enable it to see the error message.
Your addon must be in a folder and not directly in the "addons" folder, otherwise you won't be able to find it in the Preferences.
If you need console (to print message and values by doing print("my message") ) do Window > Toggle System Console on Windows. On Linux download Blender from the website, open the Linux terminal (shortcut Ctrl + Alt + t), type the path to the Blender folder using cd (ls to list the files and folders) then launch Blender by typing ./blender.





  Single file addon


This is the most minimalistic addon you can create, it contains a single file, it displays a button that prints "Hello World!" in the console.

__init__.py

bl_info = {
    "name" : "Minimalist addon",                        # The name in the addon search menu
    "author" : "Your name",
    "description" : "A minimalistic addon",
    "blender" : (2, 80, 0),                             # Lowest version to use
    "location" : "View3D",
    "category" : "Generic"
}

import bpy

class theInterface_PT_Panel(bpy.types.Panel):
    bl_label = "Panel Name"
    bl_category = "Tab name"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"

    def draw(self, context):
        layout = self.layout

        layout.label(text= "Properties:")

        row = layout.row()                              # Create a new line
        row.operator("view3d.print_text", text = "Print text", icon='WORLD_DATA') # Display the operator by calling his idname

class theTools_OT_Operator(bpy.types.Operator):         # Create the operator
    bl_idname = "view3d.print_text"                     # idname to display the operator
    bl_label = "Simple operator"
    bl_description = "Tool description when overing the mouse"

    def execute(self, context):                         # What the operator does
        print("Hello World!")
        return {'FINISHED'}

classes = (theInterface_PT_Panel, theTools_OT_Operator) # Classes name here

register, unregister = bpy.utils.register_classes_factory(classes)





  Multiple files addon


__init__.py (gives the addon informations and gather the files)

The difference here are that the classes are in other files. You must add the lines with the name of your file without .py and class like this:
from . File_Name import Classe_Name

bl_info = {
    "name" : "Minimalist addon",
    "author" : "Your name",
    "description" : "A minimalistic addon",
    "blender" : (2, 80, 0),
    "location" : "View3D",
    "category" : "Generic"
}

import bpy

from . Interface_Panel import Interface_PT_Panel
from . Tool_Operator import Tool_OT_Operator

classes = (Interface_PT_Panel, Tool_OT_Operator)

register, unregister = bpy.utils.register_classes_factory(classes)


Tool_Operator.py (what is executed in the addon)

import bpy

class Tool_OT_Operator(bpy.types.Operator):
    bl_idname = "view3d.print_text"
    bl_label = "Simple operator"
    bl_description = "Tool description"

    def execute(self, context):
        print("Hello World!")
        return {'FINISHED'}


Interface_Panel.py (the interface)

import bpy

class Interface_PT_Panel(bpy.types.Panel):
    bl_idname = "MenuName_PT_Panel"
    bl_label = "Panel Name"
    bl_category = "Tab name"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"

    def draw(self, context):    
        layout = self.layout

        scene = context.scene

        layout.label(text= "Properties:")

        row = layout.row()
        row.operator("view3d.print_text", text = "Print text", icon='WORLD_DATA')



  Getting commands


You can get the commands of every tools each time you use one in the Info Window, you can display it by clicking on the Scripting tab at the top of Blender's interface.
For example after selecting a mesh, doing right click and selecting Shade Smooth, this command appears: 

bpy.ops.object.shade_smooth()



  Adding settings and using the values


WIP


  Frequent mistakes



If you operator isn't visible in the interface, check if his class name is unique and do not forget to import it at the classes line at the bottom by writing his name.
Your addon won't be accessible if it is directly in the scripts folder, you must put it in a sub-folder.



  FAQ


What is an operator?

An operator does one or several actions like adding a cube in the 3D view, scaling it then applying a material, all with a single button. The operators are often available by the interface.

What row = layout.row() does?

It creates a new line in the interface, without it your button operators and settings can't be displayed. You can add multiple settings at the same line, however it is recommended to displayed one on each line for a better visiblity.