关于设计:什么是设计领域的-4-eyes-design

4 Eyes Design(四目设计)是一种设计审查和验证过程,旨在确保设计我的项目的品质、准确性和可靠性。这一设计办法通常用于软件开发和产品设计等畛域,其外围概念是通过引入多个独立的视角和专业知识,来审查和验证设计方案,以升高谬误和问题的危险。4 Eyes Design的名称源自于“四双眼睛”即四个独立的视角,它侧重于减少设计决策的透明度和品质管制。 在4 Eyes Design中,通常波及以下四个次要角色: 设计师(Designer):设计师是我的项目的创造者,负责制订和施行设计方案。他们负责将想法和概念转化为具体的设计,以满足我的项目的需要和指标。初审者(Reviewer 1):初审者是第一个独立的审查者,通常是另一位有教训的设计师。他们的工作是审查设计方案,查看是否符合规范和最佳实际,并提出倡议和改良意见。复审者(Reviewer 2):复审者是第二个独立的审查者,通常也是一位有教训的设计师,但与初审者不同。他们的工作是再次审查设计,提供额定的视角,确保没有脱漏的问题或潜在的改良机会。产品经理或项目经理(Product/Project Manager):产品经理或项目经理是我的项目的监督者,负责确保设计方案满足我的项目的业务需要和指标。他们能够提供战略性的反馈,并协调设计师和审查者之间的交换。4 Eyes Design的核心理念是多样性的审查和验证,以确保设计方案的全面性和品质。以下是一个示例,具体阐明4 Eyes Design的过程和益处: 示例:电子商务网站的4 Eyes Design假如一个团队正在设计一个新的电子商务网站,以提供在线购物体验。以下是该项目标4 Eyes Design过程: 步骤1:设计师制订初步设计计划首先,设计师开始制订初步的电子商务网站设计方案。他们思考用户界面、网站导航、商品展现、购物车和领取流程等方面。设计师应用工具如Sketch或Adobe XD创立初步设计原型。 步骤2:初审者审查设计初审者是另一位有教训的设计师,他们承受初步设计计划的审查工作。他们查看设计是否合乎用户体验准则,如易用性、可拜访性和响应性。初审者可能会提出以下倡议和问题: 导航栏是否清晰?:初审者关注网站的导航构造,确保用户可能轻松找到所需的信息和产品。响应性设计是否足够?:他们查看设计在不同设施上的体现,包含桌面、平板和手机。色调搭配是否适合?:初审者评估色调计划是否与品牌标识相符,并提供改良倡议。步骤3:设计师批改设计基于初审者的反馈,设计师进行必要的批改和改良。他们可能从新设计导航栏、优化页面布局,并确保网站在不同设施上的显示良好。 步骤4:复审者审查设计复审者是第二个独立的审查者,他们的工作是再次审查设计,提供额定的视角。他们可能关注不同的细节,例如网站的速度性能、安全性和跨浏览器兼容性。复审者还能够提供与初审者不同的倡议,以确保设计方案的全面性。 步骤5:设计师进一步欠缺设计基于复审者的反馈,设计师进一步欠缺设计,确保网站在各个方面都达到最佳程度。 步骤6:产品经理或项目经理的最终审查最初,产品经理或项目经理表演监督者的角色,对设计方案进行最终审查。他们确保设计满足业务需要和指标,合乎我的项目估算和时间表,并与其余我的项目阶段协调一致。他们还能够提供战略性的反馈,确保设计与整体业务策略相符合。 益处与重要性4 Eyes Design具备多重益处和重要性: 质量保证:通过引入多个独立的审查者,4 Eyes Design有助于检测和纠正设计中的谬误和问题,进步设计方案的品质。升高危险:通过多样性的审查,能够升高我的项目前期呈现重大问题的危险,缩小从新设计和修复的老本和工夫。多视角:每个审查者都有不同的专业知识和教训,他们的审查提供了多个视角,有助于发现潜在的改良机会。透明度:4 Eyes Design促成了团队成员之间的单干和交换,减少了设计决策的透明度,确保每个人都了解设计的指标和决策依据。业务一致性:产品经理或项目经理的参加确保设计与我的项目的业务指标和策略统一,有助于放弃我的项目的一致性和方向。客户满意度:通过进步设计品质和用户体验,4 Eyes Design有助于进步客户满意度,减少用户忠诚度。总之,4 Eyes Design是一种有助于进步设计品质和升高危险的无效办法,它通过多样性的审查和验证,确保设计方案满足我的项目的需要和规范。在古代简单的设计我的项目中,采纳这种办法能够帮忙团队提高效率,并确保最终交付的设计是高质量的。

September 24, 2023 · 1 min · jiezi

关于设计:一文弄懂访问者模式

