This project is build with the purpose of given a base code from where to start developing a Web app with little effort.
This project is licensed under the terms of the MIT license.
- The idea behind this is to have a base project where backend and frontend development are separated, in a way that each team, backend team and frontend team, can "focus" in their respective project "independently", but having the development tools integrated in order the facilitate all the process.
- Integrated in way that the developers only have to download the code and only need to have installed Java to start working (not need for installing Gradle[1], neither NodeJS[2]).
- Allowing hot changes in both frontend and backend.
- Independently but running on the same server[3].
Some things are Opinionated based on best practices and professional experience[4].
[1] Using Gradle Wrapper.
[2] Using Gradle Node.
[3] Another approach will be to have a server from frontend and another server for backend, but this will among other things require more resource from system and some projects can not afford that.
[4] Some topics in the README files have References so you can dig more on details. And code has been "widely" commented to assist you to understand some fragments.
- All in 1 project.
- Code Style Checking.
- Project code (Java & Javascript).
- Build code (Gradle).
- Test Driven Development.
- Unit, Integration, End to end tests.
- Code coverage checking.
- Code Documentation.
- Hot run.
- All in 1 project.
- Backend: Java & Spring Boot.
- Frontend: Javascript, NodeJS & npm.
- Code Style Checking.
- Java: Checkstyle & PMD.
- Javascript: ESlint.
- CSS: StyleLint
- Gradle: CodeNarc.
- Test Driven Development.
- Code Documentation.
- Java: JavaDoc.
- Javascript: JSDoc.
- Continuous build & Hot run: Spring Dev Tools + Gradle parallel task
- Java (for running Gradle), which basically comes with every operating system, so this should not be a problem.
- Chrome and Firefox for End to End Test [1].
- Git (only if the project is going to be cloned).
[1] If only one of these is required or present, then configuration could be changed in order to use only what is required in e2e project.
Clone or download the project[1], in the desired folder execute:
git clone https://github.com/gmullerb/basecode
- No need, only download and run (It's Gradle! Yes!).
-
gradlew
, will run default tasks: -
gradlew run
: will run the project.- Go to the web browser look at the url: http://localhost:8080/
-
gradlew tasks --all
: will get all the tasks for the project.
Backend project + Frontend project + End to End Tests project
It's a gradle multi-project[1]:
- Backend project is located on
back/
.- It's a Spring Boot Project.
- Frontend project is located on
front/
.- It's a NodeJS Project.
- End to End Tests project is located on
front/e2e
.- It's a NodeJS Project.
Structure:
/back
/front
/e2e
/config
/local_gradle
/gradle
/readme
back
: Backend project[2].front
: Frontend project[2].front/e2e
: End to End Tests project.gradle
: Gradle Wrapper folder.config
: Configuration files.local_gradle
: Local gradle modules folder[3].readme
: Readme attachments folder.
[1] Remember to change the root project name in
settings.gradle
, even in single project builds:rootProject.name = 'name'
to avoid Continuous Integration servers issues.
[2] Both, backend and frontend projects, try to have the same folder structure.
[3] "Heavy" gradle logic is extracted here.
src/main
: Folder of Source code.src/test
: Folder of Test code.- Configuration folders will be named:
config
. - Configuration files will be named ending with:
cfg.*
,.yml
. - Folder's name may use
_
, but not-
. - Files' name may use
-
, but not_
. - Throughout any documentation,
..
will represent an ellipsis to avoid possible confusion with...
programming language operator.
- In
/gradle/wrapper
thegradle-wrapper.properties
file setsgradle-#.#-all.zip
(this file allows access to gradle source), If this is no required, then change forgradle-#.#-bin.zip
ongradle-wrapper.properties
for a smaller JAR file for the wrapper. - Don't use the base or absolute name on project's paths names.
Task ordering enforces to run quicker and lighter task before longer tasks when is possible.
Each task is has:
- First its own settings.
- Followed by base Gradle task settings.
task name (..) {
// task settings
..
// gradle task settings
..
}
gradlew tasks
: Lists the runnable tasks for root project basecode (some of the listed tasks may belong to subprojects).
Both project use Code's Common Tasks plugin which allows contains common gradle tasks definitions between Frontend and Backend in order to allow "same" set of task between both.
In general, build.gradle files are structured in this way:
- Buildscript dependencies.
- Plugins.
- Configurations.
- Dependencies.
- Constants.
- Custom Tasks definition.
- Plugin tasks configuration[1].
Project configurations are defined in[2]:
[1] Usually plugin tasks depends on custom tasks.
- If custom task depends on plugin tasks these are already defined on plugins.
[2] Usually gradle files are all named
build.gradle
, but in order to avoid confusion each one has a a name that represents the respective project(this is all set in settings.gradle).
Properties are defined in gradle.properties files. Properties are defined with prefixes in order to differentiate where is the origin and can be locate "quickly":
GLOBAL$property
-> Maingradle.properties
.BACK$property
-> Backgradle.properties
.FRONT$property
-> Frontgradle.properties
.
- Remote: jcenter.
- Local: Maven local.
By default, the project use Remote repositories, but it could be changed to use local repository, for this execute: gradlew .. -PlocalRepo
GLOBAL$DEFAULT_ENVIRONMENT is defined in the gradle.properties
file and sets the default environment (or profile) to dev
[1].
It could be changed using command line: gradlew bootRun -Penv=TARGET_ENVIRONMENT
.
[1] Value should always be in lowercase.
- By default, Gradle daemon is disable,
org.gradle.daemon=false
, in thegradle.properties
. (Some developers can not afford having daemon, They have hardware that don't have that much memory, this way memory is released after use). - Gradle files are populate everywhere with different logging with different levels, use command line option
--debug
to get more information when running a task. - Use
--debug-jvm
command line option for debugging.
Gradle is Superb! but when is about logging it has a good internal (not shared) Classes for this (with colors, etc., like classes derived from StyledTextOutput). Internal LocationAwareException exception some times can be really confusing, e.g. when it prints the line of a gradle file, at sometimes this line doesn't represents the real problem. A custom logger "overrides" the default logger for removing this from Gradle's logs. In logger.gradle
is where this is done:
project.gradle.useLogger(new BuildAdapter() { ...
- if log level is debug this is completely ignore.
- Change versions: Most versions are set to the latest using
*
or+
, so it can get the latest version the first time the project is started, although is recommended to set it to fixed values later.- Test dependencies can remain dynamic since this will not affect production build, and allow to have latest improvements and fixes.
- This project was develop under Linux so, Windows user may (or may not) need to adjust some configuration values.
Code style will allow to follow the best practices and standard coding across team development.
The idea is to catch errors before code is submitted by developers.
All projects have code style checking and have subsets of rules defined. Subsets try to be similar for all the code (Backend's, Frontend's and Build's code), in order to allow "almost" the same look and rules of the code:
- Rules are defined in base-style-config project.
In the root project is defined a Checkstyle task, defined by project-style-checker plugin, that do some common checks for all files of the multi-project, assessCommon
:
- Rules are defined in base-style-config project.
- The only files that are not processed are
.gitignore
files (due to some internal excluding of the Checkstyle ant task). - and It will ignore almost all patterns set in the
.gitignore
files, but patterns with ̣!
and[
+]
will be bypassed (then avoid using these if possible).
Gradle files (basically Groovy files) are checked with CodeNarc using project-style-checker plugin. To highlights:
- Rules are defined in base-style-config project.
- Report will be in
build/reports/codenarc
. assessGradle
task is executed by default on the project.- Version is defined with
GLOBAL$CODENARC_VERSION
ongradle.properties
-
Use
BASE_STYLE_CONFIG_VERSION
to establish the version of Base Style Configuration to be used, e.g.gradle.properties
:- If not set, then last version will be used.
BASE_STYLE_CONFIG_VERSION=1.0.6
-
Use
CHECKSTYLE_VERSION
to establish the version of Checkstyle to be used, e.g.gradle.properties
:- If not set, Gradle's default version will be used.
- At the present, should be set in order to be compatible with the set of rules defined by Base Style Configuration
- If not set, Gradle's default version will be used.
CHECKSTYLE_VERSION=8.13
-
*Use
CODENARC_VERSION
to establish the version of CodeNarc to be used, e.g.gradle.properties
:- If not set, Gradle's default version will be used.
- At the present, should be set in order to be compatible with the set of rules defined by Base Style Configuration
- If not set, Gradle's default version will be used.
CODENARC_VERSION=1.2
[1] This is done by the project-style-checker plugin.
- Both projects, back and front, have small tests to be used as a guide for real case test.
- Test are located in:
src/test
. - Both projects have a
coverage
task in order to calculate code coverage. - Code coverage is based on Unit Tests [1].
- End to end tests are defined in the e2e project.
- All tdd tasks will generate console information and a file report with detail information.
[1] Code coverage should be based only in coverage tests.
Use the hotRun
task [1] to run the project and at the same time edit [2] Backend Java Code and Frontend JS code and the code will be reflected "immediately"[3]. This run will generate information that will be shown to console and into files.
For changing configuration go to 'hotrun.gradle':
- Tasks
concurrentClasses
andconcurrentBootRun
:showOutput
: Show the output for each run in console (true
orfalse
, default:false
).showError
: Show error information for each run in console (true
orfalse
, default:false
).outputFilePath
: If set, saves the output for each run in the specified file.errorFilePath
: If set, saves error information for each run in the specified file.
- Task
concurrentClasses
[4]:extraParams[0]
: Milliseconds between checking Code changes.extraParams[1]
: Show run number and time (true
orfalse
, default:true
).
[1] Based in Gradle Daemons. [2] If do it other way, it will possibly need 2 opened consoles for doing this. [3] Every 10s Code is check this can be change. [4] Both parameters must be set, even when requiring only one.
- Both projects, back and front, can generate documentation for their code.
CHANGELOG.md
: add information of notable changes for each version here, chronologically ordered [1].
[1] Keep a Changelog
- Use code style verification tools => Encourages Best Practices, Efficiency, Readability and Learnability.
- Start testing early => Encourages Reliability and Maintainability.
- Code Review everything => Encourages Functional suitability, Performance Efficiency and Teamwork.
Don't forget:
- Love what you do.
- Learn everyday.
- Learn yourself.
- Share your knowledge.
- Learn from the past, dream on the future, live and enjoy the present to the max!.
At life:
- Let's act, not complain.
- Be flexible.
At work:
- Let's give solutions, not questions.