博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
<Android+敏捷>:架构设计与代码造形
阅读量:5764 次
发布时间:2019-06-18

本文共 6657 字,大约阅读时间需要 22 分钟。

前言:其实大家都知道,架构师最关键的任务就是:接口(Interface)设计。所以,”足够好架构”的核心部分就是:接口的定义(Definition)和表述(Representation)。那么,有什么有效的方法能清晰而明确地定义和表述接口设计呢?

ee                                                                        ee

欢迎访问 ==>

高焕堂:MISOO(大数据.大思考)联盟.台北中心和东京(日本)分社.总教练

EE                                                                        EE

<Android+敏捷>:架构设计代码造形

前言

  在敏捷开发里,流行的敏捷设计观点是:“敏捷是把原来架构设计里的详细设计放到了编码的过程中,开发人员要有架构师的思维,架构师的预先架构设计要<正好足够>。”在敏捷中,将传统的架构设计分成:架构 + 设计。

  • 敏捷开发的架构师,将架构部分做到”足够好”即可。

  • 然后,将(详细)设计转移到代码撰写阶段、重构阶段、以及单元测试阶段等。

     简而言之,在敏捷中,架构设计仅止于”足够好”的架构,不进行详细设计。但详细设计仍然存在,只是转移到了开发阶段而已。这些详细设计需要花费大量的时间,包含详细的流程、数据结构等设计;而且在编程阶段,也蕴含了很多详细设计的内容。如果直接将设计表现于代码中(Code is design),就能避免开发人员同时既要维护一套设计,又要维护一套代码;可大幅减轻开发者的负担,提升效率。

1.  如何表述(Represent)”足够好的架构?

架构设计被切分为”足够好的架构”和”详细设计”两个部分,那么这两部分又如何相互衔接呢?

26193910-b4712d90f4544f609781542f2511e7b

其实大家都知道,架构师最关键的任务就是:接口(Interface)设计。所以,”足够好架构”的核心部分就是:接口的定义(Definition)和表述(Representation)。那么,有什么有效的方法能清晰而明确地定义和表述接口设计呢?

26193654-1d86607c7d8e4b5d99d35e2dfaf1792

答案是:代码造形(Code Form)。

26193745-f4d5ad00315a4c8eb090e0f1512fd57

2. 什么是代码造形?

顾名思义,代码造形就是代码层级的设计造形(Form)。代码造形就是开发者常用的词汇(Vocabulary),其能直接对映(Map)到程序语言的基本结构,此结构大多定义成为关键词(Key word)。例如,指令(Instruction)、函数(Function)和类(Class)[]

3. 代码造形在软件开发上的用处

  • 因为代码造形能直接对映到程序语言的结构,具有高度的精确性(Precision),架构师能准精确地传达设计的涵义。

  • 因为代码造形是开发者的词汇,架构师以<代码造形>表述架构,基于共同词汇,提升了共识(Shared Understanding),开发者很容易理解其架构的设计涵意。

  • 所以,代码造形能大幅提升开发者的效率;而且迅速配合需求变更、架构创新(或重构)设计,大幅提升了整体团队的敏捷性。

  • 架构师如同妈妈,使用kid language来与小孩交谈,非常有助于小孩语言天份的开发。同样地,架构师以<代码造形>来表述架构,来与开发者交谈;非常有助于开发者设计能力的提升。

  • 架构师自由创意去思考架构设计(加法设计),但是都以一致的<代码造形>来表述架构设计(减法设计)。就如同唐诗的<七言绝句>造形,李白、杜甫、白居易人人都能发挥创意、尽情思考,但都以一致的造形来表述(Representation)。不但没有伤害创意,而且还基于<诗同形>而相互激发创作的氛围。

  • 即使架构尚未达到”足够好”,只要能清晰而明确地表述,就能随着敏捷迭代而互相切磋着磨而达到”足够好”的境界了。

4.大家熟悉的2种代码造形:函数和类

在软件开发中,大家最熟悉的代码层级的基本造形有二:函数(Function)和类(Class)。

1970年代的主要造形:函数(Function)

像C语言的代码基本结构就是函数,例如:

        /* C语言程序代码 */

        int function add( int x, int y)

             {

               int sum;

               sum = x + y;
               return sum;
              }
         int function mul( int x, int y)
              {

                int sum;

                sum = x * y;
                return sum;
              }
   int function exec( int a, int b)
             {
                int k = mul( add(a, b), 100);
              }
         void main()

              {

                printf(“%d”, exec(3, 5));
               }

