首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我的软件模型有某种循环依赖关系。

我的软件模型有某种循环依赖关系。
EN

Software Engineering用户
提问于 2015-11-17 21:04:40
回答 2查看 313关注 0票数 0

我需要一个关于我的软件模型的建议。

我认为这不是很好,因为有某种循环依赖。

我在库拉应用框架下有一个OSGI包,下面是类:

  • Main类:包的入口点
  • TwoWaySerialComm:用于与Arduino设备的串行通信
  • SerialReader:负责从串口读取来自Arduino的数据,然后使用KURA服务DataService将接收到的数据发送到云。类Main { public静态DataService m_dataService;//KURA服务,通过MQTT保护的void (ComponentContext componentContext) { serialCom =新的TwoWaySerialComm ();//负责串行通信serialCom.connect("/dev/ttyUSB0");}类TwoWaySerialComm{ void (String){/代码省略在= serialPort.getInputStream();//添加事件侦听器从串口serialPort.addEventListener(新的SerialReader (In))读取数据;//代码省略}}公共类SerialReader实现SerialPortEventListener { public void serialEvent(SerialPortEvent arg0) {//代码,用于串口读取省略/从串口获取的数据通过MQTT通过MQTT发送到//云,使用库拉服务DataService作为以下内容: Main.m_dataService.publish();}}

这是个糟糕的模特儿,如果是这样的话,我该怎么办呢?

EN

回答 2

Software Engineering用户

回答已采纳

发布于 2015-11-18 18:40:22

是的,对其他类的过度了解和相应的紧密耦合是不好的。

好消息!依赖反转很容易解决这个问题。

关键的缺陷是SerialReader知道Main有它的DataService依赖项。它不需要知道这一点,也不应该知道,相反,它应该使用DataService构建。这被称为依赖反转或依赖注入。

SerialReader.java:

代码语言:javascript
复制
public final class SerialReader  implements SerialPortEventListener {
    private final DataService dataService;

    public SerialReader(DataService dataService) {
        this.dataService = dataService;
    }

    public void serialEvent(SerialPortEvent arg0) {
        //code for serial port reading omitted

        //the data obtained from the serial is sent to the 
        //cloud via MQTT using the KURA service DataService as the following: 
        dataService.publish(); 
    }
}

同样的技术可以在TwoWaySerialComm上得到更多的应用,因为它可以依赖于SerialPortEventListener接口,而不是特定的类,使得它非常松散地耦合。

TwoWaySerialComm.java

代码语言:javascript
复制
final class TwoWaySerialComm  {
    private final SerialPortEventListener serialPort;

    TwoWaySerialComm(SerialPortEventListener serialPort) {
        this.serialPort = serialPort;
    }

    void connect(String portName)  {
        //code omitted
        in = serialPort.getInputStream();
        //add event listener to read data from the serial port
        serialPort.addEventListener(new SerialReader(in));
        //code omitted
    }
}

并且主服务器完成了它的工作,这是并且应该一直被限制在连接依赖项和启动系统上。

Main.java:

代码语言:javascript
复制
final class Main  {
    //KURA service to send information to the cloud via MQTT
    public static final DataService dataService;

    protected void activate(ComponentContext componentContext) {
        SerialReader serialReader = new SerialReader(dataService);
        TwoWaySerialComm serialCom = new TwoWaySerialComm(serialReader);//responsible for serial communication
        serialCom.connect("/dev/ttyUSB0");
    }
}

您可能会注意到,我已将m_dataService重命名为dataService。m_偶尔在C++中使用,但在C++中被认为是糟糕的样式。

票数 2
EN

Software Engineering用户

发布于 2015-11-18 15:38:30

这似乎是一个有问题的设计。如果一个类不能独立存在,它实际上成为意外的类的一部分,以及它的硬依赖关系。在这种情况下,MainTwoWaySerialCommSerialReader实际上是一个类,可能是MainTwoWaySerialCommSerialReader

我能看到几种绕过它的方法。

如果Main需要对DataService的引用,则将该引用共享为TwoWaySerialComm的参数,并最终作为SerialReader的参数。不要把它暴露为公众成员。

代码语言:javascript
复制
class Main {

    private static DataService m_dataService;

    protected void activate(ComponentContext componentContext) {    
      serialCom = new TwoWaySerialComm();
      serialCom.connect("/dev/ttyUSB0", m_dataService); 
    }
}

class TwoWaySerialComm{
    void connect (String portName, DataService service) {
       in = serialPort.getInputStream();
       serialPort.addEventListener(new SerialReader(in, service));
    }
}

public class SerialReader implements SerialPortEventListener {

    private Stream in;
    private DataService service;

    SerialReader (Stream in, DataService service) {
        this.in = in;
        this.service = service;
    }

    public void serialEvent(SerialPortEvent arg0) {
        this.service.publish();
    }
}

现在,TwoWaySerialCommSerialReader都可以在其他上下文中使用。他们不需要Main

另一种选择是将DataService的责任推到更接近使用它的位置。如果可行的话,SerialReader可以“拥有”它。

代码语言:javascript
复制
class Main {    
    protected void activate(ComponentContext componentContext) {    
      serialCom = new TwoWaySerialComm();
      serialCom.connect("/dev/ttyUSB0"); 
    }
}

class TwoWaySerialComm{
    void connect (String portName) {
       in = serialPort.getInputStream();
       serialPort.addEventListener(new SerialReader(in));
    }
}

public class SerialReader implements SerialPortEventListener {

    private Stream in;
    private DataService service;

    SerialReader (Stream in) {
        this.in = in;
        // Not sure if this is possible.
        // If it is, it reduces the need to juggle the DataService
        // reference between classes.         
        this.service = ResolveDataServiceSomehow();
    }

    public void serialEvent(SerialPortEvent arg0) {
        this.service.publish();
    }
}
票数 2
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/302853

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档