精华内容
下载资源
问答
  • 体系结构设计 案例 1-Software Architecture Document,软件体系结构设计的标准文档 英文版
  • 体系结构设计 案例 2-Course Registration System Software Architecure document.doc ) 软件体系结构设计标准规范
  • 软件体系结构设计模式 一【实验目的】 理解设计模式基本概念 掌握主要的设计模式 二【实验内容】 1. 简单工厂模式 1)理解案例1,然后完成2)部分的实验 我们将创建一个 Shape 接口和实现 Shape 接口的实体类。下...

    软件体系结构设计模式

    一【实验目的】

    1. 理解设计模式基本概念
    2. 掌握主要的设计模式
      二【实验内容】
      1. 简单工厂模式
      1)理解案例1,然后完成2)部分的实验
      我们将创建一个 Shape 接口和实现 Shape 接口的实体类。下一步是定义工厂类 ShapeFactory。
      FactoryPatternDemo,我们的演示类使用 ShapeFactory 来获取 Shape 对象。它将向 ShapeFactory 传递信息(CIRCLE / RECTANGLE / SQUARE),以便获取它所需对象的类型。

    步骤 1
    创建一个接口:
    Shape.java

    public interface Shape { 
    void draw();
     }
    

    步骤 2
    创建实现接口的实体类。
    Rectangle.java

    public class Rectangle implements Shape {
     @Override 
    public void draw() { 
    System.out.println("Inside Rectangle::draw() method."); 
    	} 
    }
    

    Square.java

    public class Square implements Shape {
     @Override 
    public void draw() {
     System.out.println("Inside Square::draw() method."); 
    } 
    }
    

    Circle.java

    public class Circle implements Shape { 
    @Override 
    public void draw() { 
    System.out.println("Inside Circle::draw() method."); 
    } 
    }
    

    步骤 3
    创建一个工厂,生成基于给定信息的实体类的对象。
    ShapeFactory.java

    public class ShapeFactory { 
    //使用 getShape 方法获取形状类型的对象 
    public Shape getShape(String shapeType){ 
    if(shapeType == null){
     return null; 
    } 
    if(shapeType.equalsIgnoreCase("CIRCLE")){ 
    return new Circle(); 
    } 
    else if(shapeType.equalsIgnoreCase("RECTANGLE")){ 
    return new Rectangle(); 
    } 
    else if(shapeType.equalsIgnoreCase("SQUARE")){ 
    return new Square(); 
    } 
    return null;
     } 
    } 
    

    步骤 4
    使用该工厂,通过传递类型信息来获取实体类的对象。
    FactoryPatternDemo.java

    public class FactoryPatternDemo { 
    public static void main(String[] args) { 
    ShapeFactory shapeFactory = new ShapeFactory(); 
    //获取 Circle 的对象,并调用它的 draw 方法 
    Shape shape1 = shapeFactory.getShape("CIRCLE"); 
    //调用 Circle 的 draw 方法 shape1.draw(); //获取 Rectangle 的对象,并调用它的 draw 方法 
    Shape shape2 = shapeFactory.getShape("RECTANGLE"); 
    //调用 Rectangle 的 draw 方法 shape2.draw(); //获取 Square 的对象,并调用它的 draw 方法 Shape shape3 = shapeFactory.getShape("SQUARE"); 
    //调用 Square 的 draw 方法 
    shape3.draw()
     } 
    }
    

    步骤 5
    执行程序,输出结果:
    Inside Circle::draw() method.
    Inside Rectangle::draw() method.
    Inside Square::draw() method.

    2、工厂方法

    2)以案例1简单工厂模式为启发,利用工厂方法模式思想,编程实现 下面例子的工厂模式
    工厂模式也就是鼠标工厂是个父类,有生产鼠标这个接口。
    戴尔鼠标工厂,惠普鼠标工厂继承它,可以分别生产戴尔鼠标,惠普鼠标。

    步骤一:
    创建一个接口

    public interface Mouse {
        void sayHi();
    }
    

    步骤二:
    创建实体类实现接口

    public class HpMouse implements Mouse{
        @Override
        public void sayHi() {
            System.out.println("sayHi:惠普鼠标");
        }
    }
    
    public class DellMouse implements Mouse{
        @Override
        public void sayHi() {
            System.out.println("sayHi:戴尔鼠标"); }
    }
    

    步骤三:
    创建鼠标工厂抽象类

    步骤四:
    创建实体类工厂继承抽象类并实现抽象方法

    public class DellMouseFactory extends MouseFactory{
        @Override
        public Mouse creatMouse() {
            return new DellMouse();
        }
    }
    
    public class HpMouseFactory extends MouseFactory{
        @Override
        public Mouse creatMouse() {
            return new HpMouse();}
    }
     
    

    步骤五:
    使用该工厂创建对应的实体对象

    public class MouseFactoryDemo {
        public static void main(String[] args) {
            MouseFactory DellMouseFactory=new DellMouseFactory();
            Mouse dellMouse=DellMouseFactory.creatMouse();
            dellMouse.sayHi();
            MouseFactory HpMouseFactory=new HpMouseFactory();
            Mouse HpMouse=HpMouseFactory.creatMouse();
            HpMouse.sayHi();
        }
    }
    

    2.理解抽象工厂思想,然后用一个例子来体现抽象工厂模式,并编程实现
    例子说明:
    假如我们要创建红色圆形、红色三角形、蓝色圆形、蓝色三角形四个对象,如果我们用工厂方法模式的话,这样一来我们系统中会增多非常多的工厂类,那么通过抽象工厂方法就可以解决这个问题,抽象工厂方法就是将对象等级和族进行分类,比如所有正方形为一个等级,所有红色形状为一个族。
    下面是实现抽象工厂方法代码:
    步骤一:
    定义公共抽象接口并定义不同形状的具体实现类

    public interface Shape {
        public void draw();
    }
     
    

    将不同的形状声明为抽象类(等级划分)并实现公共的抽象接口(Shape)

    public abstract class Circle implements Shape{
        @Override
        public abstract void draw();
    }
    
    public abstract class Rectangle implements Shape{
        @Override
        public abstract void draw();
    }
    

    实现各自的抽象类

    public class RedCircle extends Circle{
        @Override
        public void draw() {
            System.out.println("创建红色圆形对象!");
        }
    }
    
    public class BlueCircle extends Circle{
        @Override
        public void draw() {
            System.out.println("创建蓝色圆形对象!");
        }
    }
    
    
    public class RedRectangle extends Rectangle{
        @Override
        public void draw() {
            System.out.println("创建红色长方形对象!");
        }
    }
    
    
    public class BlueRectangle extends Rectangle{
        @Override
        public void draw() {
            System.out.println("创建蓝色长方形对象!");
        }
    }
    
    

    步骤二:
    定义抽象工厂接口,并根据族(颜色)实现抽象工厂接口

    public interface ShapeFactory {
        Shape getCircle();
        Shape getRectangle();
    }
    
    
    public class RedShapeFactory implements ShapeFactory{
        @Override
        public Shape getCircle() {
            return new RedCircle();
        }
        @Override
        public Shape getRectangle() {
            return new RedRectangle();
        }
    }
    
    
    public class BlueShapeFactory implements ShapeFactory{
        @Override
        public Shape getCircle() {
            return new BlueCircle();
        }
        @Override
        public Shape getRectangle() {
            return new BlueRectangle();
        }
    }
    
    

    步骤四:
    测试代码

    public class AbstractFactoryDemo {
        public static void main(String[] args) {
            ShapeFactory redShapeFactory=new RedShapeFactory();
            redShapeFactory.getCircle().draw(); //创建红色圆对象并执行方法
            redShapeFactory.getRectangle().draw();//创建红色长方形对象并执行方法
            ShapeFactory blueShapeFactory=new BlueShapeFactory();
            blueShapeFactory.getCircle().draw();//创建蓝色圆对象并执行方法
            blueShapeFactory.getRectangle().draw();//创建蓝色长方形对象并执行方法
        }
    }
    

    说明 简单工厂,工厂方法和抽象工厂 的特点
    简单工厂:
    优点:1、不需要关心类的创建细节。
    2、减轻类之间的耦合依赖,具体类的实现只是依赖于工厂,而不依赖于其他类。
    缺点:1、扩展复杂,当简单工厂需要生产出另外一种产品的时候,需要扩展工厂的内部创建逻辑,比较有可能引起大的故障。
    2、由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻集中到了一个工厂类中。
    工厂方法:
    优点:创建一个工厂接口和创建多个工厂实现类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。这样就实现了开闭原则。首先完全实现‘开-闭 原则’,实现了可扩展。其次实现更复杂的层次结构,可以应用于产品结果复杂的场合。工厂方法模式是对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不在负责具体的产品生产,而是只制定一些规范,具体的生产工作由其子类去完成。在这个模式中,工厂类和产品类往往可以依次对应。即一个抽象工厂对应一个抽象产品,一个具体工厂对应一个具体产品,这个具体的工厂就负责生产对应的产品。
    抽象工厂模式:
    抽象工厂模式中我们可以定义实现不止一个接口,一个工厂也可以生成不止一个产品类,抽象工厂模式较好的实现了“开放-封闭”原则,是三个模式中较为抽象,并具一般性的模式。
    优点:抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。
    缺点:产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。

    3. 观察者模式

    当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。
    主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
    何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。
    如何解决:使用面向对象技术,可以将这种依赖关系弱化。
    关键代码:在抽象类里有一个 ArrayList 存放观察者们

    理解观察者模式思想,然后用一个例子来体现观察者模式,并编程实现
    例子说明:
    微信公众号中订阅了公众号,当公众号所有者发送推文的时候,会通知所有订阅了该公众号的所有用户,这个情景可以用观察者模式实现。
    代码如下:
    1、首先创建抽象观察者抽象接口,并创建具体观察者实现接口

    public interface Observer {
        void getInfo(String str);
    }
    
    public class User1 implements Observer{
        private String name;
        public User1(String name){
            this.name=name;
        }
        //定义订阅者1
        @Override
        public void getInfo(String text) {
            System.out.println(name+"收到推文:"+text);
        }
    }
    
    
    public class User2 implements Observer{
        private String name;
        public User2(String name){
            this.name=name;
        }
        //定义订阅者2
        @Override
        public void getInfo(String str) {
            System.out.println(name+"收到推文:"+str);
        }
    }
    
    

    2、创建被观察者抽象方法,并创建实体类继承抽象方法,定义添加观察者方法和移除观察者方法,定义通知观察者方法

    import java.util.ArrayList;
    import java.util.List;
    
    public abstract class Subject {
        public List<Observer> users=new ArrayList<>();
        public void addUser(Observer user){
            users.add(user);
        }
        public void removeUser(Observer user){
            users.remove(user);
        }
        public abstract void notifyObserver(String str);
    }
    
    

    定义实体类继承抽象目标,并实现抽象方法,使得所有观察者接收到信息

    public class Manager extends Subject{
        //管理员发送推文,各个订阅者接收到推文
        @Override
        public void notifyObserver(String str) {
            for(Observer user:users){
                user.getInfo(str);
            }
        }
    }
    
    

    测试代码

    public class WeiXinObserverDemo {
        public static void main(String[] args) {
            Subject manager=new Manager(); //创建被观察者
            User1 user1=new User1("渣渣林"); //创建观察者1
            User2 user2=new User2("波波波"); //创建观察者2
            manager.addUser(user1); //添加观察者1
            manager.addUser(user2); //添加观察者2
            manager.notifyObserver("推文:今天是个好日子!"); //观察者做出反应
        }
    }
    
    

    遇到的问题:在写工厂的三种模式时候,搞不清三种工厂模式的区别以及各自的优缺点,并且不熟悉三种方法的代码具体该怎么写。对抽象工厂模式比较陌生,对抽象工厂模式的分类以及分族不是很了解。
    解决方法:不了解工厂方法的三种模式,就去网上分别看了三种方法的解释以及具体代码实现,并且熟练敲了很多遍,基本已经熟练掌握。
    实验感想:在学了设计模式之后,我发现代码不能只是简单地实现功能了,而是代码要能够轻松地实现扩展功能,而不能改变其中已经定义好的内部逻辑。可以增加代码而要尽量避免修改代码。学习了设计模式之后虽然代码的复杂度变高了,但是对于代码以后的功能扩展确实铺了一条好路。

    展开全文
  • Java软件体系结构设计模式标准指南 压缩文档包括(PDF + PPT + 课程源代码 + chm文档) 第一部分 设计模式简介 第二部分 URL 第三部分 基本模式 第四部分 创建模式 第五部分 集合模式 第六部分 结构模式 第七部分 ...
  • 软件体系结构设计-1

    千次阅读 2019-02-19 17:55:16
    软件体系结构设计-1声明引言教材成绩设计工具案例 声明 《软件体系结构设计》课程笔记 授课老师 周立新 引言 教材 设计模式 黑皮书 **软件构架实践 第三版 ** 参考 软件构架编档 Paul Clelments 软件体系结构 M....

    软件体系结构与设计-1

    声明

    《软件体系结构与设计》课程笔记
    授课老师 周立新

    引言

    教材

    设计模式 黑皮书
    **软件构架实践 第三版 **
    参考
    软件构架编档 Paul Clelments
    软件体系结构 M. Shaw and David Garlon
    面向模式的软件体系结构 卷1
    BS架构用什么改造的?

    成绩

    分组作业(1个)50 设计模式笔试(6次课)20 期末笔试30

    设计工具

    Rational Software Architect
    AcmeStudio
    下次课装好

    案例

    大型项目开发需要软件架构能力

    展开全文
  • 文章目录体系结构设计体系结构设计过程分析关键需求和项目约束选择体系结构...案例的初步设计的分析连锁超市管理系统最终的软件体系结构逻辑设计方案物理包设计原则概述共同封闭原则共同重用原则重用发布原则无循环依赖...

    体系结构设计

    体系结构设计过程

    过程为:

    1. 分析关键需求和项目约束
      搞清楚体系结构的输入是什么
    2. 选择体系结构风格
    3. 进行软件体系结构逻辑设计
    4. 依赖逻辑设计进行软件体系结构设计
    5. 完善体系结构设计
    6. 添加构建接口
    7. 迭代过程3-7

    说明:

    1. 整个过程可以分为两步骤:逻辑设计(1-3)和物理设计(4-6),其中3-4是从逻辑设计到物理设计的转化
    2. 迭代过程是为了不断完善软件体系结构设计

    分析关键需求和项目约束

    1. 图示
    2. 体系结构的输入:功能需求,非功能需求(质量、性能、约束、接口,项目约束等
    3. 不同程度的系统考虑输入(需求)范围不同:
      简单系统可能只考虑功能需求——功能齐全就好
      商业产品——加入项目约束的考虑(钱、人、物、时间等)
      复杂产品——加入非功能性需求的考虑
    4. 实践案例

      需求:
      概要功能需求:10个功能
      非功能性需求:安全需求(Security1~3);约束IC2
      项目约束:
      开发技术:Java
      时间较为紧张
      开发人员:不熟悉Web技术

    选择体系结构风格

    1. 实践案例

      本例中,协议较为清晰,采用分层风格
      分层风格:协议不变情况下易于修改;能够促进并行开发
      实际的并行开发(以逻辑、数据、展示分层为例):分三拨人员分别开发

    进行软件体系结构逻辑设计(抽象)

    依据概要功能需求与体系结构风格建立初始设计

    概述

    1. 此步骤目标:将需求分配到子系统和模块
    2. 什么样的需求分到同一模块或子系统?
      考虑功能的相同性:不同任务但是相同功能
      考虑可复用性:结构、数据、行为的可复用性(如对同一数据进行操作的行为可能被放在一起)

    实践案例

    1. 精简示例
      销售与退货:互为逆向过程,属于同一功能
      产品调整、入库、出库与库存分析:都是对库存数据的增删改查——行为复用
      会员发展与礼品赠送:会员数据的操作
      销售策略
    2. 精简结果
      基本功能:销售、库存、会员、销售策略、用户
    3. 确定功能对应的逻辑包
      注意起名字最好统一格式
      每个功能都有三层,各有一包
    4. 确定好功能对应的逻辑包后,考虑每个功能依赖的数据(需要依赖这些包中的哪些)
    5. 根据每个功能设计的包的信息产生初步设计方案(包图)

      这个方案中
      存在很多复杂的依赖关系
      如SaleUI要用到逻辑层4个包的数据——这在开发时,就意味着做展示层的某人要与做逻辑层的好多人都要打交道,代价过大
      又如数据层就集中在一个数据库包上,数据库压力大
    6. 改进包的结构后的初步设计方案

      这个方案中
      每一个展示层包只和一个业务逻辑包相连;每一个业务逻辑包只与他对应的数据包进行交互;数据分不同包——实现层间包交互是一对一的
      数据层分包的好处:如果某个数据层包发生改变,那么对上层的影响也只是一个包
      此时的SaleUI包还是需要获得好多逻辑层包的数据,他们不直接相连,而是SalesUI对应的逻辑层包负责与逻辑层其他的有数据需求的包相连进行联系,这就实现了开发中的跨足沟通(代价大)转化为组内沟通(代价相对小)

    使用非功能性需求与项目约束评价和改进初始设计

    对上述案例的初步设计的分析

    1. 能够满足项目约束(项目约束)
      分层风格能够促进并行开发,从而缩短开发时间
      分层风格可以使用Java技术,而不使用Web技术
    2. 无法满足安全需求和网络分布约束,所以需要改进(非功能需求)
      为使其满足安全需求,可以增加用户登录与验证功能,可以建立专门的三个模块(Presentation, Logic, Data),也可以将该功能并入用户管理功能,即为userUI,user,userData三个模块增加新的职责

    连锁超市管理系统最终的软件体系结构逻辑设计方案


    增加了用户登录包(逻辑层里)
    做出决策:展示层与逻辑层放在客户端,数据层放在服务器端
    逻辑层与数据层(客户短语服务器端)通过RMI相交流
    这就体现了项目约束、非功能需求对架构的更改

    物理包设计原则

    概述

    两类原则

    1. 内聚性原则:关注点在于包的内聚性,如何重用、变更;如何让包的内部具有更强大的联系,变得高内聚
      共同封闭原则(CCP)
      共同重用原则(CRP)
      重用发布等价原则(REP)
    2. 耦合性原则:关注点在于包的耦合性,如何使包与包之间关联变得弱,实现低耦合
      无循环依赖原则(ADP)
      稳定依赖原则(SDP)
      稳定抽象原则(SAP)

    共同封闭原则

    1. 一起被修改的类应该放在一个包里
    2. 如果一起改的东西都放在一个包里,那么要修改时就修改一个包就好了,这样利于维护,最小化修改的影响
    3. 一次修改的影响尽量波及到少的模块,这样编译、连接、重验证的时间和成本都减小
    4. 项目中

      两个接口处的数据对像会一起被修改,放在一起
      持久化数据连接们放在一起
    5. 总结
      有相同修改需求的放在一起,注意这里说的一起修改需求都是可预测到的修改
      不可预测的东西:要么出现了系统可以忍受,要么就是不可忍受的重大改动(代价大)
      没有预测到的改变破坏力很大
      再好的设计也是基于能预测到的影响和修改,不可能有高超的设计师能够包括不可预测的修改的影响
      共同封闭原则趋势为包越大越好,包数越少越好
      每次变更都在少数量的包进行,减少发布频率

    共同重用原则

    1. 一起重用的类放在同一个包里
    2. 要用它,就要用到它们所有——他们就被放在一起
    3. 根据重用的角度来分包
    4. 总结
      共同重用原则趋势为形成更多更小的、更加聚焦的包
      包越多越好,每个包越小越好
    5. CCP与CRP的折衷——二者互斥
      CCP希望包越大越好,CRP希望包越小越好
      CCP有利于维护者和修改者,CRP有利于重用者
      应用:在项目早期建包时(根据需求建包)即逻辑上的包时,由CCP主导,考虑开发过程,先让同时改动的东西同包,包越大越好;等到架构稳定的时候,考虑细节时,重构这些包时,考虑CRP更多,务必要分小一点

    重用发布原则

    1. 重用的单元就是发布的单元
    2. 一个包中的类要么是都可以重用的,要么是都不能重用的
    3. 重用:要由外部软件来重用,”你用,别人来维护“
    4. 对于重用来说,不管这个东西是自己开发的还是从外面买来的,都只是一个重用单元,希望重用单元就是发布单元
    5. 假如此模块是一个重用单元,就一起来发布
    6. 项目中

      Utility和Tools一起被重用,作为发布包时,一起被发布出来
    7. 总结
      单个类没法重用,要将相关联的类(一起重用的类)打个包一起发布,这个包可以单独被重用,也可以单独发布,减少了重用者的工作(每次重用,多个包不合适,一次重用都在一个包里)

    无环依赖原则

    1. 依赖结构应该是有向而无环的
    2. 如果有了闭环,一旦修改就是无穷的修改,故无环更加稳定,形成自顶向下的结构
    3. 有环依赖改成无环依赖方法一:抽象出公共依赖部分来改变方向

      Comm Error依赖GUI的依赖可以被改进,他造成连环
      改进

      Comm Error依赖GUI,只依赖于GUI中的Message Manager包,可以讲他从GUI中移出来,使他同时被GUI与Comm Error两个包依赖,消除了环
    4. 有环依赖改成无环依赖方法二:抽象出接口

      A, B, X, Y都是模块,AB的包与XY的包互相依赖
      改进图示

      从B中抽象出接口BY(即Y所依赖的部分)放入Y的包,B去实现接口
      注意:类实现接口,从类的角度来说,要遵从接口的规则,类依赖于接口(而接口与实现什么样子无关);接口的改变一定会影响到实现
    5. ADP的项目应用场景
      层次式风格(严格上层依赖下层)和主程序/子程序(树结构)风格通常不会发生
      面向对象式风格尤其要注意(对象之间互相依赖)
      客户端/服务器的MVC风格可能会发生
      基于数据流、事件/消息、数据共享进行交互的体系结构风格通常不会发生

    稳定依赖原则

    1. 依赖关系指向稳定的方向
    2. 稳定的指:改变时付出代价大的,别人依赖自己的是稳定的(外面对自己影响小)
    3. 稳定的不容易变化,但是改变要付出的代价大——应该依赖一个稳定的
    4. 稳定与不稳定的例子
      稳定的:别人依赖于我,我不依赖于别人
      X 是稳定的

      Y是不稳定的
    5. 包的稳定性度量
      计算进出该包的依赖关系的数目,可以使用这些数值来计算该包的位置稳定性(Positional Stability)
      (Ca)输入耦合度(Afferent Coupling):指处于该包的外部并依赖于该包内部的类的类的数目
      (Ce)输出耦合度(Efferent Coupling):指处于该包的内部并依赖于该包外部的类的类的数目
      不稳定性I = Ce / (Ca + Ce)
      该度量值的取值范围为[0, 1],0表示该包具有最大的稳定性,1表示该包具有最大的不稳定性
      I = 1时,就意味着没有任何其他的包依赖于该包,而该包却依赖于其他的包,这是一个包最不稳定的状态:他是不承担责任且有依赖性的,因为没有包依赖于他,所以他就没有不改变的理由,而他所依赖的包会给他提供丰富的更改理由;I = 0时,就意味着其他包会依赖于该包,但是该包却不依赖于任何其他的包,他是负有责任且无依赖性的,这种包达到最大程度的稳定性,他的依赖者使其难以更改,而且没有任何依赖关系会迫使他去改变
    6. 项目中SDP的体现

      大家都依赖database包,他相对稳定

    稳定抽象原则

    1. 稳定的包应该是抽象的包(如接口),不稳定的包应该是具体的包
    2. 抽象之后有利于扩展,修改时好修理
    3. 抽象性度量
      包抽象性用抽象类的数目和包中所有类的数目进行计算
      包中类的总数Nc,抽象类的数目Na,抽象度A = Na / Nc
    4. 到主序列的距离

      说明:
      点(0, 0):稳定而不够抽象,不好的点——因为难以改动(如Java的String类,多年类从未改过String接口)
      点(0, 1):类是稳定而抽象的,好
      点(1, 0):类不稳定且不抽象,好
      连线上的点,类的抽象性与不稳定性成较好的比例
      度量抽象性/稳定性合适与否,就看点到直线距离,近一些的问题就不大
      线上(图右上角)是不稳定而抽象的包们的位置,“依赖别人多的类”,这种类我们不太在乎是具体还是抽象(因为他们对别人的影响小)
    5. SAP在项目中

      直接这样不好,根据SAP,应该在逻辑层与数据层抽象出接口来被依赖(接口就是高抽象的)

    包设计的过程

    先CCP原则把可能一同变化的类组织成包进行发布(包大趋势)
    随着系统的不断增长,我们开始关注创建可重用的元素,于是开始使用CRP和REP来指导包的组合
    最后使用ADP、SDP、SAP对包图进行度量,去掉不好的依赖

    依赖逻辑设计进行软件体系结构设计(实现)

    开发包(构件)设计

    1. 初始物理包
    2. 细节考虑和包的添加
      考虑到要跨机器(用到RMI技术,依赖于RMI包)和数据持久化(依赖于JDBC包、databaseutility包)

      考虑到Presentation层的所有开发包要使用图形类型建立界面,都要依赖图形界面类库包;Presentation层实现时,由mainUI包负责整个页面之间的跳转逻辑,其他包负责各自页面的跳转逻辑

      考虑到展示层应该依赖逻辑层的接口、逻辑层应该依赖数据层的接口(会有接口包);传输数据中要有po和vo两个包

      考虑到应该去处循环依赖和逻辑层一些关于初始化和业务逻辑层上下文的工作被分配到utilitybl包中去
      存在的循环依赖


      根据这些物理包,画出超市管理系统开发包图(客户端、服务器端)
      客户端

      服务器端

    运行时的进程


    服务器进程、客户端进程中间靠RMI通信

    物理部署


    代表部署时要做的一些准备

    完善体系结构设计

    完善软件体系结构设计

    1. 常见完善的方面:启动、现场初始化、监控、环境建立与维护、清理现场、安全等
    2. 示例:完善启动和网络链接

    细化软件体系结构设计

    1. 细化逻辑层模块:以salesbl为例

      细化出逻辑接口与数据接口
    2. 数据定义
      接口的数据对象
      关键类的重要数据结构
      Value Object:传递一个值,用于逻辑层与展示层之间传递数据;既可以是某个实体数据的一部分,也可以是很多实体数据的组合
      Persistent Object:将数据持久化到数据库里,传递的是值
      逻辑层与逻辑层交互,只代表值,写的话只是改变这个值,并没有改变真是的逻辑层对象
    3. 数据持久化的细化

      序列化持久化:补全属性
      数据持久化:建好表

    添加构建接口

    1. 构件初步设计
      根据分配的需求确定模块对外接口
      初步设计关键类
      编写接口规范
    2. 确定模块对外接口
      分层方式下,两种接口:逻辑层提供给展示层的;数据层提供给逻辑层的
      这两种接口都是按照需求确定的:逻辑层给展示层的接口看展示层对逻辑层有什么需求;数据层给逻辑层的接口看逻辑层对数据层又什么需求

      此例中:
      两类接口:供接口(对上层展示层)、需接口(对下层数据层)
    3. 编写接口规范

    体系结构构建

    包的创建


    分层:每层一个包
    层内模块:每个模块一个包

    重要文档的创建

    源文件、数据文件、系统文件、配置文件等
    文件列表

    定义构件之间的接口

    以定义SalesBLService为例

    public interface SalesBLService{
    	//与其他模块进行交互,都是销售过程中需要获得数据
    	public CommodityVO getCommodityByID(int id);
    	public ArrayList<CommodityPromotionVO> getCommodityPromotionListByID(int commodiyID);
    
    	public MemberVO getMember();
    	
    	//销售步骤(略)
    	...
    	//这些销售过程都是会被Sales展示层调用的,故提供这些接口(按需求)
    }
    

    关键需求的实现

    1. 实现一些关键功能需求
      目的:“让心里更有底”,消除风险,先完成一些有代表性的功能(一般都是有完整端到端的功能,需要有足够的覆盖面),证明现阶段的成果使我们有能力完成软件(结果是做出一个demo之类)
      比如连锁超市中,销售用例就是一个最关键的用例;他所覆盖的面最广,如果销售用例可以实现,其他用例实现就比较有信心了;而这个需求需要做到端到端的实现
      比如,连锁超市系统中存在客户端和服务器端,那么我们就需要在客户端通过GUI界面发出指令,通过客户端的业务逻辑处理,访问服务器端的数据,对数据进行修改;只有这样才能表明当前体系结构可以胜任功能性需求
    2. 对原型的非功能性需求进行估算和验证;如果出现不符合非功能性需求和项目约束的情况,我们还需要对体系结构设计重新调整
      比如,连锁超市系统中,我们用文件来保存数据,而当数据越来越多,特别是销售记录要保存一年;这时候,客户端跨网络对服务器上文件查找就比较慢,可能会使我们不满足实时性需求;这时候,可能我就要调整体系结构中数据存储方案,比如换成数据库;或者在客户端的逻辑层和数据层之间假设数据映射层,在客户端运行初始化时,将数据从服务器端载入到客户端的内存中去
      注意:估算、验证不一定必须在使用后全都保证正确,只不过测出来不对就要先做调整

    体系结构集成与测试

    概述

    1. 体系结构设计完成之后(包、文件、接口定义好之后,验证过非功能需求等之后)进行体系结构集成与测试
    2. 需求阶段结束时,进行验收测试——验收时按照需求,做的是验收测试用例结果
      体系结构设计阶段结束时,进行集成测试——将设计的components拼在一起,可能会出现各种各样问题,如果有就解决

    集成策略

    概述

    1. 当体系结构中原型各个模块代码都编写完成并经过单元测试之后,需要将所有模块组合起来形成整个软件原型系统,这就是集成
    2. 集成的目的是为了逐步让各个模块合成为一个系统来工作,从而验证整个系统的功能、性能、可靠性等需求
    3. 对于被集成起来的系统,一般主要是通过其暴漏出来的接口,伪装一定的参数和输入,进行黑盒测试
    4. 根据从模块之间集成的先后顺序,一般有下列几种常见的集成策略
      大爆炸式:所有东西放在一起,不利于问题定位
      增量式:每次多集成一个小部分(一个模块),一出问题就可以定位在新加入的东西上
      自顶向下式,自底向上式,三明治式,持续集成

    自顶向下

    1. 图示
    2. 过程
      如M1写好之后,与已经写好的M1相邻的模块M2、M3、M4的桩程序(作为这几个模块的代替)来测试,如果测试通过,那么M1就OK
    3. 写好的模块测试时,直接相连的模块用桩程序代替参与测试
    4. 优点:
      按深度优先可以首先实现和验证一个完整的功能需求
      只需最顶端一个驱动(Driver)
      利于故障定位
    5. 缺点:
      桩的开发量大
      底层验证被推迟,且低层组件测试不充分
    6. 软件测试什么时候停:一般不会测试到100%正确再停,而是“钱用尽了就停”,“时间到了就停”
    7. 测试费时间、费钱(三分之一的经费有时)

    自底向上

    1. 图示
    2. 过程
      底下模块先测试好再搞上面的,被测试模块上面全都改成驱动,测试好了该测下一个模块时就往上加模块
    3. 优点:
      对底层组件较早验证
      底层组件开发可以并行
      桩的工作量少
      利于故障定位
    4. 缺点:
      驱动的开发工作量大
      对高层的验证被推迟,设计上的高层错误不能被及时发现

    三明治式

    既写桩又写驱动,两头同时开测

    持续集成

    1. 集成:将代码集合在一起形成一个可以发布的版本
    2. 一种增量集成的方法,但他提倡尽早集成和频繁集成
      不要等全部开发完再做集成,而是体系结构设计完就把桩程序写完,之后,写完一个模块就可以测试这个写完的模块
    3. 尽早集成是指不需要总是等待一个模块开发完才把它集成起来,而是在开发之初就利用Stub集成起来
    4. 结合尽早集成和频繁集成的方法,持续集成可以做到:
      防止软件开发中出现无法集成与发布的情况,因为软件项目在任何时刻都是可以集成和发布的
      有利于检查和发现集成缺陷,因为最早的版本主要集成了简单的Stub,比较容易做到没有错误;后续代码逐渐开发完成后,频繁集成又使得即使出现集成问题也能够尽快发现、尽快解决
    5. 持续集成的频率很高,所以手动的集成对软件工程师是无法接受的,必须利用版本控制工具和持续集成工具;入股程序员可以仅仅通过一条命令就完成一次完整的集成,开发团队才有动力并且能够坚持进行频繁的集成
    6. 持续发布:集成好后将它发布出去,必须有控制工具

    依据模块接口建立桩程序Stub

    1. 桩:
      为了完成程序的编译和连接而使用的暂时代码
      对外模拟和代替承担模块接口的关键类
      比真实程序简单的多,使用最为简单的逻辑
    2. 桩的定义与使用
      模块的类图和一部分交互

      该模块桩的定义和使用:使用时,把想要的内容的数据直接填进来,要调用哪个方法就这样调

      驱动的定义和使用:看期望结果与通过调用方法得到的结果是否一致
    3. 编写驱动程序,在桩程序帮助下进行集成测试

      驱动程序调用被测部件,被测部件联系到其他模块,这部分联系用其他模块的桩完成

    集成与构建

    1. 集成
      使用桩程序辅助集成
      编译与链接
    2. 持续集成
      逐步编写各个模块的内部程序,替换相应的桩程序(原来的桩程序是为了测试该体系结构是否合格)
      真实程序不仅实现业务逻辑,而且会使用其他模块的接口程序(真实程序或桩程序)
      每次替换之后都进行集成测试

    项目实例

    体系结构文档化

    体系结构设计文档模版

    体系结构验证与评审

    1. 评审角度
      设计方案正确性、先进性、可行性
      系统组成、系统要求以及接口协调的合理性
      对于功能模块的输入参数、输出参数的定义是否明确
      系统性能、可靠性、安全性要求是否合理
      文档的描述是否清晰、明确
    2. 评审方法
      对结果的评审:checklist(评审的是体系结构设计的结果——文档,要求评审人员对细节很熟悉,要能判断是否合理;而不同软件系统结构差别很大,这种对细节的判断代价很大)
      对设计决策的评审(不评审结果,评审的是开发过程的决策质量;思想是“决策不差、结果就不会差”;进行评审的人不必懂项目,请人就行)
    3. CheckList
    内容 解释
    体系结构设计是否为后续开发提供了一个足够的视角 体系结构设计是后面的蓝图,能否提供视角很重要(如果用户根据此蓝图产生了新的想象,就说明视角不够)
    是否所有的功能都被分配给了具体模块
    是否所有的非功能属性都得到满足
    是否所有的项目约束都得到了满足
    体系结构设计是否为后继设计提供了简洁的概述、背景信息、限制条件和清晰的组织结构
    体系结构设计是否能对应可能发生的变更 预测变更
    不同的体系结构设计视角的依赖是否一致 有否矛盾
    是否关注点在详细设计和用户接口的层次之上 是否够高层
    系统环境是否定义,包括硬件、软件和外部系统
    展开全文
  • 1.3 软件体系结构设计 1.4 方法和表示法 1.5 COMET:一种基于UML的软件应用建模和设计方法 1.6 UML标准 1.7 软件体系结构的多视图 1.8 软件建模和设计方法的发展 1.9 面向对象分析和设计方法的发展 1.10 ...
  • 软件体系结构安例

    2013-06-28 20:02:46
    讲述了Web体系结构设计案例,适合体系学习体会体系结构的设计。
  • 软件体系结构笔记

    千次阅读 2020-07-12 13:27:12
    软件体系结构笔记 软件开发流程 1.软件开发流程_简介 1.1从管理角度 即从业务和经济的角度来看,软件的生命周期包括四个主要阶段: ​ 起始阶段:有一个好的想法:具体构想产品的设想和它的业务案例,确定项目的范围 ...

    软件体系结构笔记

    软件开发流程

    1.软件开发流程_简介

    1.1从管理角度

    即从业务和经济的角度来看,软件的生命周期包括四个主要阶段:

    ​ 起始阶段:有一个好的想法:具体构想产品的设想和它的业务案例,确定项目的范围 。

    ​ 细化阶段: 计划必要的活动和所需资源,具体确定功能并设计构架 。

    ​ 构建阶段: 构建产品, 发展最初的设想、构架和计划,直到一个能够交付给用户的产品(完毕后的设想)完毕。

    ​ 移交阶段: 将产品移交用户使用,包含:交付、培训、支持、维护,直到用户惬意。

    1.2从技术角度

    1.需求: 需求就是我们需要做些调研,挖掘用户想要的功能,来帮助用户完成什么事情,在进一步探讨,实现用户的更多需求

    2.设计: 在需求的基础上,开展项目设计,如业务系统详细设计/结构设计/数据库设计…

    3.开发: 根据设计来完成具体的实现(编码),自我测试

    4.测试: 功能测试/性能测试/其他测试,问题修复后再测试,直到没有出现问题为止

    5.上线: 将项目部署,正式环境使用,交付用户使用

    ​ 1.新项目上线 :将项目打包上传服务器启动

    ​ 2.迭代项目:在已有项目上新增功能/变更功能

    6.运维: 软件上线后,线上监控,维护,确保系统的可用性

    运维工程师处理,但是我们开发时需要懂一些

    1.3迭代

    用户建议增强功能、用户环境的改变、重要技术的变更,以及应对竞争的需要

    每次迭代包含步骤:计划、分析、设计、实施和测试

    迭代: 举例拿了一块地,修房子(小区) 第一期,反响很不错,建议再修一起,

    ​ 产生了一个迭代

    开发商:迭代建筑 ~

    备注:不是每一个项目都有迭代过程

    ###2.软件开发流程_详细介绍

    需求

    1.相关系统分析员向用户初步了解需求,然后用相关的工具软件列出要开发的系统的大功能模块,每个大功能模块有哪些小功能模块,对于有些需求比较明确相关的界面时,在这一步里面可以初步定义好少量的界面。

    2.系统分析员深入了解和分析需求,根据自己的经验和需求用WORD或相关的工具再做出一份文档系统的功能需求文档。这次的文档会清楚列出系统大致的大功能模块,大功能模块有哪些小功能模块,并且还列出相关的界面和界面功能。

    3.系统分析员向用户再次确认需求 (反复确认)

    设计

    A概要设计(架构设计)

    需要对软件系统进行概要设计,即系统设计。概要设计需要对软件系统的设计进行考虑,包括系统的基本处理流程、系统的组织结构、模块划分、功能分配、接口设计、运行设计、数据结构设计和出错处理设计等,为软件的详细设计提供基础。

    B.详细设计(数据库设计(非必选)/接口详细设计)

    实际设计: 1.架构设计 2.概要设计 3.数据库设计 4.详细设计

    开发

    ​ 主要指软件编码阶段,开发者根据《软件系统详细设计报告》中对数据结构、算法分析和模块实现等方面的设计要求,开始具体的编写程序工作,分别实现各模块的功能,从而实现对目标系统的功能、性能、接口、界面等方面。在规范化的研发流程中,编码工作在整个项目流程里最多不会超过1/2,通常在1/3的时间,所谓磨刀不误砍柴功,设计过程完成的好,编码效率就会极大提高,编码时不同模块之间的进度协调和协作是最需要小心的,也许一个小模块的问题就可能影响了整体进度,让很多程序员因此被迫停下工作等待,这种问题在很多研发过程中都出现过。编码时的相互沟通和应急的解决手段都是相当重要的,对于程序员而言,bug永远存在,你必须永远面对这个问题!

    ####测试

    ​ 测试编写好的系统。交给用户使用,用户使用后一个一个的确认每个功能。软件测试有很多种:按照测试执行方,可以分为内部测试和外部测试;按照测试范围,可以分为模块测试和集成测试;按照测试条件,可以分为正常操作情况测试和异常情况测试;按照测试的输入范围,可以分为全覆盖测试和抽样测试。以上都很好理解,不再解释。总之,测试同样是项目研发中一个相当重要的步骤,对于一个大型软件,3个月到1年的外部测试都是正常的,因为永远都会有不可预料的问题存在。完成测试后,完成验收并完成最后的一些帮助文档,整体项目才算告一段落,当然日后少不了升级,修补等等工作

    ​ 非必现bug: 项目中测试过程没有出现,或者这个流程测试过,当时没有问题,后来有问题

    ​ 必现bug

    ​ 上线: 开发人员,开发好,测试通过之后,会编写部署文档,部署文档内容:1.项目(软件)的存放地址 (ftp) 软件迭代管理目录 2.如何部署 (相关的配置 Ip 目录 其他线上的配置) 3.如何启动(shell脚本) :目标时: 让运维人员能够按照流程执行 项目的先后启动顺序

    ####交付

    ​ 软件测试证明软件达到要求后,软件开发者应向用户提交开发的目标安装程序、数据库的数据字典、《用户安装手册》、《用户使用指南》、需求报告、设计报告、测试报告等双方合同约定的产物。

    ​ 《用户安装手册》应详细介绍安装软件对运行环境的要求、安装软件的定义和内容、在客户端、服务器端及中间件的具体安装步骤、安装后的系统配置。

    ​ 《用户使用指南》应包括软件各项功能的使用流程、操作步骤、相应业务介绍、特殊提示和注意事项等方面的内容,在需要时还应举例说明。

    ​ 操作步骤:完成某个业务,每一步的操作

    ​ 相应的业务介绍:需求报告中要求的重点的需求,进一步介绍

    ​ 特殊提示: 必须的,我们一般都是定义一个异常码 (100002: 操作错误)

    ​ 注意事项:可能会导致项目问题的注意事项

    ​ 举例: 认证登陆:输入5次密码,都错了,这个时候,系统会封号

    ​ 项目交付前流程:先交定金30%,项目验证通过之后,付50%,尾款20%

    软件开发中应具备的思想

    1.欲速则不达~

    ​ A. 不推荐拿到需求马上就开发,先构思,先想清楚

    ​ B. 减少做无用功

    2.先验证再答复

    ​ A. 技术先写demo,验证后再答复

    ​ B. 不太确定的需求,不能立即答复

    3.胸中成竹

    ​ 所有流程/业务场景我们得了然于胸,做好准备

    ​ 如果作为一个产品经理一样得考虑,每个场景,和每种场景的解决方式

    4.新技术的使用

    ​ 并不是使用最流行的技术就是最好的,根据项目的具体情况而言

    ​ 没有太熟练的技术,不建议使用 。

    5.解决问题的方法~开发人员会遇到各种各样的问题

    ​ A. 看下论坛 /百度

    ​ B. 请教大神

    ​ C. 如果请教大神都解决不了怎么办 ?参考1思想

    ​ D. 如果不能转换为已解决的问题,向上反馈

    软件开发中常用的辅助工具

    1. Notepad++

    记录文本,使用 ,不会自动销毁

    2. HiJson/json格式化工具

    推荐在线的json格式化工具

    3. XMind/百度脑图/迅捷画图/Office Visio/axure

    画流程图/结构图/思维导图/时序图

    4. Beyond Compare

    用户文本/文件夹内容比较 SVN:比较线上的文件不同之处

    5.有道云笔记

    用户记录日常文件/总结/日志/灵感

    6. 有道词典

    翻译,变量名称

    7. Xshell

    链接服务器的工具(必备工具)

    8. TeamViewer

    控制对方或者请求对方控制自己电脑/协助完成某个事

    需求与需求分析

    一.需求收集归纳

    1. 初步收集

    收集需求~用户说我现在系统/软件

    2. 归纳

    把用户的需求整理成一个文档

    3. 需求的分析

    概念:把计划中的软件需求进行一个可行性分析,细化/求精 ,分配软件元素(软件模块)需求过程中最后一步,确定了系统必须要完成的工作。

    举例: 需要给家禽养殖场开发一个温感控制系统

    提问: 到底需要什么样子的温感控制系统 ?

    ​ 1.准确描述用户的需求以及功能

    ​ 2.帮助客户挖掘需求

    ​ 3.分析客户需求的可行性 同时给出一个专业的设计建议

    4. 需求分析的难点

    ​ 1.客户说不清楚需求 2.需求本身是具有变动性的 3.沟通有误

    5. 需求分析的分类:

    功能需求:用户最直观的最主要的需求

    非功能性需求:响应时间/存储效率/页面美观

    领域的需求:系统应用领域,基本会出现的问题,针对这些问题,该领域存在的潜在需求

    6. 需求分析的不同层次 (了解)

    业务需求:反应了组织机构对系统/产品有高层次的要求

    用户需求:需求文档要完成的任务

    功能需求(分功能性需求):开发人员必须实现的软件功能

    7. 评估:

    这个过程实际上,需要系统分析员,产品经理,架构,项目经理,开发团队

    8. 需求分析的方法

    1. 功能分析法: 定义各种功能与功能之间的关系 ,以及子接口

      2.数据流分析法: 分析数据流程

    2. 信息建模 实际上就是面向对象的抽象过程

    ​ powerDesger

    二.需求补充:

    如果有页面,最好做出原型图(画流程图)/墨刀或者参考系统/链接

    目标:确定好需求是为了尽量去解决需求变更的问题

    需求文档,没有固定的模板,各个公司都不同,没有最好,只有更好

    备注:无法彻底解决,总有意想不到的业务情况变动或新增

    概要/架构设计

    一.架构概念

    1.定义:

    通用定义:计算机内部组件的组合,整合和交互

    此处的定义:实现某个软件/系统,需要组件整合和组件的交互方式

    2.架构设计详细分解:

    架构设计包括了功能性架构和技术架构设计两个部分的内容

    功能性架构解决业务流程和功能问题。(举例 登陆认证系统复用)

    在这里插入图片描述

    技术架构解决非功能性需求等问题。

    提问:什么是非功能性需求 ?

    二.架构特性与原则

    1.理解架构和编程的区别?

    编程和架构最大的区别是“不确定性”,编程写出来的程序是确定的,而不同的架构可能都适合于某个场景。

    2.为什么架构是不确定性?

    因为不同的架构都可能或看似可能适用于需求,或者团队成员又更熟悉某种技术栈,多种选择困难症压在架构师身上。这些选择哪一种都可能正确,但是哪一种合适却没有一套通用的规范,

    3.既然架构具有不确定性,那么如何确定 ?如何去选择那种架构?

    A.根据业务功能需求/非功能性需求,同时根据架构师的经验和直觉

    举例:一般的网站单点部署 ,新浪微博架构

    在这里插入图片描述
    其他架构扩展:

    在这里插入图片描述

    B.看开发团队的使用的技术栈

    举例:(springCloud 和 Dubbo )解决了分布式架构

    备注:Dubbo功能和文档完善,在国内有很多的成熟用户,然而鉴于Dubbo的社区现状(曾经长期停止维护,2017年7月31日团队又宣布重点维护),使用起来还是有一定的门槛。

    Dubbo具有调度、发现、监控、治理等功能,支持相当丰富的服务治理能力。Dubbo架构下,注册中心对等集群,并会缓存服务列表已被数据库失效时继续提供发现功能,本身的服务发现结构有很强的可用性与健壮性,足够支持高访问量的网站。

    备注:Spring Cloud由众多子项目组成,如Spring Cloud Config、Spring Cloud Netflix、Spring Cloud Consul 等,提供了搭建分布式系统及微服务常用的工具,如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性token、全局锁、选主、分布式会话和集群状态等,满足了构建微服务所需的所有解决方案。比如使用Spring Cloud Config 可以实现统一配置中心,对配置进行统一管理;使用Spring Cloud Netflix 可以实现Netflix 组件的功能 - 服务发现(Eureka)、智能路由(Zuul)、客户端负载均衡(Ribbon)。

    4.架构考虑原则

    4.1合适原则

    在设计架构的时候,不能总是瞄准着大厂的水准,总是想成为业界领先。但往往这样会忽略了业务的实际需求,而放大了工作量,导致失败。往往没有业务量,就不会有太多的人力资源去支撑“大架构”

    业界顶尖的架构都是通过逐步完善得出的,好的架构不是想出来的,是业务场景和压力的情况下完善而来

    脱离了业务,空谈架构反而做不好架构师 。

    4.2简单原则

    组件/方案选择遵从简单原则,Zookeeper的主备策略让人总比心跳机制更高大上,导致更多的人觉得更可靠而选择更复杂的方案。反而让架构走向复杂~

    补充:

    软件领域的复杂性体现在结构的复杂性和逻辑的复杂性

    ​ 结构的复杂性: a.组件数量多 b.组件之间的关系复杂 C.定位组件问题困难

    ​ 提问:是不是减少组件数量就解决了架构复杂性呢?

    ​ 逻辑复杂性:当组件的逻辑过于复杂,会带来新的问题,例如扩展性问题,协作问题

    4.3演化原则

    据说,软件架构起源于建筑学。但是建筑一旦完成就不可变,而软件却还要根据业务的发展不断地变化。因为业务总是在变化,所以呢,架构并不是一劳永逸的。

    软件架构都需要经历以下过程:

    ​ a.设计出来的架构满足当前业务

    ​ b.架构不断迭代重构,吸取优点舍弃缺点

    三.架构实现步骤

    1…将功能业务模块拆分成各个子模块,根据模块的用户数量,性能要求,决定是否将该模块独立成服务模块

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SZeY6K54-1594531077335)(file:///C:\TMP\ksohtml6556\wps15.jpg)]

    2.模块件的集成架构,分析完成后,各个模块之间的接口基本就整理出来了。

    (考虑到复用性)

    解释:

    模块之间的接口:服务对外部提供了接口,外部通过这个接口,发起请求(携带数据),服务接受到之后,

    进行数据处理,相应的响应消息返给调用方

    同步:

    异步:

    可以再回调通知

    3.设计事务,缓存,异常 ,性能,可用性,容错能力

    扩展: 分布式事务

    缓存: 减少数据库压力,提高效率 ,经常用,公共的数据

    异常消息提醒(书写用户手册时提到)

    通知管理者: 短信 邮件

    性能: 硬件方面 ,横向扩展多台服务器

    ​ 软件方面 ,缓存、队列,数据库层面

    容错能力:出现错误后,对系统的影响程度

    四.如何书写架构设计说明书

    1. 软件实现所需硬件要求

    例如:

    *硬件类型* *数量* *参数* *要求*
    数据库服务器 3 2*12core32G300G 物理机
    应用服务器 2 2cpuMem:8G40G 物理机或者虚拟机
    内部网络 千M以太网或以上

    2. 软件的构件组成以及版本

    *名称* *版本*
    操作系统 Linux Redhat 6.4
    关系型数据库 Oracle 11g以上
    Web服务器 Tomcat 8.0.18以上
    运行环境 JDK 1.7以上
    其他软件 Spring 4.1.7
    Log4j 1.2.14
    junit 4.1.2
    mybatis 3.2.7

    3. 物理架构

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CLIoDIfz-1594531077341)(file:///C:\TMP\ksohtml6556\wps16.png)]

    4. 软件架构

    企业使用的框架来做软件架构

    五.概要设计

    根据架构设计进一步对某个模块的设计进一步细化~举例

    在模块内部应该实现的功能点

    举例:具体如何实现的细节不关注,我们关注实现的方式
    在这里插入图片描述

    为什么要做概要设计?

    为了项目最终的目的,为了保证实现的功能不会偏差,即使性能上,易用性上有问题,不影响整理功能 。

    数据库相关设计

    一.案例实际处理

    1.教学管理系统

    基本需求:

    某学校设计学校教学管理系统,学生实体包括学号、姓名、性别、生日、民族、籍贯、简历、入学日期,每名学生选择一个主修专业,专业包括专业编号、名称、类别,一个专业属于一个学院,一个学院可以有多个专业。学院信息要存储学院号、学院名、院长。教学管理要管理课程表、学生成绩表。课程包括课程号、课程名、学分,每门课程由一个学院开设。学生选修的每门课程获得一个成绩。

    如何设计数据库?

    1.进行数据抽象

    2.数据表示:

    学生实体(学号、姓名、性别、生日、民族、籍贯、简历、入学日期,专业编号)

    专业实体(专业编号、名称、类别,学院号)

    学院实体(学院号、学院名、院长)

    课程实体(课程号、课程名、学分,学院号)

    成绩单实体(学号,课程号,成绩)

    备注: 做了一个抽象过程和一个关联关系

    3.表达方式:

    ​ 用英文来代替(s_id,p_id,c_id)

    4.写入数据库中

    ​ 4.1创建数据库

    ​ 4.2创建表

    ​ 数据库第一范式:比较有用,

    ​ 数据冗余关系 不建议 但是实际情况比较常见

    5.数据分析

    2.权限管理系统

    基本需求:多个用户,每个用户最多只能有一种角色,每个角色可以有多种权限 。

    3.评论留言系统

    任何人都可以对某好友动态进行多次评论,该好友可以在该评论下进行一次回复 。

    二.逆向看理论知识

    数据库实施中:增量上线

    ​ 新项目上线

    数据库维护:垃圾数据处理,数据备份,数据的转储

    三.思考数据库设计到底应该是做什么?

    一.引擎选择

    Mysql

    Innodb:支持事务

    Mysam:查询

    二.数据库表的设计(范式概念)

    遵循范式概念 ,但是怎么方便怎么来~

    三.sql语句的优化

    A. 优化思路: 经量不用关联查询

    ​ Select id

    ​ …

    详细设计

    实现功能的具体处理办法和业务逻辑/流程

    前/后端的逻辑

    详细设计和业务逻辑密不可分,要想写出详细设计,必须要清楚理解到业务逻辑 。

    安卓:

    ios:

    服务端:

    1.登陆: 输入手机号码 -->获取验证码

    2.验证码校验

    3.服务端给出响应 -

    详细接口文档编辑:

    http://www.docway.net/dashboard

    评估/完善

    一.软件设计的评估时机

    1.有初步需求后会先进行一次需求评估

    2.架构/概要设计后,评估

    3.详细设计(数据库/接口设计)再次评估

    二.评估时机

    为了再次验证设计是否有误,大方向上是否有问题

    三.从哪些方面评估呢 ?

    架构方面:

    软件架构评估是在对架构分析、评估的基础上,对架构策略的选取进行决策。它也可以灵活地运用于对软件架构进行评审等工作中。

    1 软件架构评估的方法

    业界已开发出多种软件架构评估的方法,按基于的技术手段来看,可以分为三类:基于调查问卷或检查表的方式、基于场景的方式和基于度量的方式。

    (1)基于调查问卷或检查表的方式:该方式的关键是要设计好问卷或检查表,它充分利用系统相关人员的经验和知识,获得对架构的评估。其缺点是在很大程度上依赖于评估人员的主观推断。

    (2)基于场景的方式:基于场景的方式由 SEI 首先提出并应用在架构权衡分析法(Architecture Tradeoff Analysis Method,ATAM)和软件架构分析方法(Software Architecture Analysis Method,SAAM)中。它是通过分析软件架构对场景(也就是对系统的使用或修改活动)的支持程度,从而判断该架构对这一场景所代表的质量需求的满足程度。下节将对ATAM 进行重点介绍。

    (3)基于度量的方式:它是建立在软件架构度量的基础上的,涉及三个基本活动,首先需要建立质量属性和度量之间的映射原则,即确定怎样从度量结果推出系统具有什么样的质量属性;然后从软件架构文档中获取度量信息;最后根据映射原则分析推导出系统的质量属性。它能提供更为客观和量化的质量评估,但它对评估人员及其使用的技术有较高的要求。ATAM 中也使用了度量的思想(度量效用)。

    2 架构的权衡分析法

    从技术角度对软件架构进行评估,旨在通过分析来预见软件的质量;通过分析来创建、选择、评估与比较不同的架构。例如,Kazman 等人在 2000 年提出的架构的ATAM方法。 ATAM方法不但能够揭示架构如何满足特定的质量需求(例如,性能和可修改性),而且还提供了分析这些质量需求之间交互作用的方法。使用 ATAM 方法评价一个软件架构的目的是理解架构设计满足系统质量需求的结果。

    ATAM 产生如下结果。

    (1)一个简洁的架构表述:ATAM 的一个要求是在一小时内表述架构,这样就得到了一个简洁、可理解的、面向普通项目关系人的架构表述。它是从架构文档中提炼形成的。

    (2)表述清楚的业务目标。

    (3)用场景集合捕获质量需求。

    (4)架构决策到质量需求的映射。

    (5)所确定的敏感点和权衡点集合:这个集合是一些对一个或多个质量属性具有显著影响的架构决策。如:备份数据库就是这样一个架构决策,它对可靠性产生正面影响,而对系统性能产生负面影响,因此需要进行权衡。

    (6)有风险决策和无风险决策。

    (7)风险主题的集合。找到这些风险主题旨在采取相应的措施。

    (8)产生一些附属结果。评估过程形成的文档(经受住了评估的考验)可以作为经验保留下来。

    (9)还产生一些无形结果,如能够使项目关系人产生“团队感”,提供了一个交流平台和沟通渠道,使大家更好地理解架构(优势及弱点)。

    3 成本效益分析法

    在大型复杂系统中最大的权衡通常必须考虑经济性,因此,需要从经济角度建立成本、收益、风险和进度等方面软件的“经济”模型。成本效益分析法(the Cost Benefit Analysis Method,CBAM)是在 ATAM 上构建,用来对架构设计决策的成本和收益进行建模,是优化此类决策的一种手段。CBAM 的思想就是架构策略影响系统的质量属性,反过来这些质量属性又会为系统的项目关系人带来一些收益(称为“效用”),CBAM 协助项目关系人根据其投资回报(ROI)选择架构策略。CBAM 在 ATAM 结束时开始,它实际上使用了 ATAM 评估的结果。

    CBAM 的步骤如下:

    (1)整理场景。整理 ATAM 中获取的场景,根据商业目标确定这些场景的优先级,并选取优先级最高的 1/3 的场景进行分析。

    (2)对场景进行求精。为每个场景获取最坏情况、当前情况、期望情况和最好情况的质量属性响应级别。

    (3)确定场景的优先级。项目关系人对场景进行投票,其投票是基于每个场景“所期望的”响应值,根据投票结果和票的权值,生成一个分值(场景的权值)。

    (4)分配效用。对场景的响应级别(最坏情况、当前情况、期望情况和最好情况)确定效用表

    (5)架构策略涉及哪些质量属性及响应级别,形成相关的策略—场景—响应级别的对应关系。

    (6)使用内插法确定“期望的”质量属性响应级别的效用。即根据第 4 步的效用表以及第 5 步的对应关系,确定架构策略及其对应场景的效用表。

    (7)计算各架构策略的总收益。根据第 3 步的场景的权值及第 6 步的架构策略效用表,计算出架构策略的总收益得分。

    (8)根据受成本限制影响的 ROI(Return On Investment,投资报酬率)选择架构策略。根据开发经验估算架构策略的成本,结合第 7 步的收益,计算出架构策略的 ROI,按 ROI 排序,从而确定选取策略的优先级。

    详细设计(接口设计)方面:

    面向对象软件设计原则:

    A.单一职责原则(SRP):

    一个类应该有且只有一个改变的理由。也就是解决职责不清的问题,通俗地讲,既当爹又当妈这种行为用在软件设计中是不可取的。采用这一原则进行设计的最大好处是提高软件的可靠性与可维护性。

    B.开放—封闭原则(OCP):

    在不用修改原有类的基础上就能扩展一个类的行为。如何正确理解“开放与封闭”,其对谁“开放”对谁“封闭”?这是我们理解这一原则的最大困难之处。它强调的重点在于“对于扩展它是开放的,对于修改它是封闭的”,其实也就是隔离变化,既达到职责单一又达到了扩展的目的。

    C.替换原则(LSP):

    派生类要与其基类自相容。也就是说“子类型必须能够替换掉它们的基类型”。这一原则其实是对OCP原则的扩展,它强调的重点其实就是“父为子纲”。没有父亲也就没儿子,这种继承关系始终如一,不得改变。这一常理在这一原则中倒是得到了很好的体现。

    D.依赖倒置原则(DIP):

    依赖于抽象而不是实现。还有一种说法:抽象不应该依赖于细节,细节应该依赖于抽象。就我个人的观点来讲,我不喜欢后面这种说法。它不简洁也容易让人误解。谁的抽象谁的细节?顺藤摸瓜,瓜是抽象,藤是细节。其实这里面包含了归纳的思想,那就是从细节上抽象出其本质的东西。我们依赖的就是这个抽象本质,而不是它的具体实现细节。这又回到我上一原则所讲的“父为子纲”。

    E.接口隔离原则(ISP):

    客户只要关注它们所需的接口。说得明白一点就是,“不应该强迫客户依赖于它们不用的方法。接口属于客户,不属于它所在的类层次结构”。如果我们把接口理解成角色,一个接口只是代表一个角色,每个角色都有它特定的一个接口,每个角色都服务于其客户端对象。那么用“投其所好”这个成语来形容这一原则,我觉得再恰当不过。虽然其意含贬义,但是它定制化服务、个性化服务则值得我们学习。这一原则强调了对软件实体通信之间的限制,它限制了通信的宽度,同时提供了一个指导化的设计思想,就是说通信要尽可能的窄,只投其所好。遵从这一原则带给我们的好处是:在软件系统功能需要扩展时,其修改的压力会最小。

    实际呢?

    所有人坐在一起吃下午茶-全凭经验和自己的理解情况

    最终目的: 达成统一思想,解决大家的分歧 。

    软件评估的结果:完成时间/内部的问题

    开发前准备工作

    1. 环境的安装搭建

    JDK版本与项目运行版本统一

    提问: 1.6编辑的程序是否可以在1.8上运行 ?版本向下兼容

    提问:怎么验证是否安装成功

    Eclipse安装 /sts安装

    Maven仓库安装

    存放Jar包 以及jar包管理

    svn权限申请/配置

    管理项目版本的工具

    GIT

    2. 梳理/熟悉《设计文档》

    3.给自己制定开发计划

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mrIoCXm7-1594531077347)(file:///C:\TMP\ksohtml6556\wps18.jpg)]

    4. 计划原则 (从主体出发 – 局部方法)

    意思是:准备写代码,应该先写那一部分呢?

    开发中注意事项

    1. 写注释

    作者

    时间

    版本号

    功能

    场景

    写注释原则: 1.有意义 2.正确描述 3必须最新

    2. 命名规范

    a) 方法命名采用大小写混合的形式。以小写字母开头,名字中其他单词的首字母以大写字母开头, 所有其它的单词都为小写字母;

    b) 方法的命名应该能描绘出方法的作用和功能,方法的名字建议使用祈使动词或者动词短语;

    selectUserById

    c) 获取或者设置类的某种属性的方法显式的命名为 getProperty()或者 setProperty()。其 中 property 是指类的属性的名字;

    d) 用于判断类的布尔属性的方法要显式的命名为 isProperty(),property 是指类的属性的名 字;

    isEntiy

    e) 用正确的反义词组命名具有互斥意义的变量或相反动作的函数。

    Int num;

    Int notNnum;

    3. 风格:

    A. 缩进 Tab

    B. 空格

    C. 对齐

    D. 空行

    备注:可以参考阿里的开发规范

    4. 记得备份/即使可以自动保存-注意项

    5. 版本上传/下载注意

    6. 开发中可以配置的尽量选择配置,代码要写得活络一些

    7. 开发时考虑到扩展性

    例如:功能性代码和工具类代码区分开

    8.开发中有问题及时反馈,很多开发做不到这一点

    展开全文
  • 在体系结构的设计、演化和...该方法利用时段时序逻辑对关注点之间的横切关系进行形式化描述和分析,可以发现横切关注点之间的时序冲突,有助于提高面向方面软件体系结构设计质量.最后结合案例给出了该方法的实施过程.
  • 软件体系结构1~5章知识点整理

    千次阅读 2020-08-13 11:05:17
    目录绪论第一章 软件工程和软件设计概述第二章 软件模型和描述第三章 软件体系结构建模和UML第四章 软件设计过程第五章 软件体系结构风格 绪论 案例一:圣·玛丽亚大教堂 案例二:瑞典瓦萨战舰 由建筑体系架构——&...
  • 从关联的角度考虑软件体系结构的组成, 用关联矩阵和关联基数矩阵描述软件体系结构及其动态演化的各项需求, 提出了一种基于关联矩阵的软件体系结构动态演化方法, 并设计相应的算法进行实现, 最后通过案例进行分析和...
  • 读过我这一系列文章的朋友一定听说过Apworks框架,虽然这个框架至今仍未成熟到能够用在真正的系统开发上,但它已经实现了CQRS体系结构模式,已经可以用于软件架构设计的演示上了。从这一讲开始,我将逐步介绍如何...
  • 软件体系结构的评估为提高软件质量、控制系统复杂性...最后对某保险案例体系结构设计方案进行对比与选择, 验证了方法的可行性及实用价值。两种技术的结合为更全面地进行面向方面软件体系结构的评估提供支持与参考。
  • 从关联的角度考虑软件体系结构的组成, 用关联矩阵和关联基数矩阵描述软件体系结构及其动态演化的各项需求, 提出了一种基于关联矩阵的软件体系结构动态演化方法, 并设计相应的算法进行实现, 最后通过案例进行分析和...
  • 读过我《领域驱动设计案例:Tiny Library》这一系列文章的朋友一定听说过Apworks框架,虽然这个框架至今仍未成熟到能够用在真正的系统开发上,但它已经实现了CQRS体系结构模式,已经可以用于软件架构设计的演示上了...
  • Library》这一系列文章的朋友一定听说过Apworks框架,虽然这个框架至今仍未成熟到能够用在真正的系统开发上,但它已经实现了CQRS体系结构模式,已经可以用于软件架构设计的演示上了。从这一讲开始,我将逐步介绍...
  • 面向模式的软件体系结构(卷3)

    热门讨论 2013-07-30 13:16:56
     我们经常在软件开发生命周期的后期才发现资源管理需求,而在这么晚的时候改变系统设计很困难。所以,在生命周期的早期执行这样的任务就很重要。因为属于不同领域的系统有不同的约束和需求,所以对某个特定系统或者...
  • 然后,提出了软件定义价格的概念,综合说明了SDN应用的特点,设计了基于软件定义价格的SDN 应用框架,并将其应用于OpenDaylight 开源项目;最后,给出了基于软件定义价格的虚拟租户网络测试案例。实验表明,用户可...
  • 这是看的第2类体系结构,不是有所收获:大致可抽象出一些常见设计的范式 1、体系结构现过程关键点:拆、定义接口/格式、合、出错处理 2、优点关注:重用度 “考虑到一般变更的设计是优秀系统深化的一个主要助推器” ...
  • 同时,我们希望为这些机器的软件系统设计人员提供对体系结构发展的可能方向的理解,以及确定硬件设计将遵循的特定路径的力量。 并行计算机体系结构中最近最令人兴奋的开发是传统上完全不同的方法(即共享内存、...
  • 软件开发领域中,从事数据库方向的人员,可以不甚了解硬件体系结构;从事计算机图形学的人,可以不懂SQL语言;做处理器设计的人员也可以不了解数据仓库。但是他们都必须掌握数据结构和算法,因为这是程序的灵魂。 ...
  • 软件设计的任务是将软件需求变换成为软件的具体设计方案。概要设计根据软件需求导出软件体系结构;详细设计给出软件模块的内部过程描述。该文档是设计结果的详细描述,也是程序员编写程序的功能依据。
  • 《数据结构课程设计案例精编(用C/C++描述)》

    千次下载 热门讨论 2008-10-08 10:33:11
    附:《数据结构课程设计案例精编(用C/C++描述)》一书简介 本书是数据结构案例教程,以软件重用为指导思想,以STL库中实现的数据结构(容器)为参照,重构了数据结构的视角和知识体系,并突出实战性和应用性。. 本书...
  • 未定义书签 1.1 QQ 空间系统概述 4 1.1.1 系统功能 4 1.1.2 系统的体系结构 5 1.1.3 开发环境 6 1.2 QQ 空间系统测试计划 7 1.2.1 测试需求 7 1 功能测试 7 2 性能测试 7 3 兼容性测试 7 1.2.2 测试资源 8 1 人力...
  • 全书为第1版,从基础知识开始入手,逐步介绍嵌入式处理器体系结构、网络设备、驱动程序、进程间通信以及程序建模与编程方面的相关知识。本书是嵌入式系统初学人员的理想学习资料,也可以作为嵌入式系统设计人员非常...
  • 提出一种软件体系结构... 该方法利用时段时序逻辑对关注点之间的横切关系进行形式化描述和分析, 可以发现横切关注点之间的时序冲突, 有助于提高面向方面软件体系结构设计质量. 最后结合案例给出了该方法的实施过程.

空空如也

空空如也

1 2 3 4 5 ... 17
收藏数 338
精华内容 135
关键字:

软件体系结构设计案例