函数造形简单,其内部的组成要素是:指令(Instruction),或称叙述(Statement)。也有简单的造形组合规律:线性排列,并相互调用(Function call)。

1980年代的主要造形:类(Class)

  自从1980年代到今天,软件开发的主要造形是:类(Class)。类造形并不难理解,它只是对函数造形加以扩大;也就是以函数为基础(保留了函数的各项功能),扩大结合了属性(Attribute);让开发者拥有更大的视野,具有更好的整体观。就如同太极图,引导人们掌握更宏大的整体观。

27030835-57f95fbb6c2c41e487b471ce5950162

像C++语言的代码基本结构就是类,例如:

// C++程序代码

       class Calculator {
               int x, y, value;
           public:
               void set(m, n){
                      x = m;
                      y = n;
                   }
               void add() {
                      value = x + y;
                   }
               void mul() {
                      value = x * y;
                   }
               int get() {
                      return value;
                   }
           }
      //-----------------------------------------------
      class Adder extends Calculator {
             public:
                 int exec(int m, int n){
                      set(m, n);
                      add();
                      set(get(), 100);
                      mul();
                      return get();
                   }
            }
        //------------------------------------------------
        void main(){
               Adder adderObj = new Adder();
               printf(“%d”, adderObj.exec(3, 5);
        }

    自从1986年C++语言问世以来,类(Class)都是主要的软件代码造形(Form),例如C++、Objective-C、Java和C#等语言的主要代码造形就是类。 类造形内含2个要素(更小的组成单位):属性(Attribute)和函数(Function)。也有清晰的造形组合规律:定义了类与类之间的组合关系,例如上述范例里的”扩充( Extends)”关系等;并透过内含的函数来相互调用。

5. 介绍新的EIT代码造形

EIT造形的涵意

自从1996年Java问世之后,接口(Interface)成为Java语言的关键词(Key Word)。于是,<接口>的位阶已经提升了,其与<类>是同位阶了,而不再隐藏于类造形里。这意味着,我们可以设计一个更大的代码造形来包容类和接口两种元素。为了凸显接口角色,就得考虑两项特性:

  • 为了清楚地定义一个接口(主角),需要两个类来当配角。

  • 此外,接口以能实现为类(造形)。

于是,高焕堂 老师将3个<类造形>组合起来,成为一个更大的造形;就像生物DNA的螺旋结构,组合如下图:

27034153-a6212e88a60e47e09e4608d68095e39

在上图里,为于中间的类就是接口实现类。高老师将其命名为EIT造形:

27034211-26baed1eb1bb413c90f75330b1e0ff3

 EIT造形也不难理解,它只是对类造形加以扩大;也就是以类为基础(保留了类的各项功能),将3个类结合在一起,各扮演不同角色;让开发者拥有更大的视野,具有更好的整体观。例如,Java语言的程序:

class Tasks implements Runnable{

   public void run() {

             int sum = 0;
             for (int i = 0; i <= 100; i++)
                    sum += i;
                    System.out.println("Result: " + sum);
     }

}

// ----------------------------------------------------------
public class JMain {
     public static void main(String[] args) {
              Thread t = new Thread( new Tasks());
              t.start();
              System.out.println("Waiting...");
     }
}

 其主要意图是:凸显出<接口>元素与类同位阶的角色。为了清楚地定义一个接口(主角),需要两个类来当配角。例如,为了凸显Runnable接口,而且要精确地表述它,就需要Thread和Tasks两个类来陪衬,如下图:

27034609-2eaabc64566d4e689c2a5ff7b93f2b0

由于接口定义是架构师的主要职责,所以EIT可以协助架构师清晰地定义接口,非常有助于清晰表达架构。

EIT造形的重复组合

EIT造形也内部结构简单,也能透过内含的类的组合关系,将EIT造形组合起来,轻易地组合出大型而复杂的系统。例如,EIT造形能像DNA螺旋结构一样,组合起来:

27034741-034778a77b4e43de9b2ed805f182e9d

EIT造形提供更宏大的整体观,更易于重构,迅速从简单组合出复杂系统。

27034803-c486fc536fc540f48354441b9357f1a

 这是由两个EIT造形(即Thread造形和View造形)所组成的。

27034821-aee71ff457624b25a15c4c79465de6d

 在游戏软件应用上,这个Thread造形里的小线程(由UI线程所诞生的)扮演一个特殊的角色:成为游戏的主控循环(Game Loop),而UI线程则专注于响应UI 的事件,创造出两个线程完美分工。由于这个线程专注于游戏主控循环,所以又称为游戏线程(Game Thread)。游戏线程调用postInvalidate()函数,间接触发UI线程去调用invalidate()函数了,也触发View重新调用App子类的onDraw()去重新绘图了。现在就将上图落实为Android程序码,如下:

// GameLoop.java

package com.misoo.pk001;

public class GameLoop implements Runnable {

    myView mView;
    GameLoop(myView v){
              mView = v;
        }
    public void run() {
              mView.doUpdate();
              mView.postInvalidateDelayed(1000);
        }
}

// myView.java

package com.misoo.pk001;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;

public class myView extends View {

     private Paint paint= new Paint();
     private int x, y;
     private int line_x = 100;
     private int line_y = 100;
     private float count = 0;

     myView(Context ctx)

          { super(ctx); }
     public void doUpdate(){
            if( count > 12) count = 0;
            x = (int) (75.0 * Math.cos(2*Math.PI * count/12.0));
            y = (int) (75.0 * Math.sin(2*Math.PI * count/12.0));
            count++;
          }
     @Override protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.drawColor(Color.WHITE);
            paint.setColor(Color.BLUE); paint.setStrokeWidth(3);
            canvas.drawLine(line_x, line_y, line_x+x, line_y+y, paint);
            paint.setStrokeWidth(2); paint.setColor(Color.RED);
            canvas.drawRect(line_x-5, line_y - 5, line_x+5, line_y + 5, paint);
            paint.setColor(Color.CYAN);
            canvas.drawRect(line_x-3, line_y - 3, line_x+3, line_y + 3, paint);
            Thread gt = new Thread(new GameThread(this));
            gt.start();
       }

}

