记可视化项目代码设计的心路历程以及理解

前言: 这篇文章包含了我这段时间的对代码的理解以及设计的反思,又到了否定以前的代码尝试去做更好的设计与想法的时候。从前引以为傲,自觉还行的代码如今看来,尽管仍然有它的可取之处,但有更多的需要精进的地方。俗话说得好,代码能跑了就不要动,而且说到底,现在的结构其实比较很多前端码农来说已是写的尚可。

业务场景

脱离场景以及问题的代码没有任何价值。你需要解决什么问题,以及你用什么方式去做,这是写代码的核心思考。尽管经过无数次的迭代,最终代码都会变成屎山的模样,但还是得让这个屎山拉的规律,尽可能的维持住整体,不要造成屎崩。

业务如下:
1、有多种效果栅格、粒子、温盐深、风暴潮等等
2、需要能随时切换4种投影坐标系4326、3D (WGS84)、南极投影、北极投影。
3、有3种控制地图表现的粒子开关、栅格开关、以及矢量边界开关。
4、接入数据类型(如GFS、EARTH等)、这个业务跟windy挺像,大家可类比,虽然是那个意思,但里面多了挺多自定义的一些东西。
5、时间轴、海拔轴
6、数据切换

可供参考的实图就这个,但相信应该还挺好理解。树的结构无非就是很多种类的表现。
在这里插入图片描述

当时刚刚工作3个多月的我,完全想不到第一步要如何开始。经由领导的提示下,有了这个可视化项目的第一个设计。

以对象表达状态

其实业务代码多的是对状态的表示,比如最为基础的开关两个状态, 我们只需要一个变量 诸如:

let a = Boolean(0)
// it means false 
a = Boolean(1)
// then true

但如此繁杂、多变的状态,我们显然已经不太适合去维护每一个变量了。那么换种想法,我们是否可以通过一个数组,这个数组是所有这些数据表示状态的集合,简单来说就是数组包对象,每一个对象负责去描述该数据所表示的状态集合。以上方业务场景为例:我们对1、2、4做处理

// 维护一个 typeId 映射 。 例如 1 => 栅格 2=> 粒子 3 => 其他 作为类型标识 做统一的处理
let obj = {
	typeId: 1,
	// 渲染投影
	renderPlane: '3D',
	// 使用的数据类型,
	dataMode: 'GFS'  
}

如此,只需要我们存放一个数组,那么再多的状态表示我们只需要通过一个数组对象 都可以表示出来,如此也就完成了第一步的处理。

此时随着项目的不断进展,逐渐繁杂的状态处理,你会渐渐的发现,有一个处理一个,尽管你已经很努力的写出来了,还是时不时的出BUG,原因在于交互的是存在互相影响的,这是由业务本身决定的影响,比如:有些数据不需要矢量边界,但此时矢量边界仍然在活动,你需要把它删除或者隐藏,如此繁杂的、混乱的操作,自然会不断地带来BUG。这个系统此时正在走向崩溃,只要你第二天离职跑路了,下个人需要可能付出大量的时间去琢磨才能继续开发。

所以如果你之前没有过类似的经验,你会在这里才开始意识到,程序的运行,单有状态的表示顶多只能作为判断的基础,而并不能帮助你达成完善的实现

实现状态的设计(功能的工程化)

对于现在常常提的工程化,我相信对于很多刚刚入门的、培训班刚出来的、或者是我们所说的cv工程师应该是只听过概念,并不能理解这其中的精妙。包括vue里的组件分包,纯粹只是为了缩短代码行数的封装,本质上都是由于对工程化不理解而导致的。(os: 因为我前段时间去维护了另一个项目,那项目差不多2,3年,来来回回人也走了不少了,改的头皮发麻,我甚至不知道为什么大部分同样的代码要复制新建一个专门去新增路由的组件)

像java来说,java 写接口 通常的设计是 controoler ,service,dao ,分别去做对应的事,例如:controller层用于将通过调用service层 调用到DAO层访问数据库 取回的数据发送给前端。这三个层的概念就是一个完整良好的设计:各个逻辑单元各司其职。细想下计算机底层的部分处理器,还分逻辑单元跟算术单元呢。。

对于功能上的逻辑,我们在项目一开始就需要往整体上去设计,不管是你,还是后来者都会受益良多。

有关于功能的设计从何谈起?首先,到这里的时候,以免大家走入误区,我们需要完全摒弃之前的状态,说实话,状态跟功能不是联系的重点,重点是你想实现什么功能,换成最简单理解的话就是:我说你这个函数或者类能干啥,你就能干啥。这是设计,不叫实现,我们先不需考虑实现,这也不是本文的重点。

在绝大多数的场景下,我们的设计都应该是一个树的形状,(写文章都得总分总,是这个理吧)

在这里插入图片描述
当时我的考虑如下,在需要的组件内部生成主控制器,由主控制器,做一些主题更换的内容: **主要是由于投影坐标的切换,我们需要更换挂载到dom上的地图实例,因此,从整个业务逻辑出发,它应该是处于主控制器下一级的。**在主控制器内部,我们做一些初始化实例的操作,原因在于各个地图所需做的处理不同,所以我们在这个初始化的过程中传递对应的参数进入对应的效果处理器进行处理。同理,渲染视图也是对应当前处理的投影坐标系内容传递对应的参数,调用实例的处理。重置 则意味着当坐标系发生变更时需要重新做的初始化内容,垃圾回收则是避免残留的内存未被释放。

以上来说,结构已经尽可能的完善、清晰,刚刚做出来的时候也是我满足的时候,就剩下实现了。

代码的实现

首先从实现上来说,我写糟糕了,可能某种情况来说他也没这么糟糕,问题出在哪呢?问题还是出在没有对实现花太多思考的情况上。
在这里插入图片描述
在这里插入图片描述

以下是我总结的几点不到位的地方:
1、class的 构造器函数里,最好还是使用Object options的形式进行注入。在时隔几个月之后重新回看,需求需要增加点击事件去处理某个业务逻辑,需要进行新的处理时, 你们应该能从代码中读到明显的割裂感,这是我有意为之。提醒自己之后写项目时需要注意。
2、不应该往类里传入vuex的store对象。我大可使用getter、mutation、action 等等 进行引入,控制。它影响了整个类的纯净,意味着当这个类不在这个项目运行时,他就是一坨毫无价值的屎。
3、对诸如初始化注入实例的属性,可以通过函数的形式去书写,这样子会更整体和谐。

修改激活数据函数参考
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值