The MTC team is following a set of patterns and practices throughout the development of this project.
- Master branch points to the latest stable branch of the repository which contains approved PRs only.
- Feature branches are created under the feature branch folder. The naming convention is
feature/(ticket number)-(description)
- Bug branch naming onventions are similar to feature branches:
bug/(ticket number)-(description)
All work has to be done TDD style - tests first. Create a PR once you have written a few tests, and invite team members to review. This gives a clear indiciation of what the feature is expected to do, and shows you are practising TDD. This is easy for new features, but a little more involved when refactoring existing work that has no coverage.
As an example, lets say you are refactoring an existing controller and the services it depends on.
- Create a new spec for the controller and write some tests that assert the expectation of the controller (returns 200 OK, has x,y in the body etc), building out the controller as you complete each test and it passes.
- Once you reach a point where there is enough definition to create a commit, do so, and then create a PR and invite the team in to review your WIP
- Repeat this process for dependent services
Any code from the old/legacy controller that you feel is useful should be introduced to the new controller after the tests are written and you the SUT starts to emerge. That way your new controller tests only pass if the code works in the expected way.
Once the new controller and services are complete, update the routes to point to the new controller, and now you can delete the old controller/components.
- For the function names inside controllers, use full names for clarity instead of destructuring the methods from the controller, such as
someService.someMethod()
instead ofsomeMethod()
- From the controllers, export only the functions needed in the routes, since there is no true 'private' way in javascript.
- There should not be methods inside the controllers that are not used in the routes, consider moving them into a service.
- Use
lowerCamelCase
for all method names. - Method names should be descriptive and properly name the scope of the function.
- Do not prefix functions by underscore to signify 'private', any private functions should be declared after the non-private functions and should not be exported. When / where is used, TypeScript makes it easy to identify private functions in classes with the proper private definition.
- The
routes/index.js
file is responsible for defining the top-level routes, and delegating their responsibility to a route file in the same directory to define any further sub-routes needed; there should be no routes in the app.js file except using theroutes/index.js
. - All routes should follow the general pattern of
controller-name/method-name
(usingdashed-case
where needed). - Routes should use the methods prepended with the type of request (get / post) in the controller (all
lowerCamelCased
, i.econtrollerName.getMethodName
for a GET request tocontroller-name/method-name
).
Small example for creating the routes (using school controller with method1 as an example):
app.js
only doesapp.use('/', index)
where index isrequire('./routes/index')
index.js
defines the top-level routes, such as:
// ... imports
const schoolRoute = require('./school')
router.get('/school', schoolRoute)
module.exports = router
school.js
inroutes/
exports a router that defines the routes for/school
, like:
// ... imports
const schoolController = require('../controllers/school)
router.get('/method1', schoolController.method1)
module.exports = router
It may be useful to use madge for existing modules to view the dependency graph. This may help in quickly identifying older code, that should be reviewed to see if needs to be refactored.
The process for developing new features is as follows...
- Pull the latest version of the master branch
- Create a new branch using the above naming conventions
- Integrate bug/feature
- pull master branch and merge back into feature/bug branch 4.1 Optional: Rebase and squash extraneous commits
- Push branch back to remote.
- Create Pull Request. The name must be of the format 'branch-name' + 'brief description'. If the branch name contains a sufficient description, omit the brief description.
- Set the assignee to yourself.
- Get at least 1 review approval.
- Choose 'Squash & merge' option to merge back into master branch
- Delete remote branch
- Delete local branch
- Brew tea & eat biscuits
- run
ng lint
- run
ng test
- run
ng serve --aot --open
- run ruby tests (see additional documentation) [TODO: add link]
- browse application locally and exercise new functionality
Upon development of a new feature or bug the contributor will have to check the latest code locally or update to the latest version from master branch.
After making the necessary commits to reach completion the contributor can raise a pull request through GitHub against master branch.
The dev team members should be assigned as reviewers and as soon as the code changes have been accepted the pull request can be merged using the option 'Squash and merge'
Codacy is an automated code analysis/quality tool that the team integrated with GitHub.
Travis is a hosted, distributed continuous integration service used to build and test software projects hosted at GitHub.
In Javascript the only way to "freeze" a computation and have the "rest of it" execute latter (asynchronously) is to put "the rest of it" inside a callback. When multiple callbacks are nested after each other in a chain of asynchronous activity the code is much harder to read. For more information readhere.
Solutions like promises and async functions drastically decrease the complexity and the length of callbacks and make the logical flow of the code much easier to follow.
Promisesare a way to write async code that still appears as though it is executing in a top-down way, and handles more types of errors due to encouraged use of try/catch style error handling.
Async functions will further wrap generators and promises in a higher level syntax.
Javascript is constantly changing and is actually just an implementation of a standard called ECMAScript.The term ECMAScript 6 or 7 refers to the specific version of this standard.
Taking into account thatcross-browser compatibilityis necessary, HTML, CSS and Javascript must render web pages in the same way.
For the purpose of testing the following libraries are used:
- Karma- a test runner that spawns a web server and executes source code against test code for each of the browsers connected
- Jasminetesting framework for JavaScript
- Sinona standalone tool to create test spies, stubs and mocks
Code coverage is achieved throughIstanbulwhich is an instrumentation library that tracks statement, branch, function coverage and generates a full report.
Migrations are incremental. Never edit an existing one, always create a new one and perform any transformations of existing data as necessary.