答应我,别再写上千行的类了好吗

从MVC到DDD的架构演进 DDD这几年越来越火,资料也很多,大部分的资料都偏向于理论介绍,有给出的代码与传统MVC的三层架构差异较大,再加上大量的新概念很容易让初学者望而却步。本文从MVC架构角度来讲解如何演进到DDD架构。 从DDD的角度看MVC架构的问题 代码角度: 瘦实体模型:只起到数据类的作用,业务逻辑散落到service,可维护性越来越差; 面向数据库表编程,而非模型编程; 实体类之间的关系是复杂的网状结构,成为大泥球,牵一发而动全身,导致不敢轻易改代码; service类承接的所有的业务逻辑,越来越臃肿,很容 阅读详情

作者:橙味菌

链接 : juejin.im/post/5e11dd736fb9a047f42e61ad

答应我,别再写上千行的类了好吗?

最近在对已有项目进行扩展的时候,发现要改动的一个类它长766行,开放了近40个public接口,我流着泪把它给改完了。为了防止这样的惨剧再次发生在我的身上,我觉得有必要写一篇博客来让广大程序猿同胞知道代码重构的重要性

如果你身边有一个类写上千行的猿,一定要把此文转给ta

为什么类不能过长?

类过长——读不通,扩展不通

  • 读不通——直接用滚轮滚都得好几秒,就算是原作者,时间长了恐怕也难以理清整个类,更不用说是其他的读者

  • 扩展不通——一个类有过多的接口,会让扩展这个类变得异常困难,一动千行

类过长——可能有冗余代码

此时CV工程师打了个冷战

冗余代码,就是重复代码,通常出自使用Ctrl+C,Ctrl+V来生产代码的CV工程师之手,冗余代码的危害非常大:

  1. 冗余代码使方法、类过长,不简洁

  2. 冗余代码会造成发散式修改(冗余代码需要变动时,每一处Ctrl+V都需要修改)

类过长——多半是职责过多

一个类开放几十个接口,绝对存在职责过多的问题,就像图中的Tom猫一样手忙脚乱,一个类的职责过多也有巨大问题:

  1. 违反设计原则——单一职责原则(单一职责原则要求一个类只实现一个职责,比如一只Tom只做扫地、擦桌、拖地中的一件事,而其他事的实现可以转移给史派克狗或肥胖女佣),违反了这个原则会导致发散式变化、发散式修改、类过长等代码问题,还会让你的类难以扩展,甚至会让其他程序猿认为你不专业

  2. 发散式变化(指引发此类修改的地方很多),如果一个类的职责很多,那它的扇入(调用者)一定很多,每个调用者的修改都有可能让你这个类不得不随之修改,也就是发散式变化

    就是说不管哪儿出了问题,你这个类都得遭殃

  3. 发散式修改(指此类修改引发修改的地方很多),相同的,如果一个类职责很多,那支撑它实现的下级,即扇出(被调用方)一定很多,如果此类逻辑发生变动,所有下级被调用者可能都得随之修改,也就是发散式修改

    就是说你这个类出了问题,不管哪儿都会遭殃

  4. 难以扩展:如果你的一个类接口非常多,那它的子类怎么办?它的包装类怎么办?难道全部都要实现这么多接口,全部都要承担同样多的职责吗?扩展起来真的非常麻烦

  5. 触发机关:【测试之怒】【运维之怒】

我已经写了几千行了,怎么办?

重构——抽取冗余代码

抽取冗余代码就是将重复代码抽取成一个独立的方法,之后再使用这段代码时就不再需要Ctrl + C,Ctrl + V,而是直接调用对应的方法即可

这样做也可以缩短原方法,使原方法更加简洁易懂

更值得一提的是如果这段代码需要修改,也只需修改一处,而不是发散式地到处修改

真是一箭三雕

使用IDEA进行冗余代码的抽取
  1. 找到重复代码

2.进行方法抽取 右键->选择重构->抽取->方法 (或者直接使用快捷键Ctrl + Alt + m)

自动检测出个别重复代码的细微差别,有些代码可能只改动一两个变量,IDEA会自动检测出来,并在抽取方法时提醒我们,选择左侧Accept Signature Change(接受签名变动)可以使抽取的方法自动替换更多的重复点

可以选择替换掉所有的重复代码(竟然有18处)

  1. 重构——更改方法签名

    如果你对抽取出的方法的名字、参数、返回值或是修饰符不满意,不要使用Ctrl + R 修改,IDEA提供了重构方法——更改签名(快捷键Ctrl + F6)

    注意:方法的名字指的是方法做了什么,而非怎么去做,最好是 动词+名词格式

    比如:Tom.扫地() √

    Tom.扫地With扫把() ×

    Tom.用扫把扫地() ×

重构——转移成员变量+函数(转移职责)

将不应该由自己管理的成员变量和函数转移出去

那就要考虑两个问题:该转移谁?转移给谁?

