精华内容
下载资源
问答
  • (chenlil@cn.ibm.com), I/T 架构师, IBMElaine Zhan (ezhan@cn.ibm.com), 软件咨询工程师, IBM齐 克科 (qikeke@cn.ibm.com), I/T 架构师, IBM 2009 年 5 月 25 日本文介绍开发 JavaServerFaces(JSF)自定义复合组件

    陈 荔龙 (chenlil@cn.ibm.com ), I/T 架构师, IBM
    Elaine Zhan (ezhan@cn.ibm.com ), 软件咨询工程师, IBM
    齐 克科 (qikeke@cn.ibm.com ), I/T 架构师, IBM

     

    2009 年 5 月 25 日

    本文介绍开发 JavaServer Faces(JSF)自定义复合组件的新思路,提供如何快速开发可重用 JSF 组件的技巧,而不用像传统方式那样自己实现渲染器 (renderer)、状态管理和事件监听器。本文提供的原则和技术也对一般的 JSF 开发很有帮助。

    介绍

    JavaServer Faces(JSF)提供可扩展的组件模型,开发人员可以创建可重用的组件,使用这些自定义组件提高开发效率和降低开发成本。虽然对于定制和重用而言 JSF 的组件模型非常强大,但是开发人员普遍认为开发 JSF 自定义组件并不容易,因为通常至少需要熟悉 JSF encode/decode 和 state holder 的内部机制并覆盖相应的方法(参考“怀疑论者的 JSF: JSF 组件开发 ” 所述),如 encodeBegine()、decode()、saveState() 和 restoreState() 等,对于开发复杂的自定义组件,甚至需要深入理解更多的接口,如 NamingContainer、StateHolder、EditableValueHolder 和 ActionSource 等接口。

    然 而,重用 JSF 标准组件的功能可以极大地简化自定义组件的开发,尤其对于自定义复合组件更是如此。在大部分情况下,我们可以重用 JSF 框架已经提供的标准渲染器、状态管理、事件监听器、转换器和验证器。已有的文章或书籍对如何重用这些标准功能涉及很少,本文基于重用的策略提出快速开发 JSF 自定义复合组件的原则和技巧。

    本文首先总结了 JSF 组件开发的通用原则,然后通过一个例子(Value Scroller 自定义复合组件)的开发详解说明了哪些标准功能可以重用以及如何重用,以达到简化 JSF 自定义复合组件开发的目的。

     




    回页首


    原则与技巧

    开发 JSF 自定义复合组件主要有两个原则,一方面强调重用已有的标准组件;另一方面如何确保自定义组件易于重用。

    1. 尽可能的重用标准组件的功能和实现

      传 统的自定义复合组件开发建议完全覆盖实现 encode/decode 逻辑,但这样做耗费时间而且容易出错。毫无疑问,我们可以通过重用标准组件的渲染器等机制减少甚至根本不用自行编写这部分代码。另外,为了实现灵活的配置 和使用,自定义复合组件通常需要提供很多属性,我们需要写很多代码来处理这些属性的读写和状态管理。实际上,我们可以简单地把自定义复合组件的属性传递给 它自身包含的标准组件,由已有的标准代码去处理这些属性,而不用重复写这些代码。

    2. 清晰地分离组件类、标签类和模型类

      JSF 的组件模型建议在组件类、标签类和模型类之间有明确清晰的责任分配,以便于重用和扩展。组件类不应该依赖于 javax.faces.component.html 包,因为组件类不仅可以用于 HTML,而且还应该可以重用于其它标记语言(如 WML)。也就是说组件类不应该直接引用 javax.faces.component.html 包内的 HTML 组件。例如,在你的组件类中创建一个 HtmlCommandButton 的实例是不可取的,你应该考虑用 javax.faces.component 包中的 UICommand 。另一方面,如果你希望你的模型类可以重用于不同的 Web 框架,那么你的模型类就不应该依赖于 JSF 的任何包,即模型类只表示业务对象而不包含任何用户界面相关的组件、数据和状态。

    基于这些原则,对比传统方式和本文介绍的技巧,我们可以发现基于重用的开发策略会极大简化 JSF 自定义复合组件的编写。开发 JSF 自定义组件通常需要如下 3 个步骤(参考“怀疑论者的 JSF: JSF 组件开发 ”)。

    1. 扩展 UIComponent

      传统方式:创建一个类,扩展 UIComponent,保存组件状态,在 faces-config.xml 中注册组件

      重用技巧:

      1.  
        • 选择 UIPanel 作为布局容器,重用标准组件作为复合组件的子组件。
        • 实现内部动作监听器。
    2. 定义渲染器或者内联实现它

      传统方式:覆盖实现 encode/decode,在 faces-config.xml 中注册渲染器。

      重用技巧:重用标准渲染器类型。

    3. 创建自定义标签,继承 UIComponentTag

      传统方式:返回渲染器类型和组件类型,设置 JSF 表达式属性

      重用技巧:传递属性值给作为子组件的标准组件。

     




    回页首


    示例概述

    我们通过一个自定义复合组件 Value Scroller 的开发步骤说明如何运用多种技巧重用标准组件的功能和实现,达到简化开发易于重用的目的。 Value Scroller 可以让你通过点击增值或减值按钮来输入数值,而不用手工键入,如 图 1 所示。这个示例只包含最基本的功能,如只支持整型数值输入,但对于本文要介绍的内容已经足够了。


    图 1. 测试页面中的 Value Scroller
    图 1. 测试页面中的 Value Scroller

    图 2 说明了 Value Scroller 的基本类结构,遵循 MVC 模式。组件类 ValueScroller 扩展了 UIPanel,作为控制器(Controller)负责与用户的交互。标签类 ValueScrollerTag 继承了 UIComponentTag, 作为视图(View)处理页面显示。与 Value Scroller 绑定的值对象作为模型(Model)存储用户键入的数值。


    图 2. Value Scroller 的类结构
    图 2. Value Scroller 的类结构

    在后面章节中,本文将结合 Value Scroller 示例说明如何应用前面提到的原则和技巧快速开发 JSF 自定义复合组件。

     




    回页首


    选择 UIPanel 作为容器

    创 建 JSF 自定义复合组件的第一步就是要选择一个标准组件类进行扩展。通常我们会考虑将这个组件类作为容器,在其中嵌入子组件,从而构成复合组件。这里选择继承 UIPanel 作为 Value Scroller 的容器,以 Grid 的方式渲染生成页面,并且其中包含一个 UIInput 和两个 UICommand,分别作为数值输入框和加减值按钮,如 清单 1 所示:


    清单 1. 扩展类 UIPanel

    				
    public class ValueScroller extends UIPanel {
    /**
    * The default constructor
    *
    */
    public ValueScroller() {
    super();
    addChildrenAndFaces();
    }
    }

     

    作为 Value Scroller 子组件的那些标准组件将在 addChildrenAndFaces 方法中加入布局容器之中。

     




    回页首


    重用标准渲染器类型

    接 着,我们开始创建 Value Scroller 的子组件,并且实现渲染器的功能。按照传统方式,必须覆盖 UIComponent 的 encodeBegin() 和 decode() 方法,但是,如果我们开发的复合组件只是由多个标准组件构成,我们完全可以将不依赖于特定标记语言的标准组件基类加入到自定义组件中,并且为每个标准组件 设定一个标准的渲染器类型,就可以完成复合组件要实现的渲染器功能。重用标准组件渲染器类型好处在于两方面:减少开发的工作量和可能出错的机会,对于 JSF 初学者尤为重要;不用实现与特定标记语言相关的 encode/decode 逻辑,使组件类更易于重用。

    JavaServer Faces 实战 ” 这本书列出了 JSF 规范提供的标准渲染器类型。


    表 1. JSF 标准渲染器

    控件族 组件类 渲染器类型 HTML 渲染结果
    ImageHtmlGraphicImageImage显示图片
    InputHtmlInputHiddenHidden隐藏类型输入字段
    HtmlInputSecretSecret密码类型输入字段
    UIInput, HtmlInputTextText文本类型输入字段
    HtmlInputTextareaTextarea多行输入字段
    MessageUIMessage, HtmlMessageMessage特定组件消息
    MessagesUIMessages, HtmlMessagesMessages所有消息
    OutputHtmlOutputFormatFormat输出参数化文本
    HtmlOutputLabelLabel输入字段的文本标签
    HtmlOutputLinkLink未与命令关联的链接
    UIOutput, HtmlOutputTextText普通文本
    PanelHtmlPanelGridGrid可定制的表格
    HtmlPanelGroupGroup将所包含组件归为一组
    CheckboxHtmlSelectBooleanCheckboxCheckbox单个复选框
    SelectManyHtmlSelectManyCheckboxCheckbox一组复选框
    UISelectMany, HtmlSelectManyListboxListbox可多选的列表框
    HtmlSelectManyMenuMenu可多选的菜单
    SelectOneHtmlSelectOneRadioRadio单选钮
    HtmlSelectOneListboxListbox单选列表框
    UISelectOne, HtmlSelectOneMenuMenu单选菜单

     

    表 1 可以看出,一个组件基类通常对应于多个渲染器类型(如果使用 HTML 作为标记语言,即对应于多个 HTML 元素),因为组件基类只定义了通用的数据和行为。比如说,UICommand 有两个 HTML 子类 HtmlCommandButton 和 HtmlCommandLink,分别对应于渲染器类型 javax.faces.Link 和 javax.faces.Button 。当我们想在一个复合组件内部包含一个链接时,只需要创建一个 UICommand 实例,并将其渲染器类型设置为 javax.faces.Link,而不用从头覆盖实现 encodeBegin() 和 decode() 方法。清单 2 列出了 Value Scroller 中的子组件如何在组件类 ValueScroller 中被创建,以及渲染器等属性如何被设定。


    清单 2. 重用标准渲染器创建自定义复合组件

    				
    private static final String PANEL_GRID_RENDERER = "javax.faces.Grid";
    private static final String INPUT_TEXT_RENDERER = "javax.faces.Text";
    private static final String COMMAND_LINK_RENDERER = "javax.faces.Link";
    private static final String GRAPHIC_IMAGE_RENDERER = "javax.faces.Image";

    /**
    * Add children to the base container
    *
    */
    private void addChildrenAndFaces() {

    // Set attributes of the base container
    this.setRendererType(PANEL_GRID_RENDERER);
    this.getAttributes().put(COLUMNS_ATTRIBUTE, new Integer(2));

    // Add the input component
    input = new UIInput();
    input.setId(INPUT_ID);
    input.setRendererType(INPUT_TEXT_RENDERER);
    this.getChildren().add(input);

    // Add the container of the up and down links
    UIPanel linkContainer = new UIPanel();
    linkContainer.setId(LINKPANEL_ID);
    linkContainer.setRendererType(PANEL_GRID_RENDERER);
    linkContainer.getAttributes().put(COLUMNS_ATTRIBUTE, new Integer(1));
    ScrollerActionListener listener = new ScrollerActionListener();

    // Add the up link
    UICommand upLink = new UICommand();
    upLink.setId(UPLINK_ID);
    upLink.setRendererType(COMMAND_LINK_RENDERER);
    upLink.addActionListener(listener);
    UIGraphic upImage = new UIGraphic();
    upImage.setId(UPIMAGE_ID);
    upImage.setRendererType(GRAPHIC_IMAGE_RENDERER);
    upImage.setUrl(UPIMAGE_URL);
    upLink.getChildren().add(upImage);
    linkContainer.getChildren().add(upLink);

    // Add the down link
    UICommand downLink = new UICommand();
    downLink.setId(DOWNLINK_ID);
    downLink.setRendererType(COMMAND_LINK_RENDERER);
    downLink.addActionListener(listener);
    UIGraphic downImage = new UIGraphic();
    downImage.setId(DOWNIMAGE_ID);
    downImage.setRendererType(GRAPHIC_IMAGE_RENDERER);
    downImage.setUrl(DOWNIMAGE_URL);
    downLink.getChildren().add(downImage);
    linkContainer.getChildren().add(downLink);
    this.getChildren().add(linkContainer);
    }





    回页首


    将属性值传递给标准组件

    我们先看一下标签描述文件(TLD)中定义的 Value Scroller 提供的属性。


    清单 3. 在 TLD 中定义自定义复合组件的属性

    				
    <tag>
    <name>valueScroller</name>
    <tag-class>component.taglib.ValueScrollerTag</tag-class>
    <body-content>JSP</body-content>
    <attribute>
    <name>id</name>
    <description>ValueScroller ID</description>
    </attribute>
    <attribute>
    <name>value</name>
    <description>ValueScroller value</description>
    </attribute>
    <attribute>
    <name>size</name>
    <description>Input field size</description>
    </attribute>
    <attribute>
    <name>min</name>
    <description>Minimum value</description>
    </attribute>
    <attribute>
    <name>max</name>
    <description>Maximum value</description>
    </attribute>
    <attribute>
    <name>step</name>
    <description>Scrolling step</description>
    </attribute>
    </tag>

     

    我 们看到,除了 min/max/step 是自定义的属性之外,其他的都属于 JSF 标准组件的属性,可以直接传递给构成 Value Scroller 的标准组件处理,完全不用为这些标准组件的属性覆盖实现方法 saveState() 和 restoreState() 。

    通常有两种方法传递属性值。当你需要对属性进行一些额外的操作(如验证或者转换等),可以在标签类 ValueScrollerTag 中将属性传递给自定义组件类,如下所示:


    清单 4. 传递自定义属性

    				
    /**
    * Override the setProperties method
    */
    protected void setProperties(UIComponent component) {
    super.setProperties(component);

    ValueScroller vs = (ValueScroller)component;

    Application app = FacesContext.getCurrentInstance().getApplication();
    // Set value attribute
    if (value != null) {
    if (isValueReference((String)value)) {
    ValueBinding vb = app.createValueBinding((String)value);
    vs.setValueBinding("value", vb);
    } else {
    throw new IllegalArgumentException("The value property must be a value " +
    "binding expression that points to a bean property.");
    }
    }

    // Set id attribute
    if (id != null) {
    vs.setId((String)id);
    }

    // Set other attributes
    vs.setMin(min);
    vs.setMax(max);
    vs.setStep(step);

    }

     

    另外一种方法就是在标签类 ValueScrollerTag 中直接把属性值加入相应标准组件的属性 Map 。例如,将 size 属性传递给自定义复合组件包含的 UIInput:


    清单 5. 传递标准属性

    				
    vs.findComponent("input").getAttributes().put("size", new Integer(size));





    回页首


    实现内部动作监听器

    在 Value Scroller 中,点击增值或减值按钮,输入框内的值会随之增大或者减小。我们可以简单地在组件类 ValueScroller 中实现一个内部动作监听器,重用 UICommand 的事件处理逻辑。


    清单 6. 实现 Value Scroller 动作监听器

    				
    /**
    * Internal action listener for Value Scroller
    * _cnnew1@author cll
    *
    */
    private class ScrollerActionListener implements ActionListener {
    public void processAction(ActionEvent e) {
    // Only Integer is supported for this demo
    if (input.getValue() instanceof Integer) {
    String commandId = ((UICommand)e.getSource()).getId();
    int value = ((Integer)input.getValue()).intValue();
    // Increase value if the up link is clicked
    if (commandId.equals(UPLINK_ID)) {
    if (value + getStep() > max) {
    input.setValue(new Integer(max));
    } else {
    input.setValue(new Integer(value + getStep()));
    }
    }
    // Decrease value if the down link is clicked
    else if (commandId.equals(DOWNLINK_ID)) {
    if (value - getStep() < min) {
    input.setValue(new Integer(min));
    } else {
    input.setValue(new Integer(value - getStep()));
    }
    }
    } else {
    throw new IllegalArgumentException(
    "Unsupported binding type, " +
    "and only Integer instance allowed for this demo.");
    }
    }
    }

     

    最后,在调用 addChildrenAndFaces 方法创建添加子组件的时候,将这个自定义动作监听器添加到增值和减值组件中去。


    清单 7. 注册 Value Scroller 动作监听器

    				
    ScrollerActionListener listener = new ScrollerActionListener();
    upLink.addActionListener(listener);
    downLink.addActionListener(listener);





    回页首


    使用 Value Scroller

    Value Scroller 的开发已经完成,使用也非常简单,首先在 faces-config.xml 中声明引用 Value Scroller,如下所示:


    清单 8. 在 faces-config.xml 中声明引用 Value Scroller

    				
    <component>
    <component-type>xyz.ValueScroller</component-type>
    <component-class>
    component.ValueScroller
    </component-class>
    </component>

     

    然后,在测试 JSP 页面 Test.jsp 上包含 Value Scroller 的标签描述文件。


    清单 9. 在 JSP 中包含 Value Scroller 的 TLD

    				
    <%@ taglib uri="/WEB-INF/lib/ValueScroller.tld" prefix="xyz"%>

     

    最后,在 Test.jsp 页面上使用 Value Scroller 的标签,并且指定 size/min/max/step 属性值,部署运行,就可以看到 图 1 所示的结果了。


    清单 10. 在 JSP 中创建 Value Scroller 并设置属性

    				
    <xyz:valueScroller value="#{pc_Test.itemCount}" size="5" min="-50" max="10000" step="2">
    </xyz:valueScroller>





    回页首


    结束语

    我 们可以看到,本文介绍的自定义复合组件 Value Scroller 的实现没有编写 encode/decode 和 state/event 管理相关的逻辑,简单、快速、并且易于重用。本文总结的 JSF 自定义复合组件的开发技巧在很大程度上降低了复杂度和工作量,优于传统的开发方式。





    回页首

     

    展开全文
  • 复合材料建模分析与固化切削仿真技术 ① 一、Abaqus复合材料建模基础 二、ABAQUS入门基础:层合结构建模,静力分析为例 三、ABAQUS进阶学习:纤维增强材料(失效分析及非标实验方案设计的应用) 颗粒/短纤维(拉压/...

    在这里插入图片描述

    复合材料建模分析与固化切削仿真技术

    一、Abaqus复合材料建模基础
    二、ABAQUS入门基础:层合结构建模,静力分析为例
    三、ABAQUS进阶学习:纤维增强材料(失效分析及非标实验方案设计的应用)
    颗粒/短纤维(拉压/剪切性能分析)
    四、渐进损伤、界面开裂扩展和大变形的多重非线性复材加筋板压溃分析
    五、筋条/蒙皮界面开裂及扩展过程的薄壁加筋结构后屈曲分析
    六、大型复杂复合材料处理操作流程,了解结构建模思路及技巧(航空舱案例

    七、ABAQUS二次开发与MATLAB软件连用建模
    八、复合结构的自由振动、动力响应、低速冲击、高速冲击分析
    九、SCI论文撰写解析及创新思路写作技巧


    一、COMSOL 复合材料建模建模
    实例分析:母线板中的电加热
    实例分析:层压复合壳热膨胀
    二、结构固化实例进阶
    复合材料结构固化过程热-流-固多场强耦合数值仿真
    复合材料结构微波固化过程数值仿真
    三、微观切削实例进阶
    复合材料微观几何建模方式(ABAQUS,Digimat,Python)及切削加工仿真后处理
    四.宏观钻削实例进阶
    复合材料(CFRP/TC4)叠层结构宏观钻削建模以及计算结果分析
    详细内容请私信我

    展开全文
  • 复合材料建模分析与固化切削仿真技术 ① 一、Abaqus复合材料建模基础 二、ABAQUS入门基础:层合结构建模,静力分析为例 三、ABAQUS进阶学习:纤维增强材料(失效分析及非标实验方案设计的应用) 颗粒/短纤维(拉压/...

    在这里插入图片描述

    复合材料建模分析与固化切削仿真技术

    一、Abaqus复合材料建模基础
    二、ABAQUS入门基础:层合结构建模,静力分析为例
    三、ABAQUS进阶学习:纤维增强材料(失效分析及非标实验方案设计的应用)
    颗粒/短纤维(拉压/剪切性能分析)
    四、渐进损伤、界面开裂扩展和大变形的多重非线性复材加筋板压溃分析
    五、筋条/蒙皮界面开裂及扩展过程的薄壁加筋结构后屈曲分析
    六、大型复杂复合材料处理操作流程,了解结构建模思路及技巧(航空舱案例

    七、ABAQUS二次开发与MATLAB软件连用建模
    八、复合结构的自由振动、动力响应、低速冲击、高速冲击分析
    九、SCI论文撰写解析及创新思路写作技巧


    一、COMSOL 复合材料建模建模
    实例分析:母线板中的电加热
    实例分析:层压复合壳热膨胀
    二、结构固化实例进阶
    复合材料结构固化过程热-流-固多场强耦合数值仿真
    复合材料结构微波固化过程数值仿真
    三、微观切削实例进阶
    复合材料微观几何建模方式(ABAQUS,Digimat,Python)及切削加工仿真后处理
    四.宏观钻削实例进阶
    复合材料(CFRP/TC4)叠层结构宏观钻削建模以及计算结果分析
    详细内容请点击:https://mp.weixin.qq.com/s/BfMQDF1Fini05dm-wQreow

    展开全文
  • 程序员写好技术文章的几点小技巧

    千次阅读 2021-04-08 14:40:30
    作者 | 门柳来源 | 阿里技术公众号去年成为了内网技术分享平台的年度作者,受邀写一篇关于“如何写好文章”的文章。我本身并不喜欢写字,去年写的几篇文章,涉及的话题自带流量,所以阅读量多了一些,谈不上有多擅长...
    简介:其我本身并不喜欢写字,之前写的几篇文章,涉及的话题自带流量,所以阅读量多了一些,谈不上有多擅长。不过我还是分享一下我自己写文章时用到的一些小技巧吧,希望对大家有帮助。

    image.png

    作者 | 门柳
    来源 | 阿里技术公众号

    去年成为了内网技术分享平台的年度作者,受邀写一篇关于“如何写好文章”的文章。我本身并不喜欢写字,去年写的几篇文章,涉及的话题自带流量,所以阅读量多了一些,谈不上有多擅长。不过我还是分享一下我自己写文章时用到的一些小技巧吧,希望对大家有帮助。

    一 最重要的是内容

    和所有人强调的一样,好文章最重要的是要有好的内容,好的技术文章要让读者有益。如果你想写一篇爆款文章,但是又觉得没有内容可写,那就不要勉强了,放下笔,合上电脑,有这个时间不如去看书打游戏。

    如何让自己有源源不断的内容可写?这与平时的积累有关,多阅读,多思考,多写作,真正的技巧无外乎这些。方法论层面的东西不再赘述,我重点讲几个具体的小技巧,直接“授之以鱼”。

    二 优秀技术文章的特点

    1 阅读量 ≠ 文章质量

    有些文章标题比较吸引眼球,有些话题自带流量,有些内容的受众比较广,所以有很高的阅读量,但这并不代表文章本身的质量。

    前几天无意翻到一篇《超长用户行为建模在躺平家居内容推荐中的应用实践》,我觉得写得不错,但是内容我完全看不懂,是专业领域的文章,受众不多,有上千的阅读量就已经很不错了。但是另一篇《如何画好一张架构图?》就有超过 3W 的阅读量。当然反例也有很多,就不再列举了。我自己写的几篇讲技术细节的文章,就没有讲技术对比、讨论技术发展的文章阅读量高。内容越专越细,能读下来的人就越少,但并不代表文章质量不高,反之亦然。

    技术文章盲目追求阅读量和点赞数不是件好事,所以第一个小建议就是不要太关注阅读量和点赞数,写的文章对别人有用,才是最有成就感的。至于除了阅读量和点赞数以外,还有什么指标可以衡量一篇文章的好坏,欢迎大家留言讨论。

    2 文章要长长长长长长长长长长长长长长长(也别太长)

    我翻了几篇阿里技术公众号里阅读量较高的文章,各种话题都有,风格差异很大,但是有一个共同点:文章写得很长。这并不代表文章写了很多字就是好文章,背后的真实含义是:好文章的内容足够丰富。

    内容丰富详实,这是一篇好文章的必要条件。还有一个条件是要包含真正有价值的内容,不能含太多水分。

    提供一个小技巧:如果你写了一篇文章但是觉得内容很单薄,可以先当成一篇笔记存起来,等有了更丰富的积累之后再整理成文章。扩展文章内容的方法,并不是添加无意义的空话套话,而是根据文章探讨的问题延展开来。

    比如说介绍自己解决的一个老大难 Bug,可能真正修改的代码并没有几行,把过程讲出来也不过寥寥几段。这时候你就可以再分析一下 Bug 存在的原因,为什么一直拖到现在,再思考一下如何避免这类问题,遇到同类 Bug 怎样快速排查。这样自己想问题的角度更全面了,文章内容也更丰富了。

    比如你想介绍一项自己在学的新技术,发现自己写的东西其实就是官方文档的简化版,去重之后几乎什么都不剩了。这时候不要再继续抄文档了,把自己的思考总结先记下来,继续学习技术,持续记录新的内容,有更全面的了解之后,再写文章。

    3 清晰的叙事结构

    优秀的技术文章,结构一定是清晰的,有可能目录就代表了某个技术体系,或者代表了解决问题的思路。

    优秀的内容 + 清晰的结构 = 好文章

    能把技术问题讲清楚,就很考验表达能力,这是大部分程序员比较欠缺的。对于技术类文章,常见套路也不多,我简单介绍两类吧:

    • 线性叙事,逐步推进:适用于介绍排查问题的过程、分享设计思路、介绍项目的迭代进展。
    • 结构化叙事,层层展开:适用于讲规划、做总结、画大图、介绍一整套技术方案。

    4 线性叙事,逐步推进

    对于这类文章,读者是应该按顺序一段一段看的,写的时候脑海中模拟读者的视角来写。这类文章的小技巧就是:模拟读者视角,设定一条主线,有节奏的向前推进。和讲故事差不多,每一步的推进要有逻辑,要保持思路不要断掉。

    有时候稍微加点趣味也是不错的,比如《Flutter Widget 和 CSS 布局原理 PK》这篇文章,目标是分析 Widget 和 CSS 的设计差异,我把文章写成一场比赛,先介绍参赛选手,然后分了 5 个 Round 开始 Battle,然后是 Love&Peace,最后一个 Happy Ending。

    另外一篇《记一次完整 C++ 项目编译成 WebAssembly 的实践》介绍了自己尝试新技术的心路历程,先介绍背景,再分析需求做拆解,然后讲尝试了什么方案,遇到了什么坑,又继续试其他方案,最终是什么结果。读起来比较流畅。

    5 结构化叙事,层层展开

    除了按顺序看的,还有不按顺序看的文章吗?有的,尤其在专业的技术文章里很常见,大部分是“总-分”的结构,先讲整体框架,再分章节介绍各个部分。

    比较常见的是那种总结型的文章,比如《平台建设的7大问题:蚂蚁AI平台实践深度总结》和《救火必备!问题排查与系统优化手册》,就是翻阅性质的书,可以通读一遍,也可以只看其中一段,之后遇到相关的问题,根据目录跳着阅读。

    对于文思泉涌的人,可以一口气把整篇文章写完。但实际情况是,很多时间被碎片化,可能还要引用一些专业内容,可能需要查资料,写文章的过程会被中断。这类文章不是一口气写完的,是先搭架子再填充完整的。其实写起来也很简单:先想好标题,再划分好目录结构,再一段一段的填充内容,最后再润色一下连接部分。文章可以不按顺序看,也可以不按顺序写。

    我自己写的《关于浏览器、Weex、Flutter 的比较和思考》这篇文章就是先划分好了目录,再一点一点填充的,写文章的时间跨度也比较长,想起来一点写一点。

    线性叙事是个链表,结构化叙事是树。

    三 提升写作技巧

    我初高中的时候比较喜欢看闲书,偶尔自己写点东西,但是我作文考得并不高,这里大言不惭地聊一下怎么写作文吧哈哈哈哈哈。只讲怎么写技术文章,并不能提升任何文学功底,但说不定能帮你避开一些小坑。

    1 碎片化记录,结构化整理

    大部分人的问题是不知道该写什么,即使已经有足够的积累,有明确的话题要写,也不知道该如何下笔。这就要靠日常的积累了。

    在平时工作的时候,可以建个文档库,把日常的一些琐碎的想法记录下来,随时写随时存。我是用手机的便签 App 随手记东西,比较喜欢它的语音转汉字功能,工作相关、生活相关,随时随地想起任何话题都可以记录下来。

    在有了明确话题,准备写文章之前,先把各种碎片化的记录收集起来,形成一份“素材”文档,然后梳理文章脉络,把素材应用进去。操作起来很简单,刚开始的时候会遇到前后不通畅的问题,那就不要直接复制素材的内容,重新换个表达方式写出来。多练习练习就好了。

    2 刻意练习,先写再改

    有了素材之后,平时可以专门练习写作能力,先写一小段话,明确的描述一个观点,然后不断修改。其实写周报就是一个很好的锻炼机会(现在不要求写了,自行练习),练习把做的事情描述清楚,说话的方式简单点,不要用太多高大上的词汇。最关键的部分在于:写完花五分钟再改一遍!读一下是否通顺,有没有把问题讲清楚。反复修改才是提升写作技巧的关键。

    用周报举例有点奇怪,毕竟是邮件类型的东西,和写文章差别很大,还是不要乱改周报了,改自己以前写的文章吧。找一篇自己以前写的,内容很不错但是写得不太行的文章,重写一遍!这个过程既温习了技术,又锻炼了写作技巧。不要觉得无聊浪费时间,亲测很有效的。

    3 注意排版和语法细节

    对于不拘一格的程序员来说,写出来的文章没有排版,就是家常便饭。不需要追求高级的排版技巧,稍微注意一下几个常见的问题就好了。

    正确使用标点符号(没想到我居然在讲这个……)

    大部分的文章里就只有逗号和句号,逗号和句号也是看心情随意划分,键盘上按到哪个是哪个。其实还有单双引号、顿号、冒号、分号、叹号、破折号、省略号、书名号、中文括号「」【】等等…… 使用方法可以去网上搜,这部分我觉得问题很常见,就单独多讲了两句。对了,中文文章要用全角标点符号,尽量不要混用英文标点符号。

    添加多种展现形式,可参考 GitHub 的 Markdown 语法

    如果全都是普通段落,看起来太平,可以加上无序列表、有序列表、段落引用、表格等等。行内排版可以加上粗体、斜体、代码标记等,偶尔还可以用删除线。

    其他还有一些小的建议:

    • 区分大标题小标题,分配的均匀一些,最多不要超过三层。
    • 每个章节的长短也尽量均匀一些,太长的内容就拆个小标题。
    • 重要数据给出明确的数据源,扩展信息给出资料连接。
    • 中英文混写的时候,在中间加一个空格。
    • 注意英文的大小写,尤其是专业名词的缩写。
    • 英文喜欢长句,复合从句一层套一层;中文追求言简意赅,错落有致,可以多加标点符号,把长句分隔开。
    • 写完之后通读一遍,尽量少写错别字……

    最后一个小技巧:多用图片。即使图片里只有文字,信息量也远超文字。

    image.png

    然而我这篇文章并没有加很多图片,因为这并不是一篇技术文章,大家在讲技术原理的时候要多用图片,一图胜千言!

    四 写在最后

    最后一个小建议:文章写多了就可以逐渐形成自己的风格,让所有文章都保持某种共性。

    比如我每篇文章最后都会发招聘信息!

    欢迎优秀的你加入淘系技术部-跨平台技术团队!一起打造靠谱的跨平台方案。这里有手淘核心链路在使用的 DinamicX、淘系的 H5 容器、Weex、淘宝小程序容器。淘系的基础架构、研发支撑是隔壁的兄弟团队,我们在广泛的支撑新零售的业务。技术深度足够深,业务场景足够丰富,欢迎优秀的小伙伴来一起搞事情,手淘跨平台技术团队欢迎你的加入!(请联系 hanks.zh@alibaba-inc.com )

    原文链接:https://developer.aliyun.com/article/783387?

    版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
    展开全文
  • 云创硬见是国内最具特色的电子工程师社区,融合了行业资讯、社群互动、培训学习、活动交流、设计与制造分包等服务,以开放式硬件创新技术交流和培训服务为核心,连接了超过30万工程师和产业链上下游企业,聚焦电子...
  • 10月专题——【“复合材料建模分析与固化切削仿真技术”】 专题一:【ABAQUS复合材料建模技术与应用】 复合材料层合结构建模、静力失效分析 纤维增强复合材料层合板分层和界面损伤与扩展分析、拉伸强度、压缩强度...
  • 复合分页控件

    千次阅读 2006-03-23 16:40:00
    创建用于 ASP.NET 的分页程序控件Dino EspositoWintellect2003 年 10...还为开发复合 ASP.NET 控件提供了很多有用的提示和技巧。 下载本文的源代码(英文)。(请注意,在示例文件中,程序员的注释使用的是英文,本文中
  • 通过对excel技术论坛上上百万提问的分析与提炼,本书汇集了用户在使用excel图表过程中最常见的需求,通过190多个技巧的演示与讲解,将 excel高手的过人技巧手把手教给读者,并帮助读者发挥创意,灵活有效地使用excel...
  • 工程管理作为工程技术与管理交互复合型,而这一份工程投标策略技巧汇编则可以帮助更好更快的了解与工程投...该文档为工程投标策略技巧汇编,是一份很不错的参考资料,具有较高参考价值,感兴趣的可以下载看看
  • abaqus复合材料建模与应用技术,开展新型复合材料研发、复合材料性能预测、先进复合材料应用以及工业化生产等各个环节,提高复合材料研发与应用效率 1、ABAQUS 建模基础操作入门学习-以复合材料层合结构建模、静力...
  • abaqus复合材料建模与应用技术,开展新型复合材料研发、复合材料性能预测、先进复合材料应用以及工业化生产等各个环节,提高复合材料研发与应用效率 1、ABAQUS 建模基础操作入门学习-以复合材料层合结构建模、静力...
  • 复合材料建模分析与固化切削仿真技术 ① 一、Abaqus复合材料建模基础 二、ABAQUS入门基础:层合结构建模,静力分析为例 三、ABAQUS进阶学习:纤维增强材料(失效分析及非标实验方案设计的应用) 颗粒/短纤维(拉压/...
  • 目的:本示例主要想说明,如果使用Hibernate开发遗留数据库,那么经常会遇到这种情况,作为Java程序员必须掌握这种技巧。希望给你在使用Hibernate开发时带来方便。注意:复合主键类我使用内部类来实现--本人觉得这种...
  • 背景:协调能力是提高学习者/玩家技术性能所必需的最重要因素之一,它根据技能的要求因技能而异,复合击剑技能的性能取决于玩家控制游戏的能力。身体不同部位的工作涉及履行一定的机动职责。 这项研究的重要性是,它...
  • Excel 使用技巧集锦——163种技巧

    千次阅读 2013-06-11 11:02:35
    Excel 使用技巧集锦——163种技巧   目 录 一、基本方法 7 1. 快速选中全部工作表 7 2. 快速启动Excel7 3. 快速删除选定区域数据 7 4. 给单元格重新命名 7 5. 在Excel中选择整个...
  • 工程管理作为工程技术与管理交互复合型,而这一份招标投标项目选择方法与技巧则可以帮助更好更快的了解与...该文档为招标投标项目选择方法与技巧,是一份很不错的参考资料,具有较高参考价值,感兴趣的可以下载看看
  • 说说复合索引 写索引的博客太多了,一直不想动手写,有一下两个原因:一是觉得有炒剩饭的嫌疑,有兄弟曾说:索引吗,只要在查询条件上建索引就行了,真的可以这么暴力吗?二来觉得,索引是个非常大的话题,很难概括...
  • ABAQUS中的纤维增强复合材料建模 纤维增强复合材料(Fiber Reinforced Polymer /Plastics,简称FRP),由纤维材料与基体材料经过缠绕,模压或拉挤等成型工艺而形成的复合材料。常用的增强纤维材料有碳纤维、玻璃...
  • 工程管理作为工程技术与管理交互复合型,而这一份国内外投标报价的技巧分析和策略方法则可以帮助更好更快...该文档为国内外投标报价的技巧分析和策略方法,是一份很不错的参考资料,具有较高参考价值,感兴趣的可以...
  • 在具体的使用过程中,复合机设备强大的功能往往都会在其操控面板上体现出来,这样就需要用户对于设备操控面板的的具体功能分布和使用技巧有了一定了要求。目前,主流的复合机设备往往都搭载了大尺寸...
  •  视频采集卡的主要功能和技术  接口:现在市场上的视频采集卡接口能分为几种,视频采集卡的接口包括视频与PC机的接口和与模拟视频设备的接口。目前PC视频采集卡通常采用32位的PCI总线接口,它插到PC机主板的扩展...
  • sklearn之pipeline:pipeline的简介、使用技巧、案例应用之详细攻略 目录 sklearn.pipeline函数简介 1、Why pipeline管道机制? 2、Pipeline函数解释 pipeline的案例应用 sklearn.pipeline函数...
  • 14.4 复合文档 319 第15章 分布式程序设计 329 15.1 CORBA结构 329 15.1.1 CORBA在数据库的应用 335 15.1.2 远程访问 341 15.1.3 OSFind 341 15.2 远程数据集 342 15.2.1 基础 342 15.2.2 扩展服务器 346 15.2.3 ...
  • ActiveX是从Microsoft的复合文档技术——OLE成长起来的。OLE最初发布的版本,只是瞄准复合文档,但在后续版本OLE2中,导入了COM。COM是应OLE设计者的需求而诞生的。其基本的出发点是想让某个软件通过一个通用的机构为另...
  • 有限元法在复合材料部件的工程设计和科研领域得到了越来越广泛的重视和应用,从航空航天、交通运输到能源环境等几乎所有的设计制造都已离不开有限元分析计算。对于先进的复合材料来说,通过...基于虚裂纹闭合技术(VCC...
  • Linux技巧小总结

    千次阅读 2005-12-23 11:24:00
    Linux技巧小总结1、处理特殊的文件名假设Linux系统中有一个文件名叫“-aaa”,如果我们想对它进行操作,例如现在要删除它,如果我们按照一般的删除方法在命令行中输入rm -aaa命令,界面将会提示我们是无效选项...
  • Pytorch实用技巧

    万次阅读 2019-11-26 09:52:47
    Pytorch实用技巧 手动搭建梯度 构造一个这样的函数:y=(x+1)*3 import torch.nn as nn import torch as th def show_tensor(tensor, name="None"): print("\n***********%s*************" % name) print("Tensor...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 14,083
精华内容 5,633
关键字:

复合技术技巧