read javascript the hidden part

read javascript the hidden part

我们经常继承那些已经成长并演变成难以管理的项目。作为参与该项目开发人员之一,您有权对现有代码组织进行更改。你应该有信心向团队中的其他人提出任何问题或关注,并让大家达成共识,明确今后的做法以及如何处理技术债务。

good README:

  • How to start the project
  • File/folder conventions
  • How to handle common issues

create folder structure: 设置一个地方来存放模板文件,这样你就可以在不同的文件夹中复制和粘贴。这样开发人员每次需要新建文件时就不必从头开始了

|__client
|____components
|____helpers(or utils)
|__server
|____models
|____crons

在前端,我们使用帕斯卡命名法来命名文件,而在后端我们使用驼峰命名法。这只是为了向您展示,在整个技术栈中可以遵循不同的约定。

在组件和传递属性方面,Angular比React更加具体化

在后端方面,您可能更关注用户对应用程序中可访问数据的身份验证和授权方式以及如何获取和传输该数据到各个地方。

backend:

  • REST API
  • microservices
  • graphQL

microservices

|__api
|____users
|______getUserProfile.ts
|______updateUserProfile.ts
|______userProfiles.ts

GraphQL 相对较新,并且你将看到它被广泛使用的方式也会各不相同。当需要在前端显示复杂数据结构时,通常会使用它。尽管您可能还会看到它被用来替代 REST API。

GraphQL 由类型、模式、查询和突变组成,因此项目结构可以非常扁平化

|__src
|____resolvers
|______users.ts
|______accounts.ts
|______products.ts
|____types
|______users.sdl.ts
|______accounts.sdl.ts
|______products.sdl.ts

所有与数据库中的数据交互的查询和变更将存储在resolvers文件夹下,并且解析器的类型定义将在types文件夹中定义。您可能会使用Apollo来构建这种类型的后端,它是业界标准工具,并且对项目结构有一些意见,这将极大地影响您放置文件的位置。

根据您正在开发的应用程序类型,需要关注不同功能。某些应用程序必须遵守HIPAA或PCI等法规要求,这可能会影响很多开发决策。数据管理方式也会影响代码选择方式。

Fin-tech

One good strategy is to focus on component-driven development on the front-end. This applies to any app you build, regardless of the functionality. It helps keep data-heavy components in a reusable and testable state that you can build more complex views on top of.

components are the building blocks for views, which are specific sections of pages.

|__src
|____tests
|______LoginModal_test.ts
|______AdminAuth_test.ts
|______UserAuth_test.ts
|____components
|______LoginModal.ts
|______AdminAuth.ts
|______UserAuth.ts
|______FilterDropdown.ts
|______SearchInput.ts
|______Form.ts
|____pages
|______Accounts.ts
|______Settings.ts
|______Tools.ts
|____views
|______AccountActivity.ts
|______AccountInfo.ts
|______AccountStatements.ts
|______AccountSettings.ts
|______UserSettings.ts
|______AdminSettings.ts
|______BudgetTool.ts
|______PaymentTool.ts

|__api
|____db
|______userModel.ts
|______accountModel.ts
|______settingsModel.ts
|____repositories
|______users.ts
|______accounts.ts
|______settings.ts
|____utils
|______logger.ts
|______helpers.ts
|____services
|______auth.ts
|______email.ts
|______caching.ts
|____tests
|____routes.ts

TODO: need more deep reading

开发人员常犯的一个错误就是在完全理解问题所在之前就急于编写代码。在我职业生涯早期,我会被分配任务后立即开始编码。然后到了某个时候,我不知道下一步该往哪个方向走了。

如果当时停下来问一些背景问题、勾画出一些草图,并花时间去弄清楚细节,那将为我节省了大量重构时间和挫败感。

如果你的公司没有一个强大的产品团队或设计师,你可能需要通过提问来填补这个空白。在初创企业中,这种情况经常发生

