zhongxia245/blog

【20160928】【项目总结】大数据操作系统

Closed this issue · 0 comments

【项目总结】大数据操作系统

createTime:2016-09-28 16:30:55
原文地址,欢迎star!
总结下项目的问题,收获,不足。

产品功能:可以查看 http://www.baifendian.com/pro/subject-67.html
简单的讲,该系统提供一整套的大数据解决方案。 客户拥有大量的数据,然后如何从这大量数据中,清洗出有价值的数据。

系统GIF图

如果上图看不到,点击这里

项目人员及耗时

5个前端,10个后端,1个运维, 开发调试用时3个月, 测试用时1.5个月。

应用技术

前端技术:React全家桶 + webpack + gulp + ES6 + babel + less (react0.14)
代码版本控制使用:SVN
后端技术:Java + 大数据相关 【略】

项目架构

大数据操作系统,由多个模块组成,每个模块可以理解成一个Project, 可以单独运行,不依赖其他模块。 然后由web桌面集成在一起。

项目目录结构

整体的目录结构

    - BFD-UI  公共组件库
    - CommonComponent  公共样式,Ajax处理,正则,针对产品定制组件部分
    - DataFactoryModel  项目应用的工作流框架
    - ConfigCenter 项目
    - DataFactory   项目
    - FilaManage   项目
    - SecurityCenter  项目
    - node_modules  

单个项目目录结构

- common  项目间公共代码
- container  项目布局
- modules    一级模块目录
  - ide   一级模块
    - components    页面
    - css         样式
    - enum      枚举
    - model     Ajax相关操作
    - util 工具
    - index.js   react-router 路由
  ...
  - workflow    一级模块

问题

项目中考虑的问题和遇到问题的解决思路

一、 团队协作之间如何减少冲突?

相对刚开始,前后端还搞在一起,前端开发还需要搭建后端环境,然后后端改配置,前端居然跑不起来了,要抱着电脑去请教后端,这个坑啊。模块化开发好很好,只需要关注自己的模块。

前后端分离, 项目采用模块化,每个人负责几个模块,模块内包含该模块的所有内容,除了公共的部分,保证直接删掉该代码,并去掉路由,直接可以去掉该模块,添加模块等同。
这样模块解耦,方便应对需求变动,权限控制

二、 如何管理组件?

这一块还好,没有遇到啥大问题。

组件需要分为:公共基础组件,公共定制组件,具体业务组件

公共基础组件建议采用第三方组件库,本项目使用公司的组件库,公司组件库刚开始研发,过程中各种BUG,版本迭代间,高版本用于与低版本用法不一样,很多坑爹的问题。

公共定制组件:在公共基础组件的基础上,封装成各个项目中,可以快速使用的方式,方便项目间统一维护,快速方便使用。 比如(表格数据处理,翻页处理,全选逻辑。。。)

具体业务组件:具体页面模块,但具体页面中,也有共用的部分。 最常见的就是编辑页面和创建页面可以共用。

三、如何管理整体样式?

覆盖组件样式是一个坑,因为公司组件也在研发中,作为第一个吃螃蟹的团队,就。。。。
组件库的样式,刚开始使用模块化+嵌套的方式, 后面组件库丰富了,发现有一些命名重复啦,重复啦。然后大改版,使用BEM命名方式。如果只修改命名方式也就还好,最主要还是修改了DOM结构,然后之间的覆盖样式都废了。
切记,切记,切记,使用稳定的组件库

组件库地址:https://github.com/baifendian/bfd-ui
已经提供第一个稳定版本,赞一个,一路过来不容易。

引用第三方的reset.css,比如(normalize.css),处理浏览器之间的小差异

公共基础组件已经有自带的样式,需要覆盖,换成UI设置的风格,覆盖公共组件的样式都放在一个文件中。比如 bfd-ui.less , 也可以放多个文件,然后放在同一个文件夹中。

整体布局的样式,单独抽离成 layout.less 文件

样式命名需要统一规范,否则容易造成样式名冲突。可以使用 BEM的命名方式,虽然命名长了点,但是为了命名冲突,也值了。

less 的变量也可以单独抽取出来,放在一个 文件中。 方便后期统一修改。比如:global.less

//其他使用变量的地方引入
@import "global.less";

注意less 、 sass 的 import 和 css 自带的区别。

四、Ajax请求跨域问题?错误处理问题?session过期问题?

刚开始coding,Ajax还没有封装,大家写到业务逻辑里面,这样代码很乱,一个JS中,有页面,业务逻辑,混在一起。
还好及时提出了解决方案, 抽离Ajax这一层,先封装Ajax操作,然后每个模块各自抽离出Ajax操作,模块中调用,就是一个方法的调用。

跨域: : 关闭浏览器安全策略
开发的时候,前后端是分离的,因此前端访问后端接口的时候是跨域的。考虑到最终上线的时候,是部署在一起。 因此,上线后是没有跨域问题的。 因此可以使用关闭浏览器安全策略来解决跨域问题。

Ajax接口地址: 可配置
开发的时候,可能要连接后端人员机子的IP地址,访问接口,调试完成可能要访问开发环境地址,上线需要访问上线部署的地址。 经常需要变动。 因此 接口的 基本路径 做成 配置。然后直需要改动配置,就替换了整个项目接口的访问地址。

Session过期,错误处理? 提供默认处理,并扩展接口自定义
项目开发,必须给Ajax封装一层,写统一的错误处理,错误提示,Loading效果,超时提示,Session过期等通用操作。

Ajax请求到一半,跳转页面,需要在 componentWillUnmount 中断Ajax请求。否则会报 组件已经卸载,不能使用 this.setState操作的错误。

