What's the correct way to "untie the connection" in python?

Hello I have written a code to get data using pySerial as shown below. My class depends on a serial class that doesn't follow the "loose coupling" rule.
Should I use an interface to decouple my class?
Thanks a lot for your instruction.

import serial

class ArduinoConnect:  

    def __init__(self):
        pass

    def serial_connect(self, serial_port, serial_baudrate):

        self._serial_port = serial_port
        try:
           self.ser = serial.Serial(
                port=self._serial_port,
                baudrate=serial_baudrate,
                parity=serial.PARITY_NONE,
                stopbits=serial.STOPBITS_ONE,
                bytesize=serial.EIGHTBITS,
            )
        except serial.serialutil.SerialException, e:
            print str(e)

    def serial_disconnect(self):
        self.ser.close()

    def get_quaternion(self, number_of_data=50):

        buff = []
        self.ser.write('q')
        self.ser.write(chr(number_of_data))
        for j in range(number_of_data):
            in_string = self.ser.readline()
            buff_line = in_string.split(",")
            buff_line.pop()
            buff_line = self.hex_to_quaternion(buff_line)
            buff.append(list(buff_line))
        return buff

    def hex_to_quaternion(self, list_of_hex=None):
        #......
        pass

arduino = ArduinoConnect()
arduino.serial_connect(serial_port="COM5", serial_baudrate=115200)
print arduino.get_quaternion()
arduino.serial_disconnect()

      


I have adjusted my code as recommended.
DI helps decouple the sequential process, and the factory method helps encapsulate the DI process.
Is there anything else I could do to meet the "free communication" rule?
Thanks for your help.

import serial

class ArduinoConnect:
    def __init__(self, serial_to_arduino):
        self._serial_to_arduino = serial_to_arduino

    def get_quaternion(self, number_of_data=50):
        buff = []
        self._serial_to_arduino.write('q')
        self._serial_to_arduino.write(chr(number_of_data))
        for j in range(number_of_data):
            in_string = self._serial_to_arduino.readline()
            buff_line = in_string.split(",")
            buff_line.pop()
            buff_line = self.hex_to_quaternion(buff_line)
            buff.append(list(buff_line))
        return buff

    def hex_to_quaternion(self, list_of_hex):
        ......

    def __getattr__(self, attr):
        return getattr(self._serial_to_arduino, attr)


class SerialToArduino:
    def __init__(self):
        pass

    def serial_connect(self, serial_port="COM5", serial_baudrate=115200):
        self._serial_port = serial_port
        try:
            self.ser = serial.Serial(
                port=self._serial_port,
                baudrate=serial_baudrate,
                parity=serial.PARITY_NONE,
                stopbits=serial.STOPBITS_ONE,
                bytesize=serial.EIGHTBITS,
            )
        except serial.serialutil.SerialException, e:
            print str(e)

    def serial_disconnect(self):
        self.ser.close()

    def readline(self):
        return self.ser.readline()

    def write(self, data):
        self.ser.write(data=data)


def get_ArduinoConnect():
    'factory method'
    return ArduinoConnect(serial_to_arduino=SerialToArduino())


arduino = get_ArduinoConnect()
arduino.serial_connect(serial_port="COM5", serial_baudrate=115200)
print arduino.get_quaternion()
arduino.serial_disconnect()

      

+3


source to share


1 answer


I can think of 2 possible solutions

  • Inject an "adapter" to expose methods to the main class and hide the Serial implementation. So that your main class can avoid dependency on the concrete Serial class
  • Do dependency injection, something like it

    def serial_connect (self, engine, serial_port, serial_baudrate)

Update for 1: I referred to http://en.wikipedia.org/wiki/Adapter_pattern which is commonly used when you want to decouple a specific implementation from an abstraction. Think of it as a plug adapter.

This is especially useful for a language like Java with a strict interface and everything. In your case, since we don't have an "interface" in Python, you can simulate it with an abstract class

class AbstractAdapter():
      def serial_connect(self, serial_port="COM5", serial_baudrate=115200):
          raise("Needs implementation")
      # do the same thing for the rest of the methods

      



Then in ArduinoConnect

you can check the type

def __init__(self, serial_to_arduino):
    if not isinstance(serial_to_arduino, AbstractAdapter):
        raise("Wrong type")

      

This forces your serial_to_arduino

to extend AbstractAdapter

which provides the implementation of all abstract methods, hence the adapter.

This may not be the most "pythonic" way of doing things, but from an OOP perspective, you can do it in such a way as to have the highest level of loose coupling (in my opinion)

P / s: Actually, I believe that the correct model in this case should be a Strategy, they are both very similar in terms of implementation, but they serve different purposes. You can read more about some of the patterns like Strategy, Proxy, Command, Mediator, which are often used to achieve loose communication.

+3


source







All Articles