对于设计模式,咱们得联合生存中的案例来学习;最近我在网上也看了不少文章,明天想跟大家分享一下对于访问者模式的一些常识,先来看一个简略的案例吧。 置信大家都去过医院,看完病,医生都会给咱们开一个处方单,很多医院都存在如下解决流程:划价人员拿到处方单之后依据药品名称和数量计算总价,药房工作人员依据药品名称和数量筹备药品。 咱们能够将处方单看成一个药品信息的汇合,外面蕴含了一种或多种不同类型的药品信息,不同类型的工作人员(如划价人员和药房工作人员)在操作同一个药品信息汇合时将提供不同的解决形式,而且可能还会减少新类型的工作人员来操作处方单。 在软件开发中,有时候咱们也须要解决像处方单这样的汇合对象构造,在该对象构造中存储了多个不同类型的对象信息,而且对同一对象构造中的元素的操作形式并不惟一,可能须要提供多种不同的解决形式,还有可能减少新的解决形式。在设计模式中,有一种模式能够满足上述要求,其模式动机就是以不同的形式操作简单对象构造,该模式就是咱们本章将要介绍的访问者模式。 模式概述访问者模式(Visitor Pattern):提供一个作用于某对象构造中的各元素的操作示意,它使咱们能够在不扭转各元素的类的前提下定义作用于这些元素的新操作。访问者模式是一种对象行为型模式。 访问者模式是一种较为简单的行为型设计模式,它蕴含访问者和被拜访元素两个次要组成部分,这些被拜访的元素通常具备不同的类型,且不同的访问者能够对它们进行不同的拜访操作。例如处方单中的各种药品信息就是被拜访的元素,而划价人员和药房工作人员就是访问者。访问者模式使得用户能够在不批改现有零碎的状况下扩大零碎的性能,为这些不同类型的元素减少新的操作。 在应用访问者模式时,被拜访元素通常不是独自存在的,它们存储在一个汇合中,这个汇合被称为“对象构造”,访问者通过遍历对象构造实现对其中存储的元素的一一操作。 其构造如下图所示: Vistor(形象访问者):形象访问者为对象构造中每一个具体元素类ConcreteElement申明一个拜访操作,从这个操作的名称或参数类型能够分明晓得须要拜访的具体元素的类型,具体访问者须要实现这些操作方法,定义对这些元素的拜访操作。ConcreteVisitor(具体访问者):具体访问者实现了每个由形象访问者申明的操作,每一个操作用于拜访对象构造中一种类型的元素。Element(形象元素):形象元素个别是抽象类或者接口,它定义一个accept()办法,该办法通常以一个形象访问者作为参数。ConcreteElement(具体元素):具体元素实现了accept()办法,在accept()办法中调用访问者的拜访办法以便实现对一个元素的操作。ObjectStructure(对象构造):对象构造是一个元素的汇合,它用于寄存元素对象,并且提供了遍历其外部元素的办法。它能够联合组合模式来实现,也能够是一个简略的汇合对象,如一个List对象或一个Set对象。实用场景(1)一个对象构造蕴含多个类型的对象,心愿对这些对象施行一些依赖其具体类型的操作。在访问者中针对每一种具体的类型都提供了一个拜访操作,不同类型的对象能够有不同的拜访操作。 (2)须要对一个对象构造中的对象进行很多不同的并且不相干的操作,而须要防止让这些操作“净化”这些对象的类,也不心愿在减少新操作时批改这些类。访问者模式使得咱们能够将相干的拜访操作集中起来定义在访问者类中,对象构造能够被多个不同的访问者类所应用,将对象自身与对象的拜访操作拆散。 (3)对象构造中对象对应的类很少扭转,但常常须要在此对象构造上定义新的操作。 案例场景一某银行开发了一套OA零碎,在该OA零碎中蕴含一个员工信息管理子系统,该银行员工包含正式员工和临时工,每周人力资源部和财务部等部门须要对员工数据进行汇总,汇总数据包含员工工作工夫、员工工资等。该公司根本制度如下: (1)正式员工(Full time Employee)每周工作工夫为40小时,不同级别、不同部门的员工每周基本工资不同;如果超过40小时,超出局部依照100元/小时作为加班费;如果少于40小时,所缺工夫依照销假解决,销假所扣工资以80元/小时计算,直到基本工资扣除到零为止。除了记录理论工作工夫外,人力资源部需记录加班时长或销假时长,作为员工平时体现的一项根据。 (2)临时工(Part time Employee)每周工作工夫不固定,基本工资按小时计算,不同岗位的临时工小时工资不同。人力资源部只需记录理论工作工夫。 人力资源部和财务部工作人员能够依据各自的须要对员工数据进行汇总解决,人力资源部负责汇总每周员工工作工夫,而财务部负责计算每周员工工资。 一坨坨代码实现class EmployeeList { private ArrayList<Employee> list = new ArrayList<Employee>(); //员工汇合 //解决员工数据 public void handle(String departmentName) { //财务部解决员工数据 if (departmentName.equalsIgnoreCase("财务部")) { for (Object obj : list) { if (obj.getClass().getName().equalsIgnoreCase("FulltimeEmployee")) { System.out.println("财务部解决全职员工数据!"); } else { System.out.println("财务部解决兼职员工数据!"); } } //人力资源部解决员工数据 } else if (departmentName.equalsIgnoreCase("人力资源部")) { for (Object obj : list) { if (obj.getClass().getName().equalsIgnoreCase("FulltimeEmployee")) { System.out.println("人力资源部解决全职员工数据!"); } else { System.out.println("人力资源部解决兼职员工数据!"); } } } }} 在handle()办法中,通过对部门名称和员工类型进行判断,不同部门对不同类型的员工进行了不同的解决,满足了员工数据汇总的要求。然而该解决方案存在如下几个问题: ...

April 12, 2023 · 5 min · jiezi

关于设计:电商通用型商品中心设计

作者:京东物流 顶峰1 需要构建一个电商通用型商品核心,可反对商品的品种和属性繁多,能够售卖实物、虚构、会员、服务类商品。每一种商品具备不同的规格,不同的规格的商品有多种价格,商品可反对多种货币的领取。 1)目标是什么? 带大家一起实现一个通用型商品核心,从中学到一些扩展性设计思维。 2)你能学到什么? 了解行业术语和概念动静sku表单设计属性和sku扩展性设计价格扩展性设计商品规格设计3)不能学到什么? 商品图片存储设计商品高低架设计商品标签设计库存设计搜寻筛选设计2 商品的基本概念商品核心是电商各个系统的最根底单元,为商城、订单,优惠促销、库存、仓储物流等零碎提供根底数据。 电商的根本术语。 SKU:(Stock Keeping Uint,即库存量单位),库存管制的最小可用单位。例如“iPhone 7 Plus 128G银色”就是一个SKU,仓库治理、洽购进货、库存治理都是以SKU为记录单元。SPU:(Standard Product Unit,即标准化产品单元),是一组标准化信息的汇合,例如“iPhone 7 Plus”就是一个SPU。类目:即分类树。电商罕用的有两层类目:前台展现类目和后端商品类目。 前台类目指的是展现给消费者看的类目,会依据节令、销售策略、流动进行变动; 后盾类目属于根底数据,不可随便变动,增加SKU时都须要抉择后盾类目,进行绑定。属性:分为要害属性、销售属性、非关键属性、非凡属性。要害属性 是指可能惟一确定产品的属性,是必填项,例如手机的屏幕尺寸、型号属于要害属性。销售属性 是组成SKU的非凡属性,或称为“规格属性”,例如手机的“色彩”、“内存”。非关键属性 指的是除要害属性、销售属性外的其余属性,如前置摄象头像素、后置摄像头像素、产地、分辨率。非凡属性 指须要通过调用其余服务能力获取到的属性。3 商品架构图参考上面的商品组成模块图,商品模块的组成较为简单,在定义SKU与SPU时,波及类目、属性、品牌、生产信息等数据的组合,在定义出SKU后再创立SPU,在SPU上增加商品形容和规格最初就成了商品。依据商品又衍生出了价格治理、评论治理、搜寻筛选等模块。 3.1 商品组成模块图 3.2 商品核心外围ER图 3.3 商品核心整体架构图 4 商品类目4.1 类目治理商品类目分为两层:根底数据类目层(后盾类目)、前台展现类目层(前台类目)。那为什么要将前、后盾类目离开治理,而不是前、后盾共用一套类目呢? 后盾类目面向商家或供应链人员,商品属性、销售属性及品牌等很多数据都是在根底类目上进行治理; 前台类目面向用户,不便用户查找商品,还能够随着经营须要去调整。比方而且随着节日、气节节令变动,经营会常常变更前台类目。 4.2 后盾类目后盾类目次要面向平台经营人员或商家,用于治理商品、属性和品牌等数据。 后盾类目绝对固定,确定了之后不会轻易变更或删除,如果类目下挂载有商品,就不能删除或作废。 类目树的档次不能太深,个别三层或四层。如果太深,对于商品的治理不太不便。类目树中最初一层类目称为叶子类目,商品必须挂载于叶子类目下。 4.3 前台类目前台类目次要面向用户,不便用户筛选查找商品,如图图所示。 前台类目能够依据经营须要,灵便多变。所以解决商品的前端类目时,就应该提供多样化的前端类目来反对。 前台类目可反对不同客户端的设置。PC端、H5端、APP端等 前台类目不同于固定的后盾类目,编辑很灵便、可重叠、可删除、可随时变动,定时失效。 4.4 类目表结构设计4.1.1 后端类目表设计 CREATE TABLE `category` ( `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', `name` varchar(32) NOT NULL COMMENT '类目名称', `parent_id` bigint(11) NOT NULL COMMENT '父id', `leaf` tinyint(4) NOT NULL COMMENT '是否叶子节点 1是 0不是', `level` tinyint(4) NOT NULL COMMENT '类目层级', `path` varchar(128) DEFAULT NULL COMMENT '残缺父级门路:父父id_父id', `sort` int(11) unsigned NOT NULL COMMENT '排序字段', `status` tinyint(4) NOT NULL COMMENT '分类状态:1上架 2下架', `del` tinyint(4) unsigned NOT NULL COMMENT '是否删除', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创立工夫', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新工夫', PRIMARY KEY (`id`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='类目表';4.4.2 后端类目数据展现 ...

March 31, 2023 · 5 min · jiezi

关于设计:聊一聊过度设计

 老手程序员在做设计时,因为缺乏经验,很容易写出欠设计的代码,但有一些教训的程序员,尤其是在刚学习过设计模式之后,很容易写出适度设计的代码,而这种代码比老手程序员的代码更可怕,适度设计的代码不仅写进去时的老本很高,后续保护的老本也高。因为绝对于毫无设计的代码,适度设计的代码有比拟高的了解老本。说这么多,到底什么是适度设计? 什么是适度设计? 为了解释分明,我这里用个类比,如果你想拧一颗螺丝,失常的解决方案是找一把螺丝刀,这很正当对吧。 然而有些人就想:“我就要一个不止能拧螺丝的工具,我想要一个能够干各种事的工具!”,于是就花大价格搞了把瑞士军刀。在你解决“拧螺丝”问题的时候,重心早已从解决问题转变为搞一个工具,这就是适度设计。 再举个更技术的例子,假如你进来面试,面试官让你写一个程序,能够实现两个数的加减乘除,办法出入参都给你提供好了 int calc(int x, int y, char op),一般程序员可能会写出以下实现。 public int calc(int x, int y, int op) { if (op == '+') { return x + y; } else if (op == '-') { return x - y; } else if (op == '*') { return x * y; } else { return x / y; } } 而高级程序员会使用设计模式,写出这样的代码: public interface Strategy { int calc(int x, int y);}public class AddStrategy implements Strategy{ @Override public int calc(int x, int y) { return x + y; }}public class MinusStrategy implements Strategy{ @Override public int calc(int x, int y) { return x - y; }}/** * 其余实现 */public class Main { public int calc(int x, int y, int op) { Strategy add = new AddStrategy(); Strategy minux = new MinusStrategy(); Strategy multi = new MultiStrategy(); Strategy div = new DivStrategy(); if (op == '+') { return add.calc(x, y); } else if (op == '-') { return minux.calc(x, y); } else if (op == '*') { return multi.calc(x, y); } else { return div.calc(x, y); } }} 策略模式益处在于将计算(calc)和具体的实现(strategy)拆分,后续如果批改具体实现,也不须要改变计算的逻辑,而且之后也能够加各种新的计算,比方求模、次幂……,扩展性明显增强,很是牛x。 但光从代码量来看,复杂度也明显增加。回到咱们原始的需要上来看,如果咱们只是须要实现两个整数的加减乘除,这显著适度设计了。 ...

February 26, 2023 · 1 min · jiezi

关于设计:前端需要了解的色彩知识

概述在前端畛域,咱们经常须要跟色调打交道,除了一部分从设计转过来的前端外(ps:历史起因),起初的新生代前端绝大多数根本都是学理工科出身的,个别没有通过专门的设计训练和造就,这样在还原设计图的过程中对于色调的了解都会或多或少有些出入,从而导致设计和前端产生不必要的矛盾(ps:本是同根生,都互相谅解下),本文旨在通过介绍相干的一些色调常识,为大家提供一些设计和前端双重视角下的观点,也心愿可能给大家提供一些对色调的不同的意识和了解。 色调实践人类对色调的钻研其实很早都有记录,但真正把色调作为一门学科或者说有其理论体系,还要从牛顿说起,在之后一直的迷信倒退过程中,人们逐步对色调有了不同的意识,也正是因为迷信的倒退,色调实践在不同畛域都有了长足的倒退,本文着重分享两个对咱们前端来说须要着重理解的色调实践,即:色环实践以及加增色模式实践。 色环 色环实践经验了牛顿色环、伊顿色环(传统色环)、孟塞尔色环、Yurmby色环等几个不同的阶段,这里重点介绍传统的经典色环,也就是伊顿色环,其作为包豪斯体系中重要的实践课程,对设计畛域的影响微小(ps:对设计史感兴趣的童鞋,能够参看之前的这篇文章世界古代设计史),总体来说,色环实践能够简略提炼出以下几个常见的色调概念: 名称相差度数解释邻近色0-15度色环中两色相差较小,比拟靠近,不同人辨认度不同,通常辨认度较低类似色15-45度色环中两色相差适中,既具备辨认度,又具备类似度中差色45-105度色环中两色相差有显著辨认度,但又不会显得过于跳跃对比色105-150度色环中两色相差有较强辨认度,容易产生跳跃感邻近互补色150-179度色环中两色相差较大,不倡议搭配应用互补色180度色环中两色相差比照强烈加色模式 & 增色模式 在介绍加色模式和增色模式,咱们先来看下咱们从小学到的对于色调的一些基本知识。咱们之前上学的时候,美术老师可能教过三原色和三基色的概念,或者辨别光学三原色和色调三原色等等,这其实就曾经是加色模式和增色模式的一个初步理解了,实质来说:三原色或者说三基色都是基于不同环境下资料而提出的一种根本色调而已,我这里以光学三原色和色调三原色来辨别,光学三原色是:红(R)、绿(G)、蓝(B),也是咱们前端开发过程中罕用到的元色;而除了光学三原色外,还有一个色调三原色,或者叫美术三原色,它们是:红(M)、黄(Y)、蓝(C),这个是印刷或者绘画过程中经常用到的元色。置信仔细的同学曾经发现我在标注英语的时候,色调三原色和光学三原色里的红色及蓝色如同是不一样的,没错,正是因为不同场景下对于色调应用的不同,而对色调进行加合的过程中呈现了不同的模式。这里,就要引出咱们这一部分的外围实践了,即:加色模式和增色模式。 上面给出不谨严的加色模式和增色模式的定义 加色模式是指对色调模型中的属性进行加和的模式;增色模式是指对色调模型中的属性进行排汇的模式那么为什么光学色调是加色法而美术色调却是增色呢?因为实质上,在光学场景中,比方在计算机显示器中通常应用的是从一种光源来收回不同的元色给人出现色调,不同的显示器制作资料有不同的显示特点,比方有:阴极射线管显示器(CRT)、等离子显示器(PDP)、液晶显示器(LCD)以及有机发光半导体显示器(OLED)等等,但这些通常都会是从一个光源收回的,因此这些通常就是加色模型,而一般来说会有RGB模型、YUV(YCrCb)模型等,在前端来说,咱们常见的是以RGB模型进行的相干对应关系代码操作,这里波及到了色调模型,具体请看下一部分的介绍。而在美术或者印刷场景中,则是利用的物体反射光线的原理,也就是说咱们日常看到的物体的色彩其实是显示的它不能被排汇的色彩,例如:粉色颜料其实排汇了除粉色以外的所有光线,所以咱们能力看到它是粉色,因此增色其实是排汇的模式,因此在CMYK模型中,其就是典型的增色模式。 色调模型 在有了对色调的初步意识之后,如果想要来形容色调,咱们就须要建设一个模型来形容它,这里就引出了色调模型的概念,基于wiki百科和百度百科,咱们不谨严的给出如下的定义: 色调模型是用一个元组或者汇合来形容可见光的子集,这里的元组通常为三元或者四元。通常来说,依照是否设施相干,咱们能够将色调模型分为设施相干色调模型以及设施不相干的色调模型,基于此大抵能够分为两大体系,即:RGB体系及XYZ体系,这里咱们将介绍以下几种常见的色调模型:RGB/CMYK、YUV/YCrCb、HS*、Lab、XYZ,上面将别离介绍下相干的色彩模型。 RGB & CMYK RGB模型是典型的加法模型,其通过设立RGB为三个基色进行多种色彩的不同模型组合,其中R/G/B别离作为三维欧氏空间中的维度示意,对色彩进行相干的构建,如上图所示。 不同于RGB模型的加法合成,对于印刷相干的场景,则是典型的减法合成,而这里最常见的就是跟物质相干的根底颜料作为根底模型空间的维度,最常见的便是CMYK模型,其依然是合乎欧氏空间的模型构建,只是对于合成的算法过程中应用的是减法合成。 YUV & YCrCb YUV模型作为RGB模型的变形模式,其罕用于视频、电视畛域的色调示意。因为在视频及电视畛域中,对于色调和饱和度的指标绝对更为要害,因此应用U+V来示意色度,应用Y来示意亮堂度。 随着视频编码技术的倒退,YCbCr模型作为视频流采纳的一种变形模型规范,其不再是通过u+v来示意色度,而是通过RGB输出信号的R与亮度的差别即Cr和通过RGB输出信号的B与亮度的差别即Cb进行维度构建,这绝对于YUV或者YPrPb编码而言便是数字色差信号而不再是模仿色调信号了。 YUV和YCrCb色调模型罕用于计算机视觉的相干剖析中,对于视频及图像剖析相干的同学能够更深刻理解一下HSV & HSL & HSB & HSI对于人的视觉而言,其实通常最容易形容的就是基于色相(Hue)、饱和度(Saturation)以及最初这一个明度或者说亮度来辨别,然而对于最初两个指标而言,不同模型的构建其实是不太一样的,这里咱们将重点介绍两种模型,即:类HSL和类HSV模型 对于HSL模型而言,最初定义的指标是一个混入了黑白的量,其最初的状态在欧氏空间中,体现为一个全椎体,如上图所示。 而对于HSV模型而言,最初定义的指标只是混入了一个彩色的量,其最初状态在欧氏空间中,体现为一个倒立的圆锥体,如上图所示。 正是因为这种对于S和 * 的解决不同,导致呈现了很多不同的名词及示意模型,这里咱们用以下表格做一下常见的 HS* 模型的比照: 简写全称正文HSVHue, Saturation, Value明度HSLHue, Saturation, Lightness亮度HSBHue, Saturation, Brightness明度HSIHue, Saturation, Intensity亮度论断:HSV = HSB,HSL ≈ HSI 如上图所示,后续咱们不加特地阐明的话,后续将以HSV和HSL这两种作为HS*的两种典型代表进行表述,作为RGB模型的变种,咱们后续在色调计算过程中对 HS* 和 RGB模型的换算进行详解。 LAB 随着倒退,人们对色调的钻研不再局限于设施根底条件的限定,由此,CIE(Commission Internationale de Photométrie)国内照明协会提出了Lab模型,其不同于RGB的模型,其中L代表亮度,而a则是从深绿色(低亮)到灰色(中亮)再到亮粉红色(高亮)的过渡,b则是亮蓝色(低亮)到灰色(中亮)再到黄色(高亮)的过渡,其合成模型如上图所示。 XYZ 在上一个Lab模型中咱们晓得,CIE对色调做了进一步的调研钻研,其实Lab模型也是XYZ模型的一个衍生变种,其对RGB模型中的光源做了坐标系方面的辨别,其对三元色进行了相干的修改,其是设施无关的,如上图所示,在欧氏空间中,两个坐标系产生了偏移。(ps:具体的变动,能够参考这篇文章RGB色调体系和XYZ色调体系) 色调空间 色调空间又称为色域,在上一部分咱们介绍了不同的色调模型,那么对于理论生产过程中会遇到各种不同的理论状况,因此各个厂家或者组织基于各自的设施或者场景的不同而理论造成的色调映射关系,从而提出了各自的色调范畴,这里咱们联合wiki百科及百度百科,不谨严的给出如下定义: 色调空间是基于色调模型而对理论特定场景的色调范畴的映射关系。对于常见的色调空间,咱们列举了以下几种: ...

May 30, 2022 · 6 min · jiezi

关于设计:数据密集型型系统设计LSMTree-VS-BTree

引言本文为《数据密集型利用零碎设计》的读书笔记第一局部第三章的笔记整顿,也是集体认为的这本书第一局部最重要的内容。本文将会针对目前数据库系统两个次要营垒进行开展,别离是采纳日志型存储构造高速读写的LSM-Tree和面向OLTP的事务数据库BTree两种数据结构比照。 次要内容本文的次要内容介绍如下: 最简略key/value数据库考量和拓展,从零开始理解日志型存储构造。索引对于数据库的重要性,哈希索引如何优化key/value数据库。Btree 数据结构的简略介绍,数据结构和特点等。LSM-Tree日志存储构造 VS Btree存储引擎,两大阵营的优劣比照。OLTP到OLAP的比照,行存储到列式存储构造演进,以及数据仓库呈现和数据分析的演进。数据库底层设计考量底层存储模式:记录存储的根本设计格局,尽管格局会有不同的设计,然而最终都是以文件的模式存储。查问/新增/读取/批改形式:在内部来看也就是在数据库概念中的DML操作,这种操作面对的是客户端,属于对外接口的局部。而从外部来看则是存储数据结构,操作数据结构和并发性能的考量。操作日志:出于持久性的考量,操作日志是不可或缺的因素,也是意外之后数据修复的保障。数据类型:比方Key/value存储还是针对行列的存储构造。key/value存储构造和哈希索引要害:#key/value存储构造解决 #哈希索引优化 从零开始设计一个数据库的存储模式,能够从上面的几个点思考,从存储构造登程咱们看日志存储构造数据库是如何呈现的。 首先是key/value数据库数据结构设计第一版,从最简略的k/v存储数据库开始理解由此引申出哈希索引的构造: 下面构造有如下的特点: 存储模式:次要以key/value存储模式,key/value能够是任何内容。底层应用纯文本的模式存储,应用追加形式更新数据,雷同key应用最初一次读到的key为基准。 读写形式:db_set xx设置数据,db_get xx读取数据,批改一个key通过最初一行追加模式,意味着更新和删除操作没有任何的开销,无需关注并发的问题。 查问性能:查找数据的开销为O(n),新增和批改的性能都是O(1)。 追加式解决长处 程序写比随机写好很多段文件是追加不可变的,意味着并发拜访和解体复原比拟容易压缩和合并分段能够避免数据文件碎片化问题最简略的k/v模式的数据库造成有哪些毛病? 追加对于存储空间的节约,尽管追加对于更新和新增非常方面并且保护老本较低,然而有个显著的问题是存储空间的节约,同时咱们发现其实并不需要存储原始文本的模式,同时数据自身能够通过压缩更加紧凑。查问效率随着数据的收缩而升高,所以须要对于查问速度进行优化,对于查问最简略的形式是引入索引,而对于key/value存储模式设计索引最为常见的是哈希索引对于Key/value存储引擎来说哈希是罕用的索引类型,哈希索引应用内存中的哈希表进行实现,键值对的键存储数据须要索引的数值,而值存储偏移量,偏移量通过计算获取存储地位,在原始数据中间接找到相干地位的数据间接读取。 上面是哈希索引对于key/value构造数据进行索引优化。 纯文本存储数据收缩如何避免性能变差? 分段数据:当追加到肯定水平之后则写入一个新的文件。压缩段:将最新的数据进行压缩存储,因为应用追加新增形式,能够间接抛弃旧数据。段压缩和多段合并:压缩与合并的过程没有特定布局,取决于数据结构和存储构造的抉择。如何避免性能变差: 哈希表和段进行绑定,一个段对应一个哈希表,同时执行段压缩和多端合并,保障脏数据及时清理,最初肯定在内存中引入哈希表进行保护。 理解了大抵思路之后,如何进行具体优化? 压缩合并存储:为了让存储数据更加紧凑同时没有节约,定期对于追加数据进行合并压缩是必要的,同时数据分段也能够进步线程并发读写性能。数据分段:留神数据分段是联合压缩合并一起解决的,当压缩合并存储的数据达到一定量的时候须要对于数据进行分段解决,目标是避免单文件过大同时能够进步索引的搜寻效率。哈希表:引入哈希表构造,在数据行上加一层索引目录,能够放慢查问性能,索引的key存储的是键须要保障惟一,而value则存储了行记录的指针,这实用于分段的数据结构找到数据存储的地位,通过一次遍历分段间接通过偏移指针查指定数据是否符合要求即可。下面探讨的存储构造其实存在理论的实现形式,此数据库存储引擎便是:Bitcast。 哈希索引: 哈希索引设计特点 文件格式:并没有应用纯文本存储而是应用二进制,应用字节来记录字符串长度,前面存储实在数据。(二进制也有利于压缩) 解体复原:最大的问题是重启之后哈希表会被开释,如果须要从新建设哈希表须要从新读取段,所以最大的性能开销在扫描段上,有一种优化形式是将哈希表的快照存储磁盘上间接读取。局部写入记录:应用SHA盐值和操作日志对于局部写入记录进行复原,操作日志绝对于数据存储日志更为简略,只须要做增量操作,因为目标仅仅用于存储引擎解体之后能够保证数据的持久性。并发管制:Bitcast实际上是一个写线程和多个读线程,数据应用追加形式能够保障多个线程读取,然而只能保障一个线程写入,然而因为数据分段,能够多线程同时改写不同数据段。通过下面哈希构造的介绍,咱们能够总结出哈希索引的几个特点: 哈希索引实用于查问多,增删少的状况,尽管压缩和分段合并能够解决数据存储效率低的问题,然而对于频繁的增删须要额定的开销从新保护改变哈希表。哈希表须要在内存中进行应用,所以受限于内存的大小,当然并不是说磁盘无奈存储哈希表,而是哈希表在磁盘中难以保护和存储。哈希的索引模式也存在局限性: 尽管哈希表不肯定必须放入内存,实践能够在磁盘上保护哈希表,然而这样做须要大量的IO,同时哈希抵触须要更简单的解决逻辑。区间查问效率不高,对于范畴查问的解决能力较弱,此时工夫复杂度会进化为O(n)。以上是哈希构造对于key/value存储的构造的优化。 哈希索引通常的实用场景: 点击数:对于数据的准确性要求并不是非常高,然而对于效率要求非常高大量数据的惟一记录查找,留神是大量数据,因为哈希表空间无限。小结: 咱们能够看到,从一个最简略的k/v数据库到哈希索引的构造引入,数据的存储和读取构造逐步变简单,能够看到哈希索引非常适合key/value的存储引擎,然而显然它存在比拟显著的缺点,比方只能保护哈希表到内存,并且频繁的更新插入key/value对于索引的保护开销也不小,最初最为致命的是范畴查问对于哈希索引是硬伤。 总结:索引特点 放慢原始数据的查问速度空间换工夫,须要更多的存储空间以及更长写数据工夫索引很多时候被视为和原始数据离开的构造通过下面的设计有毛病,针对哈希索引有了第一层进化,那就是 SSTable和LSM-Tree。 SSTable和LSM-Tree构造SSTable #LSM-Tree概念在具体的内容介绍之前,咱们须要弄清楚SSTable和LSM-Tree有什么区别,简略来说LSM-Tree是对SSTable概念和思维的一个继承。另外须要留神这个构造特点正好解决了哈希索引局限性问题,同时SSTable并没有摈弃key/value这样的存储构造,而是在索引构造上进一步降级。 SSTable概念SSTable起源自谷歌在2006年公布的一篇轰动世界的论文,外面的BigTable就是SSTable和LSM-Tree的前身:Bigtable: A Distributed Storage System for Structured Data。如果感觉论文难以了解,能够参考这篇文章了解: https://blog.csdn.net/OpenNai... 这里挑了其中一些和SSTable无关的内容,惋惜的是这篇论文并没有具体的介绍SSTable的外部数据结构,在论文第六个大节中介绍了SSTable的作用: BigTable和GFS 是什么关系呢?在论文中咱们能够看到一个相似树的构造,其中根节点为主服务器,主服务器负责承受申请,通过治理分片服务器将申请分片到不同的片服务器中,所以从外层看最终干活的是片服务器,实际上片服务器自身只是负责管理本人分片SSTable,通过非凡索引晓得数据在那个SSTable分片中,而后从GFS中读取SSTable文件的数据,而GFS则可能要从多个chuncker server外面搜寻数据。 而图中的metatable原数据表能够看作是和SSTable绑定的相似索引的关系,元数据表的数据是不能被外界拜访的,外界拜访的是元数据对应的SSTable分片,这和前面介绍的LSM-Tree有着非常相熟的符合关系。 改良与比照关键点: 数据存储形式,索引查找形式改良 SSTable通常如何工作?写入的时候不写入磁盘而是先写入内存表的数据结构,同时在内存将数据进行排序。当数据结构内存占用超过肯定的阈值就能够间接写入到磁盘文件因为曾经是排好序的状态,所以能够对于旧构造笼罩,写入效率比拟高。并且写入和数据结构改变能够同时进行。读写程序依照 内存 -> 磁盘 -> 上一次写入文件 -> 未找到这样的程序进行查找和搜寻。后盾定时线程定时合并和压缩排序分段,将废除值给笼罩或者抛弃。SStable的改良点上面是SSTable绝对于哈希构造的特点: 高效合并:合并段的过程更加高效,每一个段都是依照特定程序排序,当呈现多个反复数值的时候能够合并到最新的段,对于旧数据则能够间接舍弃后面的内容。范畴索引优化:内存中哈希表也是有序存储,能够将多个kv对应的数据条目一起压缩存储,这样索引条目只须要结尾局部的键值即可,因为后续所有的记录都是有序的。索引优化:比起哈希较为涣散随便的构造,这样的解决就义肯定的读写开销换来更加高效的存储和索引构造,并且能够反对范畴索引扫描。程序读写:数据顺序存储的益处是能够程序读写,防止磁盘的随机读写能够大幅度晋升读写性能上面是改良过后的压缩过程图: 最大的改变点:压缩合并的根底上对于SSTable根底内容进行合并操作。 ...

April 3, 2022 · 2 min · jiezi

关于设计:元宇宙到家那些聪明的设计工具

✏️ 编者按: 想要量身定制一款专属你的衣橱?想要亲自设计色彩和布局?外部的隔板、抽屉、网篮要什么尺寸?挂衣杆和裤架也不能少?甚至……你还想同时对比多个相似的衣橱? 在这个妇孺皆知家具和家居批发企业,你除了能够选购现成的家具,还能线上 DIY,拼接组装你想要的家具整机。在用户设计实现后,在线商城还会贴心地举荐多个类似家具供顾客参考。 这个聪慧的设计和举荐平台是如何实现的?Milvus 社区有幸邀请到了来自该外资家居企业的工程师陈晨,与大家分享 Milvus 数据库在家具行业中的利用。 嘉宾简介: 陈晨,Leader of data smart offering platform,负责构建智慧数据生成平台,毕业于复旦大学,热衷摸索新技术,迭代、重构和降级已有零碎。 业务背景在家具与家居行业,为了让用户对产品有一个直观的概念,须要先“打样”,也就是把家具拼出来展现。家具通常体积宏大,须要较大展现空间。如何在无限的空间内让用户更好地「看到」家具,成为了家具行业的痛点。 为了解决这个问题,咱们找到了一款在线解决方案(如上图所示),能够实现在线打样、部分调整、在线出样等性能。 该智能化平台须要蕴含以下数据链路: 筹备数据,定义整机在线召回,通过排序找到满足用户须要的数据一些补充的业务逻辑,随后最终交付给用户技术选型 在上图的智能生产数据平台模型中,左侧是与销售业务相干的信息,右侧是与数据生产相干的内容。为了反对设计工具的应用,咱们须要将物理空间中的家具组件转化为计算机能够意识的数据模型。 除此之外,咱们还须要反对 H5、App、小程序等多平台,须要领有在线的高性能召回排序,稳固的、可兼容的存储。为了可能满足以上需要,咱们还须要加强平台鲁棒性,让平台能够自我修复、能够本人降级、能够去做一些迭代。 基于以上需要,咱们是这样设计该智能化平台的: Elasticsearch 负责一些较粗的召回和简略筛选,这些数据来自多个数据源对基于一些规定生成的向量,应用 Milvus 数据库进行向量间隔计算,而后再做排序Backend 负责 BU、business insight 做数据后处理,这样就实现了数据的最终交付因为家具是一个平面的空间概念,须要多维度形容一件家具的构造,很难用传统的标量数据(如  SKU)形容全副信息。所以,咱们须要抉择了一款迭代迅速、兼容性好、使用方便的向量数据库实现向量数据的存储和检索,下图是咱们对 Elasticsearch、 Faiss、 Milvus 数据库等向量搜寻解决方案的横纵向测评,基于性能、稳定性、易用性等因素综合考量,咱们最初抉择了向量数据库 Milvus。 架构与数据链路 以上是咱们的平台架构示意图。其中,Milvus 数据库负责存储向量数据。基于这个架构,咱们又拆散线和在线两个局部。 离线过程分为五步: 定义 items,将物理空间上的整机示意为计算机可能了解的 item数据生成对家具进行了特色工程,包含标签选取、表征 encoding召回数据筹备,将数据转成可搜寻的数据结构数据排序筹备,此时会实现 embedding 以及数据集治理等工作在线过程分为五步: Backend 步骤中,设计工具将后盾收到的 query 与通过隐衷含糊解决的用户画像拼接,用于组织后续召回、排序的参数和策略Query understanding 步骤中,平台依据用户的需要和事后配置的参数,组织召回策略和排序参数Search platform 将解析进去的后果组成 DSL,通过多个数据集进行召回Ranking 步骤中,平台依据事后定义的规定和表征信息进行混合打分和后果调整回到 Backend 步骤,补全数据,依据经营需要重新整理数据返回给前端应用示例在实在场景中,咱们是如何实现这个平台的呢? 下图左侧的衣柜展现了多种挂置和叠放的可能性,这些特色会被转化为数据标签保留在 Elasticsearch 中,Elasticsearch 中的代码设置如右侧所示。这些标签次要用于线上的粗召回以及线上数据 debug。 ...

January 6, 2022 · 1 min · jiezi

关于设计:提升产品创新能力试试斯坦福大学设计思维模型

作者:Yvonne 起源:恒生LIGHT云社区 前言设计思维的概念目前在在教育、艺术、商业等畛域失去越来越多的利用,有翻新需要的公司越来越宽泛地应用设计思维来制订设计理念,晋升产品的创新能力。在这样的趋势下,设计思维的重要性也显而易见,作为设计师也须要借助一些迷信的办法和理念,来帮忙本人找到设计突破口,斯坦福大学设计思维模型便是一种十分无效的思维模型,咱们一起来学习一下吧。 什么是斯坦福大学设计思维?设计思维最早起源于诺贝尔奖得主赫伯特·西蒙开创性的著述《设计办法的迷信》一书。设计思维在这个根底上产生了很多变体,斯坦福大学五阶段设计思维模型便是其中一种。 那么到底什么是设计思维,在学习一个概念之前,咱们能够尝试用“黄金圈法令”去定义它。 从成绩(what)来看,设计思维帮忙创新性地解决简单问题(满足需要);从理念(why)来看,设计思维是一种以人为核心的设计观;从伎俩办法(how)来看,设计思维是设计师解决问题的工作流程和办法。 因而,综合来说,设计思维一种以人为核心的,通过使用设计师的工作流程和办法,创新性解决简单问题的一种思维形式。 作为一种思维的形式,它被普遍认为能够用来解决简单问题,可能了解问题产生的背景、可能催生洞察力及解决办法,并可能感性地剖析和找出最合适的解决方案。 斯坦福大学设计思维的五个阶段斯坦福大学五阶段设计思维模型次要包含五个阶段:共情、定义(问题)、构思、原型和测试。 一、共情设计思维是一种以人为本的设计观点,共情的外围是指作为设计者要主观地了解指标用户,满足他们的需要与偏好的思考形式。 这个步骤的要害是站在指标用户的视角,去察看、去感知,找到他们最实在的需要、实在在乎的货色。在这个阶段,设计师罕用的办法有:访谈法、观察法、问卷调研、5W1H问题法等,其中最罕用的个别为访谈法和观察法。 二、定义问题定义问题在斯坦福设计流程中也被叫做POV(Point Of View),就是指透过景象开掘实质的过程。咱们常说用户所说的经常不是他的实在诉求,诚如汽车大王亨利福特的名言:“如果我当年去问顾客他们想要什么,他们必定会通知我:‘一匹更快的马。’”。正是因为福特晓得人们想要的其实不是想要跑的更快的马,是想要更快的速度,所以他能力绕开表象,造出了世界上第一辆汽车。 其次,定义问题也是一个收敛的过程,咱们须要将共情阶段收集的信息碎片,通过整顿剖析找出需要背地的实在场景,造成清晰的问题定义。 比方在设计一款DevOps产品时,通过调研发现同样一个新建需要的页面,解决简略需要的人员会心愿创立需要的时候表单能够重点突出他们须要填写的内容,弱化掉烦扰项;而解决简单需要的人员则心愿所有字段都能够平铺开展,通过地位记忆的形式去定位到须要填写的字段。同样都是出于晋升工作效率的诉求,然而他们会给你传播截然不同的需要。所以只有通过调研,通盘考虑能力制订出适合的设计策略。 三、构想在这一步咱们须要针对定义进去的问题,去构想解决方案,这个解决方案可能是多层面的,有可能是产品交互、产品性能、服务体验等等。 这个阶段能够应用的头脑风暴的办法,来刺激自在思考和扩充问题范畴。到序幕的时候对所有计划进行收敛,挑选出一个最具备可行性或者最具备价值的解决方案。 四、原型这一步的外围是把构想出的解决方案从虚构的想法,转化为能够测试的原型。 从效率上来说原型须要做到简略、正当、疾速。因而他可能只是一个交互原型或者线上demo,只有是能够用来测试用户反馈的物理载体都能够。咱们的目标是为后面的阶段得出的每个问题寻找最正当的解决方案。 五、测试最初一步就是拿着原型去找指标客户测试,让他们去应用原型,并基于应用的体验给出反馈。 在这个过程中咱们能够引入用户调研、可用性测试去收集整理用户的反馈,并在整顿的后果中会发现新的需要。带着这些新需要,咱们回到定义阶段修改或减少问题清单,而后在构想阶段修改或者从新设计方案,而后再制作新的原型进行测试,直到最终解决客户问题为止。 基于上述介绍,咱们能够剖析得出设计思维有两个特点:一、 设计思维是一种从发散到收敛的思维过程从共情采集需要到定义具体问题,从头脑风暴寻求解决方案到造成惟一可解决问题的原型,都是发散到收敛的过程。 发散能够开辟视线、思考更多跨畛域可能性,是创新性的土壤。先发散,而后再收敛,使用谨严的逻辑和数据,通过业余的测评剖析造成可行度最高或者价值最大的指标和计划。 二、设计思维是一种非线性循环工作流程设计思维不是一个线性的过程,它而蕴含了大循环和小循环,在前面的阶段取得的信息能够用于重构或优化后面阶段的论断,从而造成一个永动的循环。 你能够依照程序执行这五个阶段,也能够灵便地将这五个阶段了解为达成指标的不同切入点的模块,彼此能够独立并行运行,不须要遵循特定的程序,并且能够迭代地反复执行来扩大解决方案空间,直到找到最佳的解决方案。 总结在我看来,设计思维不仅是一套迷信的工作模式,作为设计师更能够从中学习到一些设计哲学 从设计观来讲,咱们尊重和关爱咱们的用户,去共情、去摸索,放下执著的偏见;从心态上来讲,设计师须要放弃凋谢好奇,拥抱不确定性和模糊性,将问题视为一种时机而不是一种威逼;从工作态度上来讲,咱们须要敢于对计划进行测试和修改,有承受经常性失败的勇气和执着寻找解决方案的韧性。设计师通过设计思维这个永动的循环,一直取得新的见解,对用户体验有更粗浅的了解。 想向技术大佬们多多取经?开发中遇到的问题何处探讨?如何获取金融科技海量资源? 恒生LIGHT云社区,由恒生电子搭建的金融科技业余社区平台,分享实用技术干货、资源数据、金融科技行业趋势,拥抱所有金融开发者。 扫描下方小程序二维码,退出咱们!

December 24, 2021 · 1 min · jiezi

关于设计:设计方法与实践介绍

工夫滴答走,学习不停歇。明天的内容是《设计办法与实际介绍》,咱们将从软件设计准则、clean code、单元测试、重构和配置化架构这五大方面给大家进行解说。 还愣着干什么,学起来吧~ 01 软件设计准则1、软件设计的目标软件设计是为了使软件在长期范畴内可能容易的进行变动。咱们从上面这三个点来了解这句话。 (1)变动:软件不是变化无穷的,无论是软件自身的需要、软件依赖的其余软件资源都是始终在发生变化的,惟一不变的就是变动。 (2)容易:任何一个软件的变动都须要老本,要尽可能的升高变动的老本,使得软件能够很容易应答软件的变动。 (3)长期:事实上须要长期进行保护的软件更应该做好软件设计,因为软件长期的变动十分多,难以提前作出预测,须要良好的软件设计来应答。 2、软件设计准则 软件设计有着很多的准则,最根本的准则是高内聚低耦合,它也是软件设计谋求的最高指标。内聚指的是一个软件外部间元素相关联的水平。高内聚谋求的是严密相关联的元素要放在一起。低耦合指的是单位之间尽可能少地关联,依赖。 在高内聚低耦合之上有很多其余的准则:如SOLID准则、简略设计、正交设计,在这之上还会有设计模式作为最高层的软件设计准则。 02 clean code1、clean code的概念clean code中文解释为整洁代码,是指写的代码可能在尽可能短的工夫内被他人读懂,且代码看上去排版整洁、逻辑清晰、扩展性好。 2、命名规定代码中命名须要遵循以下的几个规定: (1) 表白它是什么,不要表白怎么做。 (2) 代码要做到自正文。 (3) 应用有意义的循环迭代变量。 (4) 防止缩写,尤其拼音缩写。 (5) 不要应用非约定俗成的缩写。 (6) 防止应用魔法数。 (7) 不要胆怯长变量名。 3、正文正文对于代码来说是必不可少的。通常状况下,好的正文蕴含:版权信息,设计用意,警示信息。 不好的正文则具备以下一个或几个特点:同义重复、费解关联关系、套用模板、提供历史批改记录以及正文掉的代码。 4、函数在写函数时,该当留神,每个函数只做一件事,每个函数都是繁多职责的。 函数分为骨架函数和步骤函数。 → 骨架函数是业务逻辑和算法是在高层次上的形象形容。 →步骤函数是业务逻辑和算法的一些实现细节,是被暗藏起来的。 5、编码细节在编码细节方面,须要遵循以下几点规定: (1)应用天然的比拟程序。 (2)简化逻辑档次,防止多层嵌套。 (3)在写三元表达式时不要呈现简单的逻辑和过长的条件。 (4)须要控制变量的作用域,也就是放大变量作用域的范畴,越小越好。 03 单元测试1、为什么进行单元测试测试是分为不同档次的:最底层是单元测试,两头是基于模块级、组件级的测试,再往上则是零碎级别的测试。 越底层的测试,越可能疾速地发现问题。底层的测试集成性更好,可能平安的进行代码批改。下层的测试个别状况下取得反馈的速度比较慢,测试过程也比拟轻便。 所以单元测试具备更早发现问题,更容易集成,更平安地代码批改的长处。 2、写好单元测试的重要性写好单元测试不是一件容易的事件,须要破费许多工夫。 请看下面的示意图:x轴上方示意的是单元测试的老本,在理论开发的过程中,写单元测试的老本甚至不亚于写代码的老本。单元测试带来的益处就是能够升高产品开发的老本 好的单元测试可能升高产品开发的老本。如果单元测试写得不好的话,岂但会减少产品开发的老本,而且还会减少单元测试老本。 3、单元测试准则与模式单元测试具备许多的准则与模式,本次课程重点介绍四个准则。 第一个准则:Tests As Documentation将测试当成一个文档工作,也就是说咱们须要把测试写得像文档一样简洁,通过一些形容,能够清晰地晓得这个测试的作用。在之后对我的项目批改时,只须要查看单元测试即可。第二个准则:Fully Automated and Self-Checking单元测试都是能够进行自我查看、自我校验的,通过代码的编写,可能晓得测试是否胜利,不须要人为断定。第三个准则:Do No Harm,不可破坏性。局部开发人员在进行测试时,为了实现目标,会基于测试代码创建一些逻辑,这种做法是谬误的。在写测试时不能独自为测试创立特地的逻辑,更不能毁坏原有代码的逻辑。第四个准则:Keep tests as simple as possible,简洁性。单元测试尽管是用来保障代码的正确性,但单元测试也是一份代码,为了防止过多的测试代码相笼罩,要尽可能地把单元测试的代码写得简略,保障其不会出错。04 重构在进行重构时须要遵循肯定的规定。 1、业务导向重构肯定是要解决理论的业务问题的,而不是为了重构去重构。 2、小步快跑通常重构是须要多人同时参加,重构过程中开发人员要随时比照骨干与分支的状况。当某一个开发人员在分支上进行了大量改变并筹备将其合并到骨干时,有可能骨干和分支的代码有很大的差别。所以进行重构时,要将问题拆分成多个小的单元进行批改,并且每批改一个就进行一次分支合并。这种小步快跑的模式能够随时同步骨干上的代码,缩小出错的可能。 ...

September 14, 2021 · 1 min · jiezi

关于设计:Windows-10-中到底有多少层不一样的-UI

原文链接:https://ntdotdev.wordpress.co...可能你据说过这种说法:如果咱们深刻开掘 Windows 10 的 UI,很可能会发现这里边甚至有 Windows 3.X 时代的设计元素。不过事实真的如此吗?在这篇文章中,咱们会探寻 Windows 10 中到底有多少层不一样的 UI,以及这些 UI 最早是什么时候呈现的。 思考到试验的目标,我抉择了最新的 Windows 10 版本(2021 年 2 月 6 号公布),也就是 Windows 10 build 21301 版本。 那么,话不多说,咱们开始吧! 第一层:Fluent Design咱们先从最新也是最棒的 UI 层开始,也即 Fluent Design(晦涩设计)。这种 UI 最早公布于 2017 年,之后在 WIndows 10 1803 版本的更新中引入。Fluent Design 是 Modern Design Language 2 (MDL2)通过大幅度重设计后的版本,旨在带来具备光感、深度、动效、质感与缩放的元素。同时,它也带来了全新的光照成果和亚克力半透明背景。 当初,大部分的 UWP 利用都进行了降级以应用全新的晦涩设计提供的元素,当然还包含了局部前端元素,包含开始菜单、活动中心以及登陆页面等。 尽管 Fluent Design 广受好评,但很多死忠粉还是认为这种设计来得太晚了,而且利用得还不够全面 —— 只有局部个性遵循这种新的设计格调进行了拓展。 上面咱们通过几张图片感受一下 Fluent Design: ...

June 21, 2021 · 2 min · jiezi

关于设计模式:浅谈设计模式-迭代器模式十一

浅谈设计模式 - 迭代器模式(十一)前言 迭代器模式通常只须要晓得该模式的实现原理和理解结构图即可,在设计模式当中本人实现的状况简直是没有的,所以这个模式简略的过一遍。 什么是迭代器模式定义:提供程序的办法拜访一个聚合对象的各个元素,同时又不会裸露外部的性能 迭代器模式通过接管遍历的细节,让提供方不用关怀迭代的具体细节,只须要提供对应的聚合对象即可。 迭代器模式和加强的FOR循环: Jdk1.5之后,将泛型和加强for循环退出到语言体系,能够间接对于汇合的内容进行for循环查看,其实实质上还是调用了iterator办法,而java通过语法糖的模式为咱们进行的遍历的暗藏。 迭代器模式结构图 迭代器模式的结构图如下: Aggregate:聚合对象的独特接口,定义了具备遍历性能的聚合对象,通过定义创立迭代器的接口来建设与迭代器的组合ConcreateAggregate:具体的迭代器实现对象,通过接口办法返回具体的迭代器实现Iterator:迭代器接口,定义迭代器的对立标准,所以派生类都须要强制依照接口标准执行迭代器的实现。保障迭代器具备类似的行为。ConcreteIterator:具体的迭代器实现,外部聚合对象的同时,能够扩大迭代器的遍历形式,比方ListIterator。迭代器模式特点迭代器将遍历的细节进行了封装,聚合对象不须要在关怀客户端如何操作外部的变量,而是通过委托给迭代器的模式交由迭代器去实现具体的遍历细节。迭代器能够在不裸露内部结构的同时让外界能够拜访到外部的聚合对象,所以即便是齐全不同的对象也能够对立看待和解决。迭代器是一种职责的转移,将遍历的工作从本来的聚合对象中进行独立,能在不改变数据结构的同时扭转数据的操作形式。迭代器的注意事项:须要留神迭代器存在外部的迭代器和内部的迭代器,外部的迭代器供对象自身应用不对外开放,内部的迭代器通过办法返回给调用方应用。每个责任对应一个区域,超过区域象征多了一个责任,遍历和数据操作实际上是两个操作,应该辨别看待。留神迭代器是如何体现繁多职责的准则,他剥离了遍历对象的性能,将其封装到一个迭代器外部进行应用。好的迭代器该当具备“疾速失败机制”,目标是为了避免操作外部元素的指针越界,同时及时告诉客户端遍历异样。如果想让办法不反对某些性能,最好应用异样机制揭示客户端我不反对某些操作。案例 光有实践还是不够的,这里配合代码解说迭代器是如何实现解耦聚合对象的遍历的。 模仿场景: 因为迭代器在理论工作中应用概率 简直为0,这里设置的场景比较简单 咱们应用window最常见的文件系统来作为案例,咱们通常进入不同的磁盘,首先就是对该磁盘上面的第一级目录进行遍历,同时咱们依据遍历形式的不同,能够将页面展现为分组,依照工夫排序,显示不同的详略信息.....这些性能的实质都是遍历,只不过遍历的模式不同,为了实现对于菜单的不同模式遍历,咱们通过定义不同迭代器来实现这一个指标。 接着,咱们会发现迭代的品种丰盛还不够,咱们还须要迭代其余的内容,比方工作管理器须要迭代不同的过程,同样也蕴含了排序的或者暗藏局部过程等等一系列的性能,所以须要让不同的对象能够撑持类似的迭代操作,并且能够自在的替换迭代的形式,当然这部分性能不会放入案例局部,案例局部为简略的迭代器实现。 具体实现 在进行具体的编码之前,先检查一下须要的根本构建类: Travelsable:定义对象具备迭代的性能接口。MissionBoard:任务栏,储存根本的工作信息,提供迭代器供内部展现。TaskItemlIterator:工作迭代器,用于工作的迭代操作ConcreteCatalogIterator:目录迭代器的实现具体子类,定义了不同的迭代品种。TaskItem 工作项,定义一个工作的内容Computer 电脑,只须要治理任务栏和文件管理器即可。FileManager 文件管理器,负责管理文件夹的内容FileIterator 文件迭代器,治理文件夹的迭代操作FileItem 文件项 上面间接依照结构图构建具体代码: // 电脑,只须要治理任务栏和文件管理器即可。public class Computer { private FileManager fileManager; private MissionBoard missionBoard; public Computer(FileManager fileManager, MissionBoard missionBoard) { this.fileManager = fileManager; this.missionBoard = missionBoard; } public void display(){ Iterator fileManagerIterator = fileManager.createIterator(); Iterator missionBoardIterator = missionBoard.createIterator(); while (fileManagerIterator.hasNext()){ Object next = fileManagerIterator.next(); System.out.println(next); } while (missionBoardIterator.hasNext()){ Object next = missionBoardIterator.next(); System.out.println(next); } }}// 文件项public class FileItem { private String fileName; private String editDate; private String ceateDate; private long size; // 省略局部内容}// 工作项public class TaskItem { private String name; private int size; // 省略局部内容}// 迭代器标准接口public interface Travelsable<E extends Object>{ /** * 创立迭代器的办法 * @return */ Iterator<E> createIterator();}// 任务栏,治理工作项. 实现接口,反对迭代操作public class MissionBoard implements Travelsable { private Stack<TaskItem> taskItems; public MissionBoard() { taskItems = new Stack<>(); taskItems.push(new TaskItem("工作1", 10)); taskItems.push(new TaskItem("工作2", 1230)); taskItems.push(new TaskItem("工作3", 123)); taskItems.push(new TaskItem("工作4", 414)); taskItems.push(new TaskItem("工作5", 555)); } @Override public Iterator createIterator() { return new TaskItemlIterator(taskItems); }}// 文件管理器,管理文件项,实现接口并且反对迭代操作public class FileManager implements Travelsable{ private FileItem[] fileItems; public FileManager() { this.fileItems = new FileItem[10]; Random random = new Random(10000); for (int i = 0; i < fileItems.length; i++) { fileItems[i] = new FileItem("文件"+i, random.nextInt(2000)); } } @Override public Iterator createIterator() { return new FileIterator(fileItems); }}//文件迭代器public class FileIterator implements Iterator{ private FileItem[] fileItems; private int index; public FileIterator(FileItem[] fileItems) { this.fileItems = fileItems; this.index = 0; } @Override public boolean hasNext() { return index++ < fileItems.length - 1; } @Override public Object next() { return fileItems[index]; } @Override public void remove(Object ele) { throw new UnsupportedOperationException("数组不反对以后操作"); }}// 工作迭代器public class TaskItemlIterator implements Iterator{ private Stack<TaskItem> taskItems; public TaskItemlIterator(Stack<TaskItem> taskItems) { this.taskItems = taskItems; } @Override public boolean hasNext() { if(taskItems.isEmpty()){ return false; } TaskItem peek = taskItems.peek(); return peek != null; } @Override public Object next() { return taskItems.pop(); } @Override public void remove(Object ele) { taskItems.remove(ele); }}以上就是迭代的大抵实现案例代码,古代编程根本不会本人去设计迭代器,所以理解概念和晓得样板代码即可。 ...

April 11, 2021 · 2 min · jiezi

关于前端:设计稿UI视图自动生成代码方案的探索

1 背景设计稿(UI视图)转代码是前端工程师日常一直反复的工作,这部分工作复杂度较低但工作占比拟高,所以晋升设计稿转代码的效率始终是前端工程师谋求的方向之一。此前,前端工程师尝试过将业务组件模块化构建成通用视图库,并通过拖拽、拼接等模式搭建业务模块,从而实现视图复用,升高设计稿转代码的研发老本。但随着业务的倒退和个性化的驱动,通用视图库无奈笼罩所有利用场景,本文提出了一种设计稿主动生成代码的计划。 目前,业内支流的代码生成计划有两种,一种是通过训练神经网络,从图片或草图间接生成代码,以微软sketch2json为代表;另一种是基于Sketch源文件,从中解析出图层信息转化成DSL并生成代码,以imgCook为代表。通过实际,咱们发现第一种计划基于神经网络的代码生成算法尽管简略粗犷,但简单层布局的准确率较低、可解释水平不高导致后续无奈继续优化。计划二中Sketch源文件信息量丰盛、算法自定义水平高、优化空间大。因而,咱们调研了业界基于Sketch的代码主动生成计划(已对外颁布或者开源),发现了一些有余并尝试解决,上面从算法准确率、代码可读性、研发流程覆盖度等方面做一下比照(该比照后果仅考查业界计划对咱们本人业务的适用性,理论后果可能存在差别): 算法准确率方面:淘宝imgCook反对基于AI的组件辨认,不反对成组布局,准确率中等(从官网理解到能够辨认循环布局,但不能辨认出测试样本中的循环布局),58 Picasso仅反对原始组件的辨认,简单组件生成谬误较多,不反对成组/悬浮/循环布局,准确率较低。代码可读性方面:淘宝imgCook在生成布局时,测试样本中图层重叠区域应用到了基于根布局的相对定位形式,不合乎RD预期,可读性个别,而咱们的计划应用绝对定位形式,可读性较好。研发流程覆盖度方面:淘宝imgCook从RD视角构建了一个IDE,反对在IDE中实现款式调整、逻辑绑定;而咱们的计划从产研合作视角登程,反对数据、逻辑、埋点的可视化配置及上线。2 计划介绍如图所示,配置平台次要分成三块包含:设计稿转视图树(UI2DSL)、视图树转代码(DSL2Code)、以及业务信息绑定,上面简略介绍一下每一块的作用。 设计稿转DSL视图树(UI2DSL):将设计稿转化成平台无关的DSL视图树。视图树转代码(DSL2Code):将DSL视图树转化成基于Flex布局的MTFlexBox动态代码。业务信息绑定:提供可视化配置工具,反对MTFlexBox动态代码绑定后盾数据、业务逻辑、以及曝光/点击等埋点逻辑。2.1 设计稿转视图树(UI2DSL)UI2DSL次要经验以下四个步骤: 2.1.1 设计稿导入在日常开发过程中,咱们接触比拟多的组件有按钮、题目、进度条、评分组件等,然而Sketch数据源中并没有这些组件只有图层信息,图层是设计师在设计UI视图时用到的视图控件。组件与图层的对应关系是一对多的关系,图层在Sketch数据源中的表现形式如下图中的JSON数据结构所示,形容了图层的坐标、大小等信息,后续布局生成就是基于对图层的切割来实现的。 [ { "class_name":"MSTextLayer", "font_face":"PingFangSC-Medium", "font_size":13.44, "height":36.5, "index":8, "line_height":18.24, "name":"恒都民生精选猪小排带骨400g±25g", "object_id":"EF55F482-A690-4EC2-8A6E-6E7D2C6A9D91", "opacity":0.9000000357627869, "text":"恒都民生精选猪小排带骨400g±25g", "text_align":"left", "text_color":"#FF000000", "type":"text", "width":171.8, "x":164.2, "y":726.7 }, //......]2.1.2 组件辨认从下面的数据源能够看出,图层有图片、文字、矩形等根本类型,在组件辨认这一步图层须要被转化成文字/图片/进度条/评分组件/价格组件/角标等日常开发应用的组件类型。然而目前咱们的停顿还停留在只能将图层辨认为文字或者图片的阶段,后续咱们将接入淘宝开源的pipcook框架,基于神经网络算法进行更加丰盛的组件类型辨认。 2.1.3 可视化干涉设计稿作为输出源是设计稿主动转代码的根底,这对设计稿的设计规范要求较高。但在实践中,咱们发现设计师会利用Sketch中的根本图形(每个图形最终造成数据源中的一个图层)叠加来形容一个组件的视觉效果,因而设计稿中不可避免会呈现冗余图层的问题,烦扰DSL的生成。尽管咱们也尝试了利用自动化的伎俩删除冗余图层,但对于算法不能辨认的局部(例如:图片上有一个文本图层,然而理论状况中文本是显示在图片里的,这个时候无奈从算法层面决定是否删除文本),依然须要靠人工进行图层删除、合并等,否则无奈失常生成DSL。设计稿次要有以下几类问题。 图层未合并 上图是从设计稿解析进去的后果,能够发现在“美团优选”文字上方的图片中有很多红色的矩形框(每个矩形框是一个独自的图层),而算法预期的输出是一个图层,因而须要在算法解决前将多个图层合并成一个图层,右侧的三张图也有相似问题。咱们与设计同学进行过沟通,设计同学示意违心在产出设计稿之前将图层进行合并,但因为目前无奈提供检测机制(图层合并是否有脱漏无奈自动检测进去),也就无奈彻底防止图层未合并的问题。 图层地位穿插 实际中发现当设计稿中不同字体/大小/色彩的文字排列在一起时,解析进去的图层信息往往会呈现重叠的状况,因为DSL视图树算法依赖地位来确定不同组件的束缚关系,因而地位的穿插会对算法准确度造成较大的影响。 简单背景图层 上图中红色背景是由2个图层(2个蓝色矩形框)拼接造成的,左图上的蓝色图层是纯色,右图上的蓝色图层是渐变色,在两个图层未合并的状况下,算法生成的代码将会出错。 下面提出的问题,通过束缚设计师来达到设计稿的规范化,难度较大,所以咱们提供了可视化干涉工具。上面对上述问题做一个简略的总结: 问题一:图层未合并问题肉眼很容易辨认进去,利用工具将冗余图层进行疾速合并删除即可。问题二:图层穿插问题肉眼不易辨认,因而咱们提供了检测工具,基于检测工具能够对设计稿中的穿插问题疾速修复。问题三:简单背景问题肉眼不易辨认,临时也没有无效的检测工具,用户能够采纳边干涉边生成的形式生成DSL。 可视化干涉是UI2DSL重要的一环,通过可视化干涉,将不规范的设计稿转化为规范的图层信息后再输出给算法,能够极大地晋升算法的准确率。 这里咱们和imgCook的解决形式有一个区别:imgCook在引入了阈值解决等算法后(更智能,出错概率更大),可视化干涉能力次要体现在预先,而咱们在生成DSL之前容许用户对图层进行干涉,在干涉时用户面对的是直观的图层信息,能够无效升高工具的应用门槛(更稳固,成果更好)。 2.1.4 视图树生成将扁平的数据源转化为树状构造的DSL,这个过程如果是人脑来做会怎么思考呢?先确定布局的整体构造是行布局或者列布局,而后再确定部分区域应该是什么布局构造,最初组装起来造成视图树。这个过程与递归算法相似,因而咱们采纳了递归算法作为算法的主框架,同时引入了“横竖切割+布局构造+模型评估”三大利器。 利器一:横竖切割 生成DSL时采纳了整分的思路,行将大布局一直的切分成小布局,上面以动画的模式看一下简化过的DSL生成过程: 将设计稿一部分区域视为一个子区域,最开始的时候子区域和整个模板的面积一样大,基于图层的地位、大小信息,计算每个图层的上/下/左/右边缘坐标与其余图层的绝对关系,就能够寻找到切割点(如上图中红色箭头所指的地位)。接下来根据切割点,将子区域切割成更小的子区域,在切割的过程中如果切割点是横向的,则生成列布局;如果切割点是纵向的,则生成行布局。通过一直的切割子区域失去更小的子区域,直到所有的子区域只剩下图片或者文本等不可切割的图层,这样就能够生成残缺的DSL视图树了。为了不便读者了解,图例中只演示了行布局、列布局的切分过程,理论状况还蕴含了其余布局类型,会要简单许多。 这里还要留神一个问题,当有3个切割点时,咱们抉择了间接将子区域切割成4个子区域,实际上咱们能够只抉择1个切割点进行切割,也能够抉择2个切割点进行切割,当有N个切割点时,实际上存在(N的阶乘+1)种切割形式,具体抉择哪种切割形式,咱们会在利器三中探讨。 利器二:布局构造 每个图层都是一个矩形,为了生成布局构造只能依赖矩形的上下左右坐标信息。因而,对布局构造进行分类时,咱们依据矩形与矩形之间的地位关系(相交、相离和蕴含关系)做了以下分类。 留神:从生成DSL的后果来看,蕴含布局和成组布局的解决形式其实是一样的,都是应用相似于FrameLayout的层叠布局蕴含外部图层元素,然而咱们依然放弃分类准则(矩形之间的地位关系)不变。 上图中,相离、蕴含比拟好了解,为什么两个图层相交的时候,会有成组和悬浮两种类型的布局构造呢?咱们看下上述成组布局、悬浮布局两个设计稿中别离标出了相交的元素A、B,它们在地位上的绝对关系是一样的,都是A、B两个图层对应的矩形框产生了穿插。然而咱们心愿现实态的DSL视图树却有所差别,如下图所示: 成组布局中:A、B逻辑上是一个整体,穿插是必然的,最终DSL中A、B被层叠布局蕴含,层叠布局中没有其余元素。悬浮布局中:A、B逻辑上不是整体,只是碰巧穿插了,最终DSL中A、B别离在不同的层级中。 因而,对于图层相交时可能有两种类型的布局构造,别离是成组布局和悬浮布局。从上图能够看出应用成组布局还是悬浮布局是由图层内容决定的,那么就须要算法了解图层内容了,比方基于AI构建样本库,记住所有的角标款式(下面表格中4形容的),下次遇到角标相交时就生成成组布局。思考到AI模型也是对规定的形象,咱们先搭建一套自定义辨认规定。成组布局其地位信息是有法则可循的,例如:角标经常出现在右上角,标签经常出现在左上角,头像常常横向或者纵向穿插等,因而咱们针对图层之间的地位关系构建了穿插模型,如下图所示: 上图的穿插模型能够记住历史模板中成组布局图层之间的地位关系,下次遇到相交布局时判断是否在历史规定库中即可实现辨认,如果在就按成组布局解决否则依照悬浮布局解决。下图是通过历史模板构建的成组规定库。 下面介绍了本计划中波及的5种布局类型,目前来看这五种布局类型能够形容所有的模板布局,并且生成代码合乎RD的预期。上面展现两个设计稿DSL实例: ...

March 26, 2021 · 1 min · jiezi

关于设计:由近期设计的心理测试小程序所引发的关于产品设计的思考

随着互联网的倒退,工种变得越来越多,职责划分也越来越细,面向产品方向的也不只有产品经理了,还有用户体验、产品设计等等。 在作为小程序开发者,在设计与开发制作了不同行业和主题的小程序的过程中,我产生了一些对于产品设计的思考。其中最具代表性的是: 什么是产品设计? 什么是产品设计流程? 作为一个小程序创作者我须要有什么技能? 碰巧最近,我又设计与制作了一款小而美的心理测试小程序。于是,我把过后的内容整顿到了这一篇文章里了,心愿能够帮忙到更多的人。 产品设计的定义 产品设计是辨认市场机会、明确定义问题、为问题制订适当的解决方案并与理论用户一起验证解决方案的过程。 什么是产品设计流程 作为一名小程序开发者,你可能会表演问题解决者、钻研人员、设计师、产品经理、数据分析师和营销人员,但从另一方面想这意味着你的工作永远不会反复。 根本流程:筹备工作——需要剖析——根底调研——将计划制作成原型——界面设计——开发实现——可用性测试 最初要记住的最重要的事件是,咱们最终要设计的产品是要供人应用。所以,无论是从视觉上还是交互体验上,力求完满,打造小而美的产品。 那对于产品设计和产品设计流程你有什么见解呢?欢送在留言区与咱们一起分享哦。 作者:meng 原文:由近期设计的心理测试小程序所引发的对于产品设计的思考 | 微信凋谢社区

January 29, 2021 · 1 min · jiezi

关于设计:3D可视化管理推进能源革命打破常规运营手法效率提高95

在最近召开的十四五打算会议中,明确出要:“推动能源反动”、“构建生态文化体系,促成经济社会倒退全面绿色转型”和“放慢推动绿色低碳倒退”、“全面提高资源利用效率”等要求,为能源产业的继续衰弱倒退指明了方向。 为在能源行业输入一份力量,由此图扑软件(Hightopo)退出了3D可视化模块,通过3D可视化技术齐全还原能源管理中心全貌,进一步实现对泛滥子系统的集中配置管理。实时在线查看,操作简略,升高治理难度,缩小设施运行保护压力。 应用以信息化、自动化、智能化为根底,能够齐全取代粗放式、低效率的现场人工调节的传统经营模式;能够在应用期间,通过零碎实时监督各干线的运行参数,及时对生产运行状况进行剖析、管控。进步工人生产的精细化治理,实现疾速响应、疾速解决、业务全流程监管,晋升了服务口碑,以达到良好的社会效益。 当然 2/3D 仿真零碎更靠近于事实中的实在的楼宇、设施,用户易于承受;能够让用户看到零碎整体的同时,还能观测部分细节数据,兼顾整体与细节。能够提供丰盛的人机交互伎俩,便于操作。 拿图扑的换热站零碎举个例子:图扑为根底,以节能、降耗、节费为登程,为供热企业量身定做三维可视化零碎。可实现: 1、可实现整个零碎的监控; 2、可实现整个零碎的过程治理和运行治理,进步了零碎的管理效率,实现零碎的整体节能; 3、实现近程监控、无人值守,通过近程智慧管制,只需在调度核心就能实现平衡输送、准确调节,并能及时发现漏损状况,及时止损; 4、实现主动反馈生产运行大数据,精准预测将来时段所需参数,造成生产剖析报告,给调配供给量及运行参数提供领导值,并实现在简单工况下能源切换的无缝对接,大大降低能源切换给热用户带来的影响。 2020 年来,能源产业也要向数据可视化的方向进行转型,并一直寻找数据可视化的最佳计划。改善现有智能监控零碎可视化办法的缺点,从交互式、可视化的数据分析中开掘深层的技术问题。以后能源管理配合上图扑软件(Hightopo )可视化计划能直观地感触数据和提出最正当的解决方案。 利用 3D 数据可视化治理计划对能源进行治理可满足的性能有: · 缩小资源节约,优化资源配置。 · 革除治理破绽,实时无效的检测,为保护人员进步无效有序的信息,近程运维诊断,设施衰弱治理。 · 使能源产业运行效率最大化。 · 方便管理,无需更多人力参加,可近程监控操作。 · 将宏大的构造优化,更为直观的展示进去,有助于剖析并做出决策。 · 放大平安能源事变产生的可能性。 · 多维度,综合性进行治理 在网络迅速倒退的明天,工业管控叠加加上现如今曾经启动许久的 工业4.0 衍生出的新一代 工业互联网 和不久才面世于众的 5G 新时代,激发出了一代数据可视化监管的倒退。而 图扑物联 的 web 组态 提供了丰盛的组态成果,能够依据需要疾速实现一套残缺的数据可视化零碎。上面是将通过图扑的组态实现一个可视化分布式能源站零碎,带你走进丰盛的组态的大门。

January 29, 2021 · 1 min · jiezi

关于设计:GrowingIO-Design-组件库搭建之开发工具

作者:潘杰GrowingIO 工程经理,目前次要负责 GrowingIO Design 组件库搭建和微前端建设。前言在 20 世纪 60 年代,计算机技术开始超过软件编程的速度。计算机变得更快、更便宜,然而软件开发依然迟缓,难以保护,并且容易出错。这种差距,以及如何应答,被称为“软件危机”。 1968 年,在北约软件工程会议上,Douglas McIlroy 提出了基于组件的开发作为解决这一窘境的可能办法。基于组件的开发提供了一种通过使代码可重用来放慢编程后劲的办法,从而使其更高效且更易于扩大。这升高了工作量,进步了软件开发的速度,使软件可能更好地利用古代计算机的力量。 当初,50 年后,咱们正经验着相似的挑战,但这次是在设计方面。设计正在致力扩大它所反对的应用程序,因为设计依然是针对单个问题的定制解决方案。你是否已经执行过用户界面审计,发现你应用了几十种类似的蓝色色调,或者雷同按钮的排列?将其乘以应用程序中的每个 UI,您就会开始意识到设计变得如许不统一、不残缺和难以保护。 设计零碎通过使设计可重复使用,使团队可能更快地制作更好的产品成为可能。这是设计零碎的外围和次要价值。设计零碎是可重用组件的汇合,遵循明确的规范,能够将其组装在一起以构建任意数量的应用程序。 GrowingIO 产品研发团队也开始通过搭建本人的设计零碎—— GrowingIO Design System,来提供交互体验统一的产品和晋升研发效率。组件库做为设计零碎的重要组成部分,前端团队通过系列文章来介绍如何一步步搭建组件库。本篇文章次要介绍组件库 GrowingIO Design 应用的开发工具,正所谓:工欲善其事,必先利其器。 TL;DR本文依照工具的作用把工具分为:代码标准和代码治理两类,这两类次要用到的工具有: 代码标准工具 a. Prettier:用于代码格式化 b. stylelint:对款式文件( CSS 和 Less )进行标准查看 c. ESLint:对 ECMAScript/JavaScript 代码进行标准查看 代码管理工具 a. Commitzen:帮忙编写标准的 commit message b. commitlint:对 commit message 格局进行查看 c. lint-stage:只对 git 缓存的代码文件进行标准查看,进步速度 d. husky:整合所有的查看工具 husky 如何把查看工具都整合的,如下图所示: 其中: pre-commit 阶段:执行 lint-staged ,会对暂存的文件执行 prettier 、stylelint 和 eslint 三个命令。commit-msg 阶段:执行 commitlint,查看 commit message 是否符合规范。接下来,对这两类用到的工具进行具体介绍。 ...

January 13, 2021 · 3 min · jiezi

关于设计:进来抄作业分布式系统中保证高可用性的常用经验

摘要:高可用性对于咱们来说应该属于常常提到的名词,本文咱们将介绍在分布式系统中保障高可用性的一些罕用教训。高可用性对于咱们来说应该属于常常提到的名词,本文咱们将介绍在分布式系统中保障高可用性的一些罕用教训。 零碎可用性指标零碎可用性指标简略来将就是零碎可用工夫与总运行工夫之比 Availability=MTTF/(MTTF+MTTRMTTF) MTTF 是 Mean Time To Failure,指均匀故障前的工夫,即零碎均匀可能失常运行多长时间才产生一次故障。零碎的可靠性越高,MTTF 越长(简略了解MTTF 就是指零碎失常运行的工夫)。MTTR 是 Mean Time To Recovery, 均匀修复工夫,即从故障呈现到故障修复的这段时间,也就是零碎不可用的工夫,这段时间越短越好。零碎可用性指标能够用通过下表的999规范掂量,当初广泛要求至多2个9,最好4个9以上: 故障不可避免高可用性是指零碎提供的服务要始终可用,然而故障不可避免,特地是在分布式系统,面对不可控的用户流量和机房环境,系统故障将会显得更加简单和不可预测。在大规模的分布式系统中,各个模块之间存在盘根错节的依赖,任一一个环节呈现问题,都有可能导致雪崩式、多米诺骨牌式的故障,甚者能够断言呈现故障成了常态。 如上图的分布式系统中,用户申请零碎中的某个服务接口,申请须要通过长长的调用链能力解决返回。咱们起码要保障网络连接失常,服务网关失常、前端服务失常、后盾服务失常、数据库失常,申请能力被失常解决,如果调用链中的任一环节呈现问题,都会间接反馈到用户体验上。 零碎呈现故障的起因多种多样,次要有以下这些: 网络问题,网络连接故障,网络带宽呈现超时拥塞等;性能问题,数据库慢查问、Java Full GC、硬盘 IO 过大、CPU 过高、内存不足等平安问题,被网络攻击,如 DDoS 等、异样客户端申请,如爬虫等。运维问题,需要变更频繁不可控,架构也在一直地被调整,监控问题等;治理问题,没有梳理出要害服务以及服务的依赖关系,运行信息没有和控制系统同步;硬件问题,硬盘损坏、网卡出问题、交换机出问题、机房掉电、挖掘机问题(前一阵子机房电缆就常常被挖断)等面对如此多的天下大乱,可控和不可控的故障因素,仿佛零碎的高可用性变成不可能实现的工作,然而在日常开发运维中,咱们能够采纳一些无效的设计、实现和运维伎俩来进步零碎的高可用性,尽量交付一个在任何时候都根本可用的零碎。 冗余设计分布式系统中单点故障不可取的,而升高单点故障的不二法门就是冗余设计,通过多点部署的形式,并且最好是部署在不同的物理地位,防止单机房中多点同时失败。冗余设计不仅能够进步服务的吞吐量,还能够在呈现劫难时疾速复原。目前常见的冗余设计有主从设计和对等治理设计,主从设计又能够细分为一主多从、多主多从。 冗余设计中一个不可避免的问题是思考分布式系统中数据的一致性,多个节点中冗余的数据谋求强一致性还是最终一致性。即便节点提供无状态服务,也须要借助内部服务,比方数据库、分布式缓存等保护数据状态。依据分布式系统下节点数据同步的基本原理CAP(Consistency (一致性)、Availablity (可用性)、Partition tolerance (分区容忍性)三个指标不可同时满足),数据强一致性的零碎无奈保障高可用性,最典型的例子就是 Zookeeper。 Zookeeper 采纳主从设计,服务集群由 Leader、Follower 和 Observer 三种角色组成,它们的职责如下: Leader: Zookeeper 集群应用 ZAB 协定通过 Leader 选举从集群中选定一个节点作为 Leader。Leader 响应客户端的读写申请;Follower:只提供数据的读服务,会将来自客户端的写申请转发到 Leader 中。在 Leader 选举的过程中参加投票,并与 Leader 维持数据同步;Observer:与 Folllower 的性能雷同,但不参加 Leader 选举和写过程的"过半写胜利"策略,单纯为了进步集群的读能力。在 Zookeeper 集群中,因为只有 Leader 角色的节点具备写数据的能力,当 Leader 节点宕机时,在新的 Leader 节点没有被选举进去之前,集群的写能力都是不可用的。尽管 Zookeeper 保障了集群数据的强一致性,然而放弃了集群的高可用性。 ...

January 13, 2021 · 1 min · jiezi

关于设计:如何画好IT项目中的各种架构图

在上篇文章,给大家分享了一篇我的项目如何做架构设计 程序员架构修炼:架构设计概要、业务、利用、技术、数据架构,这篇文章教大家如何画这些架构图。在日常软件我的项目开发与施行中,常常会波及到各种架构图,如利用架构、技术架构、平安架构、部署架构。明天特意将这些架构图整顿如下,提供给大家进行学习参考。 一、利用架构 举荐在线作图工具(收费、实时合作): https://www.processon.com/i/5... 二、技术架构 三、平安架构 各源文件下载链接可拜访:https://www.yuque.com/itman/w... 四、部署架构 举荐在线作图工具(收费、实时合作): https://www.processon.com/i/5... 混合云服务器部署架构图: 五、分享有须要的同学,能够拜访上面地址进行克隆,学习更多内容请拜访: https://www.processon.com/u/5... 各源文件下载链接可拜访语雀:https://www.yuque.com/itman/w... 相干文章:如何画好IT我的项目中的各种架构图

December 22, 2020 · 1 min · jiezi

关于设计:移动端UI设计规范

边距、间距准则:边距(左右)要大于间距(高低)。 模块边距10px、12px、15px、16px 15px 罕用 10px 最小,要展现更多的内容才用 模块间距8px、10px、15px、16px、20px 罕用 10px 15px 20px 内容间距5px 10px 15px 内容边距5px 10px 15px 列表最小高度 40px 单行 53px 55px 66px 全局规定图片比例16:9、4:3、3:2、1:1 和 1:0.618(黄金比例)。 字体准则:在同一个零碎的 UI 设计中先建设体系化的设计思路,对主、次、辅助、题目、展现等类别的字体做对立的布局,再落地到具体场景中进行微调。少即是多,在视觉展示上用尽量少的款式去实现设计目标。防止毫无意义的应用大量字号、色彩、字重强调视觉重点或比照关系。 字重,只呈现 regular 以及 medium 的两种字体分量,别离对应代码中的 400 和 500,在英文字体加粗的状况下采纳 semibold 的字体分量,对应代码中的 600。 字号抉择在 3-5 种之间,放弃克服的准则。 行高 1.4 12px 提醒语14px 主文字16px 题目18px 大题目20px 最大题目色彩确定主题色,定义好字体、背景、禁用、线条边框、红橙黄绿蓝等色值。 每种色值最多配有 2~3 种浅谈变动,比方文字可有主、次、提醒等三种(#333 #666 #999)。 应用的大色彩品种不可过多,罕用的有黑、白、主题色、绿-胜利、红-失败、黄-正告。 暗影离高空越远的物体,产生的暗影色彩越淡、含糊度越高、面积越大;反之则色彩更深、含糊度越低、面积越小。 暗影向下:次要利用于组件外部或组件自身,是比拟惯例场景的用法 暗影向上:次要利用于底部导航或工具栏等 暗影向左:次要利用于左边导航栏、抽屉组件或固定表格栏 暗影向右:次要利用于右边导航栏、抽屉组件或固定表格栏 一级暗影 @shadow_1_down:0px 1px 2px -2px rgba(0, 0, 0, 0.16),0px 3px 6px 0px rgba(0, 0, 0, 0.12),0px 5px 12px 4px rgba(0, 0, 0, 0.09);二级暗影 ...

November 1, 2020 · 1 min · jiezi

KiCAD交互式BOM插件

KiCAD交互式BOM插件InteractiveHtmlBom仅供参考,具体操作请结合自身软件版本 KiCAD自带的BOM导出功能并不好用——而且最多也就是导出一个excel表格之类的东西而已。但是,开源软件火起来之后总会有大神想办法解决各种痛点的,InteractiveHtmlBom就是一款负责搞定BOM相关问题的插件。 先来看看演示吧,传送门 比AD的BOM好看多了是不是?而且还能看到元件在PCB上的位置。 So,这么好用的插件赶紧安排上啊! 安装步骤 KiCAD的插件存放在安装目录下一个固定的位置,不过不同版本可能略有区别,所以推荐用指令查询一下,具体如下: 首先,在PCB绘制界面下,点击“工具 --> 脚本控制台” 然后,在打开的控制台界面中输入以下指令: import pcbnewprint(pcbnew.PLUGIN_DIRECTORIES_SEARCH)然后,显示如下: 安装路径下的“.../scripting/plugins”这个文件夹就是插件应该存放的地方。 知道了插件该放哪以后,就该去下载、安装了。 首先去github上下载这个项目,传送门然后,把项目当中的InteractiveHtmlBom这个文件夹整体放到之前查询到的目录下。重新打开KiCAD,这时“工具 --> 外部插件”这一条目下应当能看到InteractiveHtmlBom这个插件了,如果没有,点击“刷新插件” 至于插件的使用就不做讲解了,打开插件点击“Generate BOM”就行。

June 27, 2020 · 1 min · jiezi

干货Flutter-原理与闲鱼深度实践

王康(正物)—— Flutter 官方成员 阿里巴巴技术专家,之前主要负责 Flutter 在闲鱼中的混合开发体系,目前重点关注 Flutter 深入度以及生态相关的工作。本文将分享三方面内容, Flutter 的原理、 Flutter 在闲鱼中的应用,最后介绍我们在深度方面的一些探索。01、Flutter 原理 当我们谈到跨平台框架时,可能会想到很多备选方案。包括早期的 HTML 和 Cordova , 后来的 React Native , Weex ,以及这两年很是流行的 Flutter ,它们都在不同阶段不同程度上解决了我们对跨平台的诉求。如果我们从一些关键指标包括动态性、性能来观察,他们的区别还比较明显。 HTML 和 Cordova 具有最好的动态性,但他们的性能却是最差的,RN / Weex 具有良好的动态性。Flutter 则是一个纯原生的设计,其设计使它天生具有很好的性能与跨端一致性。 Flutter 是如何实现优秀的性能和跨端一致性的呢?从设计上可以看出 Flutter 在操作系统之上包含了三个层次。最下面是平台相关的嵌入层,其向上提供一个 Surface 用以绘制,建立了相关的线程模型和事件循环机制。在此之上则是一个平台无关的引擎,包括用于绘制的 Skia ;Dart 的运行时,开发模式下包括一个解释器;还有一部分是文本绘制相关内容。最上面就是用 Dart 语言编写的 Flutter 框架,也是我们最常接触到的内容。Flutter 框架包含一个完整分层的 UI 框架,从基础的 Foundation 库,到动画手势,再到渲染,之上又提供了各种丰富的 Widget 库。为了方便开发者使用, Flutter 还提供了两套不同风格的组件库,针对安卓的 Material Design 的组件库和针对 iOS 的 Cupertino 风格的组件库。 从这个设计可以看出,Flutter 和平台相关的内容,其实只提供 Surface 和线程/事件循环模型的嵌入层部分。这种类似用游戏引擎的方式来开发应用的设计很好解释了为什么它具有优秀的跨端一致性。 ...

October 16, 2019 · 3 min · jiezi

如何通过MD5反查身份证号

题目:设计一个身份证查询系统,将身份证号md5 之后存储,输入md5值查询对应的身份证号。 要求:成本低,查询速度快设计思路:将所有可能的身份证号做一个简单的统计计算数据量根据数据量选择存储方式查询身份证生成规则:身份号码是特征组合码,由前十七位数字本体码和最后一位数字校验码组成。排列顺序从左至右依次为六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。 地址码: 表示编码对象常住户口所在县(市、旗、区)的行政区划代码。对于新生儿,该地址码为户口登记地行政区划代码。需要没说明的是,随着行政区划的调整,同一个地方进行户口登记的可能存在地址码不一致的情况。行政区划代码按GB/T2260的规定执行。 出生日期码:表示编码对象出生的年、月、日,年、月、日代码之间不用分隔符,格式为YYYYMMDD,如19880328。按GB/T 7408的规定执行。原15位身份证号码中出生日期码还有对百岁老人特定的标识,其中999、998、997、996分配给百岁老人。 顺序码: 表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。 校验码: 根据本体码,通过采用ISO 7064:1983,MOD 11-2校验码系统计算出校验码。算法可参考下文。前面有提到数字校验码,我们知道校验码也有X的,实质上为罗马字符X,相当于10. 校验码算法将本体码各位数字乘以对应加权因子并求和,除以11得到余数,根据余数通过校验码对照表查得校验码。 加权因子表: +-----------------------------------------------------------+ |位置序号|1 |2 |3 |4 |5 |6 |7 |8 |9 |10|11|12|13|14|15|16|17| +-----------------------------------------------------------+ |加权因子|7 |9 |10|5 |8 |4 |2 |1 |6 |3 |7 |9 |10|5 |8 |4 |2 | +-----------------------------------------------------------+ 校验码表: +----------------------------------------------------+ | 余数 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | +----------------------------------------------------+ | 校验码| 1 | 0 | X | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | +----------------------------------------------------+ 算法举例:本体码为11010519491231002 ...

August 18, 2019 · 1 min · jiezi

Touch-Bar-废物利用系列-在触控栏上显示-Dock-应用图标

都说 Intel 第八代 CPU 对比上代是牙膏不小心挤多了,而配备第八代 CPU 的 MacBook Pro,只有 Touch Bar 版本,虽然贵了一点,但就一个字 —— 买! 收到电脑后,兴冲冲地体验了一把 Touch Bar,真的很有新鲜感!前提是你是一个影像工作者。 然而随着时间推移,我的 Touch Bar 渐渐地变成了一个耗电的无用配件,还时不时地误触到「Siri」按钮。只有当我调整音量或亮度的时候,我才会有意识地使用 Touch Bar,让我多花的钱,显得有那么些意义…… 可是今天,我发现了一款让 Touch Bar 废物利用的方法了! 有人开发了一款 macOS App,可以把 Touch Bar 当作「Dock」,直接用来切换和启动 App,叫:Pock,还是开源的。 笔记本的屏幕其实是不够用的,Dock(程序坞)又会让可视面积减少一截。虽然可以隐藏 Dock,但来回唤出也挺麻烦的。 想要最大化屏幕空间利用但又不喜欢自动隐藏 Dock?试试 Pock,把 Dock 放到 Touch Bar 上,好好利用一下这块触控屏。 Pock 具有以下特性:*支持显示通知角标*提供了 ESC 按钮,所以不必隐藏 Pock 来使用系统的 ESC*可设置是否在进入系统时启动 Pock 很久以前 macOS 就把应用程序的菜单栏放到顶部状态栏,现在 Pock 把 Dock 放到 Touch Bar 上,是不是挺对称的?Pock 会保留应用图标的小红点,这样你就不会错过重要的通知信息。亮度、音量、播放之类的常用功能键也都在,用起来很方便。 如果你有一个带 Touch Bar 的苹果电脑就可以体验啦 ~ ...

July 16, 2019 · 1 min · jiezi

观察者模式

观察者模式又称订阅-发布模式,是一种一对多的依赖关系,多个观察者对象可同时监听某一主题对象,当该主题对象状态发生变化时,相应的所有观察者对象都可收到通知。 在getHumidity中会调用notifyObservers来通知所有observers,这里遵循了依赖倒置原则,被观察类(主题)依赖于抽象观察者而非具体观察者。

June 23, 2019 · 1 min · jiezi

翻译逐步替换Sass

本文来自心谭博客·「译文」逐步替换Sass,最新文章请见导航页,欢迎交流✿✿ヽ(°▽°)ノ✿翻译说明这是一篇介绍现代 css 核心特性的文章,并且借助 sass 进行横向对比,充分体现了 css 作为一门设计语言的快速发展以及新特性为我们开发者带来的强大生产力。 第一次尝试翻译技术文,为了让文章更通俗易懂,很多地方结合了文章本意和自己的说话风格。另外,时间有限水平有限,难免有些失误或者翻译不恰当的地方,欢迎指出讨论。 英文原文地址:https://cathydutton.co.uk/posts/why-i-stopped-using-sass/ 正文开始我每年都要重新搭建和设计我的网站,这是一个非常不错的方式去跟进 HTML/CSS 的最新进展、开发模式和网站生成器。在上个月,我发布了新版本:从 Jekyll 和 GithubPages 迁移到 Eleventy 和 Netlify。 一开始,我并没有移除代码中所有的 sass 代码。这本不是我计划中的事情,但随着我不断查看 sass 代码,我一直在思考:它们是否给网站带来了价值,还是仅仅增加了复杂度和依赖性(特指对:scss)?随着这年 css 的发展,曾经让我使用 sass 的原因似乎不那么重要了。 其中一个例子就是我已经移除了媒体查询。当我了解到 CSS 的一些新的特性,那些针对特定屏幕大小的代码(媒体查询)没有必要,因此被移除了。 Sass 解决了什么问题?大概 5、6 年前,我第一次了解到 sass 的时候,我是有些换衣的。随着我搭建越来越多的响应式 web 应用,我才意识到借助 sass 的  functions  和  mixins  可以大大提高代码复用。显而易见的是,随着设备、视图窗口和主题等场景的变化,使用(sass 的)变量让代码迁移的成本更低。 下面是我用 sass 做的事情: 布局变量Typography1) 布局布局一直是 css 中让人困惑的地方。而响应式布局正是我最初决定使用 Sass 去创建 css 布局的重要原因。 使用 sass我一直记得我第一次尝试用 css 创建一个响应式网格布局的时候,那要为每列创建一个对应的类名,然后再用语义化不强的类名(比如  col-span-1  和  col-span-4 )来标记它。 .col-span-3 { float: left; width: 24%; margin-left: 1%;}.col-span-4 { float: left; width: 32.3%; margin-left: 1%;}.col-span-5 { float: left; width: 40.6%; margin-left: 1%;}借助 sass 的  mixin  和变量,能够不再编写像上面那样的类名。并且能够通过改变  $gridColumns  变量,来创造更灵活的布局。 ...

June 19, 2019 · 2 min · jiezi

失业的深圳中年

人间事,经不了多少回头望 被采失业者介绍: 男,40岁,失业前为深圳某设计公司设计总监。两个孩子的父亲,大女儿上三年级,小女儿刚满一岁。有一辆麦凯瑞,一个月供八千的房子。 一 2018年的端午节,我们家迎来了第二个孩子。 在孩子出生前一个多月,刚刚去东莞把新房的首付款交了。我跟太太的工作单位都在深圳会展中心附近,但在我太太怀孕三个月的时候,从福田搬到了龙岗。同样三房的出租房,龙岗要比福田便宜两千多块,这能给马上就要降临的老二买两个月的奶粉。 为了不再让老二像她姐姐一样为了上个学各种折腾,一咬牙在东莞定了套三居室。东莞房价对比深圳房价,就类似于龙岗租金对比福田租金,虽然国家出台各种调控政策,但龙岗房价依然要四五万一平。东莞只要两万出头。 有朋友为我惋惜,说这样将来只能在东莞定居,成为东莞人了。在深圳拼了这么多年,放弃这座大都市太可惜。我打着哈哈说:“从来就没属于过,又何来的放弃?要说放弃也是这座城市用它的高房价抛弃了我们。” 二 在交房子首付后的一个星期,我就失业了。 之前我工作公司的母公司是一家在创业板上市的设计公司。按道理应该过得潇洒滋润,完全不用担心前途与钱途。因为资本市场的钱实在是来得太容易了。不过老祖宗的话一定要时刻牢记于心,比如居安思危。 世上不止笔直的路是骗人的,太顺的路也很容易让人摔跤。你不知道未来的路上究竟是埋的彩蛋还是就单纯挖了一个坑。 不久前投案自首的原证监会主席刘士余在任期间,加强了各种对资本市场的严管,并讲出了“面对资本市场的野蛮人、妖精我不能坐视不管”的知名言论。他投案后再回头看,这些话都沦为了笑柄。 人间事,经不了多少回头望。 我们的母公司当时撞到了枪口,成了被严查对象。短短时间内各种泥沙俱下,墙倒众人推,资金链全部断裂。 我们公司主营业务是程序设计,老板是个谨小慎微的人,虽然没有走得多快,但贵在踏实稳妥。2015年的一个偶然机会,接触到了一个投资人,在这位投资人的牵线搭桥下跟一家上市公司展开了合作(也就是给我们投资的这家母公司)。 后来跟我们的老板聊天,他说资本市场的钱太不好拿了,烫手烫脑。他们给了你一个硕大无比的泡泡,并且这个泡泡是彩色的、阳光一照光芒万丈的那种。但你不知道这个泡泡什么时候会破,而且也不会知道会通过怎样的方式破。 他说唯一的好处是过了一把有钱人的瘾,过了一把做什么决定不用太多考虑成本的瘾。 谨慎不代表没有想法,我们老板是个善于思考、想法不断的人,很多想法在没有跟这家上市公司合作之前没有付诸实践不是因为执行力的问题,大部分是因为没有启动资金,或者说怕一把把自己给梭哈了进去。 钱壮怂人胆,钱更壮老板胆。在钱的作用力面前,是不太分阶级与层次的。 三 2015年之前,我们公司三五十人。跟那个上市公司合作后,短短时间内扩张至两百多人。现在母公司暴雷,可以预见的大范围裁员开始了。一个月的时间,公司从两百多人锐减至五十余人。被裁的不止普通员工,也包括几个公司中高层。 我那段时间正忙于迎接第二个孩子的降临,也频繁朝东莞跑,为了新房的事情奔前忙后,所以并未太过关心公司的各种变化。同时,内心对自己的能力也还是有信心,我们做设计的,拼得是硬实力,就笃定自己不会在被裁名单。 所以,当我收到我的直属领导、同时也是公司股东之一的余峥,谈论有关我离职的微信时,有一点懵。 跟余峥相识12年,共事10年,因为配合默契,基本已经处成了哥们。他给我的微信留言也没有考虑措辞,就直来直去,说目前公司遇到困难,几个股东工资全部减半。他不忍心让我减半,跟着他们几个负责人承担现在的困境。“我是公司老板之一,必须跟着公司共存亡,但不能要求你跟着共存亡。共荣行,共艰难我自己都说服不了自己,谁都要养家糊口。你看看要不要另谋出路。” 让我心存感激的一点是,他留言里说考虑我现在刚有了二胎,又新买了房子,如果有困难,就再在公司干一个月,薪酬不变。 我说给我几天时间考虑下。 那个时候,刚刚交了房子首付,手上并无多少存款。原本余款应该更少,还是老家的哥哥姐姐和老妈赞助了一笔购房款,才让手头宽裕良多。 本来我说自己钱够了,不用麻烦他们给我凑。但我姐说对于我们普通老百姓而言,买房是一件很大的事情,兄弟姊妹不帮忙拿一些似乎缺点什么,好像这个时候不帮衬一下就不太像一家人。 哥跟姐拿了十万,老妈还给了两万。老妈没有经济来源,她的钱基本都是我们兄弟姊妹三个每年的赡养费和平日给的一点零花钱积攒下来的。 但我姐劝我收下老妈的钱。儿子买房,当妈的拿一些钱,就会觉得自己尽了当妈的责任与义务,同时也证明自己还有用,还能帮上孩子一点忙。 老母亲自己也讲,说老爸还在的时候就打算过,要在我买房的时候赞助一点。“以前觉得两万块很大一笔钱。后来钱毛了,想着怎么着也能买个厕所。现在看是一平方都买不到了。”老母亲讲的时候,自顾自地讪笑。 这些普普通通的事情,很鸡毛蒜皮又实打实地发生在每一个普通家庭里。 这也是为何我不管不顾各种压力要生二胎的原因。我想给老大留一个伴,除了情感依靠,将来遇到事的时候也有商有量、有帮有托,不至于形只影单、孤勇相抗。 尽管接下来的压力很大,考虑到自己的存款还能撑一段时间,又出于朋友角度不想让余峥难为,三天后我回复他就做到月底就好。 那个月最后一天的下午,我在办公室打包各种要带走的东西,余老板到我办公室,说老二马上要出生了,先把份子钱随上,然后硬塞给我一个公司几位股东凑起来的红包。 红包鼓鼓囊囊,拿在手里特踏实。 很多时候,越是相熟的人,话就越是不能朝明白里说,否则就显得假,特矫情。当时我打着哈哈说钱收下,酒欠着。心里清楚他们是怕我没工作了压力大,帮我顶一下。 在此一并谢过。 四 我没有把失业的消息告诉我太太。 在失业前的几个月,一次跟客户部的老周聊天,说起相识的一位圈内朋友夏总。夏总是深圳某知名设计公司的职业经理人,老周说他刚刚丢了工作。不过他没有跟家人讲,每天早晨准时拿着公文包离家,到了晚上七点左右又准时回家。整个白天时间就呆在咖啡馆里。 老周说不太理解。我也不理解。上学时候看《开往春天的地铁》也不太理解。为什么工作没了不跟女朋友讲,每天来来回回坐着地铁瞎转悠。 我现在理解了。 我太太之前在一个文化公司做文案,赚的一点钱也就是供着自己零花。怀老二7个月的时候,跟公司协商离职了。家里的支出基本只能靠我一个人的工资。 本来又是买房又是临产的各种事情挤到了一起,我怕再把失业的消息跟她讲了后让她寝食难安、心火伤身。本身自己又有一些大男子主义,觉得有些事情必须要男人扛着,不能让跟着的女人担惊受怕。就这样硬是瞒了几个月没被发现。 一个成年人的心里可以藏太多事了,表面又可以做到若无其事。 我每天早晨跟上班时候一样的拿着电脑出门,然后开车去一个距离家较远的地方。因为距离近了容易被发现穿帮。 最初选择了一家离家十多公里的咖啡馆。因为自己晕咖啡,所以只点茶水,这倒无形中省了钱。 上午一杯20元的红茶,午饭就在旁边的快餐店解决,下午又是一杯20元的红茶。 我没有投递简历,就跟两个关系走得特别近的朋友讲了自己的情况,让他们帮着看看有无工作可介绍。到了我这个年龄段,要不就很厉害,要不就很不厉害。而这两种人都不太受用人企业待见。太牛的角色企业怕用不长久,或者用不起;太差劲的又几乎等同于废物与闲人。 倒是原公司老板到处帮我联系,四下推荐。熟人推荐的好处是知根知底,会在一定程度上给予局部美化,重要的是不用像普通应聘那样面对重重关卡,可以跟用人企业的直接负责人对接。 但对于一个中年人而言,人生会凭空多出很多关卡。就像找工作,聊得倒是热火朝天,一到实际要不要去或者要不要录用就面临各种纠结。我纠结的在于薪酬、平台位置、未来发展方向,对方纠结的在于年龄、付出与产出比、是否做得长久。聊到最后的结果基本都是先加个微信,然后看看有无可能从项目合作开始。如果项目有得赚,就按照比例分红。这就像“改天请你吃饭”一样,基本属于遥遥无期的事情。 但我还是要感谢余峥他们几个,因为他们本可以不用操这份心。 以前的综艺节目是一周看一期,那段时间在咖啡馆里一天看七期。也是那段时间知道世界早就不是之前的那个世界了。作为流行文化的风向标,通过综艺节目能看出很多门道,包括社会的价值观、生活取向、人们的趣味所在、年轻人的成长方向等等。女的越来越刚硬、男的越来越阴柔并不是我的最大发现,最大发现以及让我不能理解的是那些娘炮们竟也粉丝者众。 理解不了与看不懂也让人焦虑,觉得有被抛弃之感。 五 失业第四十天。 失业后第一个月的花销超出了我的想象。有工作有固定收入之时,你可能不会太在意一些小的开支;而当你不工作的时候,没有进项来抵消出项,金钱的流失速度将远远超出你的预判。 为了节约开支,20的红茶换成了凉白开,午饭也尽量控制在20元以内。能不开车就不开,这样可以省下油费和停车费。 去的那家咖啡馆服务还不错,拿一杯白水就可以坐一天,没人赶,也没人故意在你面前转悠朝你翻白眼。但坐的时间长了我自己都过意不去,总觉得服务员扫地,或者把杯子弄得叮当响是在暗示我。以前上班的时候,也经常在咖啡馆什么都不点,就干坐着办公。那时没有任何不适与不自在。现在就多了小心翼翼。 失业会让一个人自卑很多。 失业第40天的时候,我不再去那家咖啡馆,场所换成了荔香公园。 公园的好处在于人多,尤其是闲人多,我混在其中不会很显眼。场地又大,不会动不动就莫名其妙把陌生人变成了熟人。在那家咖啡馆一个多月的时间,不但服务员成了熟人,经常去的几个客人也都互相脸熟,见面都会点头致意。我一个中年大叔,整天坐在里面不消费,又总是被这些人看见,自己都觉得脸红。 结果后来在荔香公园也经常遇见熟人。 我还是没有把失业的事情跟太太讲。每天依然是按照上班的节奏出门与回家。她也没有怀疑,唯一的疑问是问我怎么最近回家这么准时,不再加班了。我说最近公司没什么大项目,轻松一些。 ...

June 16, 2019 · 1 min · jiezi

码农如何学设计-Web-UI-设计学习心得

我的本职工作是后端开发工程师,记不清从什么时候开始对「设计」产生了兴趣,可是对「设计」领域知识的学习由于从小就受到固有思维的影响,甚至受到很多不正确教学方法的误导,在学习的过程中很容易让人产生自我怀疑,特别是对天赋的自我怀疑,从而慢慢的主动放弃。 本文结合自己的学习经历,从「什么是设计」开始切入,引出何选择设计工具,如何画下设计的第一笔以及随之而来的其他基础设计问题。希望这篇关于学习设计最初级的心得体会能给那些曾经跟我有类似兴趣的朋友们一些学习上的参考。 如果想成为一名高级的、或者艺术家级别的设计师肯定需要天赋。但是,对于大多数为了完成工作或者实现自己想法的基本设计能力完全可以通过自学学会的。 什么是设计?“设计是努力使现况接近期望的探索过程”,- by 著名建筑设计师:姚仁禄。与百科词条中对于“设计”的解释相比,我更喜欢姚先生的版本,言简意赅,直击重点。 好的思想都是相通的,不管是建筑领域还是互联网领域,对我们学习 Web UI 设计同样受用。设计并没有标准答案,通常也不是一步到位,好的设计作品大多是不断演化而成的。因此先认清现况是一个很有必要的步骤,能够帮助我们制定出更合理的期望/目标,避免好高骛远。 本文以「如何学习 Web UI 设计」为例子: 假定我们的现况/水平:新手制定出具体的期望/目标:设计一个博客网站最后,也是最重要的过程就是:付出实际行动,一步步将这个目标实现如何选择设计工具上一步已经确定了目标,下一个随之而来的问题就是:选择什么样的设计工具? 我很喜欢”随之而来“这个词,有些东西不需要刻意,只要你把当下想清楚之后,未来会主动找上门。设计工具有很多,Photoshop,Sketch,Adobe XD 等等甚至还可以直接用纸笔。 对于初学者的建议是:以最快的速度确定一款设计工具,哪怕是通过点兵点将、扔筛子的方式,重点是快速做出选择,然后付出行动,动手操作。 初学设计的时候我也很纠结,看了很多工具对比文章,甚至去看国外分享的工具对比视频。但是,当我真正开始动手去做一个实实在在作品的时候,发现设计的思想才是重点,工具之间无非就是有些软件对某些操作比较方便而已,等你亲自动手做过一次完完整整的设计作品之后就会发现,即使下一次做设计想换到其他工具也是很容易上手的。 如何在空白页面画下第一笔我们将要设计的博客网站最终需要在浏览器上显示,由于显示器屏幕有非常多的规格大小,小到手机上的浏览器、主流桌面浏览器、大到接近电视的超宽屏显示器 面对这么多的载体,会有很多问题随之而来: 如何让我们的网页能够在不同尺寸上都有比较理想的显示效果?页面上的内容应该居中对齐,还是左对齐,右对齐?如果是左对齐,应该距离左边多少?如果是右对齐,应该距离右边多少?...... 等等这些问题可以通过开启网格辅助线的方式解决,辅助我们做设计 随之而来的其他问题有了网格系统辅助我们做设计,可以大胆的画下第一笔。 可是,第一笔之后又有很多问题随之而来: 如果你第一笔写的文字,文字的字体、字号、颜色等等问题随之而来 如果你第一笔画的是形状,形状边框样式,背景颜色,阴影等等问题也会随之而来 一旦你开始第二笔,两笔元素之间的间距、对齐方式等等问题立刻紧随其后 这些问题是新手做设计最头疼的问题,是最容易产生自我怀疑的设计阶段。我在自学设计的过程中,也是参考了无数资料,做了大量练习,总体的解决思路无非下面一张图所示: 以颜色为例: 如果你有经验,这里说的有经验包括以下几种情况 不管经验是来自以往的设计经验,还是衣服搭配等等,只要你可以确定出自己最想用的颜色,就可以尝试用这种颜色及其衍生色做设计中的主要颜色公司的产品已经有品牌色来自其他的,任何可以让你不需要纠结就能确定出颜色的都属于有经验如果你没有任何经验 从现在开始,养成一个习惯:将平时看到的,自己喜欢的网站,收藏起来。收集资源是一个长期的过程,不一定等到要用了才去找从上一步收集的资源中,挑选出你最想要的配色或者变体色如果你不想参考任何其他网站的配色,那就用最简单的白底黑字去设计,但是记住一点:并不是只有纯净的黑与白,黑白之间还有很多不同等级的灰度色可以使用 动手操作设计是一门需要持续动手实践的技能,意淫多少篇都不如亲自动手实操一遍来的实在。 当你真正亲自动手做一次设计之后就会发现,哪怕只是设计一个简单的博客网站,也会遇到设计过程中90%的常见问题,而且这些问题跟你选择什么样的设计工具没有任何关系,重点在思想。有了想法之后,通过不断练习丰富自己的经验,同时完善自己的设计思想。 我已经将文章开头定下的「设计一个博客网站」的目标实现了,点击下方的链接查看完整实现过程 从 0 开始学设计、并将设计稿转成 HTML + CSS + JS 同时学习「设计」与「前端开发」基本技能

May 22, 2019 · 1 min · jiezi

UI-设计中的渐变

简评:渐变是通过两种或多种不同的色彩来绘制一个元素,同时在颜色的交界处进行衰减变化的一种设计。从拟物到扁平再到渐变,人们慢慢发现它能创造出从未有过的一种色彩感觉 —— 独特、现代和清爽。(本文译者@Aceyclee)很长一段时间以来,设计界都不怎么待见「渐变」,这还得拜 90 年代的 PowerPoint 所赐,毕竟那时候的渐变是这样的: 然而时过境迁,今天你打开 Dribbble 或者 Behance,可能会看到不少使用渐变的设计。本文将会分享如何在设计中使用「渐变」的实用技巧。 ▎为什么我们突然爱上了渐变?想回答这个问题,我们需要重返 2014。 2014 年是扁平设计流行的元年。这一年,Google 发布了 Material Design,Apple 也用扁平 UI 更新了 macOS。那年的扁平设计让人感到兴奋,特别是和拟物设计对比的时候。 但是扁平设计的局限性也是显而易见的,其中最大的一个局限是 —— 设计师能够使用的颜色和样式大大减少,几乎不到 15 种颜色可用于扁平设计。 由此,设计师们开始尝试「渐变」: 它给设计师带来了更大的创作自由。扁平设计中单一的颜色扼杀了设计的潜力,而渐变为无限可能打开了大门。通过混合颜色的手段,设计师们可以创造出更丰富的视觉样式。渐变还给设计引入了深度和维度,解决了扁平设计中一切都「太平」了的问题。▎渐变让人惊喜比如说,渐变能做出更大胆的表达。 渐变创造出了一种意想不到的效果,即使像应用图标这样微小的元素,也别有一番风味: 又或者,渐变能突出某些元素。 一个好的用户体验,往往能引导用户完成产品流程,而精心的设计有助于让用户下意识地进行下一步。比方说让页面某些部分视觉效果更强烈,从而让用户更关注这部分。 ????下面是 Mixpanel 的主页,插图是主页的一大元素,而渐变的背景则引导了用户去关注镇部分。 ▎六种创造渐变的技巧1. 让我们先看看渐变的基础类型渐变有几种基础类型,他们都会有一个中心起点,颜色从这里开始,然后逐渐融入其他颜色。 a. 线性 线性渐变是一种依直线过渡的色带,颜色从一种颜色平滑过渡到下一种。 b. 径向 径向渐变是从中心点开始往外辐射,设计师可以指定中心点的位置和渐变的大小。 c. 锥形渐变 如下图,你可以在 Adobe Illustrator 中创建锥形渐变 2. 注意渐变颜色的选取不是所有的颜色都能很好地相互配合,如果用互补色进行渐变,看起来就不是很好: 红色到绿色的渐变,看起来脏兮兮的: 创建渐变的时候,最好使用相近的颜色: 或者相同颜色的不同深度: 3. 渐变过程中注意平滑过渡理想情况下,不应该让用户注意到一种颜色流入到另一种颜色中,颜色的过渡应该非常顺畅。 ...

May 21, 2019 · 1 min · jiezi

小程序绑定用户方案-优化

在做过一系列小程序之后,对小程序的登陆鉴权的流程也有一定的理解,类似于 B 端小程序自不必说,要用户信息手机号地址可以一把梭,做一个引导页面进行判断然后要求用户给与绑定,用户自然不会多说什么,毕竟这是企业级别应用。但是当涉及到 C 端小程序时候。想让用户进行绑定,就势必要给与用户便利。这里我列出一些我觉得较为不错的小程序应用方案以供参考。 预先绑定类该类小程序在使用之前就需要绑定用户信息。常见于线下门店类功能性小程序。线下操作时有大量的优惠活动来支持小程序的流量。 功能介绍例如 便利蜂。之前在上海经常使用,价格和优惠都非常不错,这类小程序属于线下功能类小程序,内部有抽奖,付款等一系列功能。该小程序第一次打开就先用户直接要求用户绑定信息和地址,考虑到线下门店都会有一定的店员辅助。所以该小程序的绑定操作实际上用户都是可以接受的。图片如下所示。 技术要点技术1: 使用自定义导航栏让头部可以配置全局配置 "window": { "navigationStyle": "custom"}如果微信 app 的版本在 7.0.0之上,我们就可以使用页面级别的配置了。 { "usingComponents": {}, "navigationStyle": "custom"}该配置默认时default,当使用custom时候可以自定义导航,可以在头部配置 loading。 第二种这个需要 app 版本,所以如果是想简化,反而在全局下定义,再使用微信官方的组件 avigation-bar 即可。 技术2:使用小程序骨架屏骨架屏方案在后端不能很快给与前端数据时候采用这种方案,亦或者前端可以使用 Service Worker 把上次缓存数据返回到前端,等到从后端获取数据之后刷新页面也是一种方案,但是因为这是第一次打开小程序,所以采用骨架屏是一个很好的方法。 采用 小程序骨架屏 组件,如果不需要骨架屏动画效果,可以试试直接加载图片作为骨架屏。 惰性绑定类该类小程序在展示时无需绑定用户信息,但是当用户进行操作时在询问绑定。常用于线上商城等一系列无需专人引导的用户项目。 功能介绍基本上线上大部分 c 端小程序都采用此做法,功能上倒是没什么可以介绍的,但是实践上却有不同做法。 实践方式方式 1: 页面跳转 (京东购物)在每个需要绑定的按钮上添加跳转逻辑,如果当前小程序没有绑定,可以跳转到另外一个页面上确认授权。 方式2: 按钮控制 (华为商城+)在每个需要绑定按钮上添加 open-type='getuserinfo',后续可以根据状态变化,切换掉按钮(也可以不切换,因为第二次绑定数据不会跳出组件)。 方式3: 遮罩层拦截 (抽奖助手)在需要绑定的页面添加一个 透明模态框,增加以整个页面大小的button。用fixed布局,还可以向下滚动。无论在当前页面点击任何地方都会出现需要绑定选项。 组件代码: // wxml<view style="z-index: {{zIndex}}" class="mask"> <button open-type="{{ openType }}" bindtap="onClick" bindgetuserinfo="bindGetUserInfo" bindgetphonenumber="bindGetPhoneNumber" bindopensetting="bindOpenSetting" binderror="bindError" class="mask"/></view>// wxss.mask{ position: fixed; top: 0; bottom:0; left:0; right:0; background-color: inherit; opacity: 0;}然后在绑定后令 mask 消失。该方案初看起来不是那么的合适,但是仔细想想却也没什么问题,因为用户99%可能点击所需求的按钮,就算点击到按钮之间的空隙之处跳出要求绑定也没有什么问题。 ...

May 15, 2019 · 1 min · jiezi

构建可靠系统的原则与实践

随着阿里技术的发展,我们的技术系统越来越成为社会的基础设施,对于这些系统的可靠性要求也就越来越高。但是实际上很多的基础的产品和系统确仍然会出现一些稳定性问题,那么如何才能构建可靠的系统呢?是不是制定非常严格而细致的规则就可以做出可靠的系统呢? 航空业的教训在回答这个问题之前,我们先来看看对于系统可靠性要求非常高的航空业是怎么做的?美国的FAA是在航空安全领域事实上的权威,为了保证航空器的安全,FAA制订了非常详细而复杂的航空器认证规则,而这些规则是否就保证了航空器的安全了呢? 让我们来了解一下最近的两起空难: 2019年3月10日,埃塞俄比亚航空ET302航班在起飞六分钟后坠毁,飞机上载有149名乘客和8名机组人员。 2018年10月29日,印尼狮航JT610航班在起飞后约十分钟坠毁,飞机上载有181名乘客,和8名机组人员。 几百条鲜活生命的消逝,这是多么严重的后果啊!究竟是什么原因导致了这样的灾难呢? 这两起空难的共同点是都是波音的737MAX机型,并且都是在起飞后不久发生的空难。那么这个背后的原因是什么呢?虽然官方的调查还没有结束,但是民间的分析指向了同一个原因,那就是这款机型的设计问题。 上图展示了Boeing 737 MAX的CFM LEAP引擎,值得注意的是和一般民航飞机不同的是,引擎的上沿和机翼平面几乎齐平。为什么会这么设计呢?这是因为波音737系列最早是上世纪60年代设计的,当时的引擎的直径小很多,外形更加细长,而机翼的高度是和引擎直径相匹配的。但是随着技术的发展,更新更省油的引擎直径变得越来越大,这时候原来的机翼高度无法满足更大直径引擎的安装空间,要想调整机翼的高度则需要改变起落架的设计,改变起落架的设计则需要改变起落架收起时相关机体位置的设计,而机体设计的变化会带来更多的变化从而会被FAA认为是一款全新型号的飞机,而全新型号的飞机则需要经历完整的FAA认证流程,会带来巨大的时间和经济成本。为了避免这样的成本波音选择了将引擎前移并且提升高度,但是这样带来了另外一个问题,由于空气动力学方面的原因,飞机会变得静不稳定,特别是在起飞阶段,引擎的推力会导致飞机迎角过高进入危险的失速状态。为了回避这个问题,波音引入了一个自动控制程序MCAS,通过读取迎角传感器的数据判断飞机是否迎角过高,如果过高的话自动控制飞机降低迎角,从而保证飞机的安全。 那么这么一套保证飞行安全的系统和空难有什么关系呢?事实上MCAS系统工作得非常好,根据波音自己的统计,Boeing 737 MAX系列已经完成了数十万次的安全起降。但是问题在于当传感器工作不正常时,MCAS有可能会根据错误的迎角数据做出错误的判断和动作,也就是在不应该降低迎角的时候降低迎角,导致飞机直冲地面。 一起后果扩大的故障回到我们的工作中,前不久我们碰到了一起系统故障,其过程有一定典型的意义,为了描述方面,这里隐去一些具体细节,简单说一下故障的过程。开始的时候,由于某些原因导致缓存命中率有所下降,而缓存命中率下降导致了数据库load升高,而数据库load升高以及可能的慢SQL导致了部分请求在获取DB connection的时候超时,从而引发了exception。当exception发生的时候,为了保证系统的可用性,系统逻辑进入了一段兜底逻辑,而这段兜底逻辑在特定的条件下产生了错误的返回,从而导致线上脏数据,而这些脏数据带来了业务资损和大量的人工订正数据的成本。 这个故障处理的过程并不是重点所以不再赘述,我们要问的是为什么一个简单的exception会导致这么严重的后果呢? 两个事例的共同点如果我们仔细去观察上述两个事例,我们会发现其中有如下几个共同点: 为了好的目的而引入了非常简单的备用逻辑直接保证“效果”这些备用逻辑在绝大部分情况下都能正常工作但是在极端情况下这样的逻辑失效了,并且产生了严重的后果换句话说,系统设计者在尝试用非常简单的逻辑去解决一个实际上复杂的问题,虽然实际上并没有完全解决问题,但是因为这样的逻辑能够通过大量的测试(或者合规检查),所以系统设计者“假定”问题得到了解决,从而放心地应用到了生产环境。 那么一个非常复杂的问题是否真的能够通过一个简单巧妙的办法解决吗? 没有银弹在系统设计领域,我们通常会把问题的复杂性分为两类,分别是偶得复杂性,实质复杂性。 偶得复杂性 Accidental Complexity 所谓偶得复杂性是指由开发者自己在尝试解决问题时引入的复杂性挑战,一般而言是由解决问题的方法和手段带来的,对于特定的问题,不同的方法会带来不同的偶得复杂性。 实质复杂性 Essential Complexity 所谓实质复杂性是由事务本身所决定的,和解决方法无关。 对于偶得复杂性,通过变换解决办法是有可能用简单的办法来解决的,但是对于实质复杂性,我们是无法通过改变手段来解决的,而必须采用相应复杂的方法来解决问题。换句话说对于实质复杂的问题,不要指望有银弹。 上述事例中,实际的环境和问题是存在比较大的实质复杂性的,然而我们却试图通过一些非常简单的逻辑去解决问题,从而带来了严重的后果。 快速失败 Fail Fast那么要想防止这类问题,设计高可靠的系统要怎么做呢?这里我想介绍一条反直觉的软件设计原则,快速失败(Fail Fast): In systems design, a fail-fast system is one which immediately reports at its interface any condition that is likely to indicate a failure.这是一条反直觉的原则,大部分人听说这条原则的第一反应是这样不是让系统变得更加脆弱了吗? 实际上并不是,原因在于我们不能停留在某一次的失败(failure),而是需要观察完整的过程,如下图所示: 当问题发生时,系统立即停止工作,由人工介入找到并以合理的方式解决根本的问题,然后系统恢复运作。通过这样的选择,我们就能够更早更容易地暴露问题,每当系统发生问题之后,真正的根因会更快得以解决,所以最后我们就能得到一个更加可靠的系统。 需要说明的是,快速失败不是说系统设计不处理任何问题到处失败,而只是在面对essential complexity的时候,不要尝试用一个简单粗暴的方案去解决,要么就用一套合理的机制设计去解决它,要么就fail fast把控制权交给系统上层决策,通常来说最终可能会回归到人,由人来分析和处理问题。 ...

April 29, 2019 · 1 min · jiezi

拒绝版权流氓阿里巴巴重磅发布免费商用字体

摘要: 所有阿里巴巴数字经济体、商家或设计师们可通过阿里巴巴设计出品的 Alibaba ICS Design 平台或者阿里巴巴旗下专业的商家服务平台-淘宝服务市场下载。UCAN 2019 设计大会在杭州国际博览中心开幕,超过 4000 位来自世界各地的设计师参与了这场阿里巴巴设计举办的盛会。 继去年品牌升级为阿里巴巴设计(Alibaba Design)后,阿里巴巴经济体设计委员会委员长杨光(青云)再度在大会上重申了对设计的理念和期待 —— 让商业美而简单。 “阿里巴巴经过几年的发展逐渐壮大,设计师团队也越来越大,这样庞大的使命,个人认为要有强烈的使命感,所以‘让商业美而简单’就变成了我们的使命。阿里最远大的目标是‘让天下没有难做的生意’,我们希望通过新的技术,通过技术变革,能够引领商业社会的变化。” 在演讲中,杨光表示需要从设计产能的升级、素材原料的供给、生态关系的连接和设计专业的拓展四个方面,来看待设计行业和产业。 自 2016 年发布了鹿班设计系统之后,阿里巴巴“操作系统”还在不断升级和壮大,并且杨光认为只有通过将阿里的设计和技术普惠给所有的商家和所有的合作伙伴,才能建立完善的设计生态,并且让所有设计师都参与到生态的建设中。 去年阿里巴巴与汉仪合作,发布了 6 款智能字体;通过技术手段,为商家生成了超过 1700 万条视频。只有真正做到为每个人服务,才能回归商业与设计的根本。 对于产能升级,更大的一个核心就是原材料的供给。为了解决广大的素材需求和高昂版权费用之间的矛盾,站在整个行业的角度,就必须要对今天的模式作出变革 —— 按需供给、柔性供应。 在大会上,阿里巴巴设计率先向全社会发布了一款字体“阿里巴巴普惠体”,希望能够让阿里巴巴的普惠精神,让整个生态的设计师、合作伙伴因为我们平台的赋能,真正得到实惠。 这是一款由中国企业首次发布的可面向全场景使用的免费商用正文字体。 以“普惠”之名诞生,这也意味着这款字体肩负着比一般企业品牌字更重要的使命——它还将开放商业授权给所有个人和商家,让更多用户可以免费使用这款阿里巴巴字体,以普惠设计赋能商家生态,实现阿里巴巴设计“让商业美而简单”的愿景。 青云表示,“20 岁的阿里正全速奔跑在全球化的轨道上,我们迫切需要一款统一的官方字体来构建阿里巴巴品牌的一致性和完整性,从而让大家更好得认识阿里巴巴,更懂我们的业务。” 另一方面,因为注意到天猫平台上曾发生过一些因商家使用侵权字体被字体公司起诉的 case,“作为平台生态的守护者,在阿里巴巴字体立项之初,我们就已经想好了这套字体要开放给整个阿里生态,甚至更多人去使用。”青云说。 这一次可免费商用的阿里巴巴普惠体共收录 116,895 个全形汉字(含 5 个字重),西文 Alibaba Sans 共 7,205 个拉丁字母(2 种风格、共 11 个字重),覆盖 172 个语种(覆盖大部分欧语国家),并可以满足阿里巴巴集团及其经济体公司在全球化业务下的多个应用场景需求。 据阿里巴巴定制字体项目负责人、阿里巴巴集团品牌-高级创意设计专家羿光介绍,从去年 6 月至今,整套阿里巴巴普惠体的设计历时 10 个月,“不仅要包含突显企业品牌个性的标题字,还要囊括更为实用的内文字,兼顾多个场景下的应用……这么大体量的字体设计并面向全场景开放授权免费商用,开创了中国企业造字的先河。” 1、“20 岁阿里少年的精气神”说起阿里巴巴普惠体,羿光是这样形容的:“他就像一名 20 岁的小伙子,年轻有力量。” 那么他到底长什么样呢? 中文字体多采用现代简洁的笔画,造型上偏瘦长,并将字的重心提高,以展现 20 岁阿里巴巴少年的精气神。字体笔画上也做了一些简化,如标题字省略出脚部分,更显简洁。 西文字体进行了 11 个字重、四大风格的变化演绎,以适用于多个场景的应用。在 Alibaba 单词的体现上,通过增加 A 的宽度、L 的变化等来确保字体下盘的稳定性。 ...

April 28, 2019 · 1 min · jiezi

对话行癫:解密阿里云顶层设计和底层逻辑

几十个问题,万字长文,阿里云新任总裁行癫履新后首次出面与钛媒体独家深入讨论了一下阿里云对云计算未来的判断,深度解读未来阿里云生态战略,揭秘阿里技术委员会和阿里中台思想的原生思考。转载自钛媒体,作者:刘湘明 。标题为《钛媒体独家对话行癫:最详解密阿里云顶层设计和底层逻辑》 。分享给大家。钛媒体注:张建锋(花名行癫)的阿里生涯,一直在踩着技术与业务的交界线前进,某种意义上可以看作阿里战略重点转移的缩影——在担任集团CTO和阿里云总裁之前,他先后管过淘宝网技术架构部、B2C开发部及淘宝网产品技术开发部,还分管过聚划算事业部、本地生活事业部、1688事业部及天猫事业部。2015年还担任过阿里中国零售事业群总裁。2018年11月,还在担任阿里巴巴集团首席技术官,同时也在负责达摩院的张建锋,被任命为阿里云智能事业群总裁。云计算的市场发展很快,根据调研机构Canalys给出的数据,2018年全球云计算市场规模突破800亿美元,达到804亿美元,同比增长46.5%。市场的高速发展,也带来云生态环境的快速变化,技术、客户需求、伙伴关系都伴随着规模的扩张和应用的深入在不停地演变。张建锋过往的这些经历,对于他在这个快速变化的云生态环境里,理解技术与业务的关系,切换合作伙伴视角去思考问题,都带来莫大的益处。在这个高速发展的市场里,阿里云在全球排名前三,在中国排名第一。“阿里云在中国公共云市场的市场占有率是第二至第八名的总和。” 2019年3月21日,新岗位上的张建锋在北京阿里云峰会上第一次公开亮相时,这样描述阿里云的市场地位。只有操盘的人才会真实地感受到,高速的发展和庞大的规模,带来的不仅仅是风光,也还有巨大的压力。上任之后,张建锋组织管理层讨论几个核心问题:第一,阿里云如何健康地增长?第二,云的未来是什么样?第三,阿里云的核心能力是什么,该做什么,不做什么?3月21日他的发言,可以看作是这4个月讨论的结果呈现。相比他发布的一系列未来阿里云要做的事情,大家其实更应该关注阿里云不做什么——在过去的十年里,阿里云一共发布了162个产品,4610个新功能,但对于巨大体量的阿里云,清晰自己的边界,永远都是一个最重要的话题。这涉及到对于自己定位和能力的思考,更涉及到怎么看待自己与自己所营造的生态环境的关系。在大会发言的最后,张建锋明确了阿里云两个生态新定位——被集成,自己不做SaaS。这两个定位的发布,如果从弥漫阿里的金庸武侠文化来解读,与《天龙八部》中虚竹破解珍珑棋局的做法颇为神似——阿里云作为平台放弃一些主动和实地,反而让自己有了更大的腾挪空间。众所周知,随着企业上云的大势不可逆转,越来越多企业级的客户需求被叠加到云上,已经对阿里云的交付能力提出巨大挑战。被集成概念的提出,把很大部分发展空间和主动权明确留给生态伙伴,阿里云自己则专注于云生态核心能力的精益求精。但这看似双赢的设计背后,依然存在很多挑战,平台如何把自己的能力封装成成熟的产品,接受合作伙伴的考验和挑剔?技术和组织,要为这样的变化,做出什么调整?这些都是阿里云未来发展的顶层架构设计,但所有这些设计的背后,都是对于这个产业和自己,最底层最深刻的思考。在会后,张建锋接受钛媒体联合创始人刘湘明的独家专访,就云计算的未来、阿里云的战略选择,以及云对于企业的影响,进行了深入的讨论。关于云计算的未来一个有1万人的平台公司是一个非常大的平台型公司了,像淘宝做的这么大,也就几千人的规模。如果一个公司的人数与业务线性相关,可能是做了太多自己不擅长的东西。钛媒体:你关注到云计算竞争的焦点在发生什么样的变化,好像大家还比较关心价格?行癫:价格是初级竞争,最终还是回归到核心价值。价值要从两端来体现,一个是技术端,一个是应用端。云一开始都是做基础设施,但阿里巴巴从做云第一天起,做的就不仅是现在这个云,当初的理念是做一个数据处理平台,这和当时数据处理能力与业务的脱节也有关系,因为是十年前,很少有公司是基于智能、基于数据的,大部分是基于流程。后来做了一段时间,发现光做这个还不够,在中国要想成功,还得有基础设施。当然我们做的过程也比较曲折,一开始还想在开源系统上做数据处理,后来发现也不对,必须自研,阿里巴巴不仅是做了一个云的基础设施体系,也做了一个数据处理体系(备注:现在叫MaxCompute,当时叫做ODPS),这个是绝无仅有的,包括国内国外。当然这个过程有点远,所以回过头来又必须把IaaS层做好。底层的竞争肯定是拼基础设施的成熟度、稳定性和价格,但是上层的竞争肯定是拼人工智能等等。钛媒体:你刚才谈到数据处理,开源为什么不行?行癫:其实所有的开源软件公司都没有面对过这么大的数据量,Hadoop 、Spark是比数据库的处理能力前进了一大步,用分布式、用MapReduce的方法,但他们的数据量跟阿里巴巴数据量比还是差非常远。第二个是开源的稳定性要求也达不到我们的要求。所以那时候我们第一次做了一个5K的集群,开源当时不可能超过5000台机器的,我们第一次突破了机器的限制,可以用更大规模的集群来处理。第三我们考虑成本,因为数据量规模小不关心成本,大了以后我们更加考虑成本,现在我们阿里巴巴每年业务量都是增长50%以上,但是我们的成本不能线性增长。我们去年开始大规模混布(备注:一种新技术,使得在线处理与离线处理不再分别拥有专有的机器,而是运行在同一个集群的机器上,可以极大地节省资源,对于调度部署能力要求极高),我们没有专用的离线机器去处理大数据,都是用在线跑的机器做大规模的混布。双11来了,前一个小时暂时不处理数据分析全部用来跑应用,高峰过去之后,调度所有机器去做数据分析,开源是不可能做这个事情的。我觉得大数据领域如果自己公司没有应用,很难设计出一个很有弹性,很高性价比的、很高稳定性的处理平台。钛媒体:现在国外的云计算谈混合云比较多,你怎么来看混合云未来对云计算的影响?行癫:混合云未来还是一个很重要的发展方向,很多客户对混合云还是有非常刚性的需求,包括一些政府、银行客户,他们觉得对自己的应用可管可控,或者物理的隔离是很重要的事情。今天从现在的情况来看,公共云上的隔离,我们用硬件来做隔离,比如我们有神龙的服务器,原来是虚拟机的隔离,现在隔离水平也在逐年提高。但对混合云的需求这不完全是技术的原因,还有思路上的原因,所以很长一段时间内混合云还是会广泛存在。钛媒体:你怎么看待云计算的后台化趋势?你今天上午谈到阿里云不做SaaS,其实SaaS是一个很重要的跟云计算客户的连接,这样的话会不会未来云计算的厂商都会变成被遗忘的状态,就像现在的电厂、自来水厂一样。行癫:被遗忘而不可替代,也是值得期待的事情,就像空气一样,我觉得是一个非常好的状态,不见得一定要跑到最前面去和客户接触。因为真正的2B一定介入客户的业务流程,不然不能叫2B,最多只能叫to custom。但这个行业的需求太分散了,像SAP、Oracle,发布了很多ERP,他们仍然有十几万的工程师,包括自己的合作伙伴。当然也有比较集中的,比如微软,因为办公大家的需求比较一致,除此之外的业务领域,差异非常大。我们把云定位成平台,不是定位成软件系统,所以云和电商在定位上没有很大的差别。电商是无数的品牌商、商家在平台上卖他们的产品,不需要关心支付、交易的事情。云未来一定会更专业,专业化分工是现在文明一个重要基石,我们要做生态也是要解决这个问题。我们的专业到底是什么?我们擅长于做大规模的系统,擅长技术创新,对技术未来演进的趋势有一些看法。当然,我们有丰富的业务场景,让我们把前面这些事情做的比别人好,这是我们的优势。但大量行业的业务还是需要行业内专业的人去做。他们也需要创新,不是简单把云作为一个IaaS,而是要看如何基于数据、基于智能去发展,所以我们要和合作伙伴一起完成转型。再一个,中国的IT发展的很不平衡,有些公司信息化还没有实现,就要讲数据化、智能化,有些公司IT能力很弱,更需要我们合作伙伴做一些贴身的服务,包括实施、咨询、辅导,但这些阿里云都干不了。钛媒体:刚才你谈到Oracle、SAP的人员规模,是不是在你心里面对阿里云的规模是有一个预期的?行癫:是。我觉得一个有1万人的平台公司是一个非常大的平台型公司了,像淘宝做的这么大,也就几千人的规模。如果一个公司的人数与业务线性相关,可能是做了太多自己不擅长的东西。钛媒体:刚才谈到一些人工智能,现在做人工智能和开源这两个事情,起来非常快,你觉得未来对于云计算会有什么影响?行癫:开源使得云越来越标准化。不管从上面互联网的一些技术部件,包括云的一些主要的模块,像容器等等,会越来越标准化,这个对云的发展是有利的。第一个是因为开源是一些发达的大公司在用,他们的技术会更稳定。最关键的一点是,云上大量的开发技术体系会更一致,大量工程师会熟悉这套体系,更容易把自己的应用变成云的一部分,单靠一家公司去制定标准还是非常难的。钛媒体:开源基本上被大厂商瓜分掉了,未来会给开源市场带来什么影响,开源未来会不会走向收费的道路?行癫:现在有点这个趋势。原来的开源可能就是免费开源,现在有的公司做收费的服务。但是大家都在云上了,那些公司的生意模式就发生变化了,所以他们去修改开源协议,这个我觉得是反趋势、反潮流的。最终他们会发现,过了一两年时间,最后一定是云公司来做原生的云,要不然是大互联网公司推出完全免费的开源。大的互联网公司不care这点小钱,他是要繁荣整个生态。钛媒体:关于云计算最后一个问题,技术的角度来说,现在云计算你最关注的技术是什么?行癫:第一个是你刚才谈到混合云现在发展非常快,所以我们还是做了非常多工作。第二个是安全,大家都上云的话,安全就变的非常关键。从产品角度来看,数据库发展非常快,大家都在想替代Oracle数据库,但是在关键核心应用上要1比1替代还是有挑战,所以现在完全基于云原生的数据库发展非常快,像AWS完全把数据库作为一个核心能力来做,目前国内也是发展非常快。当然还有一个最底层的IaaS层的,像容器、做隔离,我们也在推神龙服务器,做硬件层的隔离,这块发展也非常快。云原来是有人做了一个比较完整的框,现在每个框它本身都在快速演进,它其实还不完全是静止的。当然生意模式也在演进,微软从SaaS往下做,aws属于另外一条道路。关于阿里云的未来钛媒体:上任四个月,这段时间你做了些什么事呢?行癫:主要是在讨论,阿里云要做到高增长,还要做到人员非线性增长,这个是我们讨论比较多的。第二个讨论云的未来,云以后到底是怎么样一个商业形态。第三个我们的核心能力到底是什么,我们不做什么,做什么,这个也讨论比较多。在这个讨论的前提下,我们怎么达成共识,怎么样去调整组织,怎么样去落实这个KPI,怎么样通过工具去保证这个流程。钛媒体:今天你的发言应该是一个讨论结果的展现。行癫:对,我觉得这是我们内部共同认定的。当然,阿里集团内部也发生一些变化,希望阿里云智能变成阿里经济体所有的技术跟产品的统一出口和客户界面,这个跟原来的定位可能也有区别,所以现在金融云、钉钉等等都作为整体一部分来考虑。我觉得阿里巴巴也是技术和商业结合最好的一家公司,有的公司CTO天天换,因为没有这个土壤,外面来的人的技术,来了之后一直跟业务结合不了,就会被组织抛弃。钛媒体:外界一直认为,技术是阿里云的一个短板。你怎么看?行癫:很多人问这个问题,阿里巴巴到底是什么公司。阿里巴巴一直是技术性公司,只是商业做得太成功了,所以人家搞不清楚到底是技术公司还是商业公司。阿里做的事情实在太多了,电子商务、支付、物流、文娱等等,所以人家觉得阿里是一家比较业务导向的公司。我一直认为,技术依赖于业务,业务依赖于技术,各个阶段比重不一样,有的时候业务拉着技术走,技术推着业务走,世界上没有纯技术的公司。阿里巴巴是一家非常奇特的公司,我们是互联网的规模、企业级的复杂程度、金融级的准确度。举个小例子——搜索引擎,你搜索一个关键词,出来5页、出来10页、出来500页,用户不care,你丢掉一半数据,人家也不觉有什么问题。但阿里不一样,只要丢了一个商品,卖家立即打过来了。你交易出一分钱的错误,人家百分之百打电话过来,而且是非常严重的问题。全世界没有一家公司,要同时处理这些事情,再加上每年要给你来一个双11,这是很复杂的。在成本没有大幅增加的情况下,要同时满足这三个条件,而且要有非常高的弹性。所以阿里技术不管怎么讲都是非常复杂的。技术有两种,一种是做单点突破,像语音、搜索、算法。第二是处理复杂流程。这是两种一样难的事情。今天在人才市场上处理复杂系统、构架复杂系统的人更稀缺,因为要有很多经验,才能处理这么一个系统。这是第一个事情。第二个事情阿里是工程能力非常强的公司。有的公司能研究,但是写不出系统,但阿里不一样,今天你有事情要做,我们一定是可以非常确定告诉你,多长时间,多少天能够上线,全球很少有公司能达到这样一个自信。第三个外界的看法,可能是因为突破性的技术不够多。但达摩院现在很多技术是非常领先的,包括语音,像法院的语音系统是用我们的。另外视频处理,在城市大脑这样的应用就更不用说了。我们自己的芯片很快就有流片,八九月就能出。到这个程度,就更立体,让大家觉得阿里巴巴是一家怎么样的公司。我觉得阿里巴巴也是技术和商业结合最好的一家公司,有的公司CTO天天换,因为没有这个土壤,外面来的人的技术,来了之后一直跟业务结合不了,就会被组织抛弃。钛媒体:你刚刚谈到提到业务技术互相拉动,你觉得阿里现在谁在拉动谁?行癫:最早,业务比技术跑的快,技术一直追业务,因为业务增长实在太快了。前两年我觉得是技术推动业务,特别是人工智能兴起的之后,包括我们程序化交易、广告平台、千人千面、推荐、搜索大量用算法和AI,包括客服等等大量用数据智能在驱动业务。云也是一样,云是技术的突破才能带来成本下降、效率的提升。云是比较典型的,原来的电商业务这两年大部分红利是靠技术突破带来的。因为商业模式突破已经非常难,今天大家都聪明,以后的竞争门槛会抬高,这个门槛很多都是技术门槛。阿里巴巴这几年的实践,特别中台提出以后,我们积累核心能力更快,浪费更少。然后我们数据中台提出后,数据全部打通,这个也是效率很高。这个是公司中台成功的一个很重要的地方。当然跟组织能力有关系,不是说有理念一定会实施。有些公司可能推都推不下去,我们也是花了大概两年的时间,逐步整合。一个中台你得证明自己,你比别人技术好,这不是这么快和容易的事情。关于阿里的中台钛媒体:你认为中台跟组织结构的关系是什么?行癫:这个还是非常非常有关系的,包括组织能力、信任关系,包括一些考核,这里边有非常多一些关系。你做中台,做不好就变成一个原来的公社。公社其实就是一个中台体系,你专门种玉米,你专门种水稻,但是为什么到后来大家都搞不下去了呢?中台不是把所有部门理一理,这个让你做,那个不让你做,技术能力跟不上、组织能力跟不上,还是低效的。我比较特别,我做中台,原来的部门都做过,还是能够影响到很多人。第二、我们还是很踏实的,承认哪些做得好,哪些做不好,也不是所有都拿来做。第三、阿里制度上做了一些创新,我们有一个技术委员会,到现在很多人都在学,但是我觉得他们都还没明白,我们到底怎么运作的。我们技术委员会下面有技术小组,因为我们有很多专家,语音的、视频的、视觉的,如果原来是三个部门做,那么三个部门成立一个小组,你们先去解决统一的问题、发展的问题。他们如果不能解决,我再出面解决。所以我们是提倡让工程师用技术的手段来解决技术的分歧和发展。中台不仅是个组织,中台是个理念,所以说这个中台的技术,如果放在高德是最适合的,就放在高德,但是对高德来说,这个技术一定要有一个定位,要为全体人负责,不仅是为自己服务。所以有些是中台的技术,但不一定在中台,例如智能机器人技术,那就是在客服部门,因为他最贴近现场。但是一些中心业务技术,要不在达摩院,要不在中台部门统一建设。阿里制度上做了一些创新,我们有一个技术委员会,到现在很多人都在学,但是我觉得他们都还没明白,我们到底怎么运作的。钛媒体:智能云的概念,和原来的IaaS是不太一样的,它会带来什么新的变化?包括组织架构、KPI等等。行癫:组织架构,现在所有CTO线的技术部门跟云的技术部门都整合。例如原来两个数据库部门,现在合并成一个数据库部门。原来两个网络部门,现在合并成一个网络部门。钛媒体:KPI的问题,我原来也跟孙权聊过这个事。现在你最看中的是什么?行癫:我觉得第一个是规模,因为这个意味着你产业的竞争,这个肯定是非常核心。第二个我们还是非常关注公共云的份额,因为最终云的基础还是公共云的发展,当然也有混合云的发展这个也很关键。第三个提倡生态,到底在多少生态上,阿里巴巴有多高的竞争力?现在我们有几千家主要的合作伙伴,我们希望把主要业务放在阿里云上的,要占一个更大的比重。钛媒体:钉钉未来会跟阿里云有更紧密的协同吗?云端协同未来是不是一个重要的打法?行癫:刚才我们讲的数据化智能化,另外很大一块就是工作在线化,包括办公的协同,这个我们想靠钉钉的能力来补上这块体系。现在,云是两个驱动力,数据+智能,到明年我们会加一块工作协同。我们认为这个工作协同是互联网公司跟其他公司的区别,因为互联网公司大量的运用这些新工具来做工作的协同,传统企业很少用这种工具。像钉钉这样的生产力工具出现之后,发生了很大变化,原来用邮件,现在钉钉在线实时工作效率非常高了。以前的审批也是,通过它的机制全部串联起来。再进一步像文本,供应链体系,都通过钉钉体系串联起来,更轻快。手机协同性不是很好,我们希望通过钉钉串联起来。然后把钉钉这个能力变成我们合作伙伴的一个基础能力输出。这是我们的一个想法。钛媒体:是不是钉钉对阿里云的价值,类似于office365对于微软 Azure?行癫:有一点类似,但是还是没有那么SaaS化。钉钉主要是一个协同沟通的平台。我们希望未来的企业既是数据的,又是智能的,还是在线协同的,这是我们对我们客户的一个主要未来的描述。钛媒体:今天还有一个事挺有意思的:繁星计划-小程序,小程序在大的部署当中现在是一个什么样的角色?行癫:小程序是很重要的角色,因为现在越来越多应用都会在无线端,不管数字政府还是各行各业的应用。这个应用有两种形式,一种是做独立APP,另一种是依托于某一个大的流量入口,我们觉得大部分长尾应用自己去做独立APP都有很大难度,可能会依托于大的流量入口,比如微信、阿里这样的。阿里跟微信有很大差别,我们叫一云多端,不仅是在支付宝、淘宝可以跑,在高德也可以跑,甚至可能以后在微博上也能跑。就像是Android一样,开发一次到处可以跑,但是微信更像是iphone,在他这里开发这里跑。我们的小程序是一个生态,我们会提供云到端的一系列工具,让开发者很快就能做出来。钛媒体:可不可以理解小程序更像一个端?行癫:一个轻量化的端,是各行各业一个轻量化的出口。钛媒体:据我所知是拿支付宝小程序做了一个框架。行癫:对,因为支付宝在这个方面接触比较多、探索比较多。这就是我们的一个好处,一下子全部都能用。关于被集成钛媒体:你今天提到“被集成”这个概念是非常新鲜的,这个思路是怎么被提出的?因为阿里其实一直是平台,平台和被集成有矛盾吗?行癫:原来阿里是个平台,我也做过两年中台,我一直在琢磨中台跟平台到底有什么区别。像阿里巴巴、淘宝、天猫这种平台只要搭好了,客户直接开店就可以了,不需要关心任何事情,但我觉得中台不一样,中台自己单独的产品不能直接产生价值、不能直接对外服务,一定要变成别人产品的一部分,让别人的产品提供更好的服务,这是我理解的中台。包括数据智能和人工智能,这两个东西肯定不是平台,肯定要变成人家的一部分,从这个角度上,阿里云智能既是一个平台,也是一个中台,所以我们提出口号叫“被集成”,就像英特尔的CPU一样,也是被集成,集成到各种各样的电脑里去,是一样的逻辑。钛媒体:“被集成”的策略对阿里云的运作,包括组织管理,都会产生一些比较大影响,这个其实是调用和被调用的关系,和以前太不一样了,内部需要做什么调整吗?行癫:其实我们原来自己也在做一些总包,我们也在做集成,集成我们的技术。但是我们发现我们的交付成本非常高。有些行业是没有办法的,像城市大脑,因为这个行业是新兴行业、增量应用,以前没有玩家,你要做些show case,这个行业我们会去做,但是做了以后去复制、大规模推广,我们肯定需要大家一起来干。钛媒体:这一步我觉得还是非常高明的,把原来阿里云很多问题缓解了,包括交付能力,把原来集中式交付变成了分布式交付。行癫:而且很多合作伙伴愿意做交付,他们擅长。钛媒体:被集成这个概念提出来以后,未来整个生态会怎么打造。行癫:简单一点就是,能合作伙伴签合同的,你们签。非得让阿里云签的,我们一起签。钛媒体:未来生态的打造会有什么变化?现在被集成之后这个关系就有点混乱。行癫:生态一定还是一个分工协同。传统的生态不像想象中那么整合,他们也是分工协作的。比如说做一个传统企业的ERP系统,他们也是分工协作的,比如德勤做咨询,SAP做软件,埃森哲去实施。我们不去破坏大家的分工合作,只是我们的产品技术变成这个体系的一部分,是这么一个逻辑。钛媒体:原来传统的2B的生态,还是一个比较均衡的生态,因为基本后来都是大公司。但是在互联网生态,基本是一个大平台,然后一堆小公司。行癫:我个人觉得,大公司一定会做比较通用的系统,但是通用系统如果被云化,像有些大公司有可能就被取代了。但是专业化的服务能力,是个性化,c2m。个性化意味着什么?意味着对大品牌来说,是要碎片化,云这个服务我觉得以后也是一样的,一定有很多细分的专业服务商,而不是一个很大的专业服务商,服务很多行业。我认为这是一个趋势。就像化妆品一样,不是天天涂大宝,它很细分,有很多的品牌。钛媒体:那未来的这种生态的打造思路会不太一样,要靠什么政策,把大家吸引过来?行癫:原来,简单的生态是reseller的模式,但是今天我觉得,我们更希望合作伙伴理解这个行业,跟我们掌握的技术有一个共创。比如我们有一个很好的语音技术,我们不知道什么行业可以用。合作伙伴掌握这个技术,也懂得客户应该怎么用,比如人可以用在考勤上,或者用在什么门禁上。所以我今天更看中的生态伙伴是对这个行业未来有定义能力的、有创新能力的公司,是我们优先去合作的人。真正头部的概念就是说这家公司是不是够专业、是不是对行业未来有洞察。毕马威有两句话说的非常好。他们把今年的策略总结成两句话,一句叫发现,一句叫实现。我们希望跟合作方一样要能发现,而且有能力实现它。钛媒体:现在怎么看阿里云的短板?行癫:我觉得阿里云的短板很明显,我们虽然做云,但是2B服务能力是我们比较缺的,所以需要通过生态快速的发展来补。第二个从核心技术积累上,有这么多年的积累之后,我们原来是一个平台化、产品化的结构,这两个还不一样,平台都得自己做,所以不用单产品剥离出去,别人可以很好用,我们内部也可以用的很好,因为开发者就在公司内部,你可以直接问他,所以他构建了一个非常复杂的平台,但是这个复杂的平台不是单一个单产品,非常结构化的构成,所以我们今天也在加紧产品化。产品化包括要丰富的文档,手册,这个其实还是有很多工作要去做。钛媒体:被集成这个事情有没有指标?你怎么衡量?行癫:我们有几千家合作伙伴,我们希望有业务的合作伙伴数量,要有非常严格的指标,包括他们的规模。对于我们大型头部的合作伙伴,大家都不是收入的指标,包括德勤、埃森哲,我们还是希望打造头部标杆案例,真正从行业未来定义的案例,这是都是我们一些共同的目标。钛媒体:今天上午说不做SaaS,咨询会做的非常少,但咨询这个事情非常重要,意味着你跟客户密切的交流,未来阿里云怎么保持跟客户之间的沟通,未来怎么了解客户的需求?行癫:今天,我们不仅是把产品简单提供给合作伙伴,我们大部分的时候,还是跟伙伴一起做样板市场,所以我刚才讲为什么头部的,有市场定义能力的人一起做,包括德勤,埃森哲,也是和我们一起在定义这个市场,只是我们今天把产品能力变成他们的解决方案的一部分。钛媒体:其实包括未来整个被集成这个事情,对阿里云也有压力,比如说技术能力封装。行癫:其实被集成是更高的要求。不仅是我接触客户少了,都是合作方在接触了。合作方为什么选阿里云,为什么不选其他的云厂商,对我要求更高,要服务好,产品一定要有竞争力。钛媒体:这样把主动权交出去了。行癫:是的,那个主动权我就是掌握了也没有用,因为那也不是云要做的事情。怎么走好我觉得还是很有挑战的。关于企业上云的未来钛媒体:因为现在架构变的非常重要,很多企业正在经历架构变化的过程,从技术到架构这一步的跨越是很困难的事情吗?行癫:企业的架构,我认为绝大部分是业务架构,不是纯粹的技术架构,他缺的是把自己的业务都分析清楚,变成了一堆业务架构的能力,用技术手段去实现。互联网公司两者兼而有之,我们公司有些是业务架构,有些是技术架构,技术架构更偏纯技术,业务架构非常复杂,它做很多决定,比如说做电子商务系统,他决定要分多少个模块,各个模块关系怎么样,最好用什么技术实现。技术怎么实现的,是技术架构干的事情,我觉得大部分企业缺乏非常好的业务架构,这个业务架构你没法招聘,一定要自己培养,这样才能理解自己业务。钛媒体:你做阿里CTO一段时间了,我特别想了解,作为一家大企业的CTO,你最大的职责是什么?行癫:阿里的CTO,第一要对未来有看法有判断,到底未来要有什么样的技术;第二个组织内部基础资源整合好,不能各自为战。第三,技术工程师的文化要定义,我们经常讨论这个事情,到底怎么激励我们的公司,第四保证业务系统的技术需求得到及时的满足,不能业务系统都支持不好,就有难度了。钛媒体:因为现在整个技术变化非常大,我想也听听,你给这些传统企业的CEO、CIO一些建议,他们怎么样树立自己的技术视角,怎么让他们用自己的视角判断技术价值?行癫:我觉得大部分公司关注好业务就差不多了,大部分中小企业都是这个状态。技术不要成为瓶颈,就非常不错了。只有很大型的互联网公司,他才能判断有没有系统性技术风险,比如一些新技术,基于一些新技术的商业模式,他可能要反复思考一些问题。比如5G起来,智能手机普及了,大概会对我们商业模式技术体系有什么影响,物联网起来了会有什么影响,智能驾驶到底会怎么样,这些都是我们要去提前想的。钛媒体:这些问题你会怎么判断?行癫:我们也会反复判断,对我们业务有什么用,因为我们业务很复杂,区块链怎么样,我们怎么用,我们不做有什么风险,这是我们经常在看。但是很难总结方法论,得出一个结论,这个是非常难的。钛媒体:现在企业里边,大家都在追求很时髦的东西,上云、架构,但是有一些被忽略的问题,包括运维、安全。从你的角度来看,传统企业上云有哪些问题应该提起他们的重视,有哪些被忽略的问题?行癫:云上系统,上云的第一刻开始,我们阿里很多人都投在运维,这样才能保证系统永远处于健康状态。原来都是开箱即用的技术,弄个oracle就可以了,弄个数据库DBA就可以了,但现在不行了。以后整个系统要保持效率最高,运维工作还是非常重要,但中国公司绝大部分没有付费做运维这个习惯,这个我觉得还需要一个改变。安全其实压力小了很多,因为云解决了很多原来线下没法解决的问题,比如说有个补丁、有个漏洞,我们第一时间知道,厂商会告诉我们,我们全部把它修复了。总体上,上云比不上云安全得多。钛媒体:真正上云之后,企业尤其是传统企业,会带来很多变化,包括能力和人员的配备。这块你看的更多,你怎么看这些变化?行癫:现在诞生了非常多一些第三方公司,专门帮政府云上做运维,给政府的IT部门带来很大变化。企业也一样,比如原来信息化部规模可能比较大,因为原来的人可能要端到端覆盖,所以工种也比较复杂。上云以后,总的来说,从固定资本投入,还有对人员的一些要求都会有很大变化,至少DBA就不是很重要的岗位了。钛媒体:人工智能的出现,有一个副作用,那就是它对技术能力的要求,几乎超过了哪怕最大规模的传统企业的承受能力。这对企业的技术选型和系统建设策略会带来很大的影响,这件事你怎么看?行癫:我觉得他们肯定更应该关注跟行业属性相关的,这部分别人没有办法复制,其他都是市场上可以采购的,包括云服务、语音服务、数据处理服务、AI服务。他需要明白的是,这个技术对我们的行业产生什么影响。很多行业现在没有能力承载(一些技术的开发),倒不在于一次性投入有多高,主要没有一个规模化的业务场景去做承载,它的演进时间就没有公司能容忍。但现在一些公司还在做云,做人脸识别,这个不会构成它的核心能力,它的核心能力是跟自己业务相关的部分。钛媒体:现在一些大型的企业,还有两三千人的IT团队,还在做大量的自己研发的工作,你觉得未来这种事未来会变的更多还是更少?行癫:我觉得更少,专业化的分工一定是现代社会的精髓,漠视这一点,可能不会获得最高效率。怎么利用社会分工,专业化服务,这是大公司也好,小公司也好,真正能够提升自己的效率,能够集中在自己核心优势的一个地方。阿里云,刚才你也问我,我觉得如果我们现在有几万人,那说明肯定不够聚焦,那样的话肯定在做我们并不擅长的事情。本文作者:阿里云头条阅读原文本文为云栖社区原创内容,未经允许不得转载。

April 2, 2019 · 1 min · jiezi

17个获取设计灵感创意必备网站

1.Sketchrepo:免费高品质的Sketch资源Sketchrepo 专门收集Sketch素材,关注它们,不仅能第一时间拿到追波、Behance上的优质素材,还能把最热门的免费素材收入囊中。2.Psdrepo:免费高品质的PSD资源PSD Repo 收录了许许多多可能是工作上会用到的 PSD 素材,包括按钮、Mockups、图标、行动装置、用户接口以及网页设计,这些设计有非常美观的预览图,也有下载按钮可引导至相关链结。这些素材多半来自于 Dribbble、Behance 或其他设计师网站,你可以参考授权方式来进行使用、修改,或是单纯做为设计灵感来源。3.Magdeleine:免费高清灵感图片网Magdeleine是一个每天分享免费高分辨率照片的网站,由文森特创办,该网站也是一个激发你灵感的图库站点,每天手工挑选高分辨率的各种图片,主要类别有自然、城市建筑、动物、视频、技术等。4.NotCot:一个集视觉效果、美学为一体的网站NOTCOT是一个由设计网站组成的不断发展的网络,现在的成员包括NOTCOT.com和创新社区支持的网站NotCouture.com和Liqurious.com。NOTCOT.ORG是一个集视觉效果,美学为一体的网站。5.BoooooooM:设计简约但内容丰富的博客Booooooom是一家博客网站,涵盖的主题包括艺术、摄影、电影、音乐、设计等方面的图片作品。Booooooom由居住在温哥华的艺术家Jeff Hamada创立于2008年,目的是希望它能发展成为一个充满创意会员的社区。类似于flicker和FFFFound这类的图片站点,该网站提供的作品与一般的艺术类站点有所不同,可以说收录分享的作品别具一格。6.Baubauhaus:提供设计灵感、插画摄影等艺术作品Baubauhaus是一个提供设计灵感、插画摄影、潮流时尚以及艺术相关的一切创意灵感作品集合。该网站旨在帮助设计师们收集整理那些可以在视觉上获得灵感和激发灵感的创意作品。7.Niice:设计师必备的灵感搜索引擎Niice 是一个设计师专用的视觉搜索引擎,内容由设计社区 Dribbble,Behance 和 Designspiration 提供。搜索质量高,而且设计都很美观。Niice通过用户输入的颜色来搜索不同的视觉作品,例如只要输入“黑白字母”等,网站会显示搜索出来的黑色内容资源。8.花瓣网:设计师寻找灵感的天堂花瓣网, 设计师寻找灵感的天堂,图片素材领导者,帮你采集,发现网络上你喜欢的事物,你可以用它收集灵感,保存有用的素材,计划旅行,晒晒自己想要的东西。9.Awwwards:最佳网页设计展示平台Awwwards是一个展示网页设计作品的站点,提供网页设计师们的网页设计作品欣赏,并且创办了最佳网页设计奖项,为那些最优秀的网页设计师评选并获得奖励。Awwwards汇集了来自世界各地的网页设计师,在这里他们分享设计经验和网页设计知识,探索Web设计的最高境界,倡导网页设计要实用、新颖、直观,为用户带来最独特的个性化体验。10.Abduzeedo:一家集创意灵感和教程的设计博客Abduzeedo 各种各样的平面设计,你都可以在这里找到,不仅仅是寻找灵感,这里还有大量的Photoshop和Illustrator教程,用心的话,你可以学到很多很多。11.Yanko Design:最棒的现代工业设计站点Yanko Design 创于2002年, 是北美、 澳洲、日本、 印度最具人气的工业设计发布站点。Yanko Design 介绍现代化工业设计的网站,它涵盖了工业设计、审美观念、设计技术、室内设计、建筑学、设计展览和时代流行等。它涉及现代作品和古典作品。你可以在这里看到所有最新的设计,它给你带来的创意是无止境的。12.SwissMiss:分享创意设计的网站SwissMiss是一个分享创意设计的网站,各种创意设计你都可以在这里找到,主要是日常的生活设计,各种创意设计产品,一定会让你获得更好的创意灵感13.Designshack:设计作品欣赏网站Designshack是一个给设计师们提交作品,获得反馈和使用常规的设计相关的新闻和文章的用户友好的一条龙方案。这个网站非常易用;图库里有三个主要分类:网页设计,品牌设计,标志和界面设计。14.Behance:全球领先的专业创意平台Behance是为那些专业艺术家,那些以艺术谋生或者将艺术作为一个非常严肃的爱好的人建立的。由于严格规定和高标准,Behance正在成为一个高级的专业网站。15.Dribbble:设计师必备网站之一Dribbble是一个面向创作家、艺术工作者、设计师等创意类作品的人群,提供作品在线服务,供网友在线查看已经完成的作品或者正在创作的作品的交流网站。16.iKesai:网页设计作品案例库iKesai是一个网页设计作品案例库,收录了海量的网页设计作品,帮助设计师们寻找可供参考的网页案例。iKesai网站提供丰富的网页类别,例如公司企业模版、网店模版、教育、旅游、IT、娱乐等等。17.CSS Winner:网站设计资源站点CSS Winner是一个独特的全球性平台,专门展示和奖励最佳网站,推广创新的网站设计师,开发者与机构。我们通过 CSS Winner这个平台宣传网站设计作品,提高大家的能力与一致性并为优秀的设计师予以奖励。 CSS Winner网站拥有最大的CSS库,展示了入门级的网站设计作品,并协助设计师晋级到候选人级,最终升级至获奖级别。为了让这成为可能,我们安排了九位来自不同国家的获奖设计师,评估每一部提交的作品,根据可用性,创造力和内容判断网站质量。比格张-发现更好的互联网资源https://bigezhang.com

March 13, 2019 · 1 min · jiezi

你的项目应该如何分层?

1.背景说起应用分层,大部分人都会认为这个不是很简单嘛 就controller,service, mapper三层。看起来简单,很多人其实并没有把他们职责划分开,在很多代码中,controller做的逻辑比service还多,service往往当成透传了,这其实是很多人开发代码都没有注意到的地方,反正功能也能用,至于放哪无所谓呗。这样往往造成后面代码无法复用,层级关系混乱,对后续代码的维护非常麻烦。的确在这些人眼中分层只是一个形式,前辈们的代码这么写的,其他项目代码这么写的,那么我也这么跟着写。但是在真正的团队开发中每个人的习惯都不同,写出来的代码必然带着自己的标签,有的人习惯controller写大量的业务逻辑,有的人习惯在service中之间调用远程服务,这样就导致了每个人的开发代码风格完全不同,后续其他人修改的时候,一看,我靠这个人写的代码和我平常的习惯完全不同,修改的时候到底是按着自己以前的习惯改,还是跟着前辈们走,这又是个艰难的选择,选择一旦有偏差,你的后辈又维护你的代码的时候,恐怕就要骂人了。所以一个好的应用分层需要具备以下几点:方便后续代码进行维护扩展。分层的效果需要让整个团队都接受各个层职责边界清晰2.如何进行分层2.1阿里规范在阿里的编码规范中约束的分层如下:开放接口层:可直接封装 Service 方法暴露成 RPC 接口;通过 Web 封装成 http 接口;进行 网关安全控制、流量控制等。终端显示层:各个端的模板渲染并执行显示的层。当前主要是 velocity 渲染,JS 渲染, JSP 渲染,移动端展示等。Web 层:主要是对访问控制进行转发,各类基本参数校验,或者不复用的业务简单处理等。Service 层:相对具体的业务逻辑服务层。Manager 层:通用业务处理层,它有如下特征:1. 对第三方平台封装的层,预处理返回结果及转化异常信息;2. 对Service层通用能力的下沉,如缓存方案、中间件通用处理;3. 与DAO层交互,对多个DAO的组合复用。DAO 层:数据访问层,与底层 MySQL、Oracle、Hbase 进行数据交互。阿里巴巴规约中的分层比较清晰简单明了,但是描述得还是过于简单了,以及service层和manager层有很多同学还是有点分不清楚之间的关系,就导致了很多项目中根本没有Manager层的存在。下面介绍一下具体业务中应该如何实现分层2.2优化分层从我们的业务开发中总结了一个较为的理想模型,这里要先说明一下由于我们的rpc框架选用的是thrift可能会比其他的一些rpc框架例如dubbo会多出一层,作用和controller层类似1.最上层controller和TService是我们阿里分层规范里面的第一层:轻业务逻辑,参数校验,异常兜底。通常这种接口可以轻易更换接口类型,所以业务逻辑必须要轻,甚至不做具体逻辑。2.Service:业务层,复用性较低,这里推荐每一个controller方法都得对应一个service,不要把业务编排放在controller中去做,为什么呢?如果我们把业务编排放在controller层去做的话,如果以后我们要接入thrift,我们这里又需要把业务编排在做一次,这样会导致我们每接入一个入口层这个代码都得重新复制一份如下图所示:这样大量的重复工作必定会导致我们开发效率下降,所以我们需要把业务编排逻辑都得放进service中去做:3.Mannager:可复用逻辑层。这里的Mannager可以是单个服务的,比如我们的cache,mq等等,当然也可以是复合的,当你需要调用多个Mannager的时候,这个可以合为一个Mannager,比如逻辑上的连表查询等。如果是httpMannager或rpcMannager需要在这一层做一些数据转换4.DAO:数据库访问层。主要负责“操作数据库的某张表,映射到某个java对象”,dao应该只允许自己的Service访问,其他Service要访问我的数据必须通过对应的Service。3.分层领域模型的转换在阿里巴巴编码规约中列举了下面几个领域模型规约:DO(Data Object):与数据库表结构一一对应,通过DAO层向上传输数据源对象。DTO(Data Transfer Object):数据传输对象,Service或Manager向外传输的对象。BO(Business Object):业务对象。由Service层输出的封装业务逻辑的对象。AO(Application Object):应用对象。在Web层与Service层之间抽象的复用对象模型,极为贴近展示层,复用度不高。VO(View Object):显示层对象,通常是Web向模板渲染引擎层传输的对象。Query:数据查询对象,各层接收上层的查询请求。注意超过2个参数的查询封装,禁止使用Map类来传输。层次领域模型Controller/TServiceVO/DTOService/ManagerAO/BODAODO每一个层基本都自己对应的领域模型,这样就导致了有些人过于追求每一层都是用自己的领域模型,这样就导致了一个对象可能会出现3次甚至4次转换在一次请求中,当返回的时候同样也会出现3-4次转换,这样有可能一次完整的请求-返回会出现很多次对象转换。如果在开发中真的按照这么来,恐怕就别写其他的了,一天就光写这个重复无用的逻辑算了吧。所以我们得采取一个折中的方案:1.允许Service/Manager可以操作数据领域模型,对于这个层级来说,本来自己做的工作也是做的是业务逻辑处理和数据组装。2.Controller/TService层的领域模型不允许传入DAO层,这样就不符合职责划分了。3.同理,不允许DAO层的数据传入到Controller/TService.3.总结总的来说业务分层对于代码规范是比较重要,决定着以后的代码是否可复用,是否职责清晰,边界清晰,所以搞清楚这一块也比较重要。当然这种分层其实见仁见智,团队中的所有人的分层习惯也不同,所以很难权衡出一个标准的准则,总的来说只要满足职责逻辑清晰,后续维护容易,就是好的分层。最后这篇文章被我收录于JGrowing-Java设计篇,一个全面,优秀,由社区一起共建的Java学习路线,如果您想参与开源项目的维护,可以一起共建,github地址为:https://github.com/javagrowin… 麻烦给个小星星哟。如果大家觉得这篇文章对你有帮助,你的关注和转发是对我最大的支持,O(∩_∩)O:

March 9, 2019 · 1 min · jiezi

leetcode355. Design Twitter

题目要求Design a simplified version of Twitter where users can post tweets, follow/unfollow another user and is able to see the 10 most recent tweets in the user’s news feed. Your design should support the following methods:postTweet(userId, tweetId): Compose a new tweet.getNewsFeed(userId): Retrieve the 10 most recent tweet ids in the user’s news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent.follow(followerId, followeeId): Follower follows a followee.unfollow(followerId, followeeId): Follower unfollows a followee.Example:Twitter twitter = new Twitter();// User 1 posts a new tweet (id = 5).twitter.postTweet(1, 5);// User 1’s news feed should return a list with 1 tweet id -> [5].twitter.getNewsFeed(1);// User 1 follows user 2.twitter.follow(1, 2);// User 2 posts a new tweet (id = 6).twitter.postTweet(2, 6);// User 1’s news feed should return a list with 2 tweet ids -> [6, 5].// Tweet id 6 should precede tweet id 5 because it is posted after tweet id 5.twitter.getNewsFeed(1);// User 1 unfollows user 2.twitter.unfollow(1, 2);// User 1’s news feed should return a list with 1 tweet id -> [5],// since user 1 is no longer following user 2.twitter.getNewsFeed(1);设计一个迷你推特,要求能够支持以下几个方法:发布推特,关注用户,取关用户,查看最近的十条关注用户发送的推特。思路和代码这道题目本质上是考察是否能将数据结构的知识灵活的运用于现实生活中。从最直观的想法来看,我们会有一个用户实体,每个用户会记录自己关注的用户的id,以及记录自己发表的所有tweet。这里唯一的难点在于我们如何按照时间顺序获取tweet流。这么一想,这题其实就转换为如何将N个有序排列的数组汇合成一个有序的数组。这题等价于我们每次都会比较当前所有被关注者发布的最新未读tweet,选出结果后将其插入结果集。这里我们可以利用等价队列帮助我们更快的完成选择的过程。public class Twitter { public Twitter() { users = new HashMap<>(); } public static int timestamp = 0; private Map<Integer, User> users; /** Compose a new tweet. / public void postTweet(int userId, int tweetId) { if(!users.containsKey(userId)) { User user = new User(userId); users.put(userId, user); } User user = users.get(userId); user.tweet(tweetId); } /* Retrieve the 10 most recent tweet ids in the user’s news feed. * Each item in the news feed must be posted by users who the user followed or by the user herself. * Tweets must be ordered from most recent to least recent. * / public List<Integer> getNewsFeed(int userId) { List<Integer> result = new ArrayList<Integer>(); if(!users.containsKey(userId)) { return result; } User user = users.get(userId); PriorityQueue<Tweet> queue = new PriorityQueue<>(user.followed.size()); for(int followee : user.followed) { User tmp = users.get(followee); if(tmp != null && tmp.headTweet != null) { queue.offer(tmp.headTweet); } } while(!queue.isEmpty() && result.size() < 10) { Tweet t = queue.poll(); result.add(t.tweetId); if(t.next != null) { queue.offer(t.next); } } return result; } /* Follower follows a followee. If the operation is invalid, it should be a no-op. / public void follow(int followerId, int followeeId) { if(!users.containsKey(followerId)) { User user = new User(followerId); users.put(followerId, user); } if(!users.containsKey(followeeId)) { User user = new User(followeeId); users.put(followeeId, user); } User user = users.get(followerId); user.follow(followeeId); } /* Follower unfollows a followee. If the operation is invalid, it should be a no-op. */ public void unfollow(int followerId, int followeeId) { if(!users.containsKey(followerId) || followerId == followeeId) { return; } User user = users.get(followerId); user.unfollow(followeeId); } public static class User{ int userId; Set<Integer> followed; Tweet headTweet; public User(int userId) { this.userId = userId; this.followed = new HashSet<>(); follow(userId); } public void follow(int userId) { followed.add(userId); } public void unfollow(int userId) { followed.remove(userId); } public void tweet(int tweetId) { Tweet tweet = new Tweet(tweetId); tweet.next = headTweet; headTweet = tweet; } } public static class Tweet implements Comparable<Tweet>{ int tweetId; Tweet next; int time; public Tweet(int tweetId) { this.tweetId = tweetId; this.time = timestamp++; } @Override public int compareTo(Tweet o) { return o.time - this.time; } }} ...

March 7, 2019 · 3 min · jiezi

亿级曝光品牌视频的幕后设定

本文由云+社区发表作者:腾讯ISUX项目背景2019年春节期间,QQ红包运营活动进行了全新改版,将卡券福利、现金奖励打包成福袋形式,并通过年俗小游戏及共享福袋的玩法吸引更多用户参与。在点击福袋进入小游戏的界面,我们推出了QQ空间新春福袋品牌视频,希望用户在等待加载的过程中感受到新春氛围,同时也加强对空间的品牌认知,深化其与产品之间的情感联动。项目在设计过程中面临两大难题:一是项目周期较短,虽然视频素材已有雏形,但在短时间需要重新确立基调及建模渲染,输出完整的3D视频,对团队来说确实是个不小的挑战。其次则是需要考虑如何做好新春氛围营造和品牌认知传达之间平衡和融合。项目流程概念探索首先从空间的品牌Logo出发,我们进行了创意发散,在众多关键词中梳理出了一条以”空间星球生产红包“为主题的故事线。空间星球作为大场景不仅可以清晰地传递出品牌认知,也可以打造出兼容性较高的世界观,整合不同主题的元素;而生产红包的概念则用于展现运营活动的分量与活力,而红包为装饰元素也能更直观地打造节日氛围。 故事线1. 故事分镜 动画的剧本以“探索星球-生产红包-新春尽在空间”为线索递进。画面第一幕将在空间星球的背景中铺开,观众将跟随远景镜头探索城市的全貌,随后镜头拉近聚焦红包工厂的生产流程。第二幕由近景镜头跟随红包上天穿越云层,并切换追踪UFO,完成地面和云层的转场衔接,最后空间星球伴随新春元素旋转进场,Logo定格完成品牌展示。为了保证动画转场与镜头运动的流畅性,我们以Motion Camera切换追踪目标的方式进行拍摄,希望能营造出一镜到底的穿梭感。2. 场景设计虽然一镜到底的构思能加强故事的串联性,但是从场景设计的角度而言,将3D模型全部创建在一个场景里可能会造成镜头路径卡顿与灯光不均等问题。因此我们将场景拆分为三个模块:空间星球城市、红包工厂、品牌灯笼。后期再以剪接手法营造无缝的镜头感。另外由于最终需要输出竖构图视频,三个场景的设计皆以三角构图作为基准。空间星球城市:以空间Logo星型作为延展,以城市为主题承载着各种以产品业务为原型的概念建筑。红包工厂则被安排在城市的视觉中心,希望能全景展示空间特性,同时也方便后期镜头走位,带出红包玩法。红包工厂:工厂的结构为带玻璃穹顶的旋转圆盘,其中展示了物料传输与形变、染色封包等制作红包的工序,希望能让用户感受到春节红包料足、量多、源源不尽的氛围。品牌灯笼:作为故事最后的转合,场景以承载着城市的灯笼旋转定格收尾,呼应星球主题也契合新春感知。背景增加云层平衡构图,前景则使用爆竹弹射粒子动画调动喜庆情绪。前期为了节约时间,我们先在充满灵魂的手稿上迅速达成场景结构的共识,后续再因应建模的情况进行机动调整。元素建模 场景融合确立场景后,我们根据空间的业务特性及新春氛围进行了元素提取与快速建模。 再以城市建筑群为整体,将业务元素与春节元素依循几何节奏感整合到同一群组中。虽然群组化的过程需要进行不断的摸索和修正(受到后期物体固有色或灯光的影响),但是完成此步骤后,无论是视频大场景拍摄还是输出单体小组合素材,都能较好的保证模型的整体复用性和局部精细度。最后再按依照三角构图的比例为画面分区,将模型组按照对应角度安插在大场景中。色彩提取 质感塑造在色彩的规划上,我们对春节主题进行了情绪版分析与提炼,最终确定了金色和红色作为主色:红色负责打造整体氛围,而金色和QQ空间品牌黄在色相上既有一定的关联,同时也能让画面的局部质感更浓烈细腻;白色则可以给予画面呼吸的空间,缓解高饱和度带来的视觉刺激。在配色较为热烈的基调上,选用材质时我们更偏向轻量的雾面质感,对高光进行收拢,并在部分红色材质上增加丝绒机理,营造温暖亲近的观感。空间2019年限定色号口红,了解一下?动画预合成1. 动态统一在动画设计的部分,含动效物体(工厂圆盘、小船、黄钻、火箭等)的位移动向和旋转方向皆统一为逆时针,同时也为其他循环动画制定了相同的节奏,一是为了暗示镜头趋势,顺应观众视线,二是使画面动态细节更整体,韵律更明确。2. 压缩渲染时长渲染时长是3D动画中永恒的痛点,在项目周期极短的情况下,减低渲染成本就变得尤其重要。作为3D动画的初心者,在元旦深夜渲染屡屡出BUG屡屡跪的情况下,我们摸爬滚打出了以下几种思路:-简化材质:减少不必要的玻璃、SSS、置换贴图材质,一来可采取较低采样数,大幅降低渲染时长,二来则可避免输出高清素材时易触发的UV错位或反射不到位等问题。-从粒子云到体积云:刚开始接触烟雾物体时,我们尝试使用Thinking Particles和Turbulance FD等插件进行云粒子渲染,发现无论是预览效率还是成像品质都并没有较好的效果,另外也由于它们的参数过多,容易在团队合作调整过程中衍生新问题。后来考虑到对云的动态没有太多的需求,我们弃用了TP和TFD,转用Octane中的VDB制作体积云,既能实时控制预览云的形态,也能缩减计算时间。-分层渲染:为了提高后期合成的可编辑性和效率,我们对背景、主体物件、前景物体进行了分层渲染,既避免渲染出错而导致全面返工,同时也能在AE中对更多图层参数(动态模糊、景深、动画速率等)进行二次调整。-善用Preview与跳帧检查:渲染出错是难以避免的,但是可以透过渲染测试来尽量降低重渲风险。对于动效而言,在制作的各个阶段都可以快速导出线框动画预览节奏以及物体位置;而对于材质和贴图,则可以在素材完整输出前按需进行跳帧渲染,检查重点帧的Full Render效果,以免一子错满盘皆落索。Final Output为大家放送高清大图与完整视频,Qzone今年你最红:项目心得有限的时间里更需要无限的沟通 在项目周期极短的情况下,团队中的每个人都需要清晰地认识到每个时间节点需要完成的任务。对于3D动画这种前期概念模糊,后期作业复杂且分段耗时不明确的任务,可以使用倒推法进行规划,为渲染保留充分的时间。另外也需要成员在动画制作的每一个环节想清楚核心目标是什么,再决定技术方案,不要为了自嗨式雕琢而丢了项目的进程。在创作脑暴期,团队成员可能会对同一个事物有不同的理解和想象。因此,在动画概念未成形或腹稿阶段,我们需要及时地将自己的想法可视化(无论是灵魂概念稿还是低面模型)以消弭双方的理解误区。同时也需要尽早确立并细化分工,并在制作过程中时时同步自己的进度、问题及意见,避免进入合流阶段才猛然惊觉大家在做不同次元的事情。前期准备的重要性除了概念稿,针对相对场景较大的动画,分镜是节省时间的利器。在前期,故事分镜包括主体物动画及转场方式都需要尽可能地构想完整,避免一边建模一边想转场动画。虽然动画都可以在模型中试错,但是并非所有项目周期都足够充裕。尤其对于烧显卡,烧时间的3D动画,分镜能最大限度减少动画在试错过程中的不稳定性,降低时间与沟通成本。而细节性动画可以在项目过程中补齐完善,避免在前期花费太多时间陷入细节。每天都要比昨天更博学一点每学会一个好方法、好工具、好插件,我们就省出了至少一次睡眠机会。这次项目来得快准狠,在许多3D制作细节上有着从未触碰过的难点和雷区,而且这也是我们第一次使用Octane进行大场景的动画输出。攻坚难点除了不断的试错,更重要还是找到对的方法。从粒子云到体积云的过程中,我们反复阅读官方文档和浸泡技术论坛,才在大神的某条回复的某个词里找到答案,最终摸索出到适合项目的工作流与素材。另外日常也要保持接触新工具时的兴奋感和手感,每天都多学一点新思路,才能在接到紧急需求而又无实战经验时,知道该去哪里找解决方法。知取舍,有的放矢在项目初期,我们为了能展示最佳的视觉体验,一直在场景装饰和材质的质感上不断地叠加与细化。然而在对项目投放渠道、时间限制和制作效率的关系有了更深刻的理解后,我们决定把重心从细节回归到动画的整体性上:毕竟如果赶不上DDL,再精良的输出也只能是一张窝藏在电脑深处的飞机稿。新春是全民欢腾的伊始,而QQ空间新春品牌视频也是我们团队在3D动画上新的开端。感谢 大师、安琪、Sugar 和 Bell厂长 对本项目艰苦卓绝的贡献!最后放送几枚红红火火手机壁纸,祝福各位创意人今年方案必过,设计红火!感谢阅读,以上内容均由腾讯ISUX团队原创设计,以及腾讯ISUX版权所有,转载请注明出处,违者必究,谢谢您的合作。此文已由腾讯云+社区在各渠道发布获取更多新鲜技术干货,可以关注我们腾讯云技术社区-云加社区官方号及知乎机构号

February 22, 2019 · 1 min · jiezi

leetcode380. Insert Delete GetRandom O(1)

题目要求Design a data structure that supports all following operations in average O(1) time.insert(val): Inserts an item val to the set if not already present.remove(val): Removes an item val from the set if present.getRandom: Returns a random element from current set of elements. Each element must have the same probability of being returned.Example:// Init an empty set.RandomizedSet randomSet = new RandomizedSet();// Inserts 1 to the set. Returns true as 1 was inserted successfully.randomSet.insert(1);// Returns false as 2 does not exist in the set.randomSet.remove(2);// Inserts 2 to the set, returns true. Set now contains [1,2].randomSet.insert(2);// getRandom should return either 1 or 2 randomly.randomSet.getRandom();// Removes 1 from the set, returns true. Set now contains [2].randomSet.remove(1);// 2 was already in the set, so return false.randomSet.insert(2);// Since 2 is the only number in the set, getRandom always return 2.randomSet.getRandom();设计一个数据结构,使得能够在O(1)的时间复杂度中插入数字,删除数字,以及随机获取一个数字。要求所有的数字都能够被等概率的随机出来。思路和代码其实有几个思路入手:如何实现O(1)的插入这里数字的插入还需要能够去重,即需要首先判断该数字是否已经存在,已经存在的话就不执行任何插入操作。如果底层是一个一般的数组,我们知道查询的时间复杂度为O(n),明显不满足题目的意思。一个有序的数组能够将查询的时间复杂度下降到O(lgn),但是这依然不满足条件1,而且也无法做到所有的元素被等概率的查询出来,因为每插入一个元素都将改动之前元素的位置。而唯一能够做到O(1)时间查询的只有一个数据结构,即hash。因此,使用hash来查询时不可避免的。如何实现O(1)的删除这个其实是一个很经典的问题了,只要能够利用hash在O(1)的时间内找到这个数字的位置,就有两种方法来实现O(1)的删除,一个是利用伪删除,即每一个位置都对应一个状态为,将状态位社会为已经删除即可,还有一种就更有意思,就是将被删除位替换为数组最后一位的值,然后只需要删除最后一位就行。这种删除就无需将删除位右侧的元素全部左移造成O(n)的时间复杂度。这里我们采用的是第二种方法。如何实现O(1)的随机查询这个其实就是强调一点,我们需要维持原有的插入顺序,从而保证各个元素等概率被随机。综上所述,我们底层需要两种数据结构,一个hashmap来支持O(1)的查询,以及一个list来支持随机数的获取。代码实现如下:public class InsertDeleteGetRandom_380 { private List<Integer> list; private Map<Integer, Integer> hash; public InsertDeleteGetRandom_380() { list = new ArrayList<Integer>(); hash = new HashMap<Integer, Integer>(); } /** Inserts a value to the set. Returns true if the set did not already contain the specified element. / public boolean insert(int val) { if(hash.containsKey(val)) { return false; } list.add(val); hash.put(val, list.size()-1); return true; } /* Removes a value from the set. Returns true if the set contained the specified element. / public boolean remove(int val) { if(!hash.containsKey(val)){ return false; } int position = hash.get(val); if(position != list.size()-1) { int last = list.get(list.size()-1); list.set(position, last); hash.put(last, position); } list.remove(list.size()-1); hash.remove(val); return true; } /* Get a random element from the set. */ public int getRandom() { int position = (int)Math.floor((Math.random() * list.size())); return list.get(position); }} ...

February 15, 2019 · 2 min · jiezi

七个你没用过的炫酷开发工具推荐

本文翻译整理自youtube 7 Amazing Developer Tools that you’re not using yet1. BundlePhobiaBundlePhobia用于分析npm package的依赖、bundle后的大小、下载速度预估等等,帮助你在引用一个package之前了解引入该package的代价:你也可以将项目的package.json文件上传,BundlePhobia会帮你评估项目中所有包的大小和加载速度:2. CloudCraft如果你用AWS,那CloudCraft将会极大程度的帮助你,CloudCraft提供可视化的操作界面,通过拖拽设计你的云服务架构CloudCraft提供云服务价格的统计功能,帮你精打细算3. FigmaFigma是这张清单里面比较有名的了,对于习惯使用illustrator和sketch的设计师,figma也绝对值得尝试。Figma提供web和desktop两个版本,web版本使用WebAssembly编写从而获得不输desktop的性能,因此在不同的操作系统上都可以快速使用。Figma可以模拟各种用户输入事件,可以直接将设计稿导出成CSS、IOS样式、Android样式。4. Fontflipper在设计或者开发时还在为使用字体发愁的同学,可以试试Fontflipper。Fontflipper只有一个目的,就是让你选到最适合你的设计的字体,上传你的设计图,添加你的文字,切换不同的字体,收藏你喜欢的,就这么简单。缺点是没有中文字体。。5. VisBugVisBug是一款Google Chrome的插件,不久之前才推出。VisBug可以帮你更快的检查元素、移动元素、改变css属性、查找元素。。极大的增加前端开发效率!6. InsomniaInsomnia是一款调试API工具,支持调试Rest Api和GraphQL Api。在写graphQL query的时候有很好的智能提示。7. FlareFlare用于设计2D的动态图,使用体验与Figma相似。与codepen类似,你也可以看到其他设计师的公开作品祝大家工作愉快!

February 13, 2019 · 1 min · jiezi

【极简壁纸】桌面壁纸美图推荐_2019/01/27

极简壁纸是一个期望呈现出简单高效美观的壁纸网站。网站链接:https://bz.zzzmh.cn推荐几张最新更新的壁纸(图片发到这里会被压缩质量,建议访问网站下载原图)网站链接:https://bz.zzzmh.cn

January 27, 2019 · 1 min · jiezi

【极简壁纸】桌面壁纸美图推荐_2019/01/24

极简壁纸是一个期望呈现出简单高效美观的壁纸网站。推荐一批新更的壁纸网站链接:https://bz.zzzmh.cn网站链接:https://bz.zzzmh.cn(图片发到这里会被压缩质量,建议访问网站下载原图)

January 24, 2019 · 1 min · jiezi

【极简壁纸】桌面壁纸美图推荐_2019/01/23

极简壁纸是一个期望呈现出简单高效美观的壁纸网站。推荐一批近期的壁纸(图片发到这里会被压缩质量,建议访问网站下载原图)网站链接:https://bz.zzzmh.cn(图片发到这里会被压缩质量,建议访问网站下载原图)网站链接:https://bz.zzzmh.cn

January 23, 2019 · 1 min · jiezi

【极简壁纸】桌面壁纸美图推荐_2019/01/22

极简壁纸是一个期望呈现出简单高效美观的壁纸网站。推荐一批近期的壁纸(图片发到这里会被压缩质量,建议访问网站下载原图)网站链接:https://bz.zzzmh.cn(图片发到这里会被压缩质量,建议访问网站下载原图)网站链接:https://bz.zzzmh.cnEND

January 22, 2019 · 1 min · jiezi

【极简壁纸】简单高效美观的壁纸网站

极简壁纸是一个期望呈现出简单高效美观的壁纸网站。灵感来源是爱壁纸APP,图片来源是wallhaven.cc极简壁纸网站建立于2018年5月1日。起初是只是由于站长个人兴趣爱好,酷爱找各种壁纸。网站链接:https://bz.zzzmh.cn界面展示首页精选:近期最火的图片精选 (与wallhaven的toplist同步)入口:极简壁纸 > 精选小姐姐:小姐姐、妹纸等相关的图片入口:极简壁纸 > 小姐姐二次元:二次元、动画、漫画、游戏CG等相关的图片入口:极简壁纸 > 二次元自然:自然、风景、摄影作品等相关的图片入口:极简壁纸 > 自然标签:按照标签分类,可以分别查看单独标签下的图片入口:极简壁纸 > 标签喜欢:每张图片右下角都有一个红心,点击红心"喜欢"该图片,所有喜欢的图片默认保存在浏览器本地,登录后可与云端同步。入口:极简壁纸 > 喜欢关于我们入口:极简壁纸 > 关于我们END如果喜欢的话可以来看看,地址 bz.zzzmh.cn ,对于网站有什么意见建议也欢迎回复留言。谢谢!

January 21, 2019 · 1 min · jiezi

极简壁纸_桌面壁纸推荐_20190120

由于这里发图片会被压缩质量,建议访问极简壁纸官网下载高清大图极简壁纸官网 : https://bz.zzzmh.cn (9102年最潮壁纸网站)由于这里发图片会被压缩质量,建议访问极简壁纸官网下载高清大图极简壁纸官网 : https://bz.zzzmh.cn (9102年最潮壁纸网站)

January 20, 2019 · 1 min · jiezi

极简壁纸_精品桌面壁纸推荐_20190118

由于这里发图片会被压缩质量,建议访问极简壁纸官网下载高清大图极简壁纸官网 : https://bz.zzzmh.cn (9102年最潮壁纸网站)今日最热壁纸由于这里发图片会被压缩质量,建议访问极简壁纸官网下载高清大图极简壁纸官网 : https://bz.zzzmh.cn (9102年最潮壁纸网站)。

January 18, 2019 · 1 min · jiezi

阿里开发者们的第17个感悟:无细节不设计,无设计不架构

2015年12月20日,云栖社区上线。2018年12月20日,云栖社区3岁。阿里巴巴常说“晴天修屋顶”。在我们看来,寒冬中,最值得投资的是学习,是增厚的知识储备。所以社区特别制作了这个专辑——分享给开发者们20个弥足珍贵的成长感悟,50本书单。多年以后,再回首2018-19年,留给我们自己的,除了寒冷,还有不断上升的技术能力与拼搏后的成就感。云栖社区钉钉技术讨论群,已有5000+开发者。云栖社区2019年1月30+场活动预告【持续更新,欢迎加入】 学习,是一种氛围。*1月14日,无细节不设计,无设计不架构。这是我们送给开发者的第17个感悟。项籍,阿里巴巴新零售供应链平台服务决策平台负责人。在专家页中如此介绍自己:“多年互联网开发经验,从事业务开发、平台开发、架构设计、云计算、APM等领域。目前专注于供应链方向的解决方案治理和服务交易域”。作为问答频道活跃的达人,欢迎交流讨论。阿里陈帅(项籍):无细节不设计,无设计不架构阿里巴巴新零售供应链平台服务决策平台负责人没有恶心的业务和应用,只有恶心的设计。只有程序员自己能把自己当成资源,多关注总结和沉淀。工程师的使命是使世界更加优雅和飘逸。推荐的书单《运筹学》《模式识别》《Java并发编程实战》《平台革命》本文作者:云篆阅读原文本文为云栖社区原创内容,未经允许不得转载。

January 14, 2019 · 1 min · jiezi

十八款为设计师提供的免费工具

在大神博客上读到的几篇不错的文章。1. JavaScript可变长度柯里化(Variable length curring in JavaScript)这是一个有趣的编程挑战,reddit用户i7_leaf分享的一个面试问题。本文介绍的内容和原始问题有一个关键的区别。这个面试题要求面试者实现一个执行如下的功能:addSubtract(1)(2)(3); // 1 + 2 - 3 = 0addSubtract(1)(2)(3)(4)(5)(6); // 1 + 2 - 3 + 4 - 5 + 6 = 5值得注意的是,这个柯里化函数不会以任何形式的分隔符结束,例如,一个终止方法.execute()或者空参数()。让这个问题变得既困难又有趣的是缺乏终止信号。2. 十八款为设计师提供的免费工具(Free tools for designers)今天给大家分享一些为设计师提供的非常酷的免费工具。这是一组免费的资源,可以用于任何项目:Colormind.ioColors.couiGradientsPalettabThe Ultimate Collection of Google Font Pairings……3. 5步轻松理解JavaScript this (Five simple steps to understanding this in JavaScript)作为Web开发者,有一些关于JavaScript的工作原理需要知道。我们将讨论函数上下文的内部原理,this运算符就是其中一个很重要的部分。你可以找到很多关于this的解释,有些很好,有些不太好,但是这里只有一个目标:简短并且关键。4. 如何使用异或(XOR)运算找到数组中缺失的数?(A JavaScript Interview Question and a Digression into XOR)在一次Javascript面试中,有这么一个问题:假设有一个由0到99(包含99)的整数组成的长度为100的数组。从数组中随机选取一个元素,得到了一个长度为99的数组,那么请问如何找到所取出的数字是几?(假设数组未排序)。5. 如何使用PHP编写一个验证码识别器?验证码通常用于防止资源被机器人访问,但也可以通过OCR方法来破解这种方法。通过本文可以学习到如何使用PHP OCR来读取验证码上的内容。

December 19, 2018 · 1 min · jiezi

为什么前端工程师需要关注设计

博客原文在很久之前我就说过同样的话,表达过我觉得做为前端工程师而言设计素养的重要性,今天我想聊天为什么我有这种观点泛化的设计实际上生活中设计是中无处不在的,大到建筑工程、工业设计,小到网页设计、产品设计。我认为设计的本质就是 理解你(或者你的用户)内心想法的一个过程,在完成了一个物件的物理功能后,你需要考虑它的适用场景及多数用户的实用需求我在北京呆了很多年,你要问我对北京的印象是什么颜色,我会毫不犹豫的告诉你「蓝色」。有的人会认为是雾霾的灰色、有的人会认为是天安门的红色。为什么我的印象是蓝色呢,因为在北京无论你去哪儿都会选择公共交通,所有的交通标识牌都是蓝背景加白前景色,环路上的路标、地铁标、普通道路的路标,到处都会有蓝色的标识牌。使用蓝色的好处在于 标识性强,尤其对我这种视觉异常的人特别友好。但是却缺乏美感,因为要照顾大多数人的体验我也常去西安,你要问我对西安的印象是什么颜色,我也会告诉你是「暗红」。西安的地铁标识牌就是这种暗红,我也不太确定这种颜色准确的叫法,赤红或者朱红?总之这种颜色和西安这个城市的调性很搭。无论是古城门上的各种架梁、门柱、瓦石的着色,还是现代的地铁标识颜色,到处都有暗红色的设计。西安地铁标的设计虽然说是和整个城市的气质具有一致性,但是 识别性很差,尤其城市里面绿化比较好,树木多的时候绿色和这种红色标识交错在一起是很难分辨的从这个例子中我们可以了解到,其实设计并不是那种只存在于理论或者艺术世界里面的东西,大多数的设计都源于生活。都表达了人们对于生活的思考与理解狭义的设计狭义点讲前端工程师(程序员)们的日常是程序设计或者软件设计。有一个关于用户体验的真相是:大多数用户当他们不喜欢你的产品时,他们会 直接离开并放弃。用户的选择是正向的,他会因为你的软件好用选择,但 并不一定 会因为你的软件不好而批评反馈。所以我一直认为很多所谓的为了提高用户体验的调查问卷并没有什么作用。相反的很多反馈都是没有经过深思熟虑,或者是很个人的需求,这反倒会影我们的判断所以说代码设计的的好不好,交互是否流畅,体验是否极致。这个门槛的最后一步就在前端当然后端也很重要,后端的重要性是我们在这聊设计聊体验的前提。「仓廪实而知礼节」,很多前端在知乎提问类似「Node.JS 和 Java 相比…」的话题的时候却从来没想过这个问题,不过这个话题就不细聊了前端需要关注设计,原因有二:一、离用户更近。这个毫无疑问,前端在整个软件的系统栈里面是最顶部一个元素,他们写出来的代码第一用户是自己,一个功能好不好用前端会有第一知觉。同时这个也依赖于工程师对于设计体验的素养。很多东西是没法区分 逻辑上的好坏,同时有些东西应该是 不言而喻 的:页面的链接到底应该在当前面页打开还是新页签这就是一个典型的没法从逻辑上区分好坏的问题。当然所有页面都新窗口打开肯定是不对的。我认为 <base target="_blank"/> 在任何时时候都不应该被使用。看看自己每天使用的浏览器 tab 页的个数就明白了。实际使用的时候要根据用户的场景、喜好、链接去向内容、技术实现等各方面因素综合考虑,一刀切 的做法绝对是错误的弹出层、hover 提示 应该是尽量少的使用这就是不言而喻的,因为在 PC 端用户的鼠标是最常用的输入设备。鼠标的 mouseover 事件会产生很多误操作,浮层的显示这会骚扰用户的视觉。当然技术上我们可以通给 mouseover 事件添加延迟的方式来避免误操作的机率,但是我认为这是一种 打补丁 的解决方法,因为当一个提示信息足够重要的时候,任何延迟都是错误的,更何况打补丁还有副作用最近刚好发现一个笔记类应用「www.notion.so」,初次使用的时候感觉真的非常棒。设计精美、交互流畅、动画细腻,好的产品不就应该是这样的么但是当你深入使用的时候你会发现这个页面上充满了各个的 hover 效果,提示信息、状态切换等。它几乎在所有的图标上都加了 功能提示或快捷键的 hover 提示,这个在我看来就非常的骚扰用户。就比如左侧菜单的收起按钮使用了左箭头的图标「<」,这种图标就是不言而喻的,不需要再用 tooltip 来提示二、审美需求。这一点其实上是所有人都需要关注的,很多程序员在使用 macOS 一段时间后就再也没法忍受 windows 的界面了。单从审美诉求这一项讲,macOS 体现出来的简洁、专注是 windows 系统没有的。结合上面的问题可以思考下:为什么 macOS 系统的鼠标 hover 的交互很少?我觉得应该是操作系统给用户带来的那种稳定、可靠的感觉。当你专注的做一件事情的时候最好不要有任何形式的打扰,像系统通知、气泡提醒什么的应该完全被禁止很多人会认为程序员不需要审美,因为他们实现功能就行了。事实上甚至很多程序员也可能是这么想的。但是他们并没有意识到一点,即使是那种特别不关心审美的人也有基本审美的需求,或者说一个长像其丑无比的人也有基本审美的需求,爱美之心人皆有之。只是程序员这类群体写代码太久就会进入特别专注的状态,只在乎代码,忘了其它一些同样有价值的东西我想表达的意思并不是说这样不好,而是我认为在专注技术的前提下了解一些设计方面的东西会让我们理解别人(用户)的想法,这其实也是一种与外界的沟通形式,也能弥补程序员天生的弱点设计的规则很多对设计一知半解的人会说一句别人经过实践总结出来的真理:Rules are meant to be broken — 规则就是用来被打破的在《写给大家看的设计书》中就讲过这个问题,我是比较同意作者的观点,即:打破规则的前提应该是你足够了解规则是什么,意味着什么同时书中开篇分享了另外一个观点,我也很赞同:当你能叫出一个东西的名字后,这个东西就无处不在了这个估计很多人都会有这种体验,某一天某个人说了一个你以前从来没听过的词儿,然后你觉得这个词很新鲜,接着在后来一段时间内这个词就会不段的出现在你的周围作者的意思是,其实就是设计在很多人眼中遙不可及并不是因为它很高深,而是你没听过、没见过一些设计规则后面的东西就不聊了,读者有兴趣可以读下原著,书中提到的几个原则至今都在我的脑海里:亲密、对齐、重复、对比欢迎关注微信公众号「肆零玖陆」— 以程序员的视角谈天说地

December 4, 2018 · 1 min · jiezi

猫头鹰的深夜翻译:设计模式EventBus

前言今天,我们将介绍一个比较新的设计模式(也就是没有在GoF那本书中出现过的一种设计模式),这个设计模式就是Event Bus设计模式。起源假设一个大型应用中,有大量的组件彼此间存在交互。而你希望能够在组件通信的同时能够满足低耦合和关注点分离原则。Event Bus设计模式是一个很好的解决方案。Event Bus的概念和网络中的总线拓扑概念类似。即存在某种管道,而所有的电脑都连接在这条管道之上。其中的任何一台电脑发送的消息都将分发给总线上所有其它的主机。然后,每台主机决定是否接收还是抛弃掉这条消息。在组件的层面上也是类似的:主机对应着应用的组件,消息对应于事件(event)或者数据。而管道是Event Bus对象。实现并没有一种绝对正确的实现EventBus的方式。在这里我会简单的介绍两种方法。第一种方法这是比较经典的一种方法,它主要取决于定义EventBus接口(从而强制实现一个特定的协议),按需对其实现,然后定义一个Subscriber(另一份协议)来进行Event的处理。/** * interface describing a generic event, and it’s associated meta data, it’s this what’s going to * get sent in the bus to be dispatched to intrested Subscribers * * @author chermehdi /public interface Event<T> { /* * @returns the stored data associated with the event / T getData();}import java.util.Set;/* * Description of a generic subscriber * * @author chermehdi /public interface Subscribable { /* * Consume the events dispatched by the bus, events passed as parameter are can only be of type * declared by the supports() Set / void handle(Event<?> event); /* * describes the set of classes the subscribable object intends to handle / Set<Class<?>> supports();}import java.util.List;/* * Description of the contract of a generic EventBus implementation, the library contains two main * version, Sync and Async event bus implementations, if you want to provide your own implementation * and stay compliant with the components of the library just implement this contract * * @author chermehdi /public interface EventBus { /* * registers a new subscribable to this EventBus instance / void register(Subscribable subscribable); /* * send the given event in this EventBus implementation to be consumed by interested subscribers / void dispatch(Event<?> event); /* * get the list of all the subscribers associated with this EventBus instance / List<Subscribable> getSubscribers();}Subscribable接口定义了一个方法来处理一个特定类型的消息,并且通过定义supports方法决定支持哪种类型。EventBus的实现持有所有Subscribable对象,并且每当一个新事件触发dispatch方法时,通知所有的Subscribable对象。这种方案的有点事可以在编译时检查传递过来的Subscribable对象,而且更加符合面向对象的思想,因为无需使用反射。同时,可以看到,这种方案更容易实现。缺点是接口的强制性–你总是需要一个新的类来处理一种类型的Event,在项目初期这个问题可能不明显,但是随着项目发展,你会发现,新建一个类只是为了处理简单的逻辑比如日志或是数据分析会显得很冗余。第二种方法这个方法来源于Guava的实现。EventBus看上去更简单更好用,对于每个时间的consumer, 你只需要通过对一个方法加上@Subscribe注解,并且在注解的参数中传入你希望处理的对象类型(单个对象/参数)。然后你通过调用eventBus.register(objectContainingTheMethod)来注册事件的消费者。要产生一个新的时间,你只需要调用eventBus.post(someObject),然后所有相关的消费者都将会被通知。如果对应一个特定的对象没有对应的消费者怎么办?在guava的实现中,它们被称为DeadEvents,在我的实现中,post调用会被忽略。import java.lang.reflect.Method;import java.util.Arrays;import java.util.List;import java.util.Map;import java.util.Vector;import java.util.concurrent.ConcurrentHashMap;import java.util.stream.Collectors;/* * Simple implementation demonstrating how a guava EventBus works generally, without all the noise * of special cases handling, and special guava collections * * @author chermehdi */public class EventBus { private Map<Class<?>, List<Invocation>> invocations; private String name; public EventBus(String name) { this.name = name; invocations = new ConcurrentHashMap<>(); } public void post(Object object) { Class<?> clazz = object.getClass(); if (invocations.containsKey(clazz)) { invocations.get(clazz).forEach(invocation -> invocation.invoke(object)); } } public void register(Object object) { Class<?> currentClass = object.getClass(); // we try to navigate the object tree back to object ot see if // there is any annotated @Subscribe classes while (currentClass != null) { List<Method> subscribeMethods = findSubscriptionMethods(currentClass); for (Method method : subscribeMethods) { // we know for sure that it has only one parameter Class<?> type = method.getParameterTypes()[0]; if (invocations.containsKey(type)) { invocations.get(type).add(new Invocation(method, object)); } else { List<Invocation> temp = new Vector<>(); temp.add(new Invocation(method, object)); invocations.put(type, temp); } } currentClass = currentClass.getSuperclass(); } } private List<Method> findSubscriptionMethods(Class<?> type) { List<Method> subscribeMethods = Arrays.stream(type.getDeclaredMethods()) .filter(method -> method.isAnnotationPresent(Subscribe.class)) .collect(Collectors.toList()); checkSubscriberMethods(subscribeMethods); return subscribeMethods; } private void checkSubscriberMethods(List<Method> subscribeMethods) { boolean hasMoreThanOneParameter = subscribeMethods.stream() .anyMatch(method -> method.getParameterCount() != 1); if (hasMoreThanOneParameter) { throw new IllegalArgumentException( “Method annotated with @Susbscribe has more than one parameter”); } } public Map<Class<?>, List<Invocation>> getInvocations() { return invocations; } public String getName() { return name; }}可以看到这种方案所需要的额外工作比较少。你只需要定义方法的名称而不是为各个处理器命名。而且你可以将所有的消费者定义在一个类中。你只需要为每个方法传递不同的事件类型即可。 ...

November 12, 2018 · 3 min · jiezi