Refining Uncle Bob’s Clean Code(五)

Symmetry of abstraction

If you look at the original code (like method parseArgument() and some of its called methods) you might detect a mix of levels of abstraction. For example, deciding if the current argument represents the introduction of a new argumentId (by comparing the first character of the current argument with ‘-’) might be a level below the next command – parsing the element. I’m not sure about that, but i think encapsulating this decision within a method hides the concrete implementation, expressing only the purpose of the inspection of the current argument.

Open Closed Principle

What do we have to do, if we want to add a new Marshaler? As Uncle Bob mentioned in his book, you have to adapt more than one place in the code to integrate a new one. Essentialy you have to alter method parseSchemaElement(). Personally, i think this method lies on a to detailed implementation level for being a good place to add new Marshalers. You have to come a long path until you end up in this method.

I think, adding a new Marshaler should be done on the very top level of the ‘application’, in a very simple way: registering a new Marshaler and that’s it – no hassling with implementation details.
Again, if we look at class Args as the root of its ‘application’, that’s the perfect place for constructing the system, and hence registering all available ArgumentMarshalers. Since Marshalers.Factory is under control of Args, it can be ‘dependency injected’ simply by registering all available ArgumentMarshalers.

01 public class Args{
02  
03     static{
04         Marshalers.Factory.register( new BooleanArgumentMarshaler() );
05         Marshalers.Factory.register( new IntegerArgumentMarshaler() );
06         Marshalers.Factory.register( new StringArgumentMarshaler() );
07         Marshalers.Factory.register( new DateArgumentMarshaler() );
08     }
09         ...
10 }

I’m not sure if we can speak about violating OCP in the orig code, but now for me it feels more like adding new Behaviour by changing configuration, not by changing implementation.

Another point in relation to OCP is the addition of a new getter method that comes with every new ArgumentMarshaler (eg. getDate() forDateArgumentMarshaler). If you want to avoid that, you could of course come up with a more generic method, using the type token idiom (that may be not type safe) – so let’s complete Args:

01 public class Args {
02         ...
03     public <T> T get( String argumentId, Class<T> asType ) throws ArgsException{
04         return (T) argumentMarshalers.getMarshalerFor( argumentId ).get();
05     }
06  
07     public int cardinality() {
08         return argumentMarshalers.size();
09     }    
10  
11     public boolean has( String argumentId ) {
12         return argumentMarshallers.isMarshalerAvailabeFor( argumentId );
13     }
14  
15 }

Of course, we could have made the get() method more type safe by doing a type check with a following cast and maybe providing a default value of for the claimed type if the client didn’t ‘hit’ the appropriate type for a certain argumentId. But at the end of the day, the client should handle its mistake, so i think it’s better to come up with an exception.

Extinguishing the campfire

As you have seen, there are quite a few changes to Uncle Bob’s orig code. I think at the end it’s the surrounding forces and given values that will drive the final structure of the code.

Of course, the refactored solution has still some obstacles and cornercases – now it’s up to the next boy scout to move on … ;o)

For me, those changes reflected the way i think and try to communicate my intentions through the code. That may not be the way of communication for other developers. In general, it’s worth to take a deeper look into the psychological context of software development when it comes to communication. Moving forward to a common understanding of how to transport intention and meaning between humans might be a key to cleaner code in respect to its readability.

下载前必看:https://pan.quark.cn/s/a4b39357ea24 在本资料中,将阐述如何运用JavaScript达成单击下拉列表框选定选项后即时转向对应页面的功能。 此种技术适用于网页布局中用户需迅速选取并转向不同页面的情形,诸如网站导航栏或内容目录等场景。 达成此功能,能够显著改善用户交互体验,精简用户的操作流程。 我们须熟悉HTML里的`<select>`组件,该组件用于构建一个选择列表。 用户可从中选定一项,并可引发一个事件来响应用户的这一选择动作。 在本次实例中,我们借助`onchange`事件监听器来实现当用户在下拉列表框中选定某个选项时,页面能自动转向该选项关联的链接地址。 JavaScript里的`window.location`属性旨在获取或设定浏览器当前载入页面的网址,通过变更该属性的值,能够实现页面的转向。 在本次实例的实现方案里,运用了`eval()`函数来动态执行字符串表达式,这在现代的JavaScript开发实践中通常不被推荐使用,因为它可能诱发安全问题及难以排错的错误。 然而,为了本例的简化展示,我们暂时搁置这一问题,因为在更复杂的实际应用中,可选用其他方法,例如ES6中的模板字符串或其他函数来安全地构建和执行字符串。 具体到本例的代码实现,`MM_jumpMenu`函数负责处理转向逻辑。 它接收三个参数:`targ`、`selObj`和`restore`。 其中`targ`代表要转向的页面,`selObj`是触发事件的下拉列表框对象,`restore`是标志位,用以指示是否需在转向后将下拉列表框的选项恢复至默认的提示项。 函数的实现通过获取`selObj`中当前选定的`selectedIndex`对应的`value`属性值,并将其赋予`...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值