大型 Android 系统重构实战
黄俊彬
Thoughtworks 资深咨询师
2840 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 29 讲
大型 Android 系统重构实战
15
15
1.0x
00:00/00:00
登录|注册

14|过大类重构:如何重构动辄过万行的一个类?

你好,我是黄俊彬。
上节课,我们一起学习了如何将大型的单体遗留系统重构为组件化架构。通过这次重构,我们有了更加低耦合、高内聚的组件。但是回到组件内部,代码质量对开发也非常重要。我相信你在过去的代码里一定会遇到一种典型的代码坏味道,那就是“过大类”。
在产品迭代的过程中,由于缺少规范和守护,单个类很容易急剧膨胀,有的甚至达到几万行的规模。过大的类会导致发散式的修改问题,只要需求有变化,这个类就得做相应修改。所以才有了有时候的“不得已而为之”的做法:为了不让修改引起新的问题,通过复制黏贴来扩展功能。
所以这节课,我们将一起来学习“过大类”的重构之法。我们将组件内分层架构重构流程分为 3 个维度和 7 个步骤,希望通过这些流程方法,可以帮助你更加高效、高质量完成代码重构。

“过大类”的典型问题

在移动应用中,“过大类”最常见的情况就是将所有的业务逻辑都写在同一个界面之中。我们来看看后面这段示例代码。
public class LoginActivity extends AppCompatActivity {
//省略相关代码... ...
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loginButton.setOnClickListener(v -> {
String username = usernameEditText.getText().toString();
String password = passwordEditText.getText().toString();
//用户登录
LogUtils.log("login...", username);
try {
//验证账号及密码
if (isValid(username) || isValid(password)) {
callBack.filed("invalid");
return;
}
//通过服务器判断账户及密码的有效性x
boolean result = checkFromServer(username, password);
if (result) {
UserController.isLogin = true;
UserController.currentUserInfo = new UserInfo();
UserController.currentUserInfo.username = username;
//登录成功保持本地的信息
SharedPreferencesUtils.put(this, username, password);
} else {
Log.d("login failed");
}
} catch (NetworkErrorException networkErrorException) {
Log.d("networkErrorException");
}
});
}
private static boolean isValid(String str) {
if (str == null || TextUtils.isEmpty(str)) {
return false;
}
return true;
}
private boolean checkFromServer(String username, String password) {
//通过网络请求服务数据
String result = httpUtil.post(username, password);
//解析Json对象
try {
JSONObject jsonObject = new JSONObject(result);
return jsonObject.getBoolean("result");
} catch (JSONException e) {
e.printStackTrace();
}
return false;
}
public static final String FILE_NAME = "share_data";
public static void put(Context context, String key, Object object) {
SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
//... ...
editor.apply();
}
//省略相关代码... ...
}
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

针对过大类的重构方法和流程 本文通过一个登录页面的代码示例展示了过大类的代码坏味道,以及对需求变化的不利影响。针对这一问题,提出了分层架构重构流程,以及针对不同维度的变化进行分而治之的重构策略。以MVP架构为例,说明了分层架构的设计和交互方式,并展示了重构后的代码扩展方式。最后总结了组件内分层架构的重构流程,分为3个维度和7个步骤,帮助读者更高效、高质量地完成代码重构。通过具体示例和重构策略,为读者提供了针对过大类的重构方法和流程,有助于提高代码质量和可维护性。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《大型 Android 系统重构实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(2)

  • 最新
  • 精选
  • Geek_a8c1a2
    重构的同时,正常的业务迭代不会停止,如果重构时间较长,如何确保这期间的需求变更? 您也提到了避免长时间周期的重构分支,请教下 一般来说 多长的重构周期会比较合理?

    作者回复: Hi,我理解你应该指的是大型的重构。大型重构也要拆解成小步集成,每个小步的重构其实也和正常的需求开发一样,我的建议是短特性分支的生命周期一般在3天左右,不超过5天。另外在开始重构前也得和业务一起沟通评估,看近期业务是否有新的需求变化,确定优先级。

    2023-03-14归属地:新加坡
    1
  • peter
    请教老师几个问题: Q1:第五步接口嵌套是笔误吗? 第五步接口设计:public interface LoginContract { interface LoginView { 。 两个接口是嵌套关系,为什么这样设计?是笔误少写一个右花括号吗? Q2:SDK中有超过一万行的类吗?我印象中好像有,也许是记错了。 Q3:安卓集成测试是由独立于开发的测试团队负责吗? Q4:安卓测试,会用模拟服务端吗? 比如,安卓团队自己开发一个模拟的服务端? Q5:国内用的安卓APP,老师建议用热更新吗? 安卓APP,只在国内使用,对于更新,老师的建议是什么?支持用热更新吗?还是支持传统的更新方案?

    作者回复: Hi,peter。 Q1:感谢反馈,少了一个}。另外是刻意这么设计的,将内聚的接口集合到一起,Contract里面应该还得有Presenter的接口。 Q2:有,非常多。 Q3:国内很多研发团队都是这样,最后由测试团队负责整体验收。 Q4: 会。 Q5: 还是得根据自己的业务来,如果使用建议使用大厂且有持续维护的方案,例如tinker。

    2023-03-13归属地:北京
    1
收起评论
显示
设置
留言
2
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部