// myActivity.java

package com.misoo.pk001;
import com.misoo.pk001.R;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;

public class myActivity extends Activity implements OnClickListener {

      private myView mv = null;
      private Button ibtn;
     @Override protected void onCreate(Bundle icicle) {
             super.onCreate(icicle);
             show_layout_01();
      }
      public void show_layout_01(){
              LinearLayout layout = new LinearLayout(this);
              layout.setOrientation(LinearLayout.VERTICAL);
              mv = new myView(this);
              LinearLayout.LayoutParams param =
                       new LinearLayout.LayoutParams(200, 200);
              param.topMargin = 10;
              param.leftMargin = 10;
              layout.addView(mv, param);
              //----------------------------------------------
              ibtn = new Button(this);
              ibtn.setOnClickListener(this);
              ibtn.setText("Exit");
              ibtn.setBackgroundResource(R.drawable.gray);
              LinearLayout.LayoutParams param1 =
                             new LinearLayout.LayoutParams(200, 65);
              param1.topMargin = 10; param1.leftMargin = 10;
              layout.addView(ibtn, param1);
              //-----------------------------------------------
              setContentView(layout);
           }
      public void onClick(View v)
              { finish(); }
 }

   由于EIT造形只是对类造形加以扩大;也就是以类为基础(保留了类的各项功能),将3个类结合在一起,各扮演不同角色。所以,只要利用类造形既有的组合机制,就能将EIT造形组合起来,成为复杂的系统了。例如,也能组合如下图:

27034837-dab3dde00a314c3ba8cf7224287929f

通称为:双层EIT造形的架构设计。

转载地址:http://cbgkx.baihongyu.com/

你可能感兴趣的文章
objective-c内存管理基础
查看>>
sap关于价值串的说法(转载)
查看>>
Migration to S/4HANA
查看>>
sed 对目录进行操作
查看>>
什么是代码
查看>>
移动端开发单位——rem,动态使用
查看>>
系列文章目录
查看>>
手把手教你如何提高神经网络的性能
查看>>
前端布局原理涉及到的相关概念总结
查看>>
递归调用 VS 循环调用
查看>>
使用sstream读取字符串中的数字(c++)
查看>>
树莓派下实现ngrok自启动
查看>>
javascript静态类型检测工具—Flow
查看>>
MachineLearning-Sklearn——环境搭建
查看>>
node学习之路(二)—— Node.js 连接 MongoDB
查看>>
Goroutine是如何工作的?
查看>>
《深入理解java虚拟机》学习笔记系列——垃圾收集器&内存分配策略
查看>>
TriggerMesh开源用于多云环境的Knative Event Sources
查看>>
GitLab联合DigitalOcean为开源社区提供GitLab CI免费托管
查看>>
通过XAML Islands使Windows桌面应用程序现代化
查看>>