From a1cb36afda90259dd88a031181cc4d8ca647d4fe Mon Sep 17 00:00:00 2001 From: Mark Tyers Date: Sat, 13 May 2017 19:03:50 +0100 Subject: [PATCH] added text from slides --- book/{CHAPTER00.md => 00 Introduction.md} | 0 book/{CHAPTER01.md => 01 Intro to NodeJS.md} | 0 ...APTER02.md => 02 Objects and Functions.md} | 0 ...PTER03.md => 03 Asyncronous JavaScript.md} | 0 ...{CHAPTER04.md => 04 Understanding APIs.md} | 0 book/{CHAPTER05.md => 05 Building APIs.md} | 0 ...CHAPTER06.md => 06 Advanced API Design.md} | 0 book/07 Writing Robust Code.md | 343 ++++++++++++++++++ book/08 Data Persistence.md | 125 +++++++ book/09 Automated Testing.md | 165 +++++++++ 10 files changed, 633 insertions(+) rename book/{CHAPTER00.md => 00 Introduction.md} (100%) rename book/{CHAPTER01.md => 01 Intro to NodeJS.md} (100%) rename book/{CHAPTER02.md => 02 Objects and Functions.md} (100%) rename book/{CHAPTER03.md => 03 Asyncronous JavaScript.md} (100%) rename book/{CHAPTER04.md => 04 Understanding APIs.md} (100%) rename book/{CHAPTER05.md => 05 Building APIs.md} (100%) rename book/{CHAPTER06.md => 06 Advanced API Design.md} (100%) create mode 100644 book/07 Writing Robust Code.md create mode 100644 book/08 Data Persistence.md create mode 100644 book/09 Automated Testing.md diff --git a/book/CHAPTER00.md b/book/00 Introduction.md similarity index 100% rename from book/CHAPTER00.md rename to book/00 Introduction.md diff --git a/book/CHAPTER01.md b/book/01 Intro to NodeJS.md similarity index 100% rename from book/CHAPTER01.md rename to book/01 Intro to NodeJS.md diff --git a/book/CHAPTER02.md b/book/02 Objects and Functions.md similarity index 100% rename from book/CHAPTER02.md rename to book/02 Objects and Functions.md diff --git a/book/CHAPTER03.md b/book/03 Asyncronous JavaScript.md similarity index 100% rename from book/CHAPTER03.md rename to book/03 Asyncronous JavaScript.md diff --git a/book/CHAPTER04.md b/book/04 Understanding APIs.md similarity index 100% rename from book/CHAPTER04.md rename to book/04 Understanding APIs.md diff --git a/book/CHAPTER05.md b/book/05 Building APIs.md similarity index 100% rename from book/CHAPTER05.md rename to book/05 Building APIs.md diff --git a/book/CHAPTER06.md b/book/06 Advanced API Design.md similarity index 100% rename from book/CHAPTER06.md rename to book/06 Advanced API Design.md diff --git a/book/07 Writing Robust Code.md b/book/07 Writing Robust Code.md new file mode 100644 index 0000000..8e73193 --- /dev/null +++ b/book/07 Writing Robust Code.md @@ -0,0 +1,343 @@ + +# Writing Robust Code + +Lots of important tools and techniques + +Need to apply these to successfully complete your work + +Increase your chances of gaining a much higher grade. + +- Modules +- Linters +- Debuggers +- Documentation + +## Modules + +Beginners often put all their code into a single file. +This: + +- Creates a huge file! +- Makes it difficult to find stuff +- Makes it impossible to write unit tests... + +NodeJS implements the CommonJS format + +This is part of the ECMA6 standard + +You should use these to organise your code + +### System Architecture + +Implement the MVC pattern + +- The route file is your controller +- The modules will be your model +- There is no view... + +Identify your API collections + +One module per collection + +Minimise module dependencies + +Identify shared functionality (e.g. auth, settings) + +Put these in their own modules + +### CommonJS + +By default all functions and vars are private + +Uses an object called exports + +Any property assigned to this object is exported + +These can then be imported into another script + +Here is a simple module: +```javascript +// shopping.js +var data = new Map() + +exports.count = () => { + return data.size +} +``` +And here is how we import this module into our code: +```javascript +const list = require('./shopping') + +const size = list.count() +console.log(`there are ${size} items`) +``` + +## Linters + +### The Lint Tool + +An old program that flagged suspicious constructs in C language source code. + +Would go through the C code + +Identify problems before it was compiled, linked, and run + +It was a static checker (didn't run the code) + +### Linters + +Programs that can be run by a developer + +Reads the source code + +Checks it for programmatic and stylistic errors. + +Helps to identify many common mistakes + +Ensures: + +- You avoid using some 'buggy' language constructs +- The style of your code is consistent. +- Forces you to use a safe 'subset' of the language + +Very important to lint JavaScript code! + +Many different language features, styles and techniques + +Many should be avoided to prevent potential bugs + +Many different JavaScript linters + +Original one by Doug Crockford (JSLint) + +Very opinionated about what was 'good' JS + +Forced programmers to use his style! + +In this module we use ESLint + +More powerful and completely configurable + +Plug-ins available for most IDEs (and Cloud9) + +## Debuggers + +Software used to test and debug your programs. + +Contains some key features to support you: + +- Pausing the program at a defined line (breakpoint) +- Executing the code line by line (single-stepping) +- Tracking the values of variables + + +- Step Over + - Execute the next line of code and move to the line directly below +- Step In + - Execute the next line by dropping into the function +- Step Out + - Run to the end of the current function then pass control to its caller +- Continue Execution + - Run the program to the next breakpoint (or the end of the program) + +### Types of Debugger + +Debuggers fall into two main categories: + +- Terminal debuggers + - Run through the terminal + - Need to learn the debugger commands +- Visual Debuggers + - Integrated into the IDE + - Mouse-driven interface + +### Terminal Debugger + +NodeJS offers a terminal debugger + +Breakpoints are added directly to the code + +Script is run in debug mode + +Can add watchers to monitor variables + +Commands for stepping through code. + + +### Visual Debugger + +Cloud9 offers a visual debugger + +Breakpoints added in editor by clicking in left gutter + +Buttons for step-over, step-in, step-out, continue + +Editor provides pane to view variables + +## Documentation Generators + +Programming tools + +Generate software documentation from a source code files. + +### JSDoc + +A markup language + +Based on Javadoc + +Used to annotate JavaScript code. + +Batch processed by a special tool + +Generates a HTML website + +Contains the human-readable documentation +```javascript +/** + * Returns details for the named item. + * @param {string} item - The item name + * @returns {string} The name of the item + * @throws {InvalidItem} item not in list + */ + ``` + http://usejsdoc.org + + ## NodeJS Modules + +Follows CommonJS standard + +This forms part of the latest ECMA6 standard + +Simple approach to writing and importing functionality + +Keeps private data private +```javascript +exports.command = function(data) { + // do stuff... +} + +var todo = require('./todo.js') +todo.command('Hello World!') +``` + +Like any good language, JavaScript has lots of useful libraries and frameworks available + +Many of these are specifically designed to work with Node on a server: + +To install, manage, and uninstall any packages that you would like to use, Node ships with NPM: the Node Package Manager. + +### Node Package Manager + +Node has a large package/library ecosystem + +Useful for common functionality - just use a pre-written module + +Modules are managed by the "Node Package Manager" NPM + +https://www.npmjs.com + +To install a module, use the npm command +``` +npm install module_name --save +``` +--save adds details to package.json + +### Developer Modules + +Some packages are to support development + +Eslint, jsdoc, etc. + +Not needed to run the API on the server + +Added using the --save-dev flag +``` +npm install module_name --save-dev +``` +Different section in package.json +```json +"dependencies": { + "request": "^2.67.0" +}, +"devDependencies": { + "eslint": "^3.1.0" +} +``` + +## Publishing NodeJS Modules + +Importing modules you have created has a problem + +Correct path needs to be provided + +Can get messy: +```javascript +const async = require('../../mod/async') +``` +We want: +```javascript +const async = require('async') +``` + +### Local Module Dependencies + +You have already imported modules from npmjs + +You can also define and import local modules +``` +npm install --save ./mod/async +``` +This will copy your module into node_modules +```json +{ + "name": "bookshop", + "dependencies": { + "request": "^2.67.0", + "async": "file:local_modules/async", + } +} +``` + +### What is a Module? + +Any directory that has a package.json file + +Everything in the directory will be included + +Files in the .gitignore or .npmignore file will not be published + +### Reloading a Module + +There are several approaches: + +Use the `rm-local-modules` command + +Increment the version number in its `package.json` then `npm install` + +Delete and reload +``` +rm -rf node_modules/async +npm install +``` + +### Logging into NPMJS + +Need an account and to be logged in +``` +npm adduser +npm login +``` +Check account details +``` +npm config ls +``` + +https://www.npmjs.com/~ + +### Publishing to NPMJS + +Package name must not exist in npmjs +``` +npm publish +``` \ No newline at end of file diff --git a/book/08 Data Persistence.md b/book/08 Data Persistence.md new file mode 100644 index 0000000..ba84bb9 --- /dev/null +++ b/book/08 Data Persistence.md @@ -0,0 +1,125 @@ + +# Data Persistence + +Data from other APIs / Screen scraping read only + +Need to add value to this + +Demonstrate CRUD + +So need to store data + +Script restart needed if code changes + +Filesystem + +Relational database + +Document database + +Graph database + +## Filesystem + +Stores text in file against key + +Formatted as JSON data + +Easy to store and retrieve by key + +Simple to implement + +Difficult to query +```javascript +const storage = require('node-persist') +storage.initSync() + +exports.addBook = function(isbn, callback) { + const data = { + title: 'The Hobbit', + authors: 'J.R.R. Tolkien', + description: 'Hobbit finds ring...' + } + storage.setItemSync(isbn, data) +} +``` + +## Relational Database + +Familiar data storage + +Supports complex queries + +Difficult to scale + +Data needs normalising +```javascript +const mysql = require('mysql') +const request = require('request') + +const connection = mysql.createConnection({ host: 'xxx', port: '3306', user: 'xxx', password: 'xxx', database: 'xxx' }) + +const sql = 'INSERT INTO books (id, title, authors, description) VALUES (NULL, "The Hobbit, "J.R.R. Tolkien", "Ring found")' + +connection.query(sql, (err, rows) => { + if (err) callback( Error(`database error: ${err}`) ) + return callback(null, rows) +}) +``` + +## Document Database + +Stores JavaScript objects + +Can be queried using JavaScript + +Mongoose Example. + +Start by defining a _schema file_: +```javascript +const mongoose = require('mongoose') +mongoose.Promise = global.Promise +const Schema = mongoose.Schema + +const bookSchema = new Schema({ + title: String, + authors: String, + description: String +}) +const Book = mongoose.model('Book', bookSchema) +module.exports = Book +``` +Storing a document. +```javascript +const book = new Book({ + title: data.title, +authors: data.authors, + description: data.description +}) + +book.save( function(err, book) { +if (err) { + callback( Error(`database error: ${err}`) ) + } + return callback(null, book) +}) +``` + +## Document Databases + +Good for modelling relationships + +## Choosing a Database + +Factors: + +- Type of data to be stored +- How this will be retrieved +- Complexity + +Online Hosting + +- Relational MySQL freemysqlhosting.net +- Document MongoDB mlab.com +- Graph Neo4J graphenedb.com + diff --git a/book/09 Automated Testing.md b/book/09 Automated Testing.md new file mode 100644 index 0000000..2a9131e --- /dev/null +++ b/book/09 Automated Testing.md @@ -0,0 +1,165 @@ + +# Automated Testing + +- Unit Testing +- Code Coverage +- Acceptance Testing + +### Traditional Development + +we write code until it 'works' + +follow an agreed architectural design + +### Why Test + +Adding features often introduces bugs + +Testing needs to take place on a regular basis + +- Check that our new code works +- Check we have not broken earlier code! + +Unfortunately manual testing is time consuming + +So it is often left out… + +### Automated Testing + +Involves writing code to test your code + +This code can be quickly run whenever you add a new feature + +Like a robot to do all the boring stuff + +Benefits: + +- Run same tests repeatedly/accurately +- Run a large 'suite' of tests +- No human time wasted + +- Quick one-click testing of all the code +- Prevents human error creeping in +- Ensure bugs have not crept into existing code +- Check that there are no bugs in new code +- When all the tests pass, your software is complete! + +### Types of Automated Testing + +- Unit Testing + - Testing code logic directly (functions) + - Sometimes called ‘white-box’ testing +- Acceptance Testing + - Testing the application as a ‘user’ + - Sometimes called ‘black-box’ testing + +### How Many Tests? + +Cover all routes in code + +Test median, edge and bad data cases + +If in doubt add more tests… + +Check code coverage + +### Unit Testing + +Automated testing + +Write logic to test discrete parts of the application + +Tests written before code is written + +Take a bit of up-front time to write + +Long-term savings + +### Components + +- An Assert Module + - defines the tests to carry out + - The built-in NodeJS Assert module +- A Test Runner + - Carries out the tests and reports the results + - The Jasmine package + +The test runner is a program that runs the tests + +In these examples we will be using Jasmine + +a nodejs package + +### Regression Testing + +Are we introducing bugs in previously working code? + +All existing code should be supported by exhaustive tests + +Even if a test is passed we should always carry it out + +All tests run every time code changes + +### Fixing Bugs + +Write a test to replicate the bug + +Test should of course fail every time it runs + +Try to fix the bug + +Bug is fixed when the test(s) pass + +Test name should match bug name/code + +### Test-Driven Development + +start by defining the goal + +unit tests are both specification and documentation + +we define our functionality through the tests + +we write our tests before starting to 'code' + +forces us to think about what we are writing + +### TDD Workflow + +- Write the tests first (they will fail) +- Write enough code to pass the tests + - simplest solution that could possibly work +- Commit the working code +- Refactor the code to improve +- Comments/documentation +- Commit (again) + +## Code Coverage + +How much of the code is being tested? + +Are all code branches being tested? + +How many times are each line tested? + +Helps identify any blind-spots + +also consider range of test data... + +### Coverage Criteria + +- Function coverage + 0 Has each function in the program been called? +- Statement coverage + - Has each statement in the program been executed? +- Branch coverage + - Has each branch of each control structure been executed? +- Condition coverage (or predicate coverage) + - Has each Boolean sub-expression evaluated both to true and false? + +### Benefits of TDD + +- Working code +- Enforcing single responsibility +- Conscious development +- Improved productivity