|
| 1 | +# Base code for a Web project - Java + JS |
| 2 | + |
| 3 | +This project is build with the purpose of given a base code from where you can start to develop with a little of extra work. |
| 4 | +This project is licensed under the terms of the MIT license. |
| 5 | + |
| 6 | +## Goals: |
| 7 | + |
| 8 | +* 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. |
| 9 | +* 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]). |
| 10 | +* Allowing hot changes in both frontend and backend. |
| 11 | +* Independently but running on the same server[3]. |
| 12 | + |
| 13 | +Some things are Opinionated based on best practices and professional experience[4]. |
| 14 | + |
| 15 | +> [1] Using [Gradle Wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html). |
| 16 | +> [2] Using [Gradle Node](https://github.com/srs/gradle-node-plugin). |
| 17 | +> [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 developers can not afford that. |
| 18 | +> [4] Some topics have _References_ so you can dig more on details. And code has been "widely" commented to assist you to understand some fragments. |
| 19 | +
|
| 20 | +## Features |
| 21 | + |
| 22 | +* All in 1 project. |
| 23 | +* Code Style Checking. |
| 24 | + * Project code (Java & Javascript). |
| 25 | + * Build code (Gradle). |
| 26 | +* Test Driven Development. |
| 27 | + * Unit, Integration, End to end tests. |
| 28 | + * Code coverage checking. |
| 29 | +* Code Documentation. |
| 30 | +* Hot run. |
| 31 | + |
| 32 | +### Using |
| 33 | + |
| 34 | +* All in 1 project. |
| 35 | + * Backend: [Java](https://www.java.com) & [Spring Boot](https://spring.io). |
| 36 | + * Frontend: [Javascript](https://developer.mozilla.org/en-US/docs/Web/JavaScript), [NodeJS](https://nodejs.org) & [npm](https://www.npmjs.com/). |
| 37 | +* Code Style Checking. |
| 38 | + * Java: [Checkstyle](http://checkstyle.sourceforge.net) & [PMD](https://pmd.github.io). |
| 39 | + * Javascript: [ESlint](https://eslint.org). |
| 40 | + * CSS: [StyleLint](https://github.com/stylelint/stylelint) |
| 41 | + * Gradle: [CodeNarc](http://codenarc.sourceforge.net). |
| 42 | +* Test Driven Development. |
| 43 | + * Unit Test & Integration Test: |
| 44 | + * Java: [JUnit](http://junit.org). |
| 45 | + * Javascript: [Jasmine](https://jasmine.github.io) & [Karma](https://karma-runner.github.io). |
| 46 | + * End to end tests: |
| 47 | + * Javascript: [Selenium](http://www.seleniumhq.org). |
| 48 | + * Code coverage checking. |
| 49 | + * Java: [JaCoCo](http://www.eclemma.org/jacoco). |
| 50 | + * Javascript: [Istanbul](https://istanbul.js.org). |
| 51 | +* Code Documentation. |
| 52 | + * Java: JavaDoc. |
| 53 | + * Javascript: [JSDoc](http://usejsdoc.org). |
| 54 | +* Continuous build & Hot run: [Spring Dev Tools](https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html) + [Gradle parallel task]() |
| 55 | + |
| 56 | +## Prerequisites |
| 57 | + |
| 58 | +* [Java](http://www.oracle.com/technetwork/java/javase/downloads). |
| 59 | +* [Chrome](https://www.google.com/chrome/browser/desktop/) and [Firefox](https://www.mozilla.org/en-US/firefox/) for End to End Test [1]. |
| 60 | +* [Git](https://git-scm.com/downloads) (only if you are going to clone the project). |
| 61 | + |
| 62 | +> [1] If you don't have one of these you could change the code in order to use only what you have. |
| 63 | +
|
| 64 | +## Getting it |
| 65 | + |
| 66 | +Clone or download the project[1], In the desired folder execute: |
| 67 | + |
| 68 | +```sh |
| 69 | +git clone https://github.com/gmullerb/basecode |
| 70 | +``` |
| 71 | + |
| 72 | +> [1] [Cloning a repository](https://help.github.com/articles/cloning-a-repository/) |
| 73 | +
|
| 74 | +## Set up |
| 75 | + |
| 76 | ++ **No need**, only download and run. |
| 77 | + |
| 78 | +## Running it |
| 79 | + |
| 80 | +* To check it: `gradlew` (this will run default tasks) |
| 81 | + |
| 82 | +* To execute it: `gradlew bootRun` |
| 83 | + |
| 84 | +* To get all the tasks for the project: `gradlew tasks --all` |
| 85 | + |
| 86 | +## Project structure |
| 87 | + |
| 88 | +[Backend project](back/README.md) + [Frontend project](front/README.md) + [End to End Tests project](front/e2e/README.md) |
| 89 | + |
| 90 | +## Folder structure |
| 91 | + |
| 92 | +It's a gradle multi-project[1]: |
| 93 | + |
| 94 | +- **Backend** project is located on `back/`. |
| 95 | + - It's a Spring Boot Project. |
| 96 | +- **Frontend** project is located on `front/`. |
| 97 | + - It's a NodeJS Project. |
| 98 | +- **End to End Tests** project is located on `front/e2e`. |
| 99 | + - It's a NodeJS Project. |
| 100 | + |
| 101 | +Structure: |
| 102 | +``` |
| 103 | + /back |
| 104 | + /front |
| 105 | + /e2e |
| 106 | + /config |
| 107 | + /local_gradle |
| 108 | + /gradle |
| 109 | + /readme |
| 110 | +``` |
| 111 | + |
| 112 | +* `back`: Backend project[2]. |
| 113 | +* `front`: Frontend project[2]. |
| 114 | +* `front/e2e`: End to End Tests project. |
| 115 | +* `gradle`: Gradle Wrapper folder. |
| 116 | +* `config`: Configuration files. |
| 117 | +* `local_gradle`: Local gradle modules folder[3]. |
| 118 | +* `readme`: Readme attachments folder. |
| 119 | + |
| 120 | +> [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. |
| 121 | +> [2] Both, backend and frontend projects, try to have the same folder structure. |
| 122 | +> [3] "Heavy" gradle logic is extracted here. |
| 123 | +
|
| 124 | +### Conventions |
| 125 | + |
| 126 | +* `src/main`: Folder of Source code. |
| 127 | +* `src/test`: Folder of Test code. |
| 128 | +* Configuration folders will be named: `config`. |
| 129 | +* Configuration files will be named ending with: `cfg.*`, `.yml`. |
| 130 | +* Folder's name may use `_`, but not `-`. |
| 131 | +* Files's name may use `-`, but not `_`. |
| 132 | + |
| 133 | +### Recommendations: |
| 134 | + |
| 135 | +* In `/gradle/wrapper` the `gradle-wrapper.properties` file sets `gradle-#.#-all.zip` (this file allows access to gradle source), If this is no required you may change for `gradle-#.#-bin.zip` on `gradle-wrapper.properties` for a smaller JAR file for the wrapper. |
| 136 | +* Don't use the _base_ or _absolute_ name on your pathnames. |
| 137 | + |
| 138 | +## Gradle Tasks structure |
| 139 | + |
| 140 | + |
| 141 | + |
| 142 | +Task ordering enforces to run quicker and lighter task before longer tasks when is possible. |
| 143 | + |
| 144 | +Each task is has: |
| 145 | +- First its own settings. |
| 146 | +- Followed by base Gradle task settings. |
| 147 | +``` |
| 148 | +task name (..) { |
| 149 | + // task settings |
| 150 | + .. |
| 151 | + // gradle task settings |
| 152 | + .. |
| 153 | +} |
| 154 | +``` |
| 155 | +[1] |
| 156 | + |
| 157 | +`gradlew tasks`: Lists the runnable tasks for root project *basecode* (some of the listed tasks may belong to subprojects). |
| 158 | + |
| 159 | +> [1] Throughout any documentation, `..` will represent an ellipsis to avoid possible confusion with `...` programming language operator. |
| 160 | +
|
| 161 | +### Backend and Frontend Common Tasks |
| 162 | + |
| 163 | + [`local_gradle/code.gradle`](local_gradle/code.gradle) contains common gradle tasks definitions between Frontend and Backend in order to allow "same" set of task between both, e.g. `assess` which analyzes and assess code (Main & Test). |
| 164 | +``` |
| 165 | + code.gradle => CodeTask + CodeConfiguration |
| 166 | +``` |
| 167 | + |
| 168 | +* CodeTask : Common Tasks names[1]. |
| 169 | +* CodeConfiguration: Common Tasks Configuration. |
| 170 | + |
| 171 | +This way is easily to achieve any task in both projects. |
| 172 | + |
| 173 | +There is the possibility to change the name of these tasks, for that, go to the main `gradle.properties` and change any of the names defined there[2]: |
| 174 | +``` |
| 175 | +CODE$ASSESS_MAIN_TASK_NAME=assessMain |
| 176 | +CODE$ASSESS_UNIT_TEST_TASK_NAME=assessUnitTest |
| 177 | +CODE$ASSESS_INTEGRATION_TEST_TASK_NAME=assessIntegrationTest |
| 178 | +CODE$ASSESS_TEST_TASK_NAME=assessTest |
| 179 | +CODE$ASSESS_TASK_NAME=assess |
| 180 | +CODE$UNIT_TEST_TASK_NAME=unitTest |
| 181 | +CODE$INTEGRATION_TEST_TASK_NAME=integrationTest |
| 182 | +CODE$COVERAGE_TASK_NAME=coverage |
| 183 | +CODE$DOCUMENTATION_TASK_NAME=doc |
| 184 | +
|
| 185 | +GLOBAL$TEST_TASK_NAME=test |
| 186 | +GLOBAL$CHECK_TASK_NAME=check |
| 187 | +``` |
| 188 | + |
| 189 | +`build.gradle` defines a default task with the purpose of doing all required checks that any developer of the project should run at least to ensure some degree of code wellness on any change before submiting the code: `assessGradle` + `:front:assessLocal` + `check` |
| 190 | + |
| 191 | +> [1] Some are just alias, since real task name is too long or some plugin creates a task with different name (but same functionality), e.g.: `jacocoTestCoverageVerification` |
| 192 | +> [2] All tasks will generate console information and a report if possible. |
| 193 | +
|
| 194 | +## Configuration |
| 195 | + |
| 196 | +In general, build.gradle files are structured in this way: |
| 197 | +1. Buildscript dependencies. |
| 198 | +2. Plugins. |
| 199 | +3. Configurations. |
| 200 | +4. Dependencies. |
| 201 | +5. Constants. |
| 202 | +6. Custom Tasks definition. |
| 203 | +7. Plugin tasks configuration[1]. |
| 204 | + |
| 205 | +Project configurations are defined in[2]: |
| 206 | +* [`build.gradle`](build.gradle). |
| 207 | +* [`back.gradle`](back/back.gradle). |
| 208 | +* [`front.gradle`](front/front.gradle). |
| 209 | +* [`e2e.gradle`](front/e2e/e2e.gradle). |
| 210 | + |
| 211 | +> [1] Usually plugin tasks depends on custom tasks. |
| 212 | +> * If custom task depends on plugin tasks these are already defined on plugins. |
| 213 | +> |
| 214 | +> [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). |
| 215 | +
|
| 216 | +### Properties |
| 217 | + |
| 218 | +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": |
| 219 | + |
| 220 | +* `GLOBAL$property` -> [Main `gradle.properties`](gradle.properties). |
| 221 | + Especial case for [`code.gradle`](local_gradle/code.gradle): |
| 222 | + * `CODE$property` -> [Main `gradle.properties`](gradle.properties). |
| 223 | +* `BACK$property` -> [Back `gradle.properties`](back/gradle.properties). |
| 224 | +* `FRONT$property` -> [Front `gradle.properties`](front/gradle.properties). |
| 225 | + |
| 226 | +### Repositories |
| 227 | + |
| 228 | +* Remote: [jcenter](https://bintray.com/bintray/jcenter). |
| 229 | +* Local: Maven local. |
| 230 | + |
| 231 | +By default, the project use Remote repositories, but you may use local repository, for this execute: `gradlew .. -PlocalRepo` |
| 232 | + |
| 233 | +### Running Environments |
| 234 | + |
| 235 | +GLOBAL$DEFAULT_ENVIRONMENT is defined in the [`gradle.properties`](gradle.properties) file and sets the default environment (or profile), `dev`[1]. |
| 236 | +You can change it using command line `gradlew bootRun -Penv=TARGET_ENVIRONMENT`. |
| 237 | + |
| 238 | +> [1] Value should always be in lowercase. |
| 239 | +
|
| 240 | +### Highlights |
| 241 | + |
| 242 | +* By default, Gradle daemon is disable, `org.gradle.daemon=false`, in the [`gradle.properties`](gradle.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). |
| 243 | +* Gradle files are populate everywhere with different logging with different levels, use command line option `--debug` to get more information when running a task. |
| 244 | +* Use `--debug-jvm` command line option for debugging. |
| 245 | + |
| 246 | +#### Logging |
| 247 | + |
| 248 | +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`](local_gradle/logger.gradle) is where this is done: |
| 249 | +``` |
| 250 | + project.gradle.useLogger(new BuildAdapter() { ... |
| 251 | +``` |
| 252 | +* if log level is debug this is completly ignore. |
| 253 | + |
| 254 | +### Recommendations: |
| 255 | + |
| 256 | +* Change versions: versions are set to the latest with * or +, so you can get the latest version the first time you start your project, although is recommended to set it to fixed values later. |
| 257 | + * Test dependencies can remain dynamic since this will not affect production build, and allow to have latest improvements and fixes. |
| 258 | + |
| 259 | +## Code Style |
| 260 | + |
| 261 | +Code style will allow to follow the best practices and standard coding across team development. |
| 262 | + |
| 263 | +### Code Style Checking |
| 264 | + |
| 265 | +The idea is to catch errors before code is submitted by developers. |
| 266 | + |
| 267 | +All projects have code style checking and have a subset of rules defined that tries to be consistent between all projects's code in order to allow "almost" the same look of the code to both developers, backend and frontend. To highlights: |
| 268 | +* CamelCase naming convention. |
| 269 | +* Egyptian brackets. |
| 270 | +* Tab character checking with 2 spaces. |
| 271 | +* Method length limit (48 lines). |
| 272 | +* Method parameter number limit (8 parameters). |
| 273 | +* Requires semicolon at the end of the line. |
| 274 | +* Requires a new line break at the end of the file[1]. |
| 275 | +* Some spacing rules are the same. |
| 276 | + |
| 277 | +In the root project is defined a task that do some common checks for all files of the multi-project: `assessCommon` |
| 278 | +* The only files that are not processed are `.gitignore` files (due to some internal excluding of the Checkstyle ant task). |
| 279 | +* 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) |
| 280 | + |
| 281 | +> [1] In order to be friendly with Code Versioning tools. |
| 282 | +
|
| 283 | +#### Gradle Code |
| 284 | + |
| 285 | +Gradle and Groovy files are checked with [CodeNarc](http://codenarc.sourceforge.net) using `assessGradle` task . To highlights: |
| 286 | +* Rules are defined in the [`gradle-rules.groovy`](config/gradle-rules.groovy). |
| 287 | +* Report will be in `build/reports/codenarc`. |
| 288 | +* `assessGradle` task is executed by default on the project. |
| 289 | +* Version is defined with GLOBAL$CODENARC_VERSION on [`gradle.properties`](gradle.properties) |
| 290 | + |
| 291 | +## Test Driven Development |
| 292 | + |
| 293 | +* Both projects, back and front, have small tests to be used as a guide for real case test. |
| 294 | +* Test are located in: `src/test`. |
| 295 | +* Both projects have a `coverage` task in order to calculate code coverage. |
| 296 | +* Code coverage is based on Unit Tests [1]. |
| 297 | +* End to end tests are defined in the [e2e project](front/e2e/README.md). |
| 298 | +* All tdd tasks will generate console information and a file report with detail information. |
| 299 | + |
| 300 | +> [1] Code coverage should be based only in coverage tests. |
| 301 | +
|
| 302 | +## Hot run |
| 303 | + |
| 304 | +You can 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 "immediatly"[3]. This run will generate information that will be shown to console and into files. |
| 305 | + |
| 306 | +For changing configuration go to ['hotrun.gradle'](back/local_gradle/hotrun.gradle): |
| 307 | +* Tasks `concurrentClasses` and `concurrentBootRun`: |
| 308 | + * showOutput: Show the output for each run in console (true or false, default: false). |
| 309 | + * showError: Show error information for each run in console (true or false, default: false). |
| 310 | + * outputFilePath: If set, saves the output for each run in the specified file. |
| 311 | + * errorFilePath: If set, saves error information for each run in the specified file. |
| 312 | +* Task `concurrentClasses`[4]: |
| 313 | + * extraParams[0]: Milliseconds between checking Code changes. |
| 314 | + * extraParams[1]: Show run number and time (true or false, default: true). |
| 315 | + |
| 316 | +> [1] Based in [Gradle Daemons](https://docs.gradle.org/current/userguide/custom_tasks.html#worker_api). |
| 317 | +> [2] If do it other way , it will possible need 2 consoles for doing this. |
| 318 | +> [3] Every 10s Code is check this can be change. |
| 319 | +> [4] When setting one, you should set both. |
| 320 | +
|
| 321 | +## Documentation |
| 322 | + |
| 323 | +* Both projects, back and front, can generate documentation for their code. |
| 324 | +* [`CHANGELOG.md`](CHANGELOG.md)[1] add information of notable changes for each version here, chronologically ordered. |
| 325 | + |
| 326 | +> [1] http://keepachangelog.com |
| 327 | +
|
| 328 | +## Remember |
| 329 | + |
| 330 | +* Start testing early. |
| 331 | +* Code Review Everything => Encourage best practices and Team work. |
| 332 | + |
| 333 | +## License |
| 334 | + |
| 335 | +[MIT License](/LICENSE.txt) |
| 336 | + |
| 337 | +## Additional words |
| 338 | + |
| 339 | +I hope this will be the start for many amazing web projects. |
| 340 | + |
| 341 | +Don't forget: |
| 342 | +* **Love what you do**. |
| 343 | +* **Learn everyday**. |
| 344 | +* **Share your knowledge**. |
| 345 | +* **Learn from the past, dream on the future, live and enjoy the present to the max!**. |
0 commit comments