教您设计从 0 到 1 的业务系统
导读
本文将以一个案例,向读者逐步揭示一套业务系统从0到1的设计过程。重点讲述架构、模型等业务系统最本质的设计精要。
一、业务系统设计概述
1、什么是业务系统
互联网公司常常将产品方向分为两类,C端和B端,C端主要是面向客户和消费者的系统,B端的范围则相对模糊,给供应商或商家使用的系统,给内部业务人员使用的系统,都统称为B端系统。C端和B端系统建设的出发点和侧重点完全不同。C端系统偏重用户体验,强调感性,持续的数据分析优化,同一个按钮不同的摆放位置都要精心设计、论证,服务对象是个人;B端系统偏重流程、模块化,强调抽象和结构性,讲究整体的规划和体系设计,服务对象是组织和机构。
如果将B端系统进一步拆分,也可以分为两类,第一类是商家端,常见于双边模式的平台型互联网公司,例如淘宝的卖家管理系统,美团的商家管理后台;第二类是内部业务系统,支持企业经营、管理、业务运转。
本文所说业务系统,指B端产品线中的企业内部业务系统。虽然B端系统也可以分为两类,但因为都是面向业务的系统(Business),服务于组织而非个人,其设计思想和原理都是相同的,所以本文讲解的内容可以应用于所有B端系统的设计场景。
常见的业务系统包括ERP(EnterpriseResource Planning),CRM(CustomerRelationship Management),SCM(Supply ChainManagement),WMS(WarehouseManagement System),TMS(TransportationManagement System),OA(Office Automation),HRM(Human ResourceManagement)等等。因为绝大多数互联网公司都有独特的业务模式,所以很多时候类似于CRM、WMS、TMS这类系统都自主研发,OA、HRM这类系统由于业务模型区别不大,多数都会采购标准软件。有些互联网巨头也会自主研发OA、HRM。习惯上,CRM、WMS这类系统被称为业务系统,OA、HRM这类系统被称为内部协同软件,但两类系统之间也并没有非常清晰的界定。
如果从软件学的角度来看,所有软件系统分为两类,第一类是能够实时产生业务数据的系统,叫做OLTP(Online TransactionProcessing)系统,第二类是对数据进行加工、处理、探查、挖掘、展现的系统,叫做OLAP(Online AnalyticalProcessing)系统,很显然,业务系统属于OLTP的范畴。
当企业发展到一定阶段,业务系统对企业的高效管理运转具备不可替代的核心作用。例如,当一家公司只有几个销售人员时,客户资料用Excel即可管理。当销售发展到上千人时,必须通过一套OCRM系统进行管理。
总体来讲,业务系统对企业具有四点价值:提升管控能力、控制经营风险、降低运营成本、提升销售业绩。很多时候,业务系统建设好坏决定了企业的核心竞争力,例如外卖公司之间的竞争,配送员的效率是业务成败的决定因素之一,而配送员的效率取决于TMS系统建设的好坏。当然,TMS系统建设的好坏,包括了软件系统本身,以及配套落地的管理运营体系的执行。
2、为什么要学习设计业务系统
商业模式的创新是互联网行业最大的特点,商业模式的创新会带来业务模式的创新,业务模式的创新会带来运营、管理机制的创新。多数情况下,互联网公司独特的业务模式,导致无法采买市面上成熟的标准软件来支持业务,而作为技术驱动型企业,自主研发系统支持新业务成为不二的选择。
例如,滴滴公司,是无法在市面上找到一款成熟的司机管理运营软件的,要么找外包公司开发,要么自主研发,自主研发似乎更靠谱一些,这时,就需要有专业经验的资深产品经理,结合业务,从无到有设计一套司机(甚至是针对司机运营的机构)管理系统。
再例如,美团有大量的地推人员和客户需要管理,传统的OCRM软件根本无法支持美团这种强POI诉求的客户管理,因为业务模式特殊,即便采购成熟的OCRM做定制化开发,也难以使用。所以,只能靠自主研发一套全新的基于独特业务模式的OCRM来支持业务。
由此可以看出,互联网企业创新的本质,决定了必须有一批优秀的业务系统设计人员,能够结合公司特殊业务诉求,快速、合理的设计配套系统,并落地支持业务。业务系统的产品经理,要具备企业经营管理、软件系统设计的多方面经验和知识储备,才能设计合理的业务系统。
3、业务系统设计的流程
业务系统从无到有的设计,是有一套标准范式可以遵循的。实际上,随便一套《软件工程学》教程,讲述的都是业务系统的设计,但是软件工程已经不满足当前时代对专业人员的培养和要求。互联网时代下的软件设计,已经被拆分成多个细分职能,产品经理参与制定业务,设计应用功能;工程师负责技术架构,编码实施;而在传统软件工程中,这两项职能由一个角色承担。如今的现实情况是,软件设计人员更多的参与到了业务决策制定,软件研发人员越来越远离业务,只聚焦于技术。
即便如此,软件设计中的经典思路、方法论,是没有改变的。业务系统的产品经理,必须理解软件工程学中的部分核心要素,才能真正设计出靠谱的系统。
一般来讲,一套业务系统从0到1的构建,需要经历如下环节。
业务方案设计
PM和业务负责人一起梳理、制定业务流程、制度、机制,理解业务的问题点,并确定软件系统解决方案。
系统整体方案设计
PM结合业务诉求与目标,完成系统概要设计,包括界定业务、系统的边界,系统功能的抽象和演进蓝图,整体应用架构的设计,如何与公司已有系统拼接、交互。
系统细节方案设计
PM完成细节方案的所有设计,包括建模、角色、界面、权限等。其中建模是最难的部分,建模好坏决定了系统未来的灵活性、可扩展性。建模要求对业务的全面理解,极强的抽象归纳能力。
实施验收
PM对最终项目落地负责,系统上线后要展开持续的迭代优化,深度参与产品运营,数据分析等。
如果是从无到有设计系统,以上环节必须全面贯彻,尤其是架构设计和模型设计,是重中之重。
4、案例:某电商公司的渠道销售系统设计
本文将结合一个虚拟的案例,逐步论述,帮助读者理解以上所有的设计环节。
背景:
某电商企业A公司,成立5年,主营生鲜商品,以C端客户为主,业务稳定,系统建设成熟。
诉求:
公司在三个月前尝试开展分销业务,成立销售团队,开发分销商合作伙伴。业务试点在北京、上海开展,三个月以来发展迅速,现急需配套的软件系统提升业务效率,控制经营风险。
评估:
经公司管理层评估,目前分销业务月流水五十万,以月增长率20%的速度快速发展。在高速发展中若干流程、管理、风险问题突出,公司决定投入研发资源建设软件系统,支撑业务发展。
任务:
公司要求在2~3个月的时间内搭建出一套可以支撑分销业务2年高速发展的软件系统,提升效率,控制经营风险。项目期间CTO全力提供人力资源支持。
5、工作计划
作为项目负责人,某高级PM接到任务后,首先要理清工作思路,拆解任务,制定时间计划。只有严格遵循时间计划执行工作,才能保证整体工作有序展开,如期落地。根据经验和初步判断,产品经理制定了粗略的工作计划表如下。
时间紧,任务重,PM需要立即开展行动。当然,计划表中的研发周期,纯粹是一个粗拍的时间,具体实施周期要结合一期项目范围,以及人力投入,在立项时细化。
二、业务调研与业务方案
设计系统之前,必须透彻理解业务现状与业务目标,考虑如何结合系统改造、优化业务流程和模式。此阶段可以由一个高级PM带领几个初级PM完成。最好邀请技术负责人一起参与,有利于技术人员提前理解业务,为技术选型和方案设计做好准备。此外,技术人员具备更好的抽象能力,深入理解业务,可以让技术负责人协助PM共同完成整体方案设计和细节方案设计。
1、业务调研的方法
理解业务最好的方法,是轮岗参与业务环节。此外更加便捷快速的方法,是调研访谈。调研之前最好对业务能有大体的认知,安排好访谈的对象,提前准备好问题,让访谈更加高效。以下是针对分销业务的访谈计划和调研表。
主持人员:产品经理、研发经理
调研对象:业务负责人、一线主管、一线业务人员、合作伙伴
调研方式:
• 访谈
• 数据分析
调研目标:
• 了解业务模式和业务特点
• 了解业务目标和业务规划
• 了解当前业务运转方式
• 挖掘当前问题与痛点
2、业务调研总结
组织架构
通过调研,理清最基本的业务组织架构图,通过组织架构图理解管理体系和职能单元的设计,以及后续规划。
业务目标
对关键业务指标和目标需要有相应梳理。
业务流程
通过调研,梳理出目前的业务运作流程,如下图。
可以看出,目前业务开展以手工作业为主。下单配送环节依托于公司已有的系统实现。
问题梳理
基于目前手工作业流程,整理出如下业务问题。
- 手工下单容易出错,效率低;
- 生鲜实时变价,每次下单要根据折扣表手工计算价格;
- 无法实现客户总部集采,大区集采,城市集采,门店自采等混合采购模式;
- 不支持特殊分拣、配送要求;
- 账期客户不能及时控制回款进度和账期风险;
- 对账和开票工作复杂,大量数据表处理,容易出错;
- 当前流程一个运营专员只能跟进维护5个左右客户,每日处理10笔订单,人效极低;
3、基于业务调研的核心诉求分析
基于整体调研结论,总结出分销系统解决业务难题的核心诉求如下。
- 客户自主下单(高优);
- 系统自动定价(高优);
- 支持客户多门店分别定价与下单(高优);
- 对账报表(高优);
- 运营人员聚焦参数设置、审核和异常问题跟进(高优);
- 运营工作要下放到各城市分部(中优);
- 支持账期和预付款模式(低优);
- 系统实现账期风控(低优);
我们将业务主链路确定为高优诉求,将扩展功能或针对部分客户的小众功能,以及风控功能列为低优,和业务达成一致,一期项目聚焦核心流程的实现。
4、业务主流程设计
经过充分的沟通,设计出结合系统支持的核心业务流程。其中,涉及到客户开发、合同审核等前置流程,依然通过线下处理完成,未来考虑实现分销业务的OCRM系统进行支持,本次项目暂不考虑。
创建一套系统或平台,支持客户签约后的账号管理、价格管理、自主下单等功能。
三、系统整体方案设计
完成业务调研后,进入系统整体方案设计环节。该环节需要由经验丰富的PM以及公司的架构师一起探讨完成,因为方案涉及到和公司现有应用架构融合,还需要经过产品委员会或架构组的评审和确认。
1、系统定位
基于对业务的分析,考虑通过实现3套独立子系统来支持分销业务。
分销商城前台(H5):分销客户的下单工具
客户管理后台(PC):分销客户的子账号管理、门店管理及业务辅助工具
运营管理后台(PC):分销业务部门对客户及商品定价管理的业务支持工具
首先,客户希望能有一个便捷快速下单的工具,所以需要有一个手机版商城C端。考虑到投入产出比,通过H5来实现,具有独立域名,外网可访问。
其次,需要有一套方便操作的管理后台,因为涉及到大量的商品编辑处理,账号、门店管理等功能,所以考虑PC版本实现,暂不支持手机版。
最后,考虑到公司运营和客户管理员的管理诉求不尽相同,操作功能和页面差异较大,所以决定将管理后台拆解为两个独立的系统,给客户管理员使用的客户管理后台,具备独立域名,外网可访问;给公司管理人员和运营人员使用的运营管理后台,具备独立域名,仅限内网访问。
设计业务系统常见的问题,是为了图省事,把所有业务单元的功能糅合到一个系统中实现,造成管理的混乱,尤其是系统维护的混乱。一般来讲,系统的抽象要结合业务完成,独立的业务职能单元,要有各自独立的系统来配合使用。如果业务部门之间边界模糊,权责界定不清,也会导致系统之间存在模糊性。
清晰的系统定位,并划清边界,可以让彼此具备足够的独立性,是系统灵活性和可扩展性的基本前提。
2、整体架构设计
现在,需要考虑分销平台的三个子系统,如何与公司的整体应用架构融合问题。公司经过多年发展,系统架构体系已经非常完备,大量公共组建和模块可以复用,这样就减轻了新平台的实现成本和难度。分销平台只需要聚焦自己业务特殊独立的地方,其他公共组建和模块复用已有系统即可。
关于如何理解公司应用架构图,可参考本人之前的文章《从一个故事说起,谈谈企业应用架构的演变史》。
我们将确定的三个子系统,绘入简化版的公司整体应用架构图,如下。
深绿色部分是分销平台的三个独立子系统,墨绿色部分是涉及打通和复用的已有系统。
电商是公司的主营业务,有成熟的订单体系和仓配体系,分销业务的独特性在于前置客户管理维护,下单后的分拣配送业务流程都一样,所以分销商城的订单中心直接复用已有订单中心,订单写入后续的处理流程完全不变,只需要订单中心稍作改造即可支持,这样也可以保证整个订单台账、财务、仓储、配送基本都不需要重写或改造。另外分销平台的商品中心复用已有商品中心SKU数据,只是价格管理模块部分需要新做一套独立的,以支持特殊报价业务。
分销业务的账户体系、权限管理体系、在线支付,都利用已有系统实现,其中账户体系要做改造,支持子母账号管理,在线支付完全复用即可。
客户资料的存储,利用已有的客户主数据(MDM)实现,MDM改造较大,要新做一套企业客户数据模型。虽然是新做,但是在架构上,必须将客户资料作为主数据来建设,统一管理维护。
最后一个问题,既然公司已经有C端商城,为什么要单独再做一套针对分销客户的C端商城?经过分析评估,两套商城整体区别较大,如果对原有商城进行改造支持分销业务,第一工时投入比新做一套还要大,第二会影响主营业务系统的健壮性,因此最终决定新做C端商城支持分销业务。
3、功能抽象
基于对业务的分析,以及三套系统的定位,可以抽象并绘制完整的系统功能蓝图。
功能模块图,是对业务诉求系统化设计的进一步高度抽象。模块的设计,要体现出同一个业务职能单元中不同业务场景和操作的集合,模块也代表了系统中的一二级导航菜单的设计。常见的问题,是设计人员对模块设计的随意和混乱,以及后来新增功能的随意摆放,会造成用户使用系统时产生困惑,同时还会导致开发人员编码设计的混乱。
功能模块图,代表了设计师对业务和系统本质的理解和提炼,包含了对业务、系统未来发展的展望。我们常说,系统建设要有规划和节奏,实际上功能模块图就是一幅远景规划蓝图,是系统的骨架,决定了系统的整体结构,结合业务需求,每一个具体功能的实现,都是在对骨架不断地填充血肉,让他更真实,更立体,更丰富。
随着业务的开展,变化,功能模块图可能会有新的规划和调整,但如果业务单元的本质和模式没有变化,功能模块图不应该出现结构性的调整和改动。
4、演进蓝图
我们已经绘制了系统的功能模块图,体现了业务和系统规划的脉络,现在,让我们开始研究这套“体系”,大概需要几期实现,每期实现的侧重点是什么,也就是常说的演进蓝图,Roadmap。
白色部分,是一期的项目范围,聚焦解决最基本的业务流程线上化问题,以及最痛的痛点,例如对账功能。一期功能有一个原则,凡是可以手工处理和解决的问题,都不做系统支持。所以,类似于“报表”,可以定期跑sql实现;类似于“价格系数设置”,考虑到维护频率低,可以由RD在后台改数据库完成;类似于“搜索、推荐”,并不影响客户下单,因为根据调研目前每个客户维护的最多sku数量只有二十个,没有搜索功能并不会严重影响客户下单效率。
绿色部分,是二期的项目范围,二期将解决部分特殊业务刚需的诉求,例如要支持“预付款”模式,“账期”模式,“发票管理”,如果时间允许,可以一并实现若干报表查询功能。
蓝色部分,是三期的项目范围,三期将聚焦风险控制,并强化运营功能。一般来讲,很多互联网公司初期会先跑业务,走流水,验证可行性,成本和风险控制并不是特别在意,当业务具备一定规模时,则必须引入系统风控机制,做到事前、事中、事后的风险控制。此外,基于本案例B2B业务的特点,设计中并没有考虑太多的C端功能。实际上C端只需要保证客户能够方便下单,并做一些很粗的运营、通知即可。
四、系统细节方案设计
系统整体架构和蓝图设计完成后,进入细节方案设计环节。建模部分建议由高级PM和技术负责人共同完成,界面、权限设计可以由高级PM带领初级PM共同完成。
1、实体建模
实体建模是细节设计中最难,也是最重要的环节。实体建模代表将客观世界的对象,抽象成结构化的描述。实体建模有问题,会导致后续业务和系统完全丧失扩展性和灵活性,甚至会很快就无法支持业务,需要推倒重做。
实体建模实际上是数据库设计中最重要的部分,会影响数据库表结构的设计,但更多体现了对业务本质的理解和认知。很多产品经理常常忽略实体建模,只关注功能界面设计,最终会陷入逻辑的混乱和旋涡中。
只要模型清晰合理,功能设计、界面设计都是水到渠成的事。我们将结合案例,以客户模型设计为起点,详细阐述实体建模的设计思路。
理想化的客户模型
首先回顾客户诉求。目前的分销客户中,有比较大型的集团客户,下设若干省市机构和库房、门店。调研时,集团客户有如下诉求:
- 上海是*仓库,需要由上海采购员账号下单配送到上海*仓库;
- 广州天河区是*仓库,需要由天河采购员下单配送到天河*仓库;
- 广州其他区是门店自采,需要由各门店采购员下单配送到各门店;
- 广东省需要有一个高级别采购员账号,能够帮广东各仓库和门店代下单;
以上诉求,是业务系统建设中,最经典常见的树形组织机构管理诉求。不论是公司,还是客户,作为企业,都有多层级管理的要求,希望软件系统能够支持多层级业务体系。
多层级机构管理,通常使用组织机构树实现,在一颗树上绘制出业务的管理层级体系。我们将分销业务作为组织机构管理树的根节点,客户属于子树,树形结构可以体现出客户的行政管理层级结构。将账号和门店(收货对象,可以是*仓,也可以是店铺)作为叶子,挂在机构节点下。账号管理的数据范畴(包括能给哪些门店下单,能查看哪些门店的数据),可以遍历所在节点的子树来实现。绘制示意图如下。
通过组织机构树,结合功能权限配置,可以实现集团客户的管理诉求。上图中实际上存在三个对象,组织机构节点,账号,门店。通过实体建模ER图,可以描述出三者的关系,如下。
每个机构都有一个“上级机构”字段,通过该字段描述的关联关系,可以绘制出完整的组织机构树。每个账号或门店,只允许隶属于一个组织机构节点,每个门店下可以维护多个收货人。
实体建模的过程,就是将业务对象抽象,并描述之间的对应关系。例如以上ER图,看似简单,但却是对组织机构树以及账号、门店管理体系的高度抽象。如果实现以上模型,可以支持任意灵活地集团客户管理诉求。
简化版的客户模型
实现组织树模型,开发复杂度很高。经过和开发、业务沟通,最终决定采用一套简版的客户模型来支持一期业务,该简版模型在需要时完全可以升级到理想版的客户模型。
首先,和业务以及客户沟通确认,一期暂不支持复杂的行政层级管理,只需要给客户实现若干子账号可以管理若干门店即可,示意图如下。
这样系统只需要实现一颗非常简单的树,每个客户只有一个根节点而没有子节点,以便业务系统开发时不需要编写大量的遍历算法,大大降低了开发难度。
根据上述规则,将模型简化如下。
仔细观察可以发现,该模型与前一个模型相比,唯一的变化,是在账号和门店两个对象之间建立了关联关系,其他结构不变。实际上这样处理,保持了模型未来的扩展性。当未来需要全面实现组织机构管理时,将账号、门店之间的对应关系打断,在业务系统中实现遍历算法,以及组织树管理维护功能即可,整个数据底层基本不需要调整。
更丰富一些的客户模型
业务需求中很重要的一条,能够针对每个客户每个门店的个性报价,设置不同的系数表,结合时价动态计算商品价格。这里涉及到几个新的对象,系数表,报价单,为了让管理可控,系数表是全公司通用的多套参数集合,包括了商品和价格系数,给每个门店关联并且只能关联一个有效的报价单,报价单关联系数表,以保证运营人员只需要调整一次系数表,就能刷新到所有需要修改的门店的价格表。数据模型设计如下。
该模型体现了真实世界针对门店单独报价的场景,同时也体现了价格系数表的设计思路。
理清了账号、门店、机构、报价单、价格系数表之间的关系,功能设计都是水到渠成的事情。如果没有梳理清楚这些关系,功能设计、界面设计时必然是一头雾水,漏洞百出。
建模错误会导致扩展的灾难
最后,我们来看一个建模错误导致灾难的例子。如果我们将上图数据模型中,账号和门店的对应关系调整成一对多,如下。
设计人员可能会认为,目前的业务诉求很明确,一个门店只能被一个账号管理,所以账号和门店被设计成一对多关系。
如果有一天,客户明确并要求必须支持一个门店被多个账号管理,也就是要实现账号和门店多对多的设计。实现此诉求,难度将非常非常大,因为从数据底层,到前端功能实现,都认为是一对多结构,如果要改成多对多,首先底层数据库结构得调整,所有历史数据要处理,其次,基本上所有涉及到读取账号和门店关系的功能代码需要全部重写,看似简单的一个改造,会造成一场灾难。
设计人员应该在设计之初,就要做好设计的预判。即便早期业务诉求是一对多,但是模型要按照多对多设计,因为这是在现实世界中合理的一种逻辑存在。即便早期没有多对多管理的诉求,但只要模型和数据底层设计好,后续再调整会简单很多。
那么问题来了,是不是所有对象的关系,都应该设计成多对多就行了呢?也不对,比如门店和订单的关系,只可能是一对多,不可能是多对多,一个订单只能是一个门店提交的,现实世界中不存在门店和订单多对多的逻辑关系。
建模的难点和重点,就是将现实世界抽象成对象,描述其关联关系。如果这些对象和关系没有梳理清楚,流程、界面的设计都会是一笔糊涂账。
2、用户角色设计和流程图
在整个方案中,我们设计了4个角色,来支持业务。
电商公司分销业务部
- 分销管理员 – 负责业务稽查,审核,分公司账号的管理维护
- 分销运营 – 负责分公司客户的账号维护,报价管理
客户
- 客户管理员 – 负责下单账号和门店的管理、维护,订单查询,对账结算
- 客户采购 – 负责给门店下单
角色的设计,取决于业务对权责的划分。用户角色设计完成后,可以绘制更加详细的,基于系统的流程图,如下。
流程图(以及页面流转图)是所有软件界面设计的基本前提,清晰的流程图和各种异常情况的分支描述,可以让后续的界面设计事半功倍。如果没有清晰地流程图,界面设计绝对会陷入混乱。
3、界面设计
建模合理,流程清晰,界面设计会变的非常简单。网上关于界面设计的文章也非常多,方法论也很多,比如尼尔森十大可用性原则,读者可自行查阅,本文不再赘述,这里只讲几个建议。
模仿是最好的设计
研究并借鉴成熟的软件系统的设计,可以提升设计能力,少走弯路。网上有很多免费开放试用的系统,都可以用来参考,比如GoogleAnalytics,百度统计,管家婆云ERP,SalesForce等。结合你设计的软件形态,找到行业内相似的SASS软件,借鉴并参考其排版、布局,可以提高设计效率与合理性。
拒绝花哨的前端
业务系统,不需要花哨的前端,不需要创意的控件。有很多初入行的PM,喜欢在交互设计上做太多的发明创造,对于业务系统,价值不大,并且会增加研发的工作量。我曾经见过一个业务系统,把其中的多选控件做的异常复杂,多选框中隐含了其他的交互形态,导致前端需要耗费大量的精力去定制开发实现,实在没有必要。选用准的控件方案,可以节约PM和前端的大量时间。
什么叫标准的控件呢?MS Visio或Axure里提供的可以绘制的控件,就是标准控件。不要在这些标准控件以外去发明创造控件!
对于复杂一点的报表和仪表盘设计,推荐两个组件库,一个是百度的ECharts,一个是Eclipse Birt,里边包含了大量经典的设计方案,这两者都是开源的,可以直接拿来用。
4、权限设计
权限设计,是业务系统设计中最重要的一部分。权限设计代表了对整个业务体系岗位和流程的理解和拆解。
软件系统的权限设计包含两部分,功能权限和数据权限。功能权限是指不同角色可以操作的界面、按钮等等,例如某一个角色在订单查询页面能看到哪些字段,能操作哪些按钮;数据权限是指不同角色在同一页面中看到的数据范围,例如分公司管理员在订单查询页面能看到分公司的所有订单,而区域主管只能看到所在区域的订单。
功能权限设计的经典方法论是RBAC(Role Based AccessControl),描述了一套用户、角色、权限组的设计理念,简单的可以抽象为以下实体关系图。该理论具体的讲解,读者可在网络上自行查阅,请读者理解RBAC的数据模型图,可以看出,软件系统的设计,即便是权限管理体系设计,最终也都会归结抽象到数据模型的设计。由此可见,抽象建模能力,是PM必须掌握的核心技能。
我们将权限管理部分,进一步做一个延伸讨论。
假设我们实现了前文提到的完整的组织机构树,同时也有完善的权限控制体系,此时,系统可以完美的支持各种复杂的业务场景诉求。
我们在之前的角色设计中,新增一个角色“客户采购员2”,其中“客户采购员2”和“客户采购员1”的区别是,前者的数据权限范围,是查询用户当前所在组织机构树叶子上的数据,而后者能够查询用户当前所在组织机构树叶子,以及叶子下边所有子节点的数据。
客户的组织架构如下。
不同账号,所能看到的数据权限范围见下表。请读者结合上图和下表,自己做出判断,账号4能查看哪些门店的订单数据。如果您理解了这个案例中隐含的逻辑,则掌握了业务系统权限管理体系的主要核心思想。
5、技术方案与项目实施
产出PRD以后,进入了技术设计和实施环节。当然,对于一套全新的系统,技术设计可能很早就已经启动。再往后,就进入实施环节,以及上线后的持续迭代和产品运营环节。以后有机会单独介绍此部分话题。
六、总结
至此,我们结合一个实际案例,完整的介绍了一套系统从无到有的设计。介绍的重点是调研、架构、模块、建模、权限,对于交互、界面等细节一笔带过。实际上,文中已经多次强调,并且读者现在应该也有了充分的认识,抽象、流程、建模才是业务系统设计的重点和核心,只有将业务最本质的东西高度剥离并正确抽象,才能构建一套灵活强大的系统。
对于一名后端产品经理来讲,以下经验和技能必不可可少。
- 具备基本的商业、管理、运营常识;
- 理解商业模式、业务目标、组织、流程;
- 理解公司的企业应用架构和系统现状;
- 具备将客观世界抽象成架构、模块、模型的能力;
路漫漫其修远,后端产品经理的成长是一个厚积薄发的过程,需要长期的坚持、积累、思考。希望本文能够帮助读者对系统的设计有一个大体的认知和理解,并融入到工作中,形成更深层次的思考。
--------------------- 本文来自 PMCAFF产品社区 的**** 博客 ,全文地址请点击:https://blog.****.net/pmcaff2008/article/details/78651273?utm_source=copy
上一篇: 管家婆软件创建账套提示:创建账套失败
下一篇: 哪款 crm 软件最好?如何选择?
推荐阅读
-
35 岁实现财务*,腾讯程序员手握2300万提前退休?-1000万房产、1000万腾讯股票、加上300万的现金,一共2300万的财产。有网友算了一笔账,假设1000万的房产用于自住,剩下1300万资产按照平均税后20-50万不等进行计算,大约花上26-60年左右的时间才能赚到这笔钱。也就是说,普通人可能奋斗一辈子,才能赚到这笔钱。在很多人还在为中年危机而惶惶不可终日的时候,有的人的35岁,就已经安全着陆,试问哪个打工人不羡慕?但问题是有这样财富积累必然有像样的实力做靠山。没有人可以不劳而获。 看到这里,肯定有人说,那么对于普通人来说,卷可能真就成了唯一的出路。但是卷也有轻松的卷,“偷懒”的卷法,对于程序员而言,刨除掉一时无法改掉的开会传统占用的大部分时间,如何把有限的时间和精力放在真正重要的架构设计、需求设计上,而不是重复的造*,编码、改bug、手动测试。因此在科技改变生活的今天,学会使用AI工具成为程序员们的必备技能。 以全栈式全自动的软件开发工具飞算SoFlu软件机器人为例,作为全球首款面向微服务架构设计和最佳实践的软件机器人,SoFlu软件机器人改变了原来手工编码的作业模式,通过可视化拖拽方式以及参数配置就能实现等同于编写复杂代码的业务逻辑,在设计业务逻辑时就完成了微服务应用开发,做到“业务即图,图即代码”,实现“软件开发,十倍提效”。 而作为飞算SoFlu软件机器人的一个重要组成部分,FuncGPT(慧函数)支持所有类型函数创建。通过自然语言描述Java函数需求,实时生成高质量、高可读性的Java函数代码。生成代码可直接复制到IDEA,或一键导入Java全自动开发工具函数库。 FuncGPT(慧函数)具有五大核心能力: ● 自然语言:通过自然语言即可生成函数,降低软件开发门槛。 ● 秒级函数开发:全自动秒级开发函数,秒级完成,效率千倍提升。 ● 一站式函数开发应用:函数生成即可直接应用,效率、安全有保障。 ● 质量可靠:生成的函数代码符合业界规范、具备良好的可读性,符合最优解。 ● 灵活生成:可以根据开发人员的具体需求生成并支持调整和修改。 以“将文件流转换为File对象”这个需求为例,以下是FuncGPT(慧函数)秒级生成的代码: / 类名:FileConverter // 函数名:convertStreamToFile // 函数功能:将文件流转换为File对象 // POM依赖包:无 import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; public class FileConverter { /** * 将文件流转换为File对象 * @param inputStream 文件流 * @param filePath 文件路径 * @param fileName 文件名 * @return 转换后的File对象 * @throws IOException 如果发生I/O异常 */ public static File convertStreamToFile(InputStream inputStream, String filePath, String fileName) throws IOException { File file = new File(filePath + File.separator + fileName); // 创建File对象 try (FileOutputStream outputStream = new FileOutputStream(file)) { // 创建文件输出流 byte buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { // 从文件流读取数据并写入文件 outputStream.write(buffer, 0, bytesRead); } } return file; // 返回转换后的File对象 } } // 函数示例 // 将文件流转换为File对象示例 // 入参:inputStream,文件流 // 入参:filePath,文件路径 // 入参:fileName,文件名 // 出参:file,转换后的File对象 // 调用示例: // InputStream inputStream = new FileInputStream("example.txt"); // String filePath = "C:\\Users\\User\\Documents"; // String fileName = "example.txt"; // File file = FileConverter.convertStreamToFile(inputStream, filePath, fileName); // System.out.println(file.getAbsolutePath); // 输出结果:例如,将文件流转换为File对象后,文件的绝对路径为:C:\Users\User\Documents\example.txt // 则输出结果为:C:\Users\User\Documents\example.txt 通过分析,不难发现以上代码:
-
教您设计从 0 到 1 的业务系统
-
广联达:"数字建筑 "将推动建筑业向现代工业化水平迈进--一是全过程、全要素、全参与方的数字化。"数字建筑 "整合了人员、流程、数据、技术和业务系统,对建筑从规划设计到施工建设、运营维护的全生命周期进行管理。 二是数字化、在线化、智能化。这也是数字化建筑的三大典型特征。其中,数字化是基础,在线化是关键,智能化是目标。 三是新设计、新建设、新运维。试想,未来通过全数字化样板设计实现个性化最优方案,通过工业化施工提高效率精益求精,通过智能化运维提升建筑品质低碳宜居,将推动建筑业向现代工业化水平迈进。 广联达的一批标杆项目和应用案例备受关注。
-
纯干货分享 | 研发效能提升——敏捷需求篇-而敏捷需求是提升效能的方式中不可或缺的模块之一。 云智慧的敏捷教练——Iris Xu近期在公司做了一场分享,主题为「敏捷需求挖掘和组织方法,交付更高业务价值的产品」。Iris具有丰富的团队敏捷转型实施经验,完成了企业多个团队从传统模式到敏捷转型的落地和实施,积淀了很多的经验。 这次分享主要包含以下2个部分: 第一部分是用户影响地图 第二部分是事件驱动的业务分析Event driven business analysis(以下简称EDBA) 用户影响地图,是一种从业务目标到产品需求映射的需求挖掘和组织的方法。 在软件开发过程中可能会遇到一些问题,比如大家使用不同的业务语言、技术语言,造成角色间的沟通阻碍,还会导致一些问题,比如需求误解、需求传递错误等;这会直接导致产品的功能需求和要实现的业务目标不是映射关系。 但在交付期间,研发人员必须要将这些需求实现交付,他们实则并不清楚这些功能需求产生的原因是什么、要解决客户的哪些痛点。研发人员往往只是拿到了解决方案,需要把它实现,但没有和业务侧一起去思考解决方案是否正确,能否真正的帮助客户解决问题。而用户影响地图通常是能够连接业务目标和产品功能的一种手段。 我们在每次迭代里加入的假设,也就是功能需求。首先把它先实现,再逐步去验证我们每一个小目标是否已经实现,再看下一个目标要是什么。那影响地图就是在这个过程中帮我们不断地去梳理目标和功能之间的关系。 我们在软件开发中可能存在的一些问题 针对这些问题,我们如何避免?先简单介绍做敏捷转型的常规思路: 先做团队级的敏捷,首先把产品、开发、测试人员,还有一些更后端的人员比如交互运维的同学放在一起,组成一个特训团队做交付。这个团队要包含交付过程中所涉及的所有角色。 接着业务敏捷要打通整个业务环节和研发侧的一个交付。上图中可以看到在敏捷中需求是分层管理的,第一层是业务需求,在这个层级是以用户目标和业务目标作为输入进行规划,同时需要去考虑客户的诉求。业务人员通过获取到的业务需求,进一步的和团队一起将其分解为产品需求。所以业务需求其实是我们真正去发布和运营的单元,它可以被独立发布到我们的生产环境上。我们的产品需求其实就是产品的具体功能,它是我们集成和测试的对象,也就是我们最终去部署到系统上的一个基本单元。产品需求再到了我们的开发团队,映射到迭代计划会上要把它分解为相应的技术任务,包括我们平时所说的比如一些前端的开发、后端的开发、测试都是相应的技术任务。所以业务敏捷要达到的目标是需要去持续顺畅高质量的交付业务价值。 将这几个点串起来,形成金字塔结构。最上层我们会把业务目标放在整个金字塔的塔尖。这个业务目标是通过用户的目标以及北极星指标确立的。确认业务目标后再去梳理相应的业务流程,最后生产。另外产品需求包含了操作流程和业务规则,具需求交付时间、工程时间以及我们的一些质量标准的要求。 谈到用户影响的地图,在敏捷江湖上其实有一个传说,大家都有一个说法叫做敏捷需求的“任督二脉”。用户影响地图其实就是任脉,在黑客马拉松上用过的用户故事地图其实叫督脉。所以说用户影响地图是在用户故事地图之前,先帮我们去梳理出我们要做哪些东西。当我们真正识别出我们要实现的业务活动之后,用户故事地图才去梳理我们整个的业务工作流,以及每个工作流节点下所要包含的具体功能和用户故事。所以说用户影响地图需要解决的问题,我们包括以下这些: 首先是范围蔓延,我们在整张地图上,功能和对应的业务目标是要去有一个映射的。这就避免了一些在我们比如有很多干系人参与的会议上,那大家都有不同想法些立场,会提出很多需求(正确以及错误的需求)。这个时候我们会依据目标去看这些需求是否真的是会影响我们的目标。 这里提到的错误需求,比如是利益相关的人提出的、客户认为产品应该有的、某个产品经理需求分析师认为可以有的....但是这些功能在用户影响地图中匹配不到对应目标的话,就需要降低优先级或弃掉。另外,通常我们去制定解决方案的时候,会考虑较完美的实现,导致解决方案括很多的功能。这个时候关键目标至关重要,会帮助我们梳理筛选、确定优先级。 看一下用户影响到地图概貌 总共分为一个三层的结构: 第一层why,你的业务目标哪个是最重要的,为什么?涉及到的角色有哪些? 第二层how ,怎样产生影响?影响用户角色什么样的行为? (不需要去列出所有的影响,基于业务目标) 第三层what,最关键的是在梳理需求时不需一次把所有细节想全,这通常团队中经常遇到的问题。 我们用这个例子来看一下 这是一个客服中心的影响地图,业务目标是 3个月内不增加客服人数的前提下能支持1.5倍的用户数。此业务目标设定是符合 smart 原则的,specific非常的具体,miserable 是可以衡量的,action reoriented是面向活动的, real list 也是很实际的。 量化的目标会指引我们接下来的行动,梳理一个业务目标,尽量去量化,比如 :我们通过打造一条什么样的流水线,能够提高整个部署的效率,时间是原来的 1/2 。这样才是一个能量化的有意义的目标。 回到这幅图, how 层级识别出来的内容,客服角色:想要对它施加的影响,把客户引导到论坛上,帮助客户更容易的跟踪问题,更快速的去定位问题。初级用户:方论坛上找到问题。高级用户:在论坛上回答问题。通过我们这些用户角色,进行活动,完成在不增加客户客服人数的前提下支持更多的用户数量。 最后一个层级,才是我们日常接触比较多的真正的功能的特性和需求,比如引导到客户到论坛上,其实这个产品就需要有一个常见问题的论坛的链接。这个层次需要我们团队进一步地在交付,在每个迭代之前做进一步的梳理,细化成相应的用户故事。 这个是云智慧团队中,自己做的影响地图的范例,可以看下整个的层级结构。序号表示优先级。 那我们用户影响地图可以总结为:
-
小红书大产品部架构 小红书产品概览--经过性能、稳定性、成本等多个维度的详细评估,小红书最终决定选择基于腾讯云星海自研硬件的SA2云服务器作为主力机型使用。结合其秒级的快速扩缩、超强兼容和平滑迁移能力,小红书在抵御上亿次用户访问、保证系统稳定运行的同时,也实现了成本的大幅降低。 星海SA2云服务器是基于腾讯云星海的首款自研服务器。腾讯云星海作为自研硬件品牌,通过创新的高兼容性架构、简洁可靠的自主设计,结合腾讯自身业务以及百万客户上云需求的特点,致力于为云计算时代提供安全、稳定、性能领先的基础架构产品和服务。如今,星海SA2云服务器也正在为越来越多的企业提供低成本、高效率、更安全的弹性计算服务。 以下是与小红书SRE总监陈敖翔的对话实录。 问:请您介绍一下小红书及其主要商业模式? 小红书是一个面向年轻人的生活方式平台,在这里,他们发现了向上、多元的真实世界。小红书日活超过 3500 万,月活跃用户超过 1 亿,日均笔记曝光量达 80 亿。小红书由社交平台和在线购物两大部分组成。与其他线上平台相比,小红书的内容基于真实的口碑分享,播种不止于线上,还为线下实体店赋能。 问:围绕业务发展,小红书的系统架构经历了怎样的变革和演进? 系统架构变化不大,影响最深的是资源开销。过去三年,资源开销大幅增加,同比增长约 10 倍。在此背景下,我们努力进行优化,包括很早就开始使用 K8S 进行资源调度。到 18 年年中,绝大多数服务已经完全实现了容器化。 问:目前小红书系统架构中的计算基础设施建设和布局是怎样的? 我们目前的建设方式可以简单描述为星型结构。腾讯云在上海的一个区是我们的计算中心,承载着我们的核心数据和在线业务。在外围,我们还有两个数据中心进行计算分流,同时承担灾备和线上业务双活的角色。 与其他新兴电子商务互联网公司类似,小红书的大部分计算能力主要用于线下数据分析、模型训练和在线推荐等平台。随着业务的发展,对算力的需求也在加速增长。
-
趣谈留言队列,搞清楚留言队列到底是什么!-说到消息队列,洪觉大概能猜到人们听到消息队列的反应,大致可以分为以下几类人。 第一类人,懵懵懂懂,刚上大学接触编程,还没用过消息队列,甚至还以为消息队列就是代码里面要新建一个List之类的;第二类人,听过消息队列,了解消息队列,但具体是什么还不是太明白,只知道一说到消息队列,脑海里马上出现了三组词,削峰、异步、解耦;第三类人,用过消息队列,对它有一定了解,但不知道为什么要这样设计,消息队列有什么样的前世今生,是如何演化到现在的模式的?**第四类人,已经对消息队列有了足够的了解,可以阅读本帖作为复习和温习。**你属于哪一类?无论你对消息队列了解多少,读完这篇文章后,我相信你都会有所收获。 什么是消息队列?我们为什么要使用消息队列?真的只是因为它看起来很勉强、很常用吗?当然不是,一项技术的出现往往是为了解决某种痛点,我们就从这个痛点出发,看看消息队列到底是为了解决什么问题而诞生的。 相信大家在工作之前,或者工作中接触单片机的次数会多一点,不管什么业务都一股脑塞进一个系统里,这种情况下接触消息队列的场景会比较少。但随着业务的增长,量上去了,单机系统就很难维护了,也扛不住并发量的增长,就需要把原来的单体应用拆分成多个服务。例如,牛奇网采用分布式架构,将原来的单体系统拆分成用户服务、题库服务、求职服务、论坛服务等,每个分布式节点都有一个集群,保证高可用性。 那虽然在这样的微服务架构下,如果某个核心业务并发量过大,系统就扛不住了。比如淘宝、淘票票、拼多多、京东等电商场景中的支付场景,你在某宝下单并支付后,调用支付服务,完成支付后,还需要更新订单的状态,这个时候就需要调用订单服务,那我们平时也下单,除了简单完成这些操作外,还会给你相应的积分;商家也会收到订单消息,并给您发送旺旺消息,确认订单无误;同时,也会给您发送消息,确认订单无误。确认订单无误;同时您还可以查看您的物流状态;还有系统为了给您推荐更适合您的商品,会根据您的订单做类似的推荐等等,我说的这些都是当我们下单后,肉眼可以感知到系统所做的动作。 **一个支付动作如果还需要调用那么多服务,等他们响应成功,最后再告诉用户你支付成功了,用户在系统中的整个体验会非常糟糕。**设想一下,假设请求服务+处理请求+响应总共需要 50ms,我们上面列出的场景:支付服务、订单服务、积分服务、商家服务、物流服务、推荐服务,总共需要 300ms。
-
对话NGC蔡岩:从机制创新到价值沉淀,解析DeFi产品开发逻辑 |链捕手 - 真正的DeFi产品首先要有足够的安全性和稳定性,如果能在此基础上有一些功能创新,那就非常好了。像 Uniswap 这样逐渐成为 DeFi 基础架构的产品,可遇而不可求。 链式捕手:固定利率协议之前关注度比较高,但观察下来发现,大部分协议还是类似于传统金融CDO(抵押债务凭证)的玩法,风险系数很高,您如何理解这块业务的价值和风险? 蔡岩:确实有些定息协议类似CDO玩法,背后绑定一个债券,但并不是所有的定息协议都是这样的玩法,像这种CDO玩法的主要代表项目是88mph,背后绑定的是Aave、Compoud这样的借贷协议,在此基础上做定息和浮息债券;像APWine,背后同样是Aave,它会发行期货收益代币来锁定你的收益;Notional本身是做借贷市场的,在此基础上做定息协议。 非 CDO 的玩法,比如 Horizon,更像是一个利率撮合器,背后需要用户通过拍卖产生更合适的目标收益率;像 Saffron、BarnBridge 等是通过风险分级来定义不同的收益率。总的来说,创新还是挺多的。 价值层面是创新和想象力,因为在传统金融领域,比如银行做固定收益证券,或者评级机构给风险分级,这些业务都非常大,利润也很丰厚。而 DeFi 的对口业务给了类似业务很大的想象空间。尤其是固定利率协议的成熟产品不多,尝试各种微创新是很有意义的。 风险程度还是要具体到不同的玩法,比如,在 Aave、Compoud 等借贷协议的固定利率协议背后,如果这些借贷协议受到攻击,与之绑定的固定利率协议也会受损。 同样,如果自己做借贷市场,可能更需要更强的开发能力。再有,如果该程序的机制或参数设计不当,同样会导致协议运行不稳定,并可能造成大量用户清盘。 总的来说,风险在于固定利率协议的设计,这是一个非常复杂的过程,需要不断地尝试和出错。 链式捕捉器:刚刚提到背后是Aave/Compound的固定费率协议风险较大,您认为Aave最大的不确定性和创新点分在哪里? 蔡岩:其实爱钱进一直被认为是走在行业前列的项目,他们的迭代速度非常快,比如率先尝试闪贷、推出新的经济激励模式、推出目前业内首个安全模块、尝试L2解决方案等等。 而在主要的借贷业务上,他们又十分谨慎,比如在抵押率、清算系数等风险参数的设计上相对于其他借贷协议较为保守,并不会存在为了吸引更多借贷资金而降低风险的要求。 与许多 DeFi 项目一样,即使 Aave 进行了多次审计,也无法保证不存在漏洞。前段时间,Aave 刚进入 V2 阶段时,白帽黑客就指出了某个漏洞。 之前的创新点可能是闪电借贷,这是当时业内独一无二的新产品功能,也为 Aave 带来了不少收益。当然,也有人批评闪电贷只能方便黑客实现资金效益的最大化,但工具本身并没有错,未来闪电贷肯定会有更多的应用场景。 其次是安全模块的设计,这有点像项目本身的储备金库,保障项目的安全性,这也是爱维开创的先河。说实话,目前大多数项目都没有做到代币模式的良性或正向运营,也做不到像Aave一样的安全模块,这是一个不小的门槛。 Chaincatcher从某种程度上来说,挖矿模式是DeFi财富效应的根本支撑,但Aave的CEO却说挖矿机制带来的动力是不可持续的,您怎么看这个观点? 蔡岩:"挖矿机制 "不可能失效,因为它是一种激励机制,或者说是项目冷启动的一种方式。但流动性开采亚博体育手机客户端不会一直高涨。比如去年11月的流行性挖矿高APY持续了一两个月就崩盘了,导致DeFi市场大幅回调。 Aave、Uniswap、Synthetix等项目真正爆发进入市值前15名也是在今年2月,我更倾向于这是头部DeFi长期价值的体现。虽然大家都喜欢抢高APY的矿机,但我个人很少参与挖矿,所以我并不觉得流动性挖矿是DeFi的基本面支撑。
-
从 0 到 1 封装您的应用程序:Android 封装指南
-
41 个下载免费 3D 模型的最佳网站-使用说明:使用权限可能因型号而异。因此,在下载文件之前,请仔细检查每个下载页面上的许可证和使用权限。 17. Clara.io Clara.io 是一个创建 3D 内容的全球平台,也是一个培养新 3D 艺术家的社区。Clara.io 提供+100,000个免费的3D模型,包括OBJ,Blend,STL,FBX,DAE,Babylon.JS,Three.JS格式,用于 Clara.io,Unity 3D,Blender,Sketchup,Cinema 4D,3DS Max和Maya。 使用说明:免费,标准和专业帐户仅供个人使用,如果您需要将 clara.io 用于商业用途,请与销售团队联系。 18. 3DExport 3DExport是一个市场,您可以在其中购买和销售用于CG项目的3D模型,3D打印模型和纹理。它提供15 +不同的3D格式供下载,如3DS MAX(.max),Cinema4D(.c4d),Maya(.mb,.ma),Lightwave(.lwo),Softimage(.xsi),Wavefront OBJ(.obj),Autodesk FBX(.fbx)等。它还提供15种不同的语言! 使用说明:免费下载仅供个人和非商业用途。 19. 3D Warehouse 3D Warehouse是一个开放的库,允许用户共享和下载SketchUp 3D模型,用于建筑,设计,施工和娱乐!任何人都可以免费制作,修改和重新上传内容到3D仓库,您可以找到任何您能想到的东西,如家具,电子产品,室内产品等。 使用说明:3D Warehouse中的所有模型都是免费的,因此任何人都可以下载文件以用于SketchUp甚至其他软件,如AutoCAD,Revit和ArchiCAD。 20. CadNav.com CadNav是CGI平面设计师和CAD / CAM / CAE工程师的在线3D模型库,我们提供超过50000 +免费3D模型和CAD模型下载。在CadNav网站上,您可以下载高质量的多边形网格3D模型,3D CAD实体对象,纹理,Vray材料,3D作品,CAD图纸等。 使用说明:免费下载仅供个人和非商业用途。 21. All3dfree.net 就像网站名称一样,它提供免费的3D模型,还包括Vray材料,CAD块,2d和3d纹理集合,无需注册即可免费下载。它是不断更新的,因此您可以查找或请求3DS,MAX,C4D,skp,OBJ,FBX,MTL等格式的模型。 使用说明:所有资源均不允许用于商业用途,否则您将承担责任。 22. Hum3D 自2005年以来,Hum3D帮助来自3多个国家的80D艺术家节省3D建模时间,并制作逼真的3D模型,用于电影,视频游戏,AR应用程序和可视化。所有模型均由首席3D艺术家进行验证,他们检查其是否符合专业要求和最新的3D建模标准。 使用说明:免费下载仅供个人和非商业用途。 23. Artist-3D.com 艺术家-3D 库存的免费 3D 模型下载按通用类别排序。它为人体解剖学、汽车、家具、火箭、卫星等模型提供 AutoDesk 3DS Max 格式。您还可以在浏览他们的网站时找到教程和类似类型的建模。 使用说明:使用权限可能因型号而异。因此,在下载文件之前,请仔细检查每个下载页面上的许可证和使用权限。 24. Free the models 就像本网站的标题一样,它为3d应用程序和3d游戏引擎提供免费的内容模型。您可以为您的任何项目找到许多有趣且有用的模型!它提供3ds,wavefront,bryce,poser,lightwave,md2和unity3d格式的模型。还有一个很棒的纹理集合,可以在您最喜欢的建模和渲染程序中使用。 使用说明:您从这里下载的所有内容都可以免费使用,除非它不能包含在另一个免费的网络或CD收藏中,也不能单独出售。否则,您可以在商业游戏,3D应用程序或渲染作品中使用它。您不必提供信用,但如果您这样做,那就太好了。 25. Resources.blogscopia 本网站由一家名为Scopia的公司创建。他们制作3D图像和视频,您可以找到许多为CGI工作的信息架构设计的模型,所有这些都可以在现实生活中使用。您可以免费下载它们,但是,如果您想一次下载它们,您可以支付 3 到 9 欧元。 使用说明:您可以免费下载模型部分的所有文件。每个压缩文件都包含您也可以在此处找到的许可证。基本上,您可以对文件执行任何操作。唯一的限制是不归属于Scopia的重新分发。 26.ambientCG 1000+公共领域PBR材料适合所有人!环境CG是使用许多不同的方法和资产类型创建的,例如照片纹理(PBR),贴花(PBR),图集(PBR),照片纹理(普通),物质存档(SBSAR),雕刻画笔,3D模型和地形。您可以在所有项目中*使用它们! 使用说明:在 ambientCG 上提供下载的所有 PBR 材料、画笔、照片和 3D 模型均根据知识共享 CC0 1.0 通用许可提供。您可以复制、修改、分发和执行作品,即使是出于商业目的,也无需征得许可。信用将不胜感激。 不要满足于平庸的大理石纹理 - 立即使用我们的免费PBR大理石纹理升级您的3D设计。 27.Pixar One Twenty Eight 这是一个提供官方动画行业经典纹理的网站:皮克斯,创建于 1993 年,该纹理库包括 128 个重复纹理,现在免费提供。 它包含您来到的纹理,包括砖块和动物毛皮。肯定会有一些你可以使用的东西。 使用说明:皮克斯动画工作室的《Pixar One Twenty Eight》根据知识共享署名4.0国际许可协议进行许可。即使出于商业目的,您也可以重新混合、调整和构建您的作品,只要您以相同的条款对新创作进行信用和许可。 访问数以千计的免费纹理并提升您的设计游戏 - 立即开始下载! 28. 3DXO 即使有近 620 个免费贴纸可供下载,3DXO 也不是最大的资源,但它的内容非常有用,不需要注册。无论是简单的墙壁或地板,还是一些奇怪的小东西,您都需要的纹理都可以在此网站上看到。 使用说明:使用权限可能因型号而异。因此,在下载文件之前,请仔细检查每个下载页面上的许可证和使用权限。 29. 3DModelsCC0 3DModelsCC0 与其他产品的不同之处在于它包含超过 250+ 个高质量 3D 模型,并且本网站上的所有内容都是免费的,完全是公共领域!使用我们的模型时无需信用或归属! 使用说明:为每个人提供完全免费的公共领域内容。 30.Sketch up texture club Sketchup Texture Club是一个非营利性的教育和信息门户网站,由3D社区的图像促进协会管理,特别强调面向学生和建筑和室内设计专业人士的可视化和渲染技术,以及所有正在学习3D可视化的人。 使用说明:您无需支付版税或使用费。纹理可以免费下载和使用。不允许将纹理作为竞争产品出售或重新分发,即使图像被修改也是如此。 31. FlippedNormals FlippedNormal 是一个提供计算机图形和 3D 资产的市场,您可以找到许多用于雕刻、建模、纹理、概念艺术、3D 模型、游戏资产或课程的高级资产! 使用说明:使用权限可能因型号而异。因此,在下载文件之前,请仔细检查每个下载页面上的许可证和使用权限。 32. NASA 3D NASA 3D网站是一个在线门户,提供与太空和各种NASA任务相关的大量三维模型和模拟。该网站是用户友好的,并提供有关每个型号的详细信息。该网站允许用户探索和下载几种不同格式的模型,包括 OBJ、STL 和 FBX,只需单击下载按钮即可。 使用说明: 要下载模型,只需单击模型页面上的下载按钮并选择所需的格式。 33. 3DAGOGO (Astroprint) 3DAGOGO 是一个提供广泛 3D 模型的网站,包括角色、车辆和建筑物。3DAGOGO 的独特功能之一是它专注于适合 3D 打印的模型,使其成为希望创建物理原型或模型的设计师的绝佳资源。要使用 3DAGOGO,设计师只需在网站上搜索他们正在寻找的模型类型,然后下载 STL 格式的文件。 使用说明: 要使用 3DAGOGO,只需搜索所需的 3D 模型类型并下载 STL 格式的文件。根据需要自定义模型,并确保在将其用于商业目的之前检查使用权限。 34. FreeCAD FreeCAD是一款了不起的3D建模软件,可让您在计算机上创建令人难以置信的3D设计。该软件可免费下载和使用,它提供了广泛的工具和功能,可用于创建用于各种目的的3D模型。 该网站易于浏览,您可以找到开始使用FreeCAD的所有必要信息。此外,该网站还提供一系列教程和指南,可帮助您了解 3D 建模的来龙去脉。 使用说明: 要下载模型,请访问网站并从库中选择所需的模型。该网站还提供了一系列使用该软件的教程和指南。 35. Pinshape Pinshape是一个提供一系列3D打印模型的网站。网站上提供的型号质量很高,因此您可以确保您的最终印刷产品看起来很棒。该网站提供了广泛的模型,包括从家居用品到小雕像和珠宝的所有物品。 但这还不是Pinshape所能提供的全部!该网站还允许用户上传和共享自己的3D模型。这意味着您不仅可以下载出色的模型,还可以通过分享自己的设计为社区做出贡献。此外,Pinshape 提供了一系列自定义选项,因此您可以调整和调整模型以满足您的特定需求。 使用说明: 要下载模型,请在网站上创建一个帐户,搜索所需的模型,然后单击下载按钮。该网站还为每种型号提供了一系列定制选项。 36.Yeggi Yeggi 提供了大量免费的 3D 模型,您可以下载各种格式的模型,例如 STL、OBJ 和 FBX。该网站易于使用,您可以按关键字、类别或特定网站搜索模型。 Yeggi 对于任何寻找 3D 模型的人来说都是一个很好的资源。它提供了大量的模型集合,从日常物品到复杂的机械,以及介于两者之间的一切。该网站的收藏量在不断增长,每天都有新的型号增加。 使用说明: 要下载模型,请在网站上搜索所需的模型,然后单击下载按钮。该网站还提供指向托管模型的原始网站的链接。 37. Open3DModel 来自开放3D模型的图像 Open3DModel具有各种类别的模型,包括建筑,车辆和角色。无论您需要建筑物,汽车还是人的3D模型,都可以在此网站上找到。 该网站易于浏览,您可以按类别或关键字搜索模型。每个模型都附带预览图像和详细信息,例如文件格式、大小和多边形数量。此信息可以帮助您选择适合您需求的模型。 使用说明: 要下载模型,请访问网站,从库中选择所需的模型,然后单击下载按钮。 使用最好的 3D 资产管理工具简化您的 3D 制作流程。立即试用它们,将您的 3D 项目提升到一个新的水平! 38. 3DExport 对于那些为其 3D 设计项目寻找 3D 模型、纹理和其他资源的人来说,该平台是一个很好的资源。该网站有大量模型可供选择,包括 3D 打印对象、游戏资产等。用户可以按类别、文件格式或价格范围浏览,以找到适合其项目的完美资源。此外,3DExport 还提供一系列教程和其他 3D 资源,以帮助用户提高技能并创建更令人印象深刻的设计。 使用说明: 要使用 3DExport,只需创建一个帐户并浏览可用型号。您可以按类别、格式和价格进行搜索,以找到所需的型号。找到喜欢的模型后,只需下载它并开始在您的项目中使用它。 39.Blend Swap Blend Swap是一个社区驱动的市场,提供与Blender软件兼容的各种免费3D模型。该平台允许用户共享和下载模型、纹理和其他资产,以便在他们的项目中使用。 使用说明: 创建免费帐户后,您可以浏览社区上传的大量3D模型。当您找到要使用的一个时,只需下载它并将其导入您选择的 3D 软件即可。 40. 3DShook 3DShook 是一个高级 3D 模型市场,提供一系列用于建筑、游戏等各个行业的高质量模型。该平台提供基于订阅的模型,具有不同的定价计划,允许用户访问一系列模型。 使用说明: 注册免费帐户后,只需浏览3D模型库,选择您喜欢的模型,然后以您需要的格式下载它们。 41. Smithsonian X 3D 史密森尼 X 3D 对于正在寻找历史文物和文物的高质量 3D 模型的设计师来说,这是一个独特的资源。该平台提供了大量3D模型,这些模型是根据史密森尼博物馆和研究中心中的真实物体扫描创建的。 使用说明:
-
= 0; i--) {
printf("%5d", *(p + i));
}
printf("\n");
return 0;
}
```
2. 利用指针计算奇数索引数组元素之和
```c
// 使用指针计算奇数索引数组元素之和
#include
int main() { int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; int n = sizeof(arr) / sizeof(arr[0]); printf("数组元素: "); for (int i = 0; i < n; i++) { printf("%3d", arr[i]); // 宽度为3,右对齐 } printf("\n"); printf("数组下标: "); for (int i = 0; i < n; i++) { printf("%3d", i); // 宽度为3,右对齐 } printf("\n"); int sum = 0; int *p = arr; // 声明指向整数的指针 for (int i = 0; i < n; i++) { if (i % 2 != 0) { sum += *(p + i); // 若索引i为奇数,累加对应元素值 } } printf("奇数索引数组元素之和: %d\n", sum); return 0; } ``` 3. 查看不同类型指针在Linux Ubuntu gcc下的字节大小 ```c // 在Linux Ubuntu gcc环境下查看不同类型指针的字节大小 #include #include int main() { printf("int指针大小: %zu bytes\n", sizeof(int *)); printf("char指针大小: %zu bytes\n", sizeof(char *)); printf("float指针大小: %zu bytes\n", sizeof(float *)); printf("double指针大小: %zu bytes\n", sizeof(double *)); return 0; } ``` 请注意,对于现代64位系统(如Linux),`int`、`char`、`float`和`double`指针通常都是8字节。但在某些特定情况下(如32位系统或特定编译环境),可能有所不同。 4. 使用指针遍历并打印字符数组 ```c // 使用指针遍历并打印字符数组 #include #include // 引入strlen函数 int main() { char str[] = "Hello, World"; // 字符串常量 int len = strlen(str); // 获取字符串长度 char *ptr = str; // 定义指向字符的指针 printf("输出字符串: %s\n", str); // 输出原始字符串 printf("遍历并打印字符数组: "); for (int i = 0; i < len; i++) { printf("%c", *ptr); // 输出当前字符 ptr++; // 移动指针到下一个字符 } printf("\n"); return 0; } ``` 对于用户自定义输入字符串的情况,请参考以下代码: ```c #include #include int main() { char input[100]; // 用于存放用户输入的字符串,假设最大长度为100 printf("请输入字符串: "); fgets(input, sizeof(input), stdin); // 从标准输入读取字符串,fgets会保留换行符 int len = strlen(input) - 1; // 去掉fgets读取的换行符 char *ptr = input; // 定义指向字符的指针 printf("输入的字符串: %s\n", input); printf("遍历并打印字符数组: "); for (int i = 0; i < len; i++) { printf("%c", *ptr); // 输出当前字符 ptr++; // 移动指针到下一个字符 } printf("\n"); return 0; } ```"> 1. 使用指针倒序显示整数数组内容 ```c // 通过指针逆序打印整数数组 #include
#include #include int main() { int arr[10] = {0}; int n = sizeof(arr) / sizeof(arr[0]); srand(time(NULL)); printf("原始数组: "); for (int i = 0; i < n; i++) { arr[i] = rand() % 100; printf("%5d", arr[i]); } printf("\n"); int *p = arr; // 指针指向数组元素 printf("反转打印数组元素: "); for (int i = n - 1; i >= 0; i--) { printf("%5d", *(p + i)); } printf("\n"); return 0; } ``` 2. 利用指针计算奇数索引数组元素之和 ```c // 使用指针计算奇数索引数组元素之和 #include int main() { int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; int n = sizeof(arr) / sizeof(arr[0]); printf("数组元素: "); for (int i = 0; i < n; i++) { printf("%3d", arr[i]); // 宽度为3,右对齐 } printf("\n"); printf("数组下标: "); for (int i = 0; i < n; i++) { printf("%3d", i); // 宽度为3,右对齐 } printf("\n"); int sum = 0; int *p = arr; // 声明指向整数的指针 for (int i = 0; i < n; i++) { if (i % 2 != 0) { sum += *(p + i); // 若索引i为奇数,累加对应元素值 } } printf("奇数索引数组元素之和: %d\n", sum); return 0; } ``` 3. 查看不同类型指针在Linux Ubuntu gcc下的字节大小 ```c // 在Linux Ubuntu gcc环境下查看不同类型指针的字节大小 #include #include int main() { printf("int指针大小: %zu bytes\n", sizeof(int *)); printf("char指针大小: %zu bytes\n", sizeof(char *)); printf("float指针大小: %zu bytes\n", sizeof(float *)); printf("double指针大小: %zu bytes\n", sizeof(double *)); return 0; } ``` 请注意,对于现代64位系统(如Linux),`int`、`char`、`float`和`double`指针通常都是8字节。但在某些特定情况下(如32位系统或特定编译环境),可能有所不同。 4. 使用指针遍历并打印字符数组 ```c // 使用指针遍历并打印字符数组 #include #include // 引入strlen函数 int main() { char str[] = "Hello, World"; // 字符串常量 int len = strlen(str); // 获取字符串长度 char *ptr = str; // 定义指向字符的指针 printf("输出字符串: %s\n", str); // 输出原始字符串 printf("遍历并打印字符数组: "); for (int i = 0; i < len; i++) { printf("%c", *ptr); // 输出当前字符 ptr++; // 移动指针到下一个字符 } printf("\n"); return 0; } ``` 对于用户自定义输入字符串的情况,请参考以下代码: ```c #include #include int main() { char input[100]; // 用于存放用户输入的字符串,假设最大长度为100 printf("请输入字符串: "); fgets(input, sizeof(input), stdin); // 从标准输入读取字符串,fgets会保留换行符 int len = strlen(input) - 1; // 去掉fgets读取的换行符 char *ptr = input; // 定义指向字符的指针 printf("输入的字符串: %s\n", input); printf("遍历并打印字符数组: "); for (int i = 0; i < len; i++) { printf("%c", *ptr); // 输出当前字符 ptr++; // 移动指针到下一个字符 } printf("\n"); return 0; } ```