Javascript接口/松耦合

Javascript接口/松耦合,javascript,design-patterns,ecmascript-6,Javascript,Design Patterns,Ecmascript 6,在像PHP这样的编程语言中,很多具体的实现都放在接口后面,因此交换具体的实现会容易得多,因为您是针对接口而不是具体化编程的 在我们的项目中,我们希望实现一个名为moment.js的日期库来为我们处理日期,但如果我们在所有javascript中实现它,则会担心与代码的耦合过于困难 为了在javascript中创建某种接口,方法和属性可以由我们自己的库包装,这样我们就可以更容易地替换我们正在使用的concretedate库,以防万一 我想知道javascript中是否有某种模式或标准化的方法来实现这

在像PHP这样的编程语言中,很多具体的实现都放在接口后面,因此交换具体的实现会容易得多,因为您是针对接口而不是具体化编程的

在我们的项目中,我们希望实现一个名为
moment.js
的日期库来为我们处理日期,但如果我们在所有javascript中实现它,则会担心与代码的耦合过于困难

为了在javascript中创建某种接口,方法和属性可以由我们自己的库包装,这样我们就可以更容易地替换我们正在使用的
concrete
date库,以防万一

我想知道javascript中是否有某种模式或标准化的方法来实现这一点。乍一看,它只是为我们自己创建了一个库,我们将把仍然使用moment.js的复杂的可重用逻辑隐藏起来

如果我们仍然在这里和那里使用
moment.js
功能,那么我们仍然与它紧密耦合。如果我们真的实现了某种模式,我们只能通过适配器或接口与
moment.js
对话,那么我们就无法为整个库实现包装器,这看起来很荒谬


javascript开发人员如何处理这个问题?

我认为有两种方法可以解决这个问题

  • 您当前的方法是:包装
  • 一路走来 当我选择“1”包装方式时。 基本上,您对库的API样式感到不舒服。例如,您反对fluent API,反之亦然。因此,您可以包装整个库以使其感觉更舒适,并且在一天结束时,当您切换到另一个库时,您只需要更改包装器的实现

    当我一路用#2方法打鸭子的时候! 您已经真正了解了动态类型语言的优点和缺点,因此您不会沉迷于强类型语言的方法,但您仍然在开发这两种编程风格

    此外,您已经了解到,我们开发人员倾向于认为我们将被迫每年或5年后进行技术切换,但这是一种错误的行为,因为虽然好的决策不会永远持续,但它们会持续一段合理的长时间,所以您的系统或应用程序可能需要的不仅仅是从一个库切换到另一个库

    在动态类型语言(如JavaScript)中,我们可以继续使用文档取代对接口的需求。检查以下代码段:

    function doStuff(moment) {
        var currentDate = moment(new Date());
    }
    
    是的,您正在注入
    moment
    ,但是一旦您意识到需要切换到另一个库,就没有什么可以阻止您创建包装器,因为您知道处理日期与处理任何库都差不多。不要再加载momentjs,开发整个包装器,调用您的自定义代码,甚至调用一个新的、奇特的库

    function moment(date) {
         return {
              date: date,
              ago: () => {
                  var date = this.date;
    
                  // do the stuff here to return a text like "3 hours ago"
    
                  return text;
              }
         };
    }
    
    您知道,除非blabox没有输出给定函数的调用方所期望的结果,否则这将起作用,对吗

    你会不会因为某一天你想从“时刻”切换到“谁知道呢”而抓挠你的头太多?可能不会,因为您对momentjs的fluent API很满意,并且创建替代实现并不困难,它从一个以相同方式调用的函数开始,遵循相同的API,但公开不同的实现

    一旦你的鸭子说嘎嘎!,谁在乎是你的老鸭子还是你的小鸭子

    你想再给我一个建议吗,如果你需要的话,只需要提供一只新鸭子

    关于松耦合 在我看来,动态类型语言本身是松散耦合的。由于调用者和被调用者之间除了API标识符(属性名、函数名…)之外没有其他耦合,因此实现可以通过设计进行热切换

    也许有一个例外:API具有特定于技术的含义。例如,您需要调用名为
    sendUsingWebSockets
    的函数,并且您不希望与特定的通信技术相耦合,因此您将该特定函数包装为
    send
    ,并且一些设置定义了发送数据的方法(REST、WebSockets、WebRTC…)

    回答OP在评论中解释的一些问题。。。 剩下的唯一问题是,你会对使用 用于突变目的的包装器?人们编写包装器方法来 检索日期并始终通过在其前面加上前缀来对其进行变异 比如一连串的“日期”之类的。我一直在告诉人们 仅仅为这种情况编写一个完整的包装器是不值得的 因为它不能保证所有的小日期实例都是 需要相同的“日期:”字符串前缀

    在过去的10年里,Web开发有了很大的发展。我们正处于UI框架的时代,自5年多以来,每个UI框架中都存在数据绑定

    在日期前加前缀是与UI需求相关的,我不会在应用程序服务中硬编码类似的内容

    例如,旧的AngularJS 1.x具有指令和组件,您可以在这些指令和组件上实现前缀,而无需在模型或服务中硬编码前缀:

    function showDateDirective() {
         return {
             scope: {
                 date: "="
             },
             link: (scope, element) {
                  element.text(`date: ${scope.date.[call here a formatting function]()}`);
             }
         };
    }
    
    module.directive("showDate", showDateDirective);
    
    也就是说,当您需要显示日期时,您只需将其绑定到某个元素,该指令将完成其余操作:

    <span show-date="model.date"></span>
    
    
    

    你需要更改前缀吗?更改指令的实现,您就可以在几秒钟内完成工作

    我认为有两种方法可以解决这个问题

  • 您当前的方法是:包装
  • 一路走来 当我选择“1”包装方式时。 基本上,您对库的API样式感到不舒服。例如,您反对fluent API,反之亦然。因此,您可以包装整个库以使其感觉更舒适,并且在一天结束时,当您切换到另一个库时,您只需要更改包装器的实现