精华内容
下载资源
问答
  • 代码解耦

    2012-12-09 21:02:00
    代码解耦

    代码解耦

    展开全文
  • 关于代码解耦

    千次阅读 2018-05-28 16:48:45
    烂的代码,都有各自烂的地方,不过基本都有一个共同的特点:耦合重,各个模块各个类各个功能点之间关系牵扯不清,经常你调用我调用你,或者全局变量漫天飞;对于怎么理清这些模块或者类,《代码大全》讲了很多,比如...
    烂的代码,都有各自烂的地方,不过基本都有一个共同的特点:耦合重,各个模块各个类各个功能点
    之间关系牵扯不清,经常你调用我调用你,或者全局变量漫天飞;
    对于怎么理清这些模块或者类,《代码大全》讲了很多,比如要形成金字塔型的调用层级关系,如果
    不能保证,也一定要保证单向的调用关系,绝对不能形成环状的调用关系;
    即:A->B->C
    而不能是 A->B->C->A,尤其要避免 A<->B
    如果不能避免这种循环调用,A和B将无法区分开来,A和B不可避免的扯到了一起,不能单独开发,不
    能单独编译,无论改动A或者B中的一个,都会影响到另外一个;这样,随着功能一多,模块一多,最后全
    扯到了一起;造成了你中有我,我中有你的感概恶心的耦合!!

    如果能保证这种单调单向的调用关系,那代码将形成一定的上下有别的层级,其中任何一层只能调用
    下层,绝对不能调用上层,最好是完全不用知道有上层!!即每层都把自己当作是最上层;
    这样有几个好处:
    1,模块解耦了,如果每层接口设计的好,那每层内部的改动对其他层或者其他模块完全是透明的,
    这样有利于分工;
    2,模块解耦之后,得到另外的一个好处是:能极大的增强代码模块的复用度,很多模块也许用着用
    着就发现提取出来,可以供很多的上层模块调用;

    对于集群中的svr节点来说,一般可以划分成一些固定的层:比如:核心数据模块,驱动模块,业务
    模块,RPC模块,基础框架模块等等;

    上面这些说的都是理论的玩意,而且很多人也都知道,但其实真正写代码的时候,往往发现事情没这
    么简单,很多情况下,会发现A->B,B确实要反过来调用B;比如我经常发现有人这样写代码:
    状态机FSM模块需要通过RPC模块拉取数据,得到数据后,然后才能接着往下继续处理;一般的 RPC
    模块的接口是 rpc::get_data(req, fsm_id),rpc得到数据后,根据fsm_id从全局FSM管理器 g_fsm_mgr 
    取出FSM,然后调用 FSM::on_data_back(resp)...

    看到没有,rpc 和 fsm 完整的融合在了一起,而且必须要通过全局变量融合(这里就会发生非常多的
    恶心的地方,比如svr里面有两类都可能调用此rpc状态机...),明显这里是有非常大的问题,rpc 明明和
    业务是没半点关系的,rpc应该做的就是远程操作,至于操作的结果,rpc是不应该管的,他只需要简单的
    把结果返回给调用者(即上层)即可;
    按上面这种做法,rpc 是无法重用的,如果另外写一个svr,而这个svr用的同一套rpc,那他就只能
    把这套rpc代码拷贝过来,然后再改几个地方...重复?恶心?低效?bug滋生?

    其实对于这个问题,有极其简单极其有效却完全被人忽视的办法:回调!!
    rpc提供的接口应该是这样的:
    typedef (*on_data_back)(resp,...)
    rpc:get_data(req, on_data_back cb, void* params)
    rpc只需要在内部建立这个req的标志(比如序列号)和 callback以及params的映射即可,当结果返回
    时,只需要通过resp的标志找到回调信息,然后 cb(resp, params) 即可,至于cb到底是干什么的,rpc无
    权知道,也不需要知道!!

    对于所有的下层需要调用上层的情况,回调都应该是最好的选择,也是必须的选择;
    C语言的精华是指针,指针的精华是函数指针,C的生命,C的灵动,C的多变来源于函数指针;君不见
    稍微大点的纯C项目,函数指针都是极其常见的;

    说起来其实很简单,确实够简单,却极致够用;那为什么很多项目中还是组织乱成一团麻呢??

    对于C++,回调没C这么简单,以前一直没有找到好用的自然的类函数指针的玩意,后来发现了boost的
    function和bind这两个玩意,能完全实现类的回调,而且能随心所欲的携带参数,用多了感觉比C的函数指

    针还好用,特别是携带参数这块;C完全依靠void*这个指针携带,而boost的回调不限!!



    https://blog.csdn.net/qwert9887/article/details/51741227

    展开全文
  • 前端代码解耦,评审

    2019-01-09 07:15:18
    代码解耦 今天看到前端小我伙伴的代码,发现两个js之间的耦合度高,一个方法里变量,两个js相互引用,这样的代码不适合阅读,更不适合未来的交接. 具体如下: @action getList = flow( function* (data) { try { ...

    代码解耦

    今天看到前端小我伙伴的代码,发现两个js之间的耦合度高,一个方法里变量,两个js相互引用,这样的代码不适合阅读,更不适合未来的交接. 具体如下:

      @action
      getList = flow(
        function* (data) {
          try {
            const res = yield modelProvider.getList(data);
            this.List = this.List.concat(.res.data);
            if (res.page) {
              this.total = res.page.total;
            }
            if (res.data.length < this.PageSize) {
              this.isMoreDisabled = true;
              console.log(res.data)
              return res.data;
            }
            this.PageNo = data.pageNo + 1;
            return res.data;
          } catch (e) {
            return handleError(e);
          }
        }
      ).bind(this)
    复制代码

    这里是store里的代码

      //获取设备列表下一页
      getMore = () => {
        const { PageNo, List, PageSize } = this.targetStore;
        this.setState({
          deviceLoading: true
        });
        getList({
          pageNo: PageNo,
          pageSize: PageSize,
        })
          .then(res => {
            console.log(res);
            message.destroy();
            this.setState({
              deviceLoading: false
            });
            if (res.length) {
              this.Progress();
            }
          })
      };
    复制代码

    这里是index.js里的文件的代码.

    很正常的获取列表的内容,在index.js里调用getMore函数,获取store里的PageNo, List, PageSize,这些变量获取后传递给store里的函数getList从后端拉取数据,然后store里返回数据给index.js做判断.

    以下是个人的看法 index.js里的文件引用store里的变量:PageNo,PageSize,index.js里的getList里的方法里需要接受来着store里的变量:res,两个js文件相互依赖,相互耦合,不利于后面的代码的维护,可能新增需求后要维护原来的代码会造成一定的困难,增加后续交接小伙伴交接难度. 在这里如果需要解耦的话,则index.js里面就不应该处理业务逻辑,把所有的业务逻辑都提到store里.

    转载于:https://juejin.im/post/5c359d9cf265da61285a4e1d

    展开全文
  • 项目模块化之代码解耦

    千次阅读 2018-01-22 16:26:32
    为什么要项目模块化? 1. 首先是因为出现了这个需求,我们是一个为医院提供服务的APP,但是某些医院希望使用某个单独功能 而并非全部,希望能够将单独功能打成一... 怎么进行代码解耦呢? 1. 代买解耦最重要的就是

    为什么要项目模块化?
    1. 首先是因为出现了这个需求,我们是一个为医院提供服务的APP,但是某些医院希望使用某个单独功能 而并非全部,希望能够将单独功能打成一个APP,所以直接导致了这个项目的启动
    2. 其次是因为项目已经很大,模块间的耦合相对严重,修改一些东西 可能牵扯到很多其他地方,所以为了解耦,也促使了这次项目的推进

    怎么进行代码解耦呢?
    1. 代买解耦最重要的就是减少类间的相互依赖,什么方法能最大程度的解耦呢? 答案当然是runtime,因为runtime是利用字符串来获取类以及类中的属性,所以我们可以认为是毫无耦合性,当然runtime最大的缺点就是当我们修改某些类或者属性名称时,runtime并不会报错,但是流程却走不下去了,所以,如何处理好这些获取的属性的字符串 是非常重要的。
    2. 由于耦合基本只存在于控制器中,所以首要是解除控制器的耦合,怎么解呢?我们使用了路由跳转的方式,也就是通过类名来获取实例对象:

    +(void)load
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            NSLog(@"%@",CLASS_URL);
            [NDJRouter registerURLPattern:CLASS_URL toObjectHandler:^id(NSDictionary *routerParameters)
             {
                  //初始化对象
                 id vc = [self new];
                 // configBlock中是对父控制器中控制传值和调用的block的注册
                 [vc configBlock];
                 return vc;
             }];
        });
    }

    我们利用了load在类加载的时候触发的特性,在其中通过类似网址的形式注册多个不同的blcok,一般是

    //注册类的URL
    #define CLASS_URL  [NSString stringWithFormat:@"xxxx://%@/%@",[[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleExecutableKey],NSStringFromClass(self)]
    //获取类得URL,每个类都可以这样写
    #define URL_FOR_CLASS(class) [NSString stringWithFormat:@"ngariDoctor://%@/%@",[[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleExecutableKey],(class)]

    当我们需要某个类时,只需要利用

    [NDJRouter objectForURL:URL_FOR_CLASS(@"类名")]

    因为这个时候回调block,初始化控制器对象并返回对象,就可以了。
    3. 那么如何传递参数呢 以及调用方法?
    我们在基础父类控制器的定义了几种block

    typedef void(^__returnBack)(NDBaseViewController *blockVC,id object);
    typedef void (^__setAttribute)(NSString*attributeName,...);
    typedef id (^__getAttribute)(NSString*attributeName) ;
    typedef id (^__fucntion)(NSString*funtionName,...) ;

    第一种是用与回调的block,参数是当前控制器和需要回调的参数,用于替换掉所有的代理传值(因为代理传值耦合很大),第二种是利用属性名称传值,第三种是获取某个类得某个属性,第四种是调用方法具体使用方法就是这种:

    BaseViewController *recipeDetailVC =  [NDJRouter objectForURL:URL_FOR_CLASS(@"NewRecipeInfoViewController")];
        //赋值
        recipeDetailVC.setAttribute(@"recipeId",recipeId);
        //调用方法
        recipeDetailVC.function(@"loadWorkPlaceArray");
        recipeDetailVC.hidesBottomBarWhenPushed = YES;
        [self.fromViewController.navigationController pushViewController:recipeDetailVC animated:YES];
        recipeDetailVC.returnBackBlock = ^(NDBaseViewController *blockVC, id object) {
          //block回调之后需要做的操作
     };

    上面是block的回调,注册的时候就是在load方法中初始化对象的时候完成的

    展开全文
  • 我想写一个服务,这个服务接受信息,如果有另外的服务想得到我的信息,只需要向我注册一下,给我一个接口,我就把服务转发给他,我接受信息的服务不用做任何改变,这样的东西应该用什么技术实现?
  • iOS 代码解耦利器(一)

    千次阅读 2016-10-28 12:18:54
    最近写demo的过程中需要通过tableView的cell跳转到多个页面,当时偷懒不想去引用头文件了,灵光一闪,写了一个跳转的方法,后来自己有完善了一下,基本满足了不带参数的页面跳转,带参数的页面跳转(用户自定义的...
  •  保持你的代码解耦  编写封闭的(shy)代码——是指一个模块不会向其他模块显露出任何不必要的东西,并且也不会依赖于其他模块的实现。如果你需要改变一个对象的状态(描述),那就让这个对象为你完成此操作。...
  • 博文『iOS——教你如何使用ReactiveCocoa和MVVM为代码解耦构建清爽APP』的代码 博文地址:http://zhoulingyu.com/2016/05/20/教你如何使用ReactiveCocoa和MVVM为代码解耦构建清爽APP/
  • 前端代码如何解耦

    2014-08-14 13:39:17
    仔细地讲解了前端代码如何解耦,对于前端工程师大有裨益的
  • 基本: Controller : 数据调度 接受request 数据 参数, 把参数传给Model 处理 Model :数据处理 根据业务逻辑处理数据 ...根据具体的业务选择不同的设计模式 , 装饰器模式 , 观察者模式 ,代理模式 ,进一步解耦
  • 前面介绍了那么多,下面介绍如何进行解耦与高性能。 一个典型的场景就是用户在注册的时候需要发送验证码,这时就需要将发送验证码的逻辑写到用户注册的业务逻辑中,如果短信发送的API发生变化后,就需要对用户注册...
  • 这篇文章来尝试将滑动验证码和抓取的代码进行解耦。 也就是滑动验证码只管获取获取之后的token,而抓取的代码只管抓取。中间通过相关数据存储介质进行通讯。 背景分析 阿里云的滑动验证码只是操作行为的验证,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 165,234
精华内容 66,093
关键字:

代码解耦方法