来看一个图

  1. 图中成员【偏A】被类【A】调用两次,而只被它所在的类【过长类】用1次,因而应该转移给【A】去管理

  2. 由于函数【偏A】与成员【偏A】的亲密度较高(只调用了【偏A】),因而应与【偏A】共进退,同去留,转移给【A】

  3. 成员【偏B】和函数【偏B】也是相同道理

  4. 职责1(函数【1】和成员【偏职责1】)和职责2(函数【2】和成员【偏职责2】)由于找不到可转移的合适的类,所以应抽取出一个新的类

注意,先决定移动哪个成员变量,然后再决定移动哪个函数

使用IDEA转移成员变量和函数
  1. 移动成员变量,鼠标选择成员变量->右键->Refactor->Move,然后选择转移至哪个类

  2. 移动函数(与移动成员变量步骤相同)

重构——抽取类

当你发现要转移的成员变量和函数找不到合适的类时(转移职责却找不到下家),要想起来,这里是程序世界,而我们程序猿就是类和对象的造物主,是时候创建一个新的类,让它来替我们分担职责(成员变量和函数)了

使用IDEA抽取类

重构 选中要搬的成员变量和函数,右键->Refactor->Extract->Delegate(抽取一个委托者,委托他来管理这部分变量和函数,如果只有变量或只有函数,可以抽出参数对象Paramater Object或方法对象Method Object)

不推荐抽取参数对象,因为一般参数对象是给参数多的方法用的(用参数对象取代一长溜的参数),而且如果成员变量抽取了也不会影响任何函数的话,那就是无用对象了,不如直接把他们删除掉

为新类起个名,选个包吧

注意,抽取的函数和成员一定要符合一个原则,那就是被抽取函数使用被抽取成员的次数一定高于剩余函数的次数,不然违反亲密性原则(成员应归于调用它最多的类,没有理由你用的比我多还让我来管理)

一些小问题

由于抽取的函数直接使用了未抽取的对象而导致重构失败,涉及到另一个重构(使用get方法而非直接使用私有成员变量),使用此重构即可解决

(完)
好文!必须点赞
第 4-2 课:反射和动态代理 + 面试题 反射 反射机制是 Java 语言提供的一种基础功能,赋予程序在运行时自省(introspect)的能力。简单来说就是通过反射,可以在运行期间获取、检测和调用对象的属性和方法。 反射的使用场景 在现实中反射的使用场景有很多,比如以下几个。 使用场景一:编程工具 IDEA 或 Eclipse 等,在写代码时会有代码(属性或方法名)提示,就是因为使用了反射。 使用场景二:很多知名的框架,为了让程序更优雅... 阅读详情

相关推荐

FCL碰撞检测库在Windows下的编译与配置(MinGW+CMake)

本文详细介绍了在Windows系统下使用MinGW和CMake编译配置FCL碰撞检测库的完整流程。内容涵盖MinGW-w64、CMake的安装与环境配置,关键依赖库Eigen和libccd的安装,以及FCL源码的编译、安装与实战测试。重点解析了CMake配置命令中的关键参数与常见错误解决方案,旨在帮助开发者高效完成FCL在Windows平台的部署,适用于机器人、游戏物理引擎等需要精确碰撞检测的开发场景。

sunny的博客 484

一个方法几千行的程序是如何产生的?

最近查看公司的代码,发现有很多体积很大的类,其中一些方法竟有几千行。 这些方法有些共同的特点: 包含大量巨大的if else嵌套。 伴随着大量的magicnumber。 存在大量的重复代码。 难以测试。 对于任何一个没有足够业务知识的人,完全不可读。 这些代码成长过程都很相似: 第一个人:把业务流程和业务代码封装在一个类里。业务不复杂,代码看起来还行。 第二个人...

李黄河 1060

如何通过CAD图中的坐标来确定是哪个坐标系

地理坐标系:为球面坐标。参考平面地是椭球面,坐标单位:经纬度。以地球参考为例,坐标系就相当于整个地球,而地理坐标系就是椭球状的完整的立体地球。所以我们可以看到生活中的数据与地图是一定含有地理坐标系的,因为他是客观上来说确确实实存在的。投影坐标系:为平面坐标。参考平面地是水平面,坐标单位:米、千米等。这就相当于把地球当成一个橘子,然后一刀切开,把橘子皮平面铺开,这个过程就是地理投影的过程。严谨一点来说就是建立一个参考系统,按照对应位置把椭球体投射到平面。那坐标系统主要有那些呢?北京54。

vjmap的博客 2万+

IDEA 代码行数很多时卡顿 已解决

最近在编辑一个两万多行的文件时出现严重卡顿, 内存都给了4g、缓存也清理了, 但还是卡, 折腾了一会随手检查了一个插件, 结果发现了问题。这个插件默认设置是100000行, 我给改成一万就不再卡顿了。

weixin_60783905的博客 3228

大数据实战:Python与MySQL在足球赔率分析中的高效应用

本文详细介绍了如何利用Python与MySQL进行大数据实战,实现足球赔率的高效分析。通过对比Excel处理的局限性,阐述了数据库在处理百万级数据时的速度优势。文章提供了从环境搭建、使用pymysql连接数据库、利用pandas进行数据清洗与分析,到构建自动化分析系统的完整流程,旨在帮助读者将大数据技术应用于实际业务场景,显著提升数据处理与洞察效率。

weixin_29080843的博客 448

东方财富API隐藏技巧:这样获取分时均价线数据更稳定(避坑指南)

本文深入解析东方财富API获取股票分时数据,特别是分时均价线的实战技巧与避坑指南。针对高频调用中常见的请求失败、数据错位及IP限制等问题,提供了从接口参数深层解析、稳健请求与错误处理机制,到系统优化与数据校验的全流程解决方案,帮助开发者构建稳定可靠的数据采集系统。

rice5的博客 2541

答应我!别再写上千行的类了,好吗?

点击上方蓝色“程序猿DD”,选择“设为星标”回复“资源”获取独家整理的学习资料!来源 |https://juejin.im/post/5e11dd736fb9a047f42e61ad...

程序猿DD 581

Ros入门 (十)----激光雷达避障 简易实现

本篇文章通过订阅/scan话题获取障碍物的距离信息,达到避障目的,提供部分代码,仅供参考。

weixin_51157015的博客 1万+

答应我!别再写上千行的类了!好吗?

点击上方 "程序员小乐"关注,星标或置顶一起成长每天凌晨00点00分,第一时间与你相约每日英文I have passed your heart, not I don...

程序员小乐 367

影像组学文章复现:ITHscore:通过多尺度放射学特征全面定量NSCLC肿瘤内异质性 ----小细胞肺癌肿瘤异质性评分

目的:通过计算机断层扫描(CT)图像量化非小细胞肺癌(NSCLC)的肿瘤内异质性(ITH)。 方法:整合局部辐射特征和全局像素分布模式,开发定量ITH测量-ITHscore。在六个患者队列(n = 1399)中检查ITHscore与肿瘤表型,基因型和患者预后的关联,以验证其在表征ITH方面的有效性。

xxx 1021

【C# + HALCON 机器视觉】HALCON经典算子:光流法运动分析(optical_flow_mg)

摘要:本文面向智能监控人流统计需求,研究C#与HALCON集成开发中optical_flow_mg算子的应用。通过RTSP获取视频流,利用光流法计算运动矢量,结合形态学操作与区域筛选实现行人区域分割,最终完成人流量统计与热力图可视化。详细阐述ROI局部处理等性能优化策略、try-catch异常捕获机制及跨平台集成方案。实验表明,该系统检测准确率达93.6%,单帧处理时间42ms,为公共场所人流量统计提供了完整可行的技术方案。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 1445

答应我!别再写上千行的类了!这样的代码让我生不如死!

点击上方 "程序员小乐"关注,星标或置顶一起成长每天凌晨00点00分,第一时间与你相约每日英文Sometimes, tears is...

程序员小乐 926

如何对EMB电子机械制动器的热衰退问题进行优化

摘要 电子机械制动器(EMB)在新能源汽车和自动驾驶中具有重要应用价值,但其在高强度工况下会出现热衰退现象。本文分析了EMB热衰退的五大机理:摩擦副热效应、电机热衰退、减速机构热失效、温度对控制策略干扰以及结构设计导致的热积累。针对这些问题,提出了从材料、结构、控制三个维度的优化措施:升级耐高温材料、改进散热设计、优化控制算法等。通过"热生成抑制-热传导优化-热失效补偿"的系统方案,可有效改善EMB的热衰退问题,为智能汽车提供更可靠的制动保障。

m0_59012156的博客 344

答应我,别再写上千行的类了好吗?试试 IDEA 这些牛逼的重构技巧吧!

来源:juejin.cn/post/6844904038383747086答应我,别再写上千行的类了好吗最近在对已有项目进行扩展的时候,发现要改动的一个类它长766行,开放了近40个pub...

程序员闪充宝 155

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

求你们了,别再写上千行代码的类好吗?

答应我,别再写上千行的类了好吗?最近在对已有项目进行扩展的时候,发现要改动的一个类它长766行,开放了近40个public接口,我流着泪把它给改完了。为了防止这样的惨剧再次发生在我的身上...

Java技术栈,分享最主流的Java技术 4547

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

求求你别再写上千行的类了,试试这些牛逼的重构技巧吧

点击关注公众号,实用技术文章及时了解来源:juejin.cn/post/6844904038383747086答应我,别再写上千行的类了好吗最近在对已有项目进行扩展的时候,发现要改动的一个...

Java知音 312

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

别再写上千行的类了,试试IDEA这些牛逼的重构技巧吧!

点击上方☝码猿技术专栏轻松关注,设为星标!及时获取有趣有料的技术来源:juejin.cn/post/6844904038383747086答应我,别再写上千行的类了好吗最近在对已有项目进...

码猿技术专栏 1727
上一篇: Intellij IDEA小技巧你玩过吗?
下一篇: 同事因在涉及金钱交易中使用double造成无法挽回的损失,已跑路
Java思维导图
博客等级 码龄10年 306粉丝 71原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值