HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Logic Gate Simulator - Proper Encapsulation

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
encapsulationlogicpropergatesimulator

Problem

So I was checking out the courses on InteractivePython, and I came across this example to demonstrate inheritance.

My focus is on the Connector class and how it interacts with BinaryGate and UnaryGate via the setNextPin method.

```
class LogicGate:

def __init__(self,n):
self.name = n
self.output = None

def getName(self):
return self.name

def getOutput(self):
self.output = self.performGateLogic()
return self.output

class BinaryGate(LogicGate):

def __init__(self,n):
LogicGate.__init__(self,n)

self.pinA = None
self.pinB = None

def getPinA(self):
if self.pinA == None:
return int(input("Enter Pin A input for gate "+self.getName()+"-->"))
else:
return self.pinA.getFrom().getOutput()

def getPinB(self):
if self.pinB == None:
return int(input("Enter Pin B input for gate "+self.getName()+"-->"))
else:
return self.pinB.getFrom().getOutput()

def setNextPin(self,source):
if self.pinA == None:
self.pinA = source
else:
if self.pinB == None:
self.pinB = source
else:
print("Cannot Connect: NO EMPTY PINS on this gate")

class AndGate(BinaryGate):

def __init__(self,n):
BinaryGate.__init__(self,n)

def performGateLogic(self):

a = self.getPinA()
b = self.getPinB()
if a==1 and b==1:
return 1
else:
return 0

class OrGate(BinaryGate):

def __init__(self,n):
BinaryGate.__init__(self,n)

def performGateLogic(self):

a = self.getPinA()
b = self.getPinB()
if a ==1 or b==1:
return 1
else:
return 0

class UnaryGate(LogicGate):

def __init__(self,n):
LogicGate.__init__(self,n)

self.pin = None

def getPin(self):
if self.pin == None:
return

Solution

You are mixing up lots of different responsibilities in your classes. For instance, AndGate has to handle both the And part and all the pin input parts. It is weird that an AndGate doesn't actually take references to its input pins. Furthermore, how in this model do we connect gates to each other? By your design, a "pin" is a value comparable to an integer. What if I wanted to model something like (picking a random circuit from google):

How would I do that in your system? The Connectors confuse the logic, since in your example you're creating a bunch of gates that are floating around - and then just to see that G1 and G2 go into G3 is split across several lines, rather than ideally:

g3 = OrGate('G3', g1, g2)


As a first go, gates should know their inputs and be able to perform logic to determine their outputs:

class NandGate(LogicGate):
    def __init__(self, name, a, b):
        LogicGate.__init__(self, name)
        self.a = a
        self.b = b

    @property
    def output(self):
        return not (self.a.output and self.b.output)


This separates the concern of input handling (determining the pins) from the concern of actually emulating the gates (determining the outputs) - and is what will let us have NandGates as input to other NandGates:

A = ConstantPin('A', True)
B = ConstantPin('B', False)
N1 = NandGate('N1', A, B)
N2 = NandGate('N2', A, N1)
N3 = NandGate('N3', N1, B)
N4 = NandGate('N4', N2, N3)
N5 = NandGate('N5', N4, N4)
Q = N5.output

Code Snippets

g3 = OrGate('G3', g1, g2)
class NandGate(LogicGate):
    def __init__(self, name, a, b):
        LogicGate.__init__(self, name)
        self.a = a
        self.b = b

    @property
    def output(self):
        return not (self.a.output and self.b.output)
A = ConstantPin('A', True)
B = ConstantPin('B', False)
N1 = NandGate('N1', A, B)
N2 = NandGate('N2', A, N1)
N3 = NandGate('N3', N1, B)
N4 = NandGate('N4', N2, N3)
N5 = NandGate('N5', N4, N4)
Q = N5.output

Context

StackExchange Code Review Q#112446, answer score: 3

Revisions (0)

No revisions yet.