原文自博客发布平台medium,做者为 better-programming 的 Ravi Shankar Rajan,传送门web
若是你想知道什么叫作敏捷开发者,首先你得先了解什么叫作敏捷开发。编程
敏捷开发是一个用于表述迭代和增量软件开发方法论的术语,例如:bash
而且,一个敏捷开发者并非指大家所认为的那些把本身绑在独立的空间中,戴着耳机享受音乐,与世隔绝的开发者。敏捷开发中开发者的角色明显要显得更为宽广和多元。框架
敏捷开发者更关注与可持续开发。可持续性意味着良好的评估、有效的代码分支管理策略、保证质量的自动化测试以及持续部署用于从用户中得到快速的反馈。编程语言
这一切意味着整个组织都应该接受,质量比 deadline 和日程规划都要重要得多,这个观念。ide
也就是说,敏捷开发的基石是将区域转换为动态变量(像每个变动的商业/市场需求),以此团队可以保证质量、构建一个活力四射的开发文化以及保持业务的紧密性。工具
还有,做为一个工做于敏捷环境中的开发者来讲,重要的是他们须要了解组织中遵循的全部敏捷开发方法论、工具以及指南。单元测试
除此以外,敏捷开发者应该具备良好的沟通技巧用于团队合做以及与客户的交谈。学习
最重要的是,敏捷开发者应该了解组织中整个开发过程的实现以及流程。测试
这里并无捷径,但如下所列出的实践点能够帮助你更好地融入到敏捷程序开发、测试和 debug 中。
意图导向编程适用于学习任意编程语言的条件中。
当咱们学习任一种语言的时候,会很天然地倾向于将问题分解为一系列功能性步骤上。步骤细化得越高,你就可以更能了解语言深层。这种技术正是证明了这一点。
意图导向编程是说,比起循序渐进地编写代码,想象你自身已经有一套合适的方法并将其实践到当前状况中会显得更能解决问题。
问问你本身:"这样一个理想的方法须要哪些输入输出呢?还有,在如今对我来讲,怎么取名才令我本身印象深入来让我本身以为这个方法已经存在?"
而且,因为方法实际上并不存在,因此除了你本身的想象外,其余因素并不会影响到你。
思考下下面的代码:
REPORT ysdnblog_class_ideal.
parameters : p_rows type count default ‘100’.
* — — — — — — — — — — — — — — — — — — — — — — — -*
* CLASS lcl_main DEFINITION
* — — — — — — — — — — — — — — — — — — — — — — — -*
CLASS lcl_main DEFINITION.
PUBLIC SECTION.
CLASS-METHODS : start.
PRIVATE SECTION.
METHODS : get_data ,
display.
CLASS-DATA : lr_main TYPE REF TO lcl_main.
DATA it_mara TYPE mara_tt.
ENDCLASS. “lcl_main DEFINITION
* — — — — — — — — — — — — — — — — — — — — — — — -*
* CLASS lcl_main IMPLEMENTATION
* — — — — — — — — — — — — — — — — — — — — — — — -*
CLASS lcl_main IMPLEMENTATION.
METHOD start.
CREATE OBJECT lr_main.
lr_main->get_data( ).
lr_main->display( ).
ENDMETHOD. “start
METHOD get_data.
— — WRITE SOME CODE HERE……
ENDMETHOD. “GET_DATA
METHOD display.
— — WRITE SOME CODE HERE……
ENDMETHOD. “display
ENDCLASS. “lcl_main IMPLEMENTATION
START-OF-SELECTION.
lcl_main=>start( ).
复制代码
start()
方法是执行报告时调用的当前类的公共方法。
其余的方法,get_data()
和 display()
,是类的私密方法,它们只会被类对象在内部调用。咱们能够将对这些方法的简单调用称为功能性步骤。
关键是它们是做为类内部实现的一部分,而不是用于外部而存在。
固然它们还没真正地实现。因此当你尝试编译这部分代码,编译器会抛出错误来讲明它们并不存在,它们必须被编写为可以被编译的代码才行。
这就是下一步咱们须要作的事情。
在乎图导向编程中,咱们容许咱们本身将注意力放到如何将问题分解到需求的整个大环境中。
咱们并不会编写和执行那种大块冗余的代码。咱们所要作的是将代码分红一步一步的功能块而且一步一步得实现它们。
思考下下面我所实现的功能步骤 get_data()
和 display()
。
METHOD get_data.
SELECT * FROM mara INTO TABLE me->it_mara UP TO P_rows ROWS .
ENDMETHOD. “GET_DATA
METHOD display.
DATA : lr_table TYPE REF TO cl_salv_table.
cl_salv_table=>factory( IMPORTING r_salv_table = lr_table
CHANGING t_table = me->it_mara ) .
lr_table->display( ).
ENDMETHOD. “display
复制代码
在这整个过程当中,没有过多的变化。咱们只是以不一样的方法和不一样的规则去简单地编写这些代码而已。
当你第一次使用 TDD 的时候也许你会以为很奇怪。
为何会这样呢?先编写单元测试?谁会作这种傻事?
话虽如此,但它但是敏捷开发中最重要的概念之一。
让咱们举一个简单的例子来讲明下吧。
这个例子是假设咱们有一个带有方法 SUM
的类 LCL_SUM
。这个方法的做用是对数字进行增长操做。
它将一个数字做为最重要的参数而且与其对象自身进行一个加法操做从而获得结果,如今让咱们把这个方法称做生产方法吧。
这个类的代码以下所示:
CLASS lcl_sum DEFINITION.
PUBLIC SECTION.
METHODS: SUM IMPORTING iv_1 TYPE i
RETURNING VALUE(rv_sum) TYPE i.
ENDCLASS. “lcl_sum DEFINITION
*
START-OF-SELECTION.
* Nothing here yet
*
*
CLASS lcl_sum IMPLEMENTATION.
METHOD SUM.
rv_sum = iv_1 * iv_1. "我故意使用乘法而非加法来产生错误" sum
ENDCLASS. “lcl_sum IMPLEMENTATION.
复制代码
如今咱们编写一个测试类。
在 SAP 当中,当你定义这中类的时候须要添加关键字 FOR TESTING
。这样能够将此类从生产代码( production code)中分离出来。
CLASS lcl_test DEFINITION FOR TESTING
PUBLIC SECTION.
METHODS: m_sum FOR TESTING.
ENDCLASS. “lcl_test DEFINITION
*
CLASS lcl_test IMPLEMENTATION.
METHOD m_sum.
ENDMETHOD. “m_sum
ENDCLASS. “lcl_test IMPLEMENTATION
复制代码
在这个测试方法中,你须要作的是测试这个生产代码。
因此,为了测试 LCL_SUM
的 SUM
方法,你须要实例化 LCL_SUM
的引用对象,而且调用方法 SUM
和传递虚拟数据。
基于这些虚拟数据,方法会返回方法的实际结果。
基于虚拟数据,你会知道指望值是什么。落日入,若是你将 3 做为参数传入到 SUM
方法中,它会返回 6,由于增长了 3。
当从测试的生产代码或者方法中得到实际结果后,你须要对结果进行比较。
若是实际值和指望值不相同,你须要让系统知道这当中出现了问题而且显示一些适当的信息。
CLASS lcl_test IMPLEMENTATION.
METHOD m_sum.
DATA: o_cut TYPE REF TO lcl_sum.
DATA: lv_result TYPE i.
*
CREATE OBJECT o_cut.
lv_result = o_cut->sum( 3 ).
*
cl_aunit_assert=>assert_equals(
EXP = 6
act = lv_result
msg = ‘something wrong in output’
).
ENDMETHOD. “m_sum
ENDCLASS. “lcl_test IMPLEMENTATION
复制代码
这提醒我在生产方法中的实现出现一些错误。
对的,若是你仔细观察 SUM
的方法实现,我有一个错误。我是用了乘法而非加法。因此我须要更正它而且从新运行测试来验证是否成功。
咱们时常在尝试编译或者运行代码前花费大量的时间在编写代码上。可是,代码的执行和测试在这里每次只须要花费2分钟左右。
所以,简而言之,TDD 是遵循,首先编写单元测试,再编写具体代码,再重构,终而复始,这个原则来进行实现短开发周期开发的。
单元测试是一种自动化测试,用于检查功能是否预期所望工做。你的第一个单元测试用例应该是失败的由于这是在你编写任何代码以前所写出来的。
在这作法中,你往测试用例完善一点,在生产代码中完善一点。两种代码共同增加,相互维护。测试用例适用于生产代码就像抗体和抗原同样。
当中的经验法则是:按策封装,按需调用(encapsulate by policy, reveal by need)。
当有疑惑的时候,隐藏它;当有须要的时候调用它们。
当抽象问题解决后,将其隐藏和封装。
抽象意味着:"你被容许以一个更高的细节点去观察全部对象",而封装则更进一步,它意味着:"你不容许经过任何级别的细节点来观察全部对象"。
这就是,继承,这个概念的由来了。
当在设计任何软件系统的时候,咱们时常会寻找那些十分相像的对象。
例如,当在设计一个合约系统时,咱们能够找到许多不一样种类的合约(全职、临时、资产、刺激性合同等等),可是每种合约的通常属性是同样的。
所以,你能够穿件一个名为 contract
的通用对象,而后定义 fixed price
(全职)合约做为继承 contract 对象的类并带有额外的属性,以此类推。
继承简化了设计由于你经过编写一个通用的对象来处理全部事情而且编写特定的对象来处理特定的场景。
不只代码变得"洁净"了,也为使用该类来进行继承的开发者提供了一个极好的方法来分离没必要要的细节。
继承是面向对象编程中其中一个重要的思想。它是一把双刃剑,当使用正确时能够提供极大的帮助;当错误地使用时会带来巨大的伤害。
简单地说,咱们应该尽力将可以封装的事物进行封装,由于它能简化咱们的维护过程。
一般,接口是链接另外一个实体 — 一个方法,一个类,一个模块或者一个程序,的一种方式。
常见的接口形式是:
而且,面向接口设计将定义层从实现层中分离开来。关键在于确保这种简化的设计可以使得测试变得更简易以及提升可维护性。
接口仅包含一组方法的签名(名字、参数、返回类型以及调用后的指望值)。接口不能包含数据成员(属性),由于这意味着实现的一步。
定义和实现的分离在设计上有明显的优点。它容许在测试以及外部的表现(例如外部格式)中轻松完成替换实现而且能够明显地与内部实现分离。
一样,你能够将程序化内部接口从外部供应商(第三方接口)或者开发组提供的 API 中进行分离。开发本身所需的接口而且对其进行调整。
这样就能够随时建立干净、易调整和可读的代码了。
敏捷以迭代的模式工做而且迭代要求工做原型须要按期进行展现和讨论。
也许原型的最大优势是可以表现设计的视觉反馈;一张图,即便规模再小,也比千字来得有用。图片不只帮助咱们确认设计的可行性,更有助于得到必要的"认同"和批准来继续推动。
原型也能做为一次性模型,用于在设计和编码以前理解项目的需求。本质上来讲,原型是项目的试金石。
即便你已经对设计做出了无数次的修改,在软件开发的过程当中,仍是会有许多预想不到的问题会发生。
原型测试至少可让开发团队知道问题的所在而且他们可以在软件发布前有机会去跟进。
与原则(discipline)一块儿使用,原型会成为开发者的主力工具,并将其用于代码和设计的冲突中。
能够参考 iPhone,这个回报能够说是很是巨大。
敏捷开发不只仅是一系列仪式。它是一种文化以及技术哲学。
它经过实践提升我的能力,借此在产品中构建一个坚固的技术基础而且在团队中产生合做文化。
敏捷开发的一个核心原则是稳步前进,这反过来,也可让你可以稳步地交付产品,而不是零星地工做最后什么都产出不了。
开发者在敏捷团队中会更加投入,编写更好的代码和得到更多的乐趣。他们每每编写可维护的代码,构建良好的关系而且可以对项目最后的回报有一个明确的分配。
真正意义上的团队合做是越作越好、不断改进。
就像爱迪生说的那样:
There is a way to do it better — Find it.
小喇叭
广州芦苇科技Java开发团队
芦苇科技-广州专业互联网软件服务公司
抓住每一处细节 ,创造每个美好
关注咱们的公众号,了解更多
想和咱们一块儿奋斗吗?lagou搜索“ 芦苇科技 ”或者投放简历到 server@talkmoney.cn 加入咱们吧
关注咱们,你的评论和点赞对咱们最大的支持