-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 9448b76
Showing
4 changed files
with
215 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Created by .ignore support plugin (hsz.mobi) | ||
|
||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# Cumulocity lodash 4.x Migration (and Style) Guide | ||
|
||
## Preferable Functional Methods | ||
Conventionally speaking, we should favor lodash methods over their native and/or Angular counterparts. | ||
|
||
> Why? | ||
- [lodash blows away the performance of native functional methods.](http://benmccormick.org/2014/11/12/underscore-vs-lodash/) | ||
- lodash has more features for those functional methods such as _chaining_ and _iteratee shorthand_. | ||
- lodash provides compatibility consistency for browser which hasn't really natively supported these functions yet (read: IE). | ||
- lodash enables us to produce code in better clarity (and of course – improve style consistency :wink:), e.g. compare: `Object.hasOwnProperty` vs `_.has`, `angular.forEach` vs `_.forEach`. | ||
|
||
![http://cloud.highcharts.com/images/utusen/0/400.pdf](400.png) | ||
|
||
|
||
Here are the two equivalence tables (note that the lists maybe incomplete, I only extract the common ones we use in our code): | ||
|
||
### Native | ||
| Native method | lodash method | | ||
| --- | --- | | ||
| `Function.prototype.bind` | `_.bind` | | ||
| `Array.prototype.forEach` | `_.forEach` | | ||
| `Array.prototype.map` | `_.map` | | ||
| `Array.prototype.filter` | `_.filter` | | ||
| `Array.prototype.reduce` | `_.reduce` | | ||
| `Object.hasOwnProperty` | `_.has` | | ||
| `Object.keys` | `_.keys` | | ||
| `Object.values` | `_.values` | | ||
|
||
### Angular | ||
| Angular method | lodash method | | ||
| --- | --- | | ||
| `angular.bind` (beware that Angular [`.bind`](https://docs.angularjs.org/api/ng/function/angular.bind) function signature expects different arguments order) | `_.bind` | | ||
| `angular.copy` | `_.cloneDeep` | | ||
| `angular.equals` | `_.isEqual` | | ||
| `angular.extend` | `_.assign` | | ||
| `angular.forEach` | `_.forEach` | | ||
| `angular.identity` | `_.identity` | | ||
| `angular.isArray` | `_.isArray` | | ||
| `angular.isDate` | `_.isDate` | | ||
| `angular.isDefined` | `!_.isUndefined` | | ||
| `angular.isElement` | `_.isElement` | | ||
| `angular.isFunction` | `_.isFunction` | | ||
| `angular.isNumber` | `_.isNumber` | | ||
| `angular.isObject` | `_.isObject` | | ||
| `angular.isString` | `_.isString` | | ||
| `angular.isUndefined` | `_.isUndefined` | | ||
| `angular.merge` | `_.merge` | | ||
| `angular.noop` | `_.noop` | | ||
|
||
## Preferable lodash Functional Method Aliases | ||
In our code, lodash functional method aliases have been used inconsistently. :disappointed: So, please help yourself to make it more consistent! | ||
|
||
| Alias | Favorable alias | | ||
| --- | --- | | ||
| `_.all` | `_.every` | | ||
| `_.any` | `_.some` | | ||
| `_.each` | `_.forEach` | | ||
| `_.extend` (beware that lodash 4.x [`.extend`](https://lodash.com/docs/4.16.2#assignIn) behaves differently and **not** an alias for `.assign`) | `_.assign` | | ||
| `_.unique` | `_.uniq` | | ||
| `_.chain` | `_()` (yup, prefer implicit chaining. Also, beware that in implicit chaining, the wrapper [methods that are not chainable](https://lodash.com/docs/4.16.2#lodash) will end the chaining without the need of calling `.value()`, e.g. `.forEach`, `.reduce`) | | ||
|
||
## Breaking Changes in 4.x (Method Removals and Renames) | ||
[R.T.F. Changelog](https://github.com/lodash/lodash/wiki/Changelog#v400). :shipit: | ||
|
||
Known to be used in our project are: | ||
- `_.include` -> `_.includes` | ||
- `_.contains` -> `_.includes` | ||
- `_.pluck` -> `_.map` with iteratee shorthand | ||
- `_.where` -> `_.filter` with iteratee shorthand | ||
- `_.first` -> `_.head` | ||
- `_.invoke` -> `_.invokeMap` | ||
- `_.rest` -> `_.tail` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
const _ = require('lodash'); | ||
const replace = require('replace'); | ||
|
||
const replacementSpecs = [ | ||
{ | ||
regex: 'Object[.]hasOwnProperty', | ||
replacement: '_.has', | ||
}, | ||
{ | ||
regex: 'Object[.]keys', | ||
replacement: '_.keys', | ||
}, | ||
{ | ||
regex: 'Object[.]values', | ||
replacement: '_.values', | ||
}, | ||
{ | ||
regex: 'angular[.]copy', | ||
replacement: '_.cloneDeep', | ||
}, | ||
{ | ||
regex: 'angular[.]equals', | ||
replacement: '_.isEqual', | ||
}, | ||
{ | ||
regex: 'angular[.]extend', | ||
replacement: '_.assign', | ||
}, | ||
{ | ||
regex: 'angular[.]forEach', | ||
replacement: '_.forEach', | ||
}, | ||
{ | ||
regex: 'angular[.]identity', | ||
replacement: '_.identity', | ||
}, | ||
{ | ||
regex: 'angular[.]isArray', | ||
replacement: '_.isArray', | ||
}, | ||
{ | ||
regex: 'angular[.]isDate', | ||
replacement: '_.isDate', | ||
}, | ||
{ | ||
regex: 'angular[.]isDefined', | ||
replacement: '!_.isUndefined', | ||
}, | ||
{ | ||
regex: 'angular[.]isElement', | ||
replacement: '_.isElement', | ||
}, | ||
{ | ||
regex: 'angular[.]isFunction', | ||
replacement: '_.isFunction', | ||
}, | ||
{ | ||
regex: 'angular[.]isNumber', | ||
replacement: '_.isNumber', | ||
}, | ||
{ | ||
regex: 'angular[.]isObject', | ||
replacement: '_.isObject', | ||
}, | ||
{ | ||
regex: 'angular[.]isString', | ||
replacement: '_.isString', | ||
}, | ||
{ | ||
regex: 'angular[.]isUndefined', | ||
replacement: '_.isUndefined', | ||
}, | ||
{ | ||
regex: 'angular[.]merge', | ||
replacement: '_.merge', | ||
}, | ||
{ | ||
regex: 'angular[.]noop', | ||
replacement: '_.noop', | ||
}, | ||
{ | ||
regex: '_[.]all', | ||
replacement: '_.every', | ||
}, | ||
{ | ||
regex: '_[.]any', | ||
replacement: '_.some', | ||
}, | ||
{ | ||
regex: '_[.]each', | ||
replacement: '_.forEach', | ||
}, | ||
{ | ||
regex: '_[.]extend', | ||
replacement: '_.assign', | ||
}, | ||
{ | ||
regex: '_[.]unique', | ||
replacement: '_.uniq', | ||
}, | ||
{ | ||
regex: '_[.]chain', | ||
replacement: '_', | ||
}, | ||
{ | ||
regex: '_[.]include', | ||
replacement: '_.includes', | ||
}, | ||
{ | ||
regex: '_[.]contains', | ||
replacement: '_.includes', | ||
}, | ||
{ | ||
regex: '_[.]pluck', | ||
replacement: '_.map', | ||
}, | ||
{ | ||
regex: '_[.]where', | ||
replacement: '_.filter', | ||
}, | ||
{ | ||
regex: '_[.]first', | ||
replacement: '_.head', | ||
}, | ||
{ | ||
regex: '_[.]invoke', | ||
replacement: '_.invokeMap', | ||
}, | ||
{ | ||
regex: '_[.]rest', | ||
replacement: '_.tail', | ||
}, | ||
]; | ||
|
||
_.forEach(replacementSpecs, replacementSpec => replace({ | ||
regex: replacementSpec.regex, | ||
replacement: replacementSpec.replacement, | ||
paths: ['/Users/glenn/cumulocity/cumulocity-ui/app/scripts'], | ||
recursive: true, | ||
})); |