[译]单一职责原则在Android中的实践
今天看书的时候摘录下一句很有意思的话,共勉之。
原文链接–S is for Single Responsibility Principle——by Donn Felker (译者注:这次原文很长。我建议先看代码部分。Uncle Bob的书的确值得多读。实现这个系列的最好方法:找一个以前写的老 这是SOLID原则五部曲的第一步。 SOLID是面向对象的五个设计原则的缩写:
接下来几周,我们会深入了解各个原则,解释它们的含义,如何与Android结合。所有课程结束后,你会抓住原则的精髓,了解到作为Android攻城狮,在日常的开发中运用这些原则是如此重要。 SOLID的历史SOLID是Rober Martin(Uncle Bob)在2000年与Michael Feathers共同提出的。结合运用这五项基本原则,能快速构建出可维护,高拓展性的系统。 如果不熟悉Rober Martin或者Michael Feathers,高度推荐他们写的书:《敏捷软件开发,原则 模式与实践》,《代码整洁之道》是软件社区的精神食粮。Michael Feathers的《修改代码的艺术》是我如果作为开发组长,必须要求每个开发成员都读的书。它能帮助你整理优化旧代码的思路,重构出更易维护的代码。更重要的是,它们能改变你对“优雅”的准确定义,比如,你的代码有单元测试嘛?没有?呵呵。 阅读这些书的确对我的职业有巨大的影响,我极度推荐开发者去阅读,买本实体书放柜子里,经常重温。 我记得自己使用SOLID原则是在2003年.NET的项目上,那时我的代码缺乏组织架构引导,搞得一团糟。这并不仅仅发生在.NET身上,新生的技术往往会经历混沌,例如Android。最终新技术会因拥抱SOLID而变得更成熟。 最近Rober Martin的演讲 - Clean Architecture又一次冲击了Android社区,正是解释基础原理的时候,下面让我们进入正题。 第一部分-单一职责原则单一职责原则很容易理解,它说的是
以RecycleView和Adapter作为例子,如你所知,
假设类和 public class LineItem { private String description; private int quantity; private long price; // ... getters/setters } public class Order { private int orderNumber; private List<LineItem> lineItems = new ArrayList<LineItem>(); // ... getters/setters } public class OrderRecyclerAdapter extends RecyclerView.Adapter<OrderRecyclerAdapter.ViewHolder> { private List<Order> items; private int itemLayout; public OrderRecyclerAdapter(List<Order> items,int itemLayout) { this.items = items; this.itemLayout = itemLayout; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent,int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(itemLayout,parent,false); return new ViewHolder(v); } @Override public void onBindViewHolder(ViewHolder holder,int position) { // TODO: bind the view here } @Override public int getItemCount() { return items.size(); } public static class ViewHolder extends RecyclerView.ViewHolder { public TextView orderNumber; public TextView orderTotal; public ViewHolder(View itemView) { super(itemView); orderNumber = (TextView) itemView.findViewById(R.id.order_number); orderTotal = (ImageView) itemView.findViewById(R.id.order_total); } } } 在上述例子中, @Override public void onBindViewHolder(ViewHolder holder,int position) { Order order = items.get(position); holder.orderNumber.setText(order.getOrderNumber().toString()); long total = 0; for (LineItem item : order.getItems()) { total += item.getPrice(); } NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.US); String totalValue = formatter.format(cents / 100.0); // Must divide by a double otherwise we'll lose precision holder.orderTotal.setText(totalValue) holder.itemView.setTag(order); } 这样的代码违反了单一职责原则。 为什么? 因为 这会有什么问题嘛? 一个包含多种职责的类会引发各种问题。首先,计算订单的逻辑与 第二个问题和第一个类似,把格式化数字耦合到 幸运的是,这个简单的例子可以通过把计算的逻辑迁移到 更新后的 @Override public void onBindViewHolder(ViewHolder holder,int position) { Order order = items.get(position); holder.orderNumber.setText(order.getOrderNumber().toString()); holder.orderTotal.setText(order.getOrderTotal()); // A String,the calculation and formatting moved elsewhere holder.itemView.setTag(order); } 我很肯定你会说,这很简单啊。是不是所有情况都如此简单呢?用一句软件工程的术语说,看情况吧…. 让我们往深层次挖掘 “职责”的含义Uncle Bob的理解无可比拟,这里引述他的原话:
有时候很难看透,尤其是你面对这个代码库很长时间了。这时,应该想到:
在软件工程里,你着重于实现而没能落眼于抽象,例如——这个花费你巨大精力写出来的庞然大物,很难看出来它可能具有多重职责。 更大的挑战在于,知道时候使用SRP,什么时候不用。考虑一下 public class OrderRecyclerAdapter extends RecyclerView.Adapter<OrderRecyclerAdapter.ViewHolder> { private List<Order> items; private int itemLayout; public OrderRecyclerAdapter(List<Order> items,int position) { Order order = items.get(position); holder.orderNumber.setText(order.getOrderNumber().toString()); holder.orderTotal.setText(order.getOrderTotal()); // Move the calculation and formatting elsewhere holder.itemView.setTag(order); } @Override public int getItemCount() { return items.size(); } public static class ViewHolder extends RecyclerView.ViewHolder { public TextView orderNumber; public TextView orderTotal; public ViewHolder(View itemView) { super(itemView); orderNumber = (TextView) itemView.findViewById(R.id.order_number); orderTotal = (ImageView) itemView.findViewById(R.id.order_total); } } }
应该把这些职责分开嘛? 最终取决于应用的迭代。如果需要修改 然而,应用的需求如果不经常变更,就没有理由去分离多重职责。在这个例子中,我们无需做无用的工作。 所以,我们应该做什么? 一个死板的例子假设新产品上市免费试用,
在大多数应用中,这会写在 这正是MVP模式带来的解耦方案,提高了可拓展性,可聚合的程度和可测试性,使类不会变得过于笨重。例如,会给 把逻辑从 也不完全是这样… 如果你深入了解
你会想,为什么不把这些东西抽出来,让单一职责原则实现呢?我又要引用Uncle Bob的解释了:
结论单一职责原理是SOLID中最简单的一个。再重复一次:
也有人说,这是实践起来最难的原则之一。如果过度实践SRP,过度的分析增加了代码的复杂度。我的建议是:以面向对象的思想看待代码,隔离你的感情,用全新的目光再度审视老代码,你就会发现以前从未知道的东西。也许需要实践SRP,也许你早已做得足够好了。 当应用需要修改的时候,强烈建议在未应用SRP的地方时间SRP。 享受生活,享受编程。 期待下一篇,开/闭原则。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |