Programming is an art, the same solution to a problem could have different versions of coding. Enterprise programming, due to its large code base, is about to provide functionalities while managing code dependencies and data encapsulation. The essence of managing dependencies and encapsulation is abstraction.
I have a terrible case of abstraction at work. We built a data access layer similar to iBATIS and Hibernate. But the abstraction is not quite generic enough(I think the abstraction level is too high, too close to the application, not close enough to JDBC/SQL) so that whenever we modify something, it breaks many others.
The intention is good - we want to reuse existing code. In general, if we abstract some logic at the wrong level, but not far off, we can still get along because there is not a lot of modifications beneath the abstraction. But in this case, where we work with generated SQL, which is highly optimizable, we get a hard hit. This is because below the abstraction, the SQL are connected more tightly than JAVA code, and for performance reason, we need to tune SQL all the time. So whenever we modify one place, the same modified code to generate SQL are used in a lot of places and potential creates bugs, because the modification, in the worst case, only applies to a particular case - meaning the abstraction fails. This results the entanglement between code reuse and vertical modification and optimization.
A better solution is that we don't abstract horizontally at the higher level(the DAO level), we abstract it at the lower level, like iBATIS does, right above JDBC, horizontally, so that we could reuse code. Then abstract the DAO layer vertically. Then the DAO can change vertically without affecting other adjacent vertical DAO abstractions. Furthermore, this is align with DDD as well, so it's easy to adopt new business requirements(new feature, modification of existing features, optimization).
This is the case where one abstraction is not enough, we need two. The first one is more system related, the second one is more application related.
This is a very interesting case because a small mistake gets amplified to an unbearable degree. Although Rod Johnson wrote his book Expert 1-1 J2EE programming in 2002 about this, we still made the same mistake in 2006. The saying says, those who do not understand history are condemned to repeat it.
[Second example]
The post
http://www.iteye.com/topic/39694?
has a discussion on how to remove duplicated code. There are several ideas and complains on Java. I think the problem here is again how to abstract the code properly for reuse. If we look close the code, there are two duplicates: one is the getters on several properties, one is to sum the values. Reflection is proposed to remove duplicated getter calls. My question is: are these getter calls really duplicated? They may look syntactically similar, but they are semantically different, namely, they are totally different in the domain. So I think we should *not* consider them duplicated code and try to use reflections. An immediate consequence of using reflection on these getters is refactoring. What if we want to rename a field, the IDE won't find the usage in the reflection. What if we want to group some fields to a more meaningful class, say we have street number, street name, city name, and we want to group them into a separate class Address, then the reflection is broken.
The summation is really a duplicated code, so we may create a separate method to sum up an array of numbers. A simple class would do the trick:
java 代码
- public class Summation
- {
- public Number sum(Number[] numbers)
- {
- double sum = 0.0;
- for (int i=0; i<numbers.length; i++)
- {
- sum += numbers[i].doubleValue();
- }
-
- return new Double(sum);
- }
- }
Though internally we are using the method doubleValue(), this method works for Integer arrays too. Here is the testing class:
java 代码
- public class SummationTest
- {
- private Summation sumOperation = new Summation();
-
- public static void main(String args[])
- {
- SummationTest test = new SummationTest();
- test.testDoubles();
- test.testfloats();
- test.testLongs();
- test.testIntegers();
- test.testShorts();
- }
-
- public void testDoubles()
- {
- Number[] inputs = new Number[] { new Double(2.4), new Double(5.8) };
- Number result = sumOperation.sum(inputs);
- print(result);
- }
-
- public void testfloats()
- {
- Number[] inputs = new Number[] { new Float(2.4), new Float(5.8) };
- Number result = sumOperation.sum(inputs);
- print(result);
- }
-
- public void testLongs()
- {
- Number[] inputs = new Number[] { new Long(2), new Long(3) };
- Number result = sumOperation.sum(inputs);
- print(result);
- }
-
- public void testIntegers()
- {
- Number[] inputs = new Number[] { new Integer(2), new Integer(3) };
- Number result = sumOperation.sum(inputs);
- print(result);
- }
-
- public void testShorts()
- {
- Number[] inputs = new Number[] { new Short((short)2), new Short((short)3) };
- Number result = sumOperation.sum(inputs);
- print(result);
- }
-
- private void print(Number number)
- {
- System.out.println("----------------------------------------------");
- System.out.println("double=" + number.doubleValue());
- System.out.println("float=" + number.floatValue());
- System.out.println("long=" + number.longValue());
- System.out.println("int=" + number.intValue());
- System.out.println("short=" + number.shortValue());
- System.out.println("byte=" + number.byteValue());
- }
- }
The summation is a property of numbers, so the abstraction should be at the Number level.
分享到:
相关推荐
资源分类:Python库 所属语言:Python 资源全名:proper_tea-0.3.4.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059
标题 "PyPI 官网下载 | use-proper-hosting-1.0.1.tar.gz" 指示了这是一个从Python Package Index (PyPI) 官方网站获取的软件包,名为 "use-proper-hosting",其版本号为1.0.1,打包格式为tar.gz。PyPI是Python社区...
解决 The connected J-Link is defective,Proper operation cannot be guaranteed keil5版本比较高时debug会出现以上错误,替换安装文件下的segger 可以解决
【标题】"Spectral Proper Orthogonal Decomposition (SPOD) in Matlab" Spectral Proper Orthogonal Decomposition(SPOD)是一种数据驱动的统计方法,主要用于处理时间序列或空间序列数据,尤其在流体动力学、...
`eslint-plugin-proper-ternary` 是一个针对 JavaScript 代码风格检查的 ESLint 插件,主要用于规范三元运算符的使用。ESLint 是一个广泛使用的静态代码分析工具,可以帮助开发者发现并修复代码中的潜在问题,提升...
解决开机出现reboot and select proper boot device的方法 在计算机启动时出现“reboot and select proper boot device”错误信息,可能是由于CMOS中的启动顺序被篡改所致,导致光盘启动而不是硬盘启动。解决这个...
PropEr(Property-based Testing for Erlang)是一种针对Erlang编程语言的属性测试框架。它允许开发者基于程序的预期行为(即属性)来编写测试,而不是传统的基于具体输入/输出值的测试用例。属性测试通常能发现更多...
the proper number_work.c
sdac_4_70_0_45_proper_CRS2009.zip
POD(Proper Orthogonal Decomposition,正交分解)是一种在工程领域得到广泛应用的强大且优雅的数据分析方法。POD能够在高维过程中获得低维的近似描述,特别是为了从实验或数值模拟过程中获得的数据集提供模态分解...
Proper operation cannot be guaranteed Jlink information Firmware J-link ARM V8 这个问题经常导致调试过程中频繁退出,或无法停止,无法reset,单步调试异常等现象 把压缩包中的文件替换到在Keil的安装...
This.book.is.mainly.written.and.organized.to.give.proper.perspectives.on.the.various. designs.of.data.converters.and.PLLs,.which.are.the.two.most.common.analog.circuit.com- ponents.in.SoCs..The....
PROPER函数.xls
在使用Segger J-Link进行调试或编程时,有时可能会遇到一个令人困扰的问题,即收到错误提示"The connected J-Link is defective"。这个错误意味着你的J-Link调试器可能遇到了故障,导致它无法正常工作。...
在嵌入式开发领域,J-Link是广受欢迎的调试工具,它允许开发者对微控制器进行编程、调试和诊断。然而,随着软件的更新迭代,可能会出现一些兼容性问题。"The connected J-Link is defective"这个错误提示,通常意味...
标题中的"PROJECT-PROPER-DATA.rar_m.symmz.com"可能是指一个项目的数据压缩包,其中包含了在m.symmz.com这个网站上发布或存储的相关文件。"laqm lcm dlmws m mz lm dwa d"这部分描述可能是错误的字符序列,无法直接...
emphasis on proper program design and structure. A standard program design process is introduced at the beginning of Chapter 4 and then followed regularly throughout the remainder of the text
MIRC.v7.1.WinAll.Cracked.PROPER-CRD
安装j-link较新版本(JLink_Windows_V632b.exe)的驱动,每烧录一次程序报一次警告,警告如下:“The connected J-Link is defective, Proper operation cannot be guaranteed.” 修改了V630版本的 JLinkARM.dll ...