尽早推动可访问性和响应式。对于视力障碍者、听力障碍者以及神经发育异常人群来说,可访问性至关重要。每个人都会说“我们稍后再回头处理”,但除非出现巨大问题,否则几乎永远不会发生。但是,在许多国家中,实际上要求遵守无障碍法规,并且响应能够吸引用户返回使用该应用程序。希望通过向产品经理和团队解释这一点,您可以获得额外时间来实施诸如WAI-ARIA用于可访问导航以及在多种设备上进行响应等功能。

继承一个现有的代码库。在了解项目组织和功能方式之后,你应该开始寻找技术债务。技术债务包括

  • 更新软件包
  • 清理过时的代码以符合最佳实践
  • 重新组织代码以适应新产品需求

即使你没有时间在推出新功能时进行修复,也没关系。保持一个记录问题的文档,并确保向团队成员和利益相关者传达这些问题

根据自己的意愿更新代码库,尤其是如果没有其他人有强烈意见。即使他们有意见,在此过程中也是了解项目工作方式以及获取一些关于思考过程反馈的好机会。看到其他开发人员如何处理技术债务问题总是很有趣,因为他们能给出一些你可能没有考虑到的见解

对于项目后端而言,存在一组核心问题需要考虑:安全性、授权、性能、与数据库交互、与多个第三方服务合作以及处理任务队列等等。根据项目类型不同,还可能需要考虑消息队列、缓存或处理大量数据的问题。

如果最大关注点是速度,则可以考虑像Go这样的语言。如果您需要大量可导入库和包,请选择Python、JavaScript或Ruby等语言。如果您正在开发游戏特定应用程序,则C#可能是一个很好的选择。

写文档是任何项目中都会出现的另一个隐藏任务

通过模块化,您可以快速确定哪些响应需要不同级别的授权,以及哪些响应需要传递大量数据负载,从而确定是否将数据缓存是一个好选择。编写实施计划的草稿代码将迅速显示出技术上的差距所在。在编写了关于功能如何运作的文档后,您可以开始填充细节。

这将给您一个机会去研究可用的工具和服务,比如Redis用于缓存、OAuth标准用于不同身份验证/授权需求以及Sentry用于日志记录。另外一个很少有人谈论到的隐藏事实是,在处理复杂功能(例如缓存、处理消息队列甚至支付系统)时使用工具和服务是可以接受的。

除非您正在开发提供其中一项服务的应用程序,否则预期您使用某种替代方案而不是试图自行构建它。这就是为什么拥有代码概要非常重要。过早深入任何细节可能导致您被锁定在特定供应商或严格架构中,并且即使随着时间推移变得越来越复杂也必须遵循。

working on a existed backend:

  • 为其他应用程序消费创建一个新版本的API
  • 添加新包以清理到处都是的自定义混乱代码
  • 增加更多测试覆盖率以减少生产环境中出现的错误

在现有的后端中,安全性是你应该考虑的首要问题之一。JavaScript Web Tokens (JWT) 是否只包含了最少量的必要信息?是否有些数据应该限制为仅供具备相应权限的个人用户或用户组使用?你是否发现了任何可能被OWASP十大漏洞(开发者和Web应用程序安全标准意识文件)所利用的潜在风险?外部人员通过你的API能否轻易找到内部资源?恶意用户是否可以通过请求过多数据来对你的应用进行分布式拒绝服务(DDOS)攻击?

在快速进行了一次安全审计之后,开始关注数据如何被使用。如果你知道特定端点将会收到很多请求,那么如何优化该端点以避免成为用户瓶颈呢?是否有一些计算可以转移到数据库并通过视图(view)而不是表格(table)提供给后端?是否可以将某些功能拆分到一个单独的端点上更好地实现?围绕数据改进性能对公司来说可能是巨大胜利,因为每个人都喜欢尽快获得所需的内容。

选择使用NoSQL数据库可能有以下几个原因:

  • 需要存储大量数据
  • 具有结构化和半结构化数据的组合
  • 与微服务后端一起工作
  • 需要可扩展架构

most commonly used types of NoSQL databases are: document, graph, wide-column, and key-value

SQL数据库, 当你被要求开发一个功能时,首先需要查看数据需求。检查以下内容:

  • 新的下拉菜单或输入
  • 用户权限级别的变化
  • 页面之间的新连接
  • 新的第三方集成

