我如何在一个有直接手森林(tslint,更漂亮的设置等)的项目中将事物整理好

你好 请联系Omelnitsky Sergey 。 今天,我将与您分享我的头疼问题之一,即当许多多层次程序员使用有角度的应用程序示例编写项目时该怎么做。



碰巧的是,很长一段时间我只与团队合作,在那里我们就格式,注释,缩进等规则达成了长期共识。 我习惯了他们,快乐地生活在一起。 为了庆祝,我什至发表了一篇关于Habr的文章,介绍了我们的代码风格 。 因此,出于某种神奇的目的,我们在预提交时仅使用了tslint。


然后我们成长了。 出现了一个带有继承代码的新项目,除新开发人员外,还有4个好伙伴。 甚至在这里也没有按计划进行。



我想很多人都知道使用遗留代码并不高。 在我的记忆中,我只收到了一个令我感到高兴的项目,其余的……我在说什么?)哦,是的。


坦白地说,项目中的体系结构还有很多不足之处,我们只梦想发表评论和打字。 在某个时候,我为我们的文档不符合设计规则而工作,没有编写注释,类型-这是什么让我感到很难过。 在这里有必要对此做一些事情。


对于那些迫不及待想立即查找所有步骤的人:
  • 我们将tslint分为软规则(用于预提交)和硬规则(用于ide,以便它使我们想起开发人员忘记做的事情)


  • 挂起硬tslint可能的规则的预提交自动修复


  • 编写更漂亮的规则


  • 用铃鼓跳舞,使皮棉阶段的皮棉运动



第一步-分而治之


当我想到收紧短绒规则时,我以为我们会上吊。 该代码是继承的。 您需要了解它,并且您可以以这样的数量进行挖掘。 决定为ide创建一个第二个linter,这将是一件令人费解的事情,并且会强制为方法和sv-c编写jsdoc,编写接口或不适当地的onPush等。


因此,从根开始,我们开始放置2个tslin文件:


tsconfig.json
{ "rulesDirectory": [ "node_modules/codelyzer" ], "rules": { "arrow-return-shorthand": true, "callable-types": true, "class-name": true, "comment-format": [ true, "check-space" ], "curly": true, "deprecation": { "severity": "warn" }, "eofline": true, "forin": true, "import-blacklist": [ true, "rxjs/Rx" ], "import-spacing": true, "indent": [ true, "spaces" ], "interface-over-type-literal": true, "label-position": true, "max-line-length": [ true, 200 ], "member-access": false, "member-ordering": [ true, { "order": [ "static-field", "instance-field", "static-method", "instance-method" ] } ], "no-arg": true, "no-bitwise": true, "no-console": [ true, "debug", "info", "time", "timeEnd", "trace" ], "no-construct": true, "no-debugger": true, "no-duplicate-super": true, "no-empty": false, "no-empty-interface": true, "no-eval": true, "no-inferrable-types": [ false, "ignore-params" ], "no-duplicate-imports": true, "no-misused-new": true, "no-non-null-assertion": true, "no-redundant-jsdoc": true, "no-shadowed-variable": false, "no-string-literal": false, "no-string-throw": true, "no-switch-case-fall-through": true, "no-trailing-whitespace": [ true, "ignore-comments", "ignore-jsdoc" ], "no-unnecessary-initializer": true, "no-unused-expression": true, "no-use-before-declare": false, "no-var-keyword": true, "object-literal-sort-keys": false, "one-line": [ true, "check-open-brace", "check-catch", "check-else", "check-whitespace" ], "prefer-const": true, "quotemark": [ true, "single" ], "radix": false, "semicolon": [ true, "always" ], "triple-equals": [ true, "allow-null-check" ], "typedef-whitespace": [ true, { "call-signature": "nospace", "index-signature": "nospace", "parameter": "nospace", "property-declaration": "nospace", "variable-declaration": "nospace" } ], "unified-signatures": true, "variable-name": false, "whitespace": [ true, "check-branch", "check-decl", "check-operator", "check-separator", "check-type" ], "directive-selector": [ true, "attribute", "app", "camelCase" ], "component-selector": [ true, "element", "app", "kebab-case" ], "no-output-on-prefix": false, "no-inputs-metadata-property": true, "no-outputs-metadata-property": true, "no-host-metadata-property": true, "no-input-rename": false, "no-output-rename": true, "use-lifecycle-interface": true, "use-pipe-transform-interface": true, "component-class-suffix": true, "directive-class-suffix": true, "no-consecutive-blank-lines": true } } 

