精华内容
下载资源
问答
  • 产品架构图通常用于比较复杂的产品项目中,是设计复杂产品时不可或缺的文档之一。在本文中,笔者也向大家介绍一下产品架构图的流程以及关键点,希望对你有所启发。一、什么是产品架构图产品架构图是产品经理用来...

    产品架构图通常用于比较复杂的产品项目中,是设计复杂产品时不可或缺的文档之一。在本文中,笔者也向大家介绍一下画产品架构图的流程以及关键点,希望对你有所启发。

    3ffb44b39aee07058ba8fe03784cd48c.png

    一、什么是产品架构图

    产品架构图是产品经理用来表达自己产品设计机制的一张概念图:

    它将可视化的具象产品功能,抽象成信息化、模块化、层次清晰的架构,并通过不同分层的交互关系、功能模块的组合、数据和信息的流转,来传递产品的业务流程、商业模式和设计思路。

    由于产品架构图通常用于比较复杂的产品项目中,目前介绍产品架构图的相关书籍和资料极少(尤其是入门级别的资料很少提及),却是设计复杂产品时不可或缺的文档之一。

    为什么要画?

    首先梳理自己对产品方向的判断,思考这张图如何设计的过程,也是帮助你梳理“半年内自己的产品该往何处去、需求应该如何分期和落地、和其他产品的依赖、竞争关系是什么、未来的可拓展性在哪里”等问题的过程。

    1. 为技术&运营的输出形成支撑

    当这张图被设计出来后,按照产品架构图的结构和路径,项目的里程碑(RoadMap)就可以被清晰的拆解出来,同时项目成员也可以根据这张架构图产出运营计划、技术系统架构方案等强依赖产品方向的方案。

    2. 让他人可视化的理解你的产品架构

    能较为清晰简单的呈现自己的思路、明确自己的产品边界、指明发展的方向,常用于在项目规划或项目总结中进行演示,帮助不了解你的产品的人快速的建立对你的产品结构、功能、复杂度的认知。

    二、何时需要画

    建议在复杂项目开始前写:

    当你要开始设计一个系统性、完整的需求时,如果跳过画产品架构图的步骤,直接开始画原型、写PRD,有时候很容易发生“改了又改”、“做了一版需求然后又推翻”的情况。如果你的项目已经进行到一半,自己却从未产出过这张图,那么就从此刻开始,按照下文的步骤尝试为自己的产品产出一张产品架构图吧。

    三、画前准备

    列出问题域

    在需求初期,产品经理得到的往往只是一句比较模糊的需求描述,它们可能来自于老板、运营或用户。

    直接把这句话作为核心产品功能是不恰当的,合理的做法是先把这个产品所有的问题域列清楚。

    “问题域”是指自己的产品能够解决的所有问题的空间集合。从核心需求出发,将所有当前需要解决、未来可能要解决的问题放入产品框架的范围,能够帮助你的产品架构图拥有更高的可拓展性,在后续具备迭代和优化的空间。

    以微信AR的需求为例,问题域是这样一个集合:

    dce9440ad1cee1ce6f614d9ba89eacdf.png

    详细操作步骤:

    1. 找到收到的需求中,跟产品形态、产品目标相关的词句,去列出“XX的流程会是什么样”、“XX该怎么达成”之类的问题,直到如果这些问题解决,能够实现核心需求的方向和业务目标。
    2. 去逐次寻找这些问题需求被解决的过程中,是否有其他要先解决掉的问题、或者其他跟业务相关的问题能够被解决/改善。
    3. 按照层级去罗列出所有的问题,并附上自己的初步回答,从而形成一个初步的、自己的产品能够解决的“问题域”。

    四、确定产品方向

    在经过问题域的罗列后,你应该能够得到一个模糊的产品方向和功能范围。把这些问题域的答案抽象总结成一个确定的产品需求。

    以微信AR的需求为例,根据问题域,我们发现需求不只是扫码组件增加AR识别能力这么简单,整个需求里需要引入广告主的角色,并且需要和腾讯等团队合作。最终得到的产品方向描述是这样的:

    cd53b1279d935fdc97f72b9ee9acbe54.png

    1. 详细操作步骤

    问题域的环节非常发散,这一步需要回归基础,把模糊的需求补充、拓展和翻译成一个在商业模式和用户体验上能够形成闭环的产品需求。

    1. 核心需求确定:我的产品核心解决的是哪批用户、哪个用户需求?
    2. 产品目标:如果以一个数字指标衡量我的产品,它应该是什么?
    3. 3.用户场景:核心需求基本的产品形态、用户使用的路径是怎样的?

    2. 清晰的业务流程

    这一步需要根据核心产品需求和问题域的答案,画出简单的业务流程。业务流程是产品设计中常见的图表,绘制方法就不再多做说明。

    以微信AR的需求为例,从广告主准备AR互动,到用户在前台使用摄像头参与互动,整个业务流程如下:

    546da99e8c06cbdd6bd9a719bc81ea06.png

    五、着手绘制

    1. 搭建基础框架

    基础的产品框架脱胎于业务流程,但相比业务流程,更加注重产品功能的枚举、功能模块之间的分界。

    2. 详细操作步骤

    对照业务流程,根据自己设想的产品机制、基本产品形态和用户的使用路径,列出需要的页面&功能&模块等前后端逻辑。

    将刚刚得到的多个流程图中所有功能类似或者范围有包含关系的机制/功能放在一起,以模块化的形式形成一张简单的矩阵图。

    将明显是同一个产品范围、同一组产品功能的模块放在同一层级,得到一个基础的产品框架。

    3. 明确架构分层

    一个具备前后台关系的产品架构图至少分为三层:用户感知层(在何种场景下通过何种方式触达用户)、功能模块层(通过哪些功能模块实现产品的核心功能、和哪些外部平台功能有信息交互)、数据层(产品的数据从哪里来、产品的数据沉淀到何处去)。

    在上一步进行简单分层后,我们已经得到一个初步框架,但是难免会有分层不明确的问题。此时需要按照两种维度来处理架构图的层级:不同信息层级的边界、同一层级内模块和模块的边界。

    4. 处理不同信息层级的边界

    架构图的层级表达的其实是信息之间的流转关系,不同信息层级之间一定是有逻辑关系的。

    其中用户感知层和数据层通常可以简化为一层(用户端的功能表达往往逻辑简单、数据的来源问题则不是自己产品的核心功能),而功能模块层则需要按照自己产品的逻辑去将功能模块层内的主要模块变成新的层级。

    5. 处理同一层级内子模块的边界

    各层次之间虽然相关,但同一层次内的子模块之间一定是互相独立、界限分明的。将解决不同问题的功能拆分成两个子模块,做到一个问题只在同一层解决,避免牵一发而动全身的情况出现。

    6. 明确产品间的边界

    产品边界对于开发设计系统架构、业务间的合作模式都非常重要。用不同颜色标识清楚产品框架中,各个部分所属产品的边界,通常其中属于自己团队的部分用亮色表示。

    01adc4a5689a9ff89e3826882a9260ac.png

    7. 加入信息流转机制

    产品架构图在表达产品的核心功能外,也应该体现信息流动的路径:当前层级数据的交互形成产品功能,产品功能又产生新的数据,从而推动下一层级的功能运转起来。

    如果当前产品的主要使用角色只有一个,则只需要用箭头标明模块间信息流动的方式即可。如果当前产品会涉及的主要角色比较多,则需要用不同颜色的线条将他们和各个模块之间的信息交互关系外化出来。

    4ccb1dc52999becc43748092afd51cea.png

    六、最终检查

    一张好的产品架构图,应该具备以下特点:

    1. 清晰的模块功能边界
    2. 功能经过抽象,做到标准化、互相独立
    3. 上下游产品功能边界清晰,架构分层明确合理
    4. 具备迭代优化的能力

    记得不断根据你的产品的发展情况来更新产品架构图,每次修改的过程对提升产品架构能力的帮助非常巨大。认真完成,才会成功。

    本文由 @寄书予影 原创发布于人人都是产品经理,未经作者许可,禁止转载。

    题图来自Unsplash,基于CC0协议

    展开全文
  • 系统架构图怎么画

    千次阅读 2015-01-24 14:56:17
    软件架构是一种无法以简单一维方式进行说明的复杂实体。 -Paul Clements 《软件架构编档》 正如上面提到,不同受众,比如用户、客户、开发人员、测试人员、运维人员,需要从各自工作角度去理解和使用架构。...

    软件架构是一种无法以简单的一维方式进行说明的复杂实体。 -Paul Clements 《软件架构编档》


    根据不同的受众,比如用户、客户、开发人员、测试人员、运维人员,需要从各自工作的角度去理解和使用架构。所以回答这个问题,需要首先了解这幅架构图画出来是给谁看,你想从那个维度去入手。
    确定了这个问题之后,再来了解架构视图有哪些维度和组成要素:
    1. 架构视图
    最经典的当属4+1视图:
    逻辑视图
    开发视图
    过程视图
    物理视图
    场景视图
    4+1视图提出后,业界也有其它的观点提出,诸如SEI(模块视图、组建和连接件视图、分配视图)、西门子4种视图(概念、模块、代码、执行视图)、以及RM-ODP(企业视图、信息视图、计算视图、工程师图)等。
    常见的视图除了上述4+1视图外还包括:数据视图、安全视图、实现视图等。


    2. 了解架构视图的四要素
    图示化主要元素和元素之间的关系
    具有明确的图例、定义和说明元素
    每个元素具备明确的接口和行为规范
    设计原理和设计决策的信息


    3. 简单说一下几个视图针对的角色和维度:
    逻辑视图一般针对客户、用户、业务人员、开发组织,主要从系统的功能元素、以及它们的接口、职责、交互维度入手。主要元素包括系统、子系统、功能模块、子功能模块、接口等。


    开发视图一般针对开发和测试相关人员,主要描述系统如何开发实现;主要元素包括描述系统的分层、分区、框架、系统通用服务、业务通用服务、类和接口、系统平台和大基础框架。用途是知道开发设计和实现。


    物理视图一般针对系统运维人员、集成人员,它是系统逻辑组件到物理节点的映射,节点与节点间的物理网络配置等,主要关注非功能性需求,诸如性能(吞吐量)、可伸缩性、可靠性,可用性等,从而得出相关的物理部署结构图。


    4. 了解这些,确定了你的受众和切入的维度后,你就可以决定你要用什么样的视图和视图组合来表达你的内容,挑选一个你得心应手的工具去实施就可以了。

    在我看来,用白板和团队一起画出来是一件极美的好玩的事情。


    方法:

    用剥洋葱的方法,一层一层来
    第一层:客户端,服务器
    第二层:客户端:可以用什么技术实现
    服务器:根据业务需求,需要怎样的服务器结构(比如,登录服务器、业务逻辑服务器(根据业务需求,可以拆分不同的业务逻辑服务器,数据库服务器(是否需要缓存服务器,根据业务需求来)))
    第三层:想清楚 每个服务器实现什么样的业务需求,客户端与服务器如何通信,服务器与服务器之间如何通信,用户数据与业务数据如何挂钩,数据存储与读取如何实现、用哪款数据库(单独还是几种数据库相配合,关系型还是非关系型,需不需要redis这种内存数据库做部分数据的缓存),客户端与服务端通信网络协议用什么(tcp还是udp),服务端之间通信网络协议用什么,数据库需不需要主从备份等等。

    展开全文
  • 关于架构的一些想法

    2020-11-17 13:31:25
    后来仔细想了一下原因,因为我的是当前我所了解的这个系统的架构图,但是因为各种原因,这套系统其实架构的不是很理想,功能和服务划分不清晰、架构上使用多种技术导致框架极其复杂、历经多次技术变迁留下很多坑,...

    最近想画一下系统架构图,怎么画都画不出来。
    后来仔细想了一下原因,因为我画的是当前我所了解的这个系统的架构图,但是因为各种原因,这套系统其实架构的不是很理想,功能和服务划分不清晰、架构上使用多种技术导致框架极其复杂、历经多次技术变迁留下很多坑,所以在这个基础上画架构图,永远画不出一个比较好的架构。
    所以正确的做法是什么?
    我觉得正确的做法,是根据自己对系统和业务的了解,画出一个即贴近当前业务需求和已有的架构,但更加理想的架构图。
    当画出这个图后,再去回看目前的架构,那样就能发现当前架构的问题、将来改进的方向,心中便有了一张图、一个方向,能够将自己的系统做的更好。
    而只有这样,才能够让自己更好的成长,这也算架构师的必经之路吧。
    所以有时候,正确的思路真的很重要,能够帮忙梳理清很多问题,而正确的思路来源于自己不断的努力学习与思考。

    展开全文
  • 从事IOS开发也有几年的时间,从刚開始最主要的语言、界面、逻辑,再到后面复杂点的线程、数据处理、网络请求、动画,最后到最复杂的底层音视频、图像算法、自己定义各种效果、网络底层处理。甚至是最后的性能:neon...
  • 假设现在要设计一个麦各类书籍的电子商务汪涵的(Shoping Card)系统,一个最简单的情况就是把所有货品的单价乘上数量,但是...由于有这样复杂的折扣算法,使得价格计算问题需要系统地解决。  那么怎么样才能解决这个

             假设现在要设计一个麦各类书籍的电子商务汪涵的(Shoping Card)系统,一个最简单的情况就是把所有货品的单价乘上数量,但是实际情况肯定要比这复杂。比如本网站可能对所有的教材类图书实行每本两元的折扣;对连环画类图书提供每本10%的促销折扣,而非教材类的计算机图书有5%的折扣;对其余书没有折扣。由于有这样复杂的折扣算法,使得价格计算问题需要系统地解决。

             那么怎么样才能解决这个问题呢?

             其实,解决方法不止一种,例如我们可以把所有逻辑放在客户端利用条件语句判断决定使用哪一种算法;也可以利用继承在子类里面实现不同打折算法;还可以利用策略模式将环境和各种算法分开,将具体实现与客户端解耦。

             实现这个策略的UML图如下:

             

                    抽象策略类(DiscountStrategy)

    package com.strategy.booksale;
    /**
     * 抽象策略类,定义了抽象算法
     * @author LLS
     *
     */
    abstract public class DiscountStrategy
    {
    	//抽象方法
        abstract public double calculateDiscount();
    }
    

     

             10%的折扣促销类(PercentageStrategy)

      

    package com.strategy.booksale;
    /**
     * 折扣销售图书类
     * @author LLS
     *
     */
    public class PercentageStrategy extends DiscountStrategy
    {	
    	//保存单价、数量、总额
        private double percent = 0.0;
        private double price = 0.0;
        private int copies = 0;
    
        public PercentageStrategy(double price, int copies,double percent)
        {   this.percent=percent;
            this.price = price;
            this.copies = copies;
        }
    
        public double getPercent()
        {
            return percent;
        }
    
        public void setPercent(double percent)
        {
            this.percent = percent;
        }
        //覆盖父类的抽象方法
        public double calculateDiscount()
        {
    		return copies * price * percent;
        }
    
    }
    

     

             平价打折类(FlatRateStrategy)

     

    package com.strategy.booksale;
    /**
     * 平价销售图书,不进行打折算法类
     * @author LLS
     *
     */
    public class FlatRateStrategy extends DiscountStrategy
    {
    	//保存图书单价、数量、总额
        private double amount;
        private double price = 0;
        private int copies = 0;
    
        public FlatRateStrategy(double price, int copies)
        {
            this.price = price;
            this.copies = copies;
        }
        
        public double getAmount()
        {
            return amount;
        }
    
        public void setAmount(double amount)
        {
            this.amount = amount;
        }
        //覆盖了抽象类的方法
        public double calculateDiscount()
        {
    		return copies * amount;
        }
    }

     

              不打折类(NoDiscountStrategy) 

    package com.strategy.booksale;
    
    public class NoDiscountStrategy extends DiscountStrategy
    {
        private double price = 0.0;
        private int copies = 0;
    
        public NoDiscountStrategy(double price, int copies)
        {
            this.price = price;
            this.copies = copies;
        }
    
        public double calculateDiscount()
        {
    		return price*copies;
        }
    }
    


     

                维护抽象类的引用

    package com.strategy.booksale;
    /**
     * 维护抽象策略类的引用
     * @author LLS
     *
     */
    public class Context {
    	//维护策略抽象类的一个引用
    	DiscountStrategy discountStrategy;
    	//传入具体策略对象
    	public Context(DiscountStrategy discountStrategy) 
    	{
    		this.discountStrategy=discountStrategy;
    	}
    	//根据具体策略对象调用其方法
    	public void ContextInterface()
    	{
    		discountStrategy.calculateDiscount();
    	}
    }
    


     

             客户端测试类(Test)

           

    package com.strategy.booksale;
    
    public class Test {
    	public static void main(String[] args)
    	{
    		//维护抽象策略类
    		Context context;
    		//采用平价打折,单价为10元,数量5本
    		context=new Context(new FlatRateStrategy(10, 5)); 
    		//采用百分比打折10%
    		context=new Context(new PercentageStrategy(10, 5,0.1));
    		
    	}
    }
    


              这样利用策略模式已经解决了多种打折的问题,但是你有没有发现策略只是实现了在不同打折方法或不同算法行为之间得灵活切换,并没有控制实例化哪一个算法,需要用哪一个优惠方式是由客户端决定的,所以客户端与具体的实现类之间耦合性很大,还需要进一步解耦。

              策略模式更注重于n选1的情况,这也就是说如果我想组合几种不同的打折策略,策略就会显得不恰当,因为你需要将多个打折方法都写到一个类里面去,为解决这种情况,可以配合装饰(Decorator)模式一起使用。

               装饰模式适合给一个类添加额外的职责,并且对客户端透明。

               我们来看一张表示装饰模式的图,这张图即表明了它的添加功能特性也它的透明性。

              大家很容器想到简单工厂,它就是一个封装产生对象的过程的类,通过传入字符串的方式决定实例化哪一个类,但是它也有不足,如果我们需要加入新的打折策略时,就需要改动工厂里面的代码,这违反了OCP原则。

              我们可以利用反射来动态决定实例化哪个策略,配置文件和反射类如下:

              配置文件设置

     

    <?xml version="1.0" encoding="UTF-8"?>
    <config>
    	<!-- 标签 -->
    	<strategy-class>
    		<!-- 折扣策略类 -->
    		<strategy id="com.strategy.booksale.DiscountStrategy" class="com.strategy.booksale.PercentateStrategy"></strategy>
    	</strategy-class>
    </config>

                      反射类

    package com.strategy.booksale;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import org.dom4j.Document;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    
    /**
     * 反射类
     * @author LLS
     *
     */
    public class Reflection{
    	
    	//采用饿汉式单利模式,可能占内存
    	private static Reflection instance=new Reflection();
    	
    	//系统缺省配置文件名称
    	private final String sysconfig="sys-config.xml";
    	
    	//保存具体策略键值对
    	private Map strategyMap =new HashMap();
    	
    	//读取出来的document对象
    	private Document doc;
    	
    	private  Reflection()
        {
    		try {
    			doc=new SAXReader().read(Thread.currentThread().getContextClassLoader().getResourceAsStream(beansConfigFile));
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	//得到实例 的方法
    	public static Reflection getInstance() {
    		return instance;
    	}
    	
    	/**
    	 * 根据策略 编号,取得的具体策略
    	 * @param beanId
    	 * @return
    	 */
    	public synchronized Object  getStrategyObject(Class c)
    	{
    		//判断serviceMap里面是否有service对象,没有创建,有返回
    		if (strategyMap.containsKey(c.getName())) {
    			return strategyMap.get(c.getName());
    		}
    		//返回指定ID的Element对象
    		Element strategyElement=(Element)doc.selectSingleNode("//strategy[@id=\""+c.getName()+"\"]");
    		
    		String className=strategyElement.attributeValue("class");
    		
    		Object strategyObject=null;
    		try {
    			strategyObject = Class.forName(className).newInstance();
    			strategyMap.put(c.getName(), strategyObject);
    			  
    		} catch (Exception e) {
    			e.printStackTrace();
    			throw new RuntimeException();
    		}
    		
    		return strategyObject;
    	}
    }


                       改写后的客户端如下:

    package com.strategy.booksale;
    
    public class Test {
    	public static void main(String[] args)
    	{
    		//维护抽象策略类
    		Context context;
    		//利用反射动态决定使用哪一种打折策略
    		DiscountStrategy discountStrategy=(DiscountStrategy)Reflection.getInstance().getStrategyObject(DiscountStrategy.class);
    		//客户端只需要识别策略抽象类即可,与具体的算法解耦
    		context=new Context(discountStrategy);
    	}
    }


                 这样一来客户端完全不知道有什么算法,也不知道该实例化哪一个,减少了客户端的职责。

                 最后,我们用装饰模式来解决策略不可以组合多个打折方式的不足,装饰模式的主要作用即可以给一个对象动态添加多种功能,下面是我画的类图,有了类图代码可以自己实现,让它们共同实现了同一个抽象类。

                         左边部分是装饰模式负责动态组合各种打折方法,右边是策略模式动态选择其中一种打折策略,之所以它们的功能可以一起使用,这里是因为他们实现了一个共同的接口 (Interface)。

                 有些问题如果我们站在接口或抽象类的角度去考虑,用接口和抽象的方式去思考,有时问题会容易解决一些,而不要一直在某个具体的类范围内考虑问题,即把思考的角度范围扩展,从高层次考虑更容容易解决下面层次的问题。

                 思想上移一些,站在这个问题的更高一层。

     

     

    展开全文
  • 最近写报告做ppt时候...平时没怎么画过类图,但为了体现后端系统的复杂性还是使用了类图作为证据。如果要手画一个一个类,那我估计已经凉了。构建项目时候,不说别,拿数据库表映射类来说,基本上就是一张表,一
  • 这是一个典型B2C网上商城,使用经典的复杂三层架构(工厂模式)进行开发。涉及图书管理、搜索、订单管理、导航管理等核心模块。在讲解ASP.Net基础后安排这样一个B2C网上商城系统,让学员在实际项目中将学到知识...
  • 很敬佩哪些想想就能出整个系统UML图的人,因为他们头脑中有整个软件架构的蓝图,这样在编写实现时候,就会知道哪个地方改怎么做,哪个地方如何扩展。  而想成为架构师,UML也是必备技能。这里就根据《大象...
  • 软件工程教程

    热门讨论 2012-07-06 23:10:29
    架构图--包图变形 任务4 UML动态建模机制 对象之间交互 状态图 交互图 活动图 四种图运用 软件模型与现实 模型与现实要匹配 对象之间交互 简单消息 同步消息 异步消息 同步且立即返回消息 什么...
  • 2017年由于组织架构的变动,我们组被拆分到360导航,所以我就变成360导航一名前端工程师;2018年就是去年,因为公司是W3C会员,所以我就加入了W3C性能工作组。 <p><img alt=...
  • 在介绍 Java 怎么学之前我给大家介绍一下学完了能干什么,因为有目标学习才是最高效。 Java 这门语言,在公司里根据分工不同衍生出了众多岗位或者技术方向。 我在 boss 直聘上搜索了 BAT 等大厂岗位,目前有...
  •  EzraSchwartz是一名信息和用户体验架构师,擅长研究复杂用户界面框架逻辑。他专注于研究全球化企业应用程序、团队协作策略、UX需求追踪,并为多版本分步实施项目制定规格文档。  Ezra帮助客户将快速UX原型...
  • asp.net知识库

    2015-06-18 08:45:45
    Asp.net 利用OleDbGetOLEDBSchemaTable方法得到数据库架构信息 用于 Visual Studio .Net IBM DB2 开发外接程序 第2章 并发操作一致性问题 (2) Using sqlite with .NET Visual Studio 2005 中新 DataSet ...

空空如也

空空如也

1 2
收藏数 40
精华内容 16
关键字:

复杂的架构图怎么画