1

In the Python program structure below there are two modules with functions.

Problem description:

  1. Functions are used inside other functions all over the place. Strong coupling (dependency). For example func1() in module 2 that reads from file is called many many times because it's called in almost every other function in both modules. That's resource and performance intensive, yet alone a bad practice.
  2. Reading from file so many times (each time funct1() is called) can be costly.

Question: What is a good way to improve this design?

For example, passing functions from helper module 2 to functions in module 1 AS PARAMETERS? [ If I do that, I still have functions in module 2 dependent upon each other (ie funct4() uses funcr1(), funct2(), funct3(), etc) ]

My paradigm I started with: I was thinking: "Ah, I'm going to have a main module where the main thing happens. Then I will have a side module for functions that do some prep work and clean-up and called them from module 1." (Well, now I have this mess.) I wonder if a good design is to make functions less dependent on each other? Each function does one thing and DOESN'T call other functions?? Should I use classes? How? Is it about when to use classes versus modules? Functional versus OO design?

How would you redesign this so as little coupling as possible and file is read only once (or as few times as possible)?

Thanks for any tips.

module 1

(main module, program execution happens here)

from module2 import *

f1()
- uses funct1() 4 times
- uses funct2() 2 times

f2()
- uses func1() 2 times
- uses func2() 2 times

f3()
- uses func1() 1 time

f4()
- uses func2() 3 times
- uses func3() 3 times
- uses func4() 1 time

f5()
- uses func1() 2 times
- uses func2() 2 times
- uses func4() 4 times

f6()
- uses func1() 3 times
- uses func2() 3 times
- uses func4() 2 times

module 2

(has helper functions that provide clean up and other functionality to module 1)

func1()
reads from file (with open('x.txt', 'r') af f: ...

func2()
- uses func1 1 time

func3()
- uses func1 1 time

func4()
- uses func1() 1 time
- uses func2() 2 times - uses func3() 1 time
1
  • 2
    The file being read multiple times is an issue completely independent of your perceived coupling "concern". Mar 23, 2015 at 23:22

1 Answer 1

0

There are at least two questions being asked here (arguably a lot more, so I'll have to ignore many of the little ones), but the solution to both comes down to writing a class that effectively encapsulates retrieving (your) data from (your) files. Since you specifically asked whether it should be a class or something else, in this language classes are the main data abstraction that's capable of remembering things, which is obviously necessary if you want to avoid reading the same file over and over, so that's why this should be a class.

Since you haven't told me what any of the functions in module 2 actually do after calling func1, I'm going to make up some fairly generic requirements. Let's pretend func1 reads a comma-separated value file of numbers. Say func2 gets the sum of all numbers. Say func3 gets the average and standard distribution of each row.

What you want to do is write a class that handles reading and parsing these files, and exposes methods to retrieve certain aspects of the data it finds. For instance, you might have the class' constructor take a single filename/filepath argument, so the file gets read exactly once during construction, and all method calls on the object merely manipulate the in-memory representation of the data you've already read. The important thing is that no other module should know (exactly) how this class gets its data. They should see getNums() and getStdDev() and getTotal() methods, but they probably shouldn't know whether these values come from a .csv file or an Excel spreadsheet or a website or wherever, and they certainly should not know whether that file/site is being cached or not.

If you do this right, it will be trivial to add getEigenvectors() and whatnot to module2 whenever you feel like it without even thinking about what module1 is doing. That is always the main goal of reducing coupling. This applies to pretty much every language that supports OOP.

If you need more specific help you'll have to explain more about what these functions actually do and why the generic advice I just gave is insufficient.

3
  • Thanks a lot, lxrec. I'm pondering on your reply and will respond in a bit. The program is XML parser. It reads one XML file of ny size. Module 1 is where the parsing happens, checking for syntax validity, is nesting correct, all brackets in place, invalid characters, no space at the beginning of the element name etc... Module two provides some helpful functionality that is not essential to parsing. For example open and read the xml file, get all tag names in order, get data content between tags.I use these helper functions in module 1 to work on xml for example Mar 23, 2015 at 22:59
  • (cont) for example I need a list of all tags in order to determine correctness of nesting). As I said, helper functions don't parse, they just prepare and clean (pre-process? if you will) the xml file so it can be parsed. I'm open to have helper functions and main parsing functions joined in the same module. I just thought separation of concerns would be a good practice. Then I ended up with function calls all over the code. I get your suggestion about crating a class. Mar 23, 2015 at 23:00
  • That does sound like you might have split up the classes at the wrong place. Maybe you can have an XMLPreParser with nothing but a constructor and a getCleanedUpXML() method, then implement XMLParser in terms of that?
    – Ixrec
    Mar 23, 2015 at 23:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.