tslint.ide_only.json
 { "rulesDirectory": [ "node_modules/codelyzer" ], "rules": { "completed-docs": [ true, { "properties": true, "methods": true } ], "no-angle-bracket-type-assertion": true, "no-any": true, "prefer-output-readonly": true, "prefer-on-push-component-change-detection": true, "array-type": [ true, "array" ], "typedef": [ true, "call-signature", "arrow-call-signature" ], "arrow-return-shorthand": true, "callable-types": true, "class-name": true, "comment-format": [ true, "check-space" ], "curly": true, "deprecation": { "severity": "warn" }, "eofline": true, "forin": true, "import-blacklist": [ true, "rxjs/Rx" ], "import-spacing": true, "indent": [ true, "spaces" ], "interface-over-type-literal": true, "label-position": true, "max-line-length": [ true, 200 ], "member-access": [ true, "check-parameter-property", "check-accessor" ], "member-ordering": [ true, { "order": [ "public-static-field", "protected-static-field", "private-static-field", "public-instance-field", "protected-instance-field", "private-instance-field", "constructor", "public-static-method", "protected-static-method", "private-static-method", "public-instance-method", "protected-instance-method", "private-instance-method" ] } ], "no-arg": true, "no-bitwise": true, "no-console": true, "no-construct": true, "no-debugger": true, "no-duplicate-super": true, "no-empty": false, "no-empty-interface": true, "no-duplicate-switch-case": true, "no-eval": true, "no-inferrable-types": [ false, "ignore-params" ], "no-duplicate-imports": true, "one-variable-per-declaration": true, "no-misused-new": true, "no-non-null-assertion": true, "prefer-template": [ true, "allow-single-concat" ], "ordered-imports": true, "no-redundant-jsdoc": true, "no-shadowed-variable": false, "no-string-literal": false, "no-string-throw": true, "no-switch-case-fall-through": true, "no-trailing-whitespace": [ true, "ignore-comments", "ignore-jsdoc" ], "ban": [ true, { "name": [ "Object", "assign" ], "message": " cloneDeep (lodash)   " } ], "max-classes-per-file": [ true, 1 ], "cyclomatic-complexity": [ true, 6 ], "static-this": true, "no-unnecessary-initializer": true, "no-unused-expression": true, "no-var-keyword": true, "object-literal-sort-keys": false, "one-line": [ true, "check-open-brace", "check-catch", "check-else", "check-whitespace" ], "prefer-const": true, "quotemark": [ true, "single" ], "radix": false, "semicolon": [ true, "always" ], "triple-equals": [ true, "allow-null-check" ], "typedef-whitespace": [ true, { "call-signature": "nospace", "index-signature": "nospace", "parameter": "nospace", "property-declaration": "nospace", "variable-declaration": "nospace" } ], "unified-signatures": true, "variable-name": false, "whitespace": [ true, "check-branch", "check-decl", "check-operator", "check-separator", "check-type" ], "directive-selector": [ true, "attribute", "app", "camelCase" ], "component-selector": [ true, "element", "app", "kebab-case" ], "no-output-on-prefix": false, "no-inputs-metadata-property": true, "no-outputs-metadata-property": true, "no-host-metadata-property": true, "no-input-rename": false, "no-output-rename": true, "use-lifecycle-interface": true, "use-pipe-transform-interface": true, "component-class-suffix": true, "directive-class-suffix": true, "no-consecutive-blank-lines": true } } 

src/tslint我们将标准tslint替换为ide


src / tslint.json
 { "extends": "../tslint.ide_only.json", "rules": { "directive-selector": [ true, "attribute", "app", "camelCase" ], "component-selector": [ true, "element", "app", "kebab-case" ] } } 

并在脚本package.json中修复了linter的启动


 ng lint --tslint-config ./tslint.json --fix` 

之后,我们开始摆脱需要纠正的带下划线的事情。


第二步-修正几点



Tslint与has fixer fixer的规则有关。 因此,让我们使用它。


 tslint --project tslint.ide_only.json --fix --force 

在这里,我们使用可用参数的自动修复来运行硬性lint的规则,并说该命令不会返回错误(这里我们的目标仍然是进行自动纠正)。


第三步-写得漂亮


当每个人都以自己的方式写作时,最终会很累。 必须编写代码,以便看起来这是由一个人完成的。 为此,我设置了以下设置,使其更漂亮:


.prettierr.yaml
 printWidth: 200 #  -    tabWidth: 2 #    singleQuote: true #    trailingComma: all #     arrowParens: always #  -  (x) => x overrides: - files: "*.ts" #   *.ts options: parser: typescript #    *.ts 

然后他添加了命令: prettier --write --config .prettierr.yaml


第四步-您如何命令全部运行?


现在,让我们仔细看看如何开始所有这一切。 为了使其正常工作,我们需要下载以下内容:


 npm i -D prettier lint-staged husky 

使用husky,我们会将命令的启动挂在git hook上-预先提交。 lint-staged将根据更改的文件为我们运行命令(也可以在命令中为我们替换这些文件)。


我还要立即概述遇到的问题。 在我们的项目中,我们使用ng lint。 当我们将其与lint阶段结合使用时,修改后的文件将添加到我们的命令中。 Ng lint具有--files键,但是据我了解,它看不到一堆文件,因此需要将此键添加到每个文件中。 为此,我必须创建一个文件:


lint.sh
 #!/bin/bash PROJECT=$1 shift SOURCES=$@ DESTINATIONS="" DELIMITER="" for src in $SOURCES do DELIMITER=" --files " DESTINATIONS="$DESTINATIONS$DELIMITER${src}" done ng lint $PROJECT --tslint-config ./tslint.json $DESTINATIONS 

要运行此文件,我们必须传递项目名称。 它位于project属性中的angular.json文件中。 就我而言,这是partner-accountpartner-account-e2e 。 我需要第一名。


返回设置。 我们的package.json现在看起来像这样:


  "husky": { "hooks": { "pre-commit": "lint-staged --relative" } }, "lint-staged": { "*.{ts,js}": [ "prettier --write --config .prettierr.yaml", "tslint --project tslint.ide_only.json --fix --force", "sh lint.sh partner-account", "git add" ], "*.{html,scss,css}": [ "prettier --write --config .prettierr.yaml", "git add" ] }, 

注意lint-staged --relative 。 此处--relative参数。 现在,当我们提交时,启动了lint-staged 。 然后,他选择文件并根据它们启动命令列表。


不幸的是,这并不能取消代码审查,但是它变得更加干净。 我注意到,我很少会开始提醒开发人员有关访问修饰符,方法和sv的描述,并且他们的工作开始以相同的风格编写(嗯,几乎是:D)。


PS-感谢您给我们的PM图片。

Source: https://habr.com/ru/post/zh-CN464383/


All Articles