Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python design guidance:

I'm a very experienced developer - done a lot of heavy duty work with Delphi, C# and C++ for years. I have always adhered very closely to the guidelines for structured programming, OOP, loosely coupled modular designs etc - and since all the languages I've used have built-in ways of enforcing these concepts - access control, static types, interface and abstract class support etc - I rely on these to structure my code.

Now, I have been doodling with Python for a few months. I am impressed by its many wonderful features - but I sorely miss the built-in constraints that make it easy to keep code modularized and organized. And, unfortunately, I see an awful lot of 'spaghetti code' out there written in Python, even from very respectable sources. I won't single anyone out but I have a few books written by major league pythonistas with examples replete with designs (better put - 'anti-designs') that make me shudder. It seems to me that because Python is so easy to use, it's also very easy to abuse.

I do try to discipline myself when I code in Python, but I find it takes a lot of extra work to implement and often I have to set up and adhere to constraints simply based on my own memory of the design with no help from the language at all. And since there is no 'compile time' checking, it's doubly difficult - often you don't discover a design flaw until you actually RUN that segment of code.

So, I'm looking for very specific information: some examples or better still a book of WELL STRUCTURED Python designs and design techniques - how to best implement encapsulation, indirection, very loosely coupled designs, etc.

Bad design IMO from a prominent python book author - (with obfuscation)

def populateList(self, selecteddisk=None):
selected = None ***#Bundling - coupling:*** 
self.listWidget.clear()
for disk in self.disks.inOrder():
item = QListWidgetItem(QString("%1 of %2/%3 (%L4)") \
.arg(disk.name).arg(disk.owner).arg(disk.country) \
.arg(disk.teu))
self.listWidget.addItem(item)
***#Bundling - coupling:*** 
if selecteddisk is not None and selecteddisk == id(disk):
    selected = item
    if selected is not None:
    selected.setSelected(True)
    self.listWidget.setCurrentItem(selected)
like image 957
Vector Avatar asked Oct 10 '22 00:10

Vector


1 Answers

I find it takes a lot of extra work to implement and compile code that adheres to constraints simply based on my own memory of the design with no help from the language when writing the code itself before compiling. Some IDE's offer help, but the language itself offers me no help at all.

And since 'compile time' checking never seems to help me find ordinary logic bugs it's doubly difficult - often you don't discover a design flaw until you actually RUN that segment of code.

Python designs and design techniques ... how to best implement encapsulation,

By encapsulating. In languages like Java and C++, "encapsulation" has grown to mean "uses private stuff all over the place." In Python that's simply not supported.

We're All Adults Here.

You still do encapsulation just like you did in every other language. Without the word private, however.

Python offers properties, decorators and overrides to __getattribute__ to implement various kinds of encapsulation techniques.

indirection,

By referencing other objects. I'm not clear on what specific problems you have here, but perhaps you've passed some wrong-type argument to a function. The way to avoid this is to read the docstrings you wrote for yourself.

very loosely coupled designs, etc.

By doing dependency injection. Again. Python works just like every other language with respect to loose coupling.

You should investigate -- and use -- docstrings heavily.

You might want to use https://www.sphinx-doc.org to generate nice documentation from your docstrings.

You can also use Python's built-in help() function to read the docstrings you wrote when you wrote your code.

like image 179
S.Lott Avatar answered Oct 18 '22 14:10

S.Lott