我遇到了一个有趣的挑战,我有以下代码:
Sm.screenfragment(function (screen, viewModel) {
//This can grow very quickly and turn into a mess
var attribA = screen.get('title'),
...
...
attribZ = screen.get('status');
var setAttribA = function (container) {
//Do Stuff
};
...
...
var setAttribZ = function(event, viewName) {
//Do Stuff
};
//So this can grow hundreads of lines and get messy.
return {
model: {
//Do Stuff
},
create: function () {
//Do Stuff
},
prepare: function (callback, config) {
//Do Stuff
},
enter: function () {
//Do Stuff
},
exit: function (callback) {
//Do Stuff
}
};
});
我尝试了一些想法,但它们只不过是搞乱了语法:
我考虑过添加一个新的util对象,我可以构造util对象,所以它只是增加了一点结构,但不多了。
Sm.screenfragment(function (screen, viewModel) {
//Still can grow into a mess
var util = {
attribA : screen.get('title'),
attribB : screen.get('status'),
setAttribA : function (container) {
//Do Stuff
},
setAttribB : function(event, viewName) {
//Do Stuff
}
};
return {
model: {
//Do Stuff
},
create: function () {
//Do Stuff
util.setAttribA...
},
prepare: function (callback, config) {
//Do Stuff
},
enter: function () {
//Do Stuff
},
exit: function (callback) {
//Do Stuff
}
};
});
然后使用点符号来获取属性,但这并不会使混乱消失。我正在重新阅读模块模式上的内容,看看我是否可以在这里应用一些东西,我有极端的情况,我可以在文件的顶部有几十个礼节和功能,它只是打破了结构。如何以更模块化的方式安排代码?所以它不会混乱。
答案 0 :(得分:1)
你的问题不容易回答,因为缺少一些信息。哪种方法使用哪些属性?分析问题时应解决这个问题(不在设计中,绝对不在代码中)。那么你的代码的哪一部分要与其他部分分离?
在更一般的层面上回答这个问题:
如果您在一个模块内部达到高内聚并且模块之间的耦合低,那么它被认为是良好的面向对象设计(OOD)。在您的情况下,这意味着:如果您的所有方法都引用了所有属性,那么将它们全部保存在一个大文件中就被认为是好的OOD。但通常情况下,现实世界的问题并没有以如此单一的方式连接。
如果你想要分离某些东西,有Single responsibility principle说明你应该将不相互影响的部分分开。在您的情况下,您可以(可能)将关于attribA
的所有内容放入一个模块中,将关于attribB
的任何内容放入另一个模块中。因此,无论您使用的具体模块实现如何,它都不会搞砸。
答案 1 :(得分:1)
嗯,我至少在可读性方面采取的方法是将函数声明从退回块中拉出来:
Sm.screenfragment(function (screen, viewModel) {
//Still can grow into a mess
var util = {
attribA : screen.get('title'),
attribB : screen.get('status'),
setAttribA : function (container) {
//Do Stuff
},
setAttribB : function(event, viewName) {
//Do Stuff
}
};
var create = function() {
//Do Stuff
util.setAttribA...
};
var prepare = function(callback, config) {
//Do Stuff
};
var enter = function() {
//Do Stuff
};
var exit = function(callback) {
//Do Stuff
};
return {
model: {
//Do Stuff
},
create: create,
prepare: prepare,
enter: enter,
exit: exit
};
});
然后如果这些函数中的代码是通用/模块化的,将该代码拉出到实用程序文件中并从那里调用它们
答案 2 :(得分:1)
我同意@Waog,好的OOD可能是你问题的解决方案。鉴于您在编写setAttribA
函数的对象上可能有很多属性,为什么不使用映射来清理代码呢?可能有很多JavaScript的地图实现,一个简单的谷歌搜索“ map polyfill ”引导我到这个,看起来不错:http://eriwen.github.io/smap.js/
答案 3 :(得分:1)
似乎有机会使用OO方法来封装类似的功能。每个类都可以存在于自己的文件中......这看起来很不错:
// In file attrs.js
function ScreenAttrs(screen) {
this.screen = screen;
this.attribA = screen.get('title');
// ...
// ... could even categorize attributes into separate methods
// this.initFooAttrs();
// this.initBarAttrs();
};
// In file modifier.js
var attrs = new ScreenAttrs(screen);
function AttribModifier(attributes) {
this.attrs = attributes;
};
AttribModifier.prototype.setAttribA = function() {
// .. do stuff w/ this.attrs.attribA
};
// ... etc.
// in api.js
var modifer = new AttribModifier(attrs);
function ScreenAPIImpl (modifier) {
this.modifier = modifier;
};
ScreenAPIImpl.proxy = function(context, method) {
return function() {
return method.apply( context, args.concat( slice.call( arguments ) ) );
};
};
ScreenAPIImpl.prototype.model = function (foo) {
// operation with this.modifier.setAttribA
// operation with this.modifier.attrs.attribA
};
ScreenAPIImpl.prototype.fetchAPI = function (screen, viewModel) {
return {
// Bind context of method to this object instance
model: this.proxy(this, this.model),
// ...
};
};
// .. etc
var api = new ScreenAPIImpl(modifier);
Sm.screenfragment(api.fetchAPI(screen, viewModel));
这也打开了创建一个帮助器构建器类,它构造了所有东西并返回最终的API对象:
var api = CreateAPI(screen);
答案 4 :(得分:1)
让我们从您的代码中考虑以下摘录,我理解问题所在:
Sm.screenfragment(function (screen, viewModel) {
//This can grow very quickly and turn into a mess
var attribA = screen.get('title'),
...
...
attribZ = screen.get('status');
var setAttribA = function (container) {
//Do Stuff
};
...
...
var setAttribZ = function(event, viewName) {
//Do Stuff
};
...
据我所知,在我看来,没有必要将属性attribA
定义到attribZ
然后设置它们,然后再为它们定义setter函数。您可以在需要的地方和时间返回或访问screen.get('x')
。
但如果由于某些原因绝对必要,那么jQuery推广的以下策略可能就足够了:
attributeX = function(x, container){
// if x and container are undefined, then we can assume API caller intends to
// read value of property 'x' otherwise, caller intends to write to the property.
if(container){
// don't forget to do stuff before setting!
container.setProp(x); // you get the idea
} else {
// well we must have a 'container' to set a prop,
// if we don't then caller must want to read.
return screen.get(x);
}
}
如果这个策略没有缓解这个问题,或者你认为我没有正确理解问题,那么请尝试让案例更清晰,让我们更接近目标。