Structure
One file
import dash
import dash_core_components as dcc
import dash_html_components as html

# Since we're adding callbacks to elements that don't exist in the app.layout,
# Dash will raise an exception to warn us that we might be
# doing something wrong.
# In this case, we're adding the elements through a callback, so we can ignore
# the exception.
app = dash.Dash(__name__, suppress_callback_exceptions=True)

app.layout = html.Div([
    dcc.Location(id='url', refresh=False),
    html.Div(id='page-content')
])

link_style = {'color':'blue', 'margin':'10px 5px 10px 5px', 'font-weight': 'bold', 'text-decoration': 'none'}

index_page = html.Div([
    dcc.Link('Home', href='/', style=link_style),
    dcc.Link('Research', href='/page-research', style=link_style),
    dcc.Link('Skill', href='/page-skill', style=link_style),
    html.Br(),
    html.Label('Homepage content')
])

page_research_layout = html.Div([
    dcc.Link('Home', href='/', style=link_style),
    dcc.Link('Research', href='/page-research', style=link_style),
    dcc.Link('Skill', href='/page-skill', style=link_style),
    html.Br(),
    html.Label('Reserach-page content')
])

page_skill_layout = html.Div([
    dcc.Link('Home', href='/', style=link_style),
    dcc.Link('Research', href='/page-research', style=link_style),
    dcc.Link('Skill', href='/page-skill', style=link_style),
    html.Br(),
    html.Label('Skill-page content')
])

@app.callback(dash.dependencies.Output('page-content', 'children'),
              [dash.dependencies.Input('url', 'pathname')])
def display_page(pathname):
    if pathname == '/page-research':
        return page_research_layout
    elif pathname == '/page-skill':
        return page_skill_layout
    else:
        return index_page

if __name__ == '__main__':
    app.run_server(debug=True)
		
Multiple files
# index.py
from layout import *
from app import app
import callbacks

app.layout = content

if __name__ == '__main__':
    app.run_server(debug=True)
		
# app.py
import dash

app = dash.Dash(__name__, suppress_callback_exceptions=True)
		
# layout.py
import dash_core_components as dcc
import dash_html_components as html

content = html.Div([
    dcc.Location(id='url', refresh=False),
    html.Div(id='page-content')
])

link_style = {'color':'blue', 'margin':'10px 5px 10px 5px', 'font-weight': 'bold', 'text-decoration': 'none'}

index_page = html.Div([
    dcc.Link('Home', href='/', style=link_style),
    dcc.Link('Research', href='/page-research', style=link_style),
    dcc.Link('Skill', href='/page-skill', style=link_style),
    html.Br(),
    html.Label('Homepage content')
])

page_research_layout = html.Div([
    dcc.Link('Home', href='/', style=link_style),
    dcc.Link('Research', href='/page-research', style=link_style),
    dcc.Link('Skill', href='/page-skill', style=link_style),
    html.Br(),
    html.Label('Reserach-page content')
])

page_skill_layout = html.Div([
    dcc.Link('Home', href='/', style=link_style),
    dcc.Link('Research', href='/page-research', style=link_style),
    dcc.Link('Skill', href='/page-skill', style=link_style),
    html.Br(),
    html.Label('Skill-page content')
])
		
# callbacks.py
from dash.dependencies import Input, Output
from layout import *
from app import app

@app.callback(Output('page-content', 'children'),
              [Input('url', 'pathname')])
def display_page(pathname):
    if pathname == '/page-research':
        return page_research_layout
    elif pathname == '/page-skill':
        return page_skill_layout
    else:
        return index_page
		
Model-View-Controller

# app.py
from model import *
from control import *
from view import *

app.layout = get_content()

if __name__ == '__main__':
    app.run_server(debug=True)
        
# model.py
import pandas as pd

def get_data():
    temp = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv')

    return temp
        
# view.app
import dash
from dash import html
from dash import dcc
import plotly.express as px
from model import *

def get_content():
    return html.Div([
        html.Button('Click', id = 'button'),
        html.Div(id='output')
    ])

def get_graph():
    fig = px.bar(get_data(), x='year', y='pop')
    return dcc.Graph(figure=fig)
        
# control.py
import dash
from dash.dependencies import Output, Input, State
from dash.exceptions import PreventUpdate
from model import *
from view import *

app = dash.Dash(__name__)

@app.callback(
    Output('output', 'children'),
    Input('button', 'n_clicks')
)
def update_table(n_clicks):
    if not n_clicks:
        raise PreventUpdate

    return get_graph()