数据库架构在创建后并不是一成不变的,它会像代码一样随着时间的推移而增长和演变。

通常情况下,你不需要担心数据库基础设施部分,这就是DBA(数据库管理员)负责的工作,他们可能只是DevOps团队的成员之一。只要你能够连接到不同环境中的数据库,在云端如何提供服务由另一个团队处理。

数据库层面上还有很多改进措施可以加快响应速度。有时候DBA会在数据库中处理计算,并将值存储在视图中,因为作为开发人员你注意到从许多不同表格中获取值会减慢响应时间。这个隐藏于开发过程中的部分是你可能不会自己去云服务提供商那里更新资源,但你将与负责此项工作的人密切合作。

检查的事项:

  • 确保数据库服务器具备足够的资源。在CPU、内存、磁盘空间和分配预算之间找到一个良好的平衡。
  • 尝试对数据建立索引。这将涉及创建新表作为表之间关系的索引,可以使查询比在必要时遍历所有数据更简单和更快。
  • 查看数据库连接池。配置可能需要更新以处理更多活动连接。
  • 看看是否有任何查询可以编写成SQL语句而不是循环。
  • 考虑进行一些数据碎片整理。它有助于清理删除和插入新数据后留下的一些空闲空间。

数据库扩展方法(scale)。

  • 一种常见的做法是将数据进行分片。分片意味着将数据拆分为较小的子集,然后将它们分布到许多不同的数据库服务器上。这些服务器会物理上隔离,因此连接字符串需要更新,并且您需要特别注意访问正确的服务器。
  • 另一种处理扩展问题的策略是对数据库进行分区。这与分片类似,只是所有数据都保留在同一台服务器上。它只允许以更细粒度地方式访问被划分成较小部分的数据。

实施了日志记录的公司通常能够更快地找到问题的根本原因。以易于访问的方式记录错误和警告对于应用程序在用户使用过程中的整体健康非常重要。

记录对数据所做的任何更改。当您试图确定何时进行了更改以及谁进行了更改时,这将非常有价值。当您处理受HIPAA或PCI-DSS等合规要求保护的数据时,它也非常重要,并且还有助于定期安全预防措施。

什么是HIPAA?

HIPAA代表《医疗保险可携带性与责任法案》(Health Insurance Portability and Accountability Act)。这是一项联邦法律,要求制定国家标准以保护敏感患者健康信息不被未经同意地披露。

什么是PCI-DSS?

PCI-DSS代表《支付卡行业数据安全标准》(Payment Card Industry Data Security Standard)。这是一个信息安全标准,适用于处理来自Visa、MasterCard和Discover等主要信用卡方案的公司。

事件记录是最容易被忽视的一种记录类型。事件可以是用户进行的任何类型活动:按钮点击、页面浏览或其他操作。对于要记录哪些事件并没有真正限制或定义。通过记录,您可以获得关于用户如何与您所开发应用程序互动方面令人难以置信的业务洞察力,并且大多数情况下,通过有针对性地记录,您可以回答大部分业务问题。

例如,您可以看到客户放弃购物车时刻、他们预约可能会选择哪个时间段以及根据GPS坐标确定他们确切位置等信息。从记录用户活动中获取到的数据通常是无法直接从用户那里获取到的。


每次向API发送请求时,都应该进行日志记录。这有助于您了解何时升级资源以处理流量增加,并有助于保持API的安全性。您可以设置警报以检测可疑活动,并查看哪些端点被最频繁使用。

通常跟踪请求日志的信息包括请求发生的日期和时间、发出请求的用户ID或IP地址、实际请求数据以及与请求一起发送的任何头部或主体信息。

当您将请求日志用于安全目的时,以下几点值得注意:

对应用程序中受限功能或数据进行未经授权访问

在后端收到无效API密钥的情况下

记录每次登录失败尝试,以便找出任何模式

记录所有在请求中发送的无效输入参数