五、团队协作开发,如何让别人看懂代码?

每个程序员都有自己的代码风格,但是,但是,但是团队开发就需要共同遵守一个代码规范。
这一块React生命周期,大家都按照顺序写,还行。其他方面由于赶时间,基本是 一个 格式化功能搞定。

JS代码规范只能口头上说说,因为实际上会不会执行,还得要比较大的Review力度。因此可以使用 eslint 来进行验证,在提交前要验证下。【验证的比较粗糙】

还有一些则需要团队之间遵守,比如使用React, 编写生命周期的时候,请按照顺序来。

constructor
componentDidMount
componentWillReceiveProps
shouldComponentUpdate
componentWillUnmount
...
其他自定义方法
...
render

创建React组件,统一使用 ES6。加 autobind 方法

六、React组件之间如何通讯?

模块功能复杂的情况下,最好先理清整体流程,操作事件,然后在coding。
写IDE模块的时候,刚开始认为这个很简单,然后直接啪啪啪开始coding了,后面发现都是坑,非常多的细节问题。各种事件,各种交互。导致后面Review做了很大改动,切记切记,理清需求,不要看起来简单。

小模块内部,使用 prop或者 context 传递方法进行通讯, 模块之间使用 事件派发。

七、减少修改公共组件和公共样式,对项目的整体影响

这一块,公共样式,和布局方面做还行,但是公共组件方面有很大的问题,有时候更新组件忘记通知大家,导致跑起来报错。还有必须注意的是,进入测试阶段就不要更新整个组件库了,有BUG自己打补丁修复。因为更新组件引入新的BUG,被测试一直说。

公共样式在整个项目中,各个页面都用到,因此修改公共样式需要慎重。尽量不要使用一些奇淫技巧,写一些稳妥的。

八、正则验证

后台类型的管理系统,需要有很多的表单,有很多表单就有很多表单验证。
可以抽离出正则表达式统一放在一个文件中,其他各个地方都使用该文件里面的正则,文件中没有,则添加上。
在项目中,除了抽离正则,还封装了有验证功能的表单组件,然后直接配置正则,和错误信息(也可以动态生成错误信息),即可使用。

九、SVN提交规范

这一块在该项目中,做的还不错。

测试阶段,尽可能减少修改BUG而引发新的BUG。因此必须写清楚每次提交代码的作用。

研发阶段还好一点,做好一个就可以提交一个,并且稍微注明下 上传什么模块代码就行了。
测试阶段,修改BUG,就必须遵守SVN提交规范

  1. 修改好 一个BUG,提交一次。 【一个BUG,一次提交】
  2. 注明修改的BUG编号,出现原因,解决方案 【重要

十、权限控制

这一块分为两种,按钮控制,模块控制
在项目刚加载的时候,同步请求,权限数据,然后判断 data-code是否有权限,没有的话, 则 不 render 到页面上

按钮的权限控制,在最初的预想是,渲染到DOM后,在remove DOM 节点,后面发现这个想法是不可行的。

React 的 componentDidMount 回调里面, 不可以remove DOM节点,否则报错。

最终封装了一个组件,替换页面上所有需要控制按钮 , 图标按钮,超链接,下拉框选项,右键菜单。

renderType 属性执行渲染成什么类型组件(按钮,下拉。。。)
data-code 核心: 按钮标识,和后端匹配上

<AuthButton style={{marginLeft: 2,marginRight:20}}
                     data-code="1021002" renderType="icon" type="plus-square"
                     onClick={this.addScript.bind(this)}>新增</AuthButton>

模块控制,则控制导航菜单即可。 过滤掉没有权限导航选项,然后把有权限的渲染出来。
每个模块的代码,是按需加载的, 也就是刚进入项目页面的时候,没有加载 模块的JS代码,这样减少了进入系统的时间很长。

遇到的技术难题

1、关闭脚本选项卡的时候,错位了。

【关掉第二个选项卡,可接口是关闭第三个选项卡】
主要问题是:对 React 的 key 和 render原理 的相关知识支持了解不够。

tabs 的内容是 存放在 数组中,循环渲染出来的,新增一个 tab,会往数组中添加一个tab,
然后react就会 重新 render,渲染出 tabs 组件。

修改前使用 index 做为key

    <TabList>
          {this.renderTool()}
          {this.state.tabs.map((tab,index) => {
            return (
              <Tab key={index} activeKey={index}>
                {this.renderTabTitle(tab)}
              </Tab>)
          })}
    </TabList>

修改前使用一个唯一标识作为key,就搞定了。

<Tab key={tab.uuid} activeKey={tab.uuid}> 

一句话就是:想要更新组件内容,请保证当前组件的key与上一状态组件的key不同。
具体可以看《ReactJS 组件的key作用》


收获与不足

一、收获

  1. 负责从0到1的项目架构设计,技术选型。
  2. 项目中越到各种问题,然后解决各种问题。项目中遇到的问题,在架构设计前能考虑到一部分,但是还有很多需要遇到在解决。
  3. 熟练掌握 React的开发模式

二、不足

  1. 技术选型, 低估了组件库升级可能带来的影响。
  2. 在coding前,评估时间 和 实际开发时间存在一点差距。
  3. webpack优化方面,有看过相关文档,不过没有具体实践在项目中。【后期忙着封版】

代考量

虽然没有使用redux进行state管理,但是整体开发过程中,没有体会到状态难管理。

  1. 可能因为模块化开发之后,各个Ajax抽离。
  2. 可能因为各个页面关联性不大