0

I recently took on a long ago python project which has some weird code style that I can't pinpoint. e.g.

# this is a params and value package?
opts={
infile="xxx",
outfile="xxx"
}
def parses():
    with open(opts['infile'], 'r') as f:
         #do something here and get a parased_object
         opts['infile2']=parased_object
    return

def fun1(): 
    # do someting here
    opts['fun1']=fun1_object
    return

def fun_xx():
    input_for_funcxx=opts['xx']
    #do someting here
    opts['fun_xx']=fun1_object
    return

parses()
fun1()
fun_xx()

I'm a noob who just took over such a large python project, and it's not clear to me if such a way of programming is acceptable, do I need to ask my boss to refactor it? Is there some easy way to make it clear?

2 Answers 2

1

Well, opts serves obviously as a wrapper for global variables, and the code seems to be written in procedural style, all input and output of each function passed through global variables.

Refactoring here should go as in any other programming language when encountering such style:

  • First (most important): don't refactor anything for which there is no real necessity to change. When the code is running well, and you don't have a requirement to add something, leave it that way. Only focus on parts of the code base where you have to fix bugs, need to add new features, or need to optimize.

  • Second: make sure you have enough automated tests for the program. You will definitely break something, so better invest some time into writing regressions tests. These don't need to be unit tests, but your tests should have some reproducible input and some recorded, validated output which is known to be "correct", for a representative sets of use cases. For a non-typesafe language like Python this is even more important since there is no compiler preventing you from typos introduced by refactorings.

  • And for the refactoring itself: as a start, get rid of as many global variables as possible. Instead, introduce explicit input parameters and return values for each functions, and restrict their usage to the smallest possible scope possible. Functions with no side effects (or at least less side effects), and functions which don't rely on side effects are way easier to reason about and to maintain as functions which do cause or rely on side effects.

Note this can be only a start. You will probably have to apply lots of more of the standard refactoring techniques you find in books like Fowler's "Refactoring" book and Feathers' "Working Effectively with Legacy Code" book. Also have a look into one of our old, but timeless questions on this site: I've inherited 200K lines of spaghetti code -- what now?.

Good luck!

TLDR; No, there is no easy way. But there are standard approaches, which require hard work, as ever.

5
  • Thanks you, Brown, Your suggestion is very clear, I really lack experience in writing process-oriented programs. There are a lot of similar codes in the actual program. Some of them are very complicated. These related functions all get input from opts and return to opts, which means I can't reuse them from the outside, but I need in fact. Could you please give me some advice to make sure I don't screw it up in the process
    – zhang
    Commented Dec 21, 2022 at 9:43
  • 1
    You are still looking for an easy solution. Sorry to say, there is none. This is hard work, and will take time to learn. Best recommendation I can give you is to have a look into this old SE post I've inherited 200K lines of spaghetti code -- what now?. You find a link to Feathers' book in the first comment below that question.
    – Doc Brown
    Commented Dec 21, 2022 at 9:50
  • Thanks for the reference, this is exactly what I need to learn, at the moment I'm thinking of writing another crappy function that generates an opts package that satisfies what it needs to run before calling the original function, and then uses another one after the call is complete to extract the variables I need from it, it's a not well solution. But I will refactor the code I need as you suggest to gradually replace existing functions
    – zhang
    Commented Dec 21, 2022 at 10:23
  • By the way, I am reading the references you gave in detail, I am also working in a scientific research team, which is the same working environment as the author mentioned in the article, as he said: Whatever you do, don't rewrite this from scratch. It would be a serious mistake. 20 years of chemical knowledge: it's stuff that you would never be able to recreate. And you would rightly lose the respect from the scientists.
    – zhang
    Commented Dec 21, 2022 at 11:32
  • This is why I am so worried about refactoring this code, there are too many tricks and empirical things in it, it is difficult for me to refactor it and and prove that it is consistent with the original. But I think the experience introduced by the author is useful
    – zhang
    Commented Dec 21, 2022 at 11:32
0

Looks normal to me in Python. Big function split up into three. Zero comments, also normal for Python. Can’t quite see where to see deeply coupled code.

If things are not clear to you then don’t refactor anything until things are clear. Go to a more experienced programmer, which may be your boss, and ask them. Tell them that you would like to refactor and how.

3
  • I think there are deeply coupled because there are a lot of similar codes in the actual program. These related functions all get input from opts and return to opts, which means I can't reuse them from the outside. function. it looks weird for me. But as @Doc Brown comment. Maybe it's because of my inexperience
    – zhang
    Commented Dec 21, 2022 at 9:38
  • Duplication doesn’t mean deep coupling. That has a specific meaning.
    – gnasher729
    Commented Dec 22, 2022 at 10:06
  • Sorry, there are sone unclear, I mean is similar code style, which is use opts as a globe value wrapper and ever function get input from opts, change the value or add value in opts as output for functions
    – zhang
    Commented Dec 23, 2022 at 3:34

Your Answer

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

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