这些可能揭示后端应用程序中存在需要调查的弱点。另一方面,通过请求日志还可以帮助您确定应用程序最常被谁使用以及什么时间段。当您拥有这些信息时,就可以建议何时增加或缩减资源。

CI/CD为我们提供了一种自动化方式来快速、稳定地将代码更改传递给用户、质量保证(QA)测试人员和其他相关方。

部署流水线是一组可重复、自动化的步骤,每当代码被推送到分支时就会执行。这样可以确保在部署过程中没有任何步骤被跳过,因为有人忘记做某事或者因为他们匆忙。

构建 → 测试 → 部署到功能分支 → 测试 → 部署到预发布环境 → 测试 → 部署到生产环境

QA环境

这是手动测试人员检查新功能或错误修复是否通过开发者初步测试并寻找代码更改引起的任何意外回归问题。

Staging环境

这是集成测试发生的地方。如果你一直在处理一个特性史诗或需要合并在一起以获得准确交互情况描述的较小项,那些单独项目将经过QA测试后传递到此级别。在应用程序进入用户之前,您将能够看到第三方服务如何与应用程序配合工作。 这是除了生产环境之外最重要的环境,因为它是在上线之前捕捉问题的最后机会。这个环境应该尽可能地与生产环境相似。这意味着它应该具有类似或者相同的数据,使用与生产环境相同的所有服务,并且触发与生产环境类似的警告和错误。拥有一个良好的预发布环境将帮助整个团队找到并调试出现的任何问题,而不会影响用户。

生产环境

用户将与之交互的环境。如果可以避免,在生产中不要进行任何测试。当您部署到生产时,更改应经过多轮自动化测试和手动测试。这样您和团队就可以放心地部署,而不用担心回归和漏洞问题。

有许多工具可以用来设置部署流水线,包括CircleCI、Jenkins和GitHub Actions。不同的云服务提供商也有特定的工具,如Azure、GCP和AWS。

首先,您需要在版本控制系统中创建不同的分支来表示不同的环境。它们可以被命名为任何你喜欢的名称。然后,您将编写一个配置文件,在合并新代码到分支时触发各种部署过程

version: 2.1
jobs:
  unit-tests:
    docker:
      - image: cimg/node:14.20.0
    steps:
      - checkout
      - run:
          name: "install dependencies"
          command: yarn
      - run:
          name: "run project unit tests"
          command: yarn redwood test
  sast:
    docker:
      - image: cimg/node:14:20.0
    steps:
      - checkout
      - run:
          name: "install dependencies"
          command: yarn
      - run:
          name: "execute retire.js"
          command: cd web; retire --path web
  build-app:
    docker:
      - image: cimg/node:14.20.0
    steps:
      - checkout
      - run:
          name: "install dependencies"
          command: yarn
      - run:
          name: "build deploy artifact"
          command: yarn redwood build
  deploy-qa:
    docker:
      - image: cimg/node:17.1.0
    steps:
      - checkout
      - run:
          name: "deploy to QA env"
          command: echo "Deployed to QA environment with AWS S3 bucket magic or Azure container magic"
  dast:
    docker:
      - image: cimg/go:1.19.0
    steps:
      - checkout
      - run: go version
      - run:
          name: "install nuclei-cli"
          command: go install -v github.com/projectdiscovery/nuclei/v2/cmd/nuclei@latest
      - run:
          name: "Nuclei scan on QA"
          command: nuclei -u https://flippedcoding.com

workflows:
  deploy-to-qa:
    jobs:
      - unit-tests
      - sast
      - build-app
      - deploy-qa
      - dast

监控是一个非常广泛的主题,并且与日志记录有些重叠

在使用第三方系统时,你需要关注的主要是可用性和延迟。这些指标可以告诉你服务是否出现错误或超时。如果你使用云提供商来托管应用程序,可以查看提供商的健康仪表盘,了解是否有异常情况发生。例如,在AWS中观察图形或查看工作队列中的列表。

网站可靠性工程师通常是开发人员,他们了解如何在操作层面上自动化各个工程团队对生产环境进行代码部署。他们编写脚本并使用工具来扩展资源。他们关注延迟和紧急响应流程,以及代码配置、不同环境的部署和监控。

SRE听起来可能很像DevOps。实际上,它们可以很好地协同工作。DevOps主要关注根据开发人员的需求保持部署流水线清晰和最新,而SRE更专注于构建自动化来解决底层操作问题。

由于SRE与任何特定的开发团队分离,他们专注于可能影响整个工程部门的高级问题。他们还学习所有项目的运作方式以及它们与不同服务之间的连接方式,因此对整体情况有独特的视角

他们将应用程序容器化。将应用程序封装在容器中可以增加其可靠性,因为它们部署到不同的环境中。

他们为所有项目编写文档,说明它们与各自服务的交互方式。这些文档与开发团队维护的文档不同,因为它们关注的是一组不同的知识。

他们根据服务级别协议(SLAs)决定可以启动哪些功能,该协议是与用户达成的,并指定了所需的可靠性水平。

他们帮助找出支持问题的根本原因。

他们创建工具来帮助使项目更加一致。如果数据库或云提供商服务有重大升级可能导致停机时间,他们会帮助管理这些变更。

及时向支持团队更新信息。他们是与用户进行接触的人员,在需要向某人报告答案时不要撇下他们。

如果你没有独立的支持团队,那通常意味着工程部门将处理用户问题


选择现有UI库之前坚持制作他们自己定制化的UI库,并忘记了他们需要考虑诸如无障碍性、跨设备响应式、跨浏览器功能以及深色模式和其他样式偏好等因素。

你能否保持比维护者更新周期更加一致的更新节奏?

在开源项目中,代码质量可能差异很大。有些软件包甚至还没有完全支持TypeScript

尝试使用yarn link功能进行测试。这是一种将项目连接到分叉版本软件包的方法。这样一来,您就可以看到您对分叉仓库所做的更改在本地项目中反映出来。然后您将深入研究该代码库以找到更新位置。当您完成更新时,请花些时间在本地测试您所做的更改。

我曾见过许多项目因此而遭遇重大范围蔓延:添加新功能到核心项目和更新软件包存储库之间可能存在重叠问题。由于特性更新通常会揭示我们需要哪些功能缺失的软件包位置,两者经常纠缠不清。

防止这种情况发生的一个策略是定义单独任务,在两个项目中定义应进行的更改内容。您可以先实施一个新核心项目特性,然后意识到您的软件包需要一些更新,暂停核心特性开发以进行软件包更新,测试软件包更新,然后继续核心特性开发

可以说,最好的方法是在一年中的固定时间计划软件包更新,这样可以避免落后。这可能是每月或每季度进行,但它将确保您不必因为软件包引入了破坏性变更而进行大规模、意外的代码重构。破坏性变更会导致代码抛出意外错误,并且可能导致应用程序崩溃

如果您无法按计划更新软件包,并且继承了一个拥有大量过时软件包的项目,那么您有几个选择。第一种是逐步更新所有内容。制作一个完整的列表,列出项目当前使用的所有软件包以及它们的当前版本和来自Node Package Manager(NPM)的最新版本。注意哪些已被弃用或未经更新,并决定项目是否仍然需要它们。确定要保留哪些软件包后,就可以开始列出依赖关系了。如果其中任何一个软件包依赖于其他软件包,则同时进行这些更新非常重要。

当你决定同时更新所有软件包时,要准备好应用程序出现很多奇怪行为的情况。首先,你应该为项目创建一个新分支,以便将这些更改合并到该分支中,以免阻塞发布流程。

然后需要协调开发工作。这可能意味着将软件包分配给不同的开发人员,或者让某个人负责更新所有软件包,并组织团队共同解决错误、更新测试和属性方法。主要目标是避免重复工作,并确保大家都在同一个页面上。

在所有方法中,这种方式最混乱且涉及最多步骤,但它能够迅速推进工作进展

其中一个我最喜欢的包增加方式是将一些自制表单改为使用其中一个表单包,这样做使得维护工作变得轻松许多。使用已经针对奇怪边界情况进行过测试、支持多种浏览器并具备支持不同场景功能的东西真是一种很棒的感觉。