Is it a bad style to reassign long variables as a local abbreviation?

I prefer to use long identifiers so that my code is semantically understandable, but in the case of repeated references to the same identifier, I would like it to "get out of the way" in the current area. Take this example in Python:

def define_many_mappings_1(self): self.define_bidirectional_parameter_mapping("status", "current_status") self.define_bidirectional_parameter_mapping("id", "unique_id") self.define_bidirectional_parameter_mapping("location", "coordinates") #etc... 

Suppose I really want to stick with this long method name and that these arguments will always be hardcoded. Implementation 1 seems to be wrong, because most of each line is busy repeating characters. Lines are also quite long in the general case and can exceed 80 characters when nested inside a class definition and / or try / except block, which leads to ugly line portability. Try using the for loop:

 def define_many_mappings_2(self): mappings = [("status", "current_status"), ("id", "unique_id"), ("location", "coordinates")] for mapping in mappings: self.define_parameter_mapping(*mapping) 

I am going to combine all such iterative methods under the auspices of implementation 2, which improves the separation of "unique" arguments on behalf of the "reuse" method. However, I do not like that this leads to the placement of arguments before the method to which they are passed, which confuses. I would prefer to keep the syntax "verb followed by a direct object."

I found myself as a compromise as follows:

 def define_many_mappings_3(self): d = self.define_bidirectional_parameter_mapping d("status", "current_status") d("id", "unique_id") d("location", "coordinates") 

In implementation 3, the long method is smoothed out by the extremely short “abbreviation” variable. I like this approach because it is immediately recognizable as a collection of repeated method calls at a glance, with fewer redundant characters and much shorter strings. The disadvantage is the use of an extremely short and semantically fuzzy identifier "d".

What is the most readable solution? Is the use of an “abbreviation variable” acceptable if it is explicitly assigned from an abbreviated version in a local area?

+4
source share
4 answers

I would go with implementation 2, but this is a close call.

I think # 2 and # 3 are equally readable. Imagine if you had 100s of mappings ... In any case, I cannot say what the code does below without scrolling up. In # 2, you name the data; in # 3 you give the name of the function. This is basically a wash.

Changing data is also erasing, because in any case, you simply add one row to the same template as there.

The difference arises if you want to change what you do with the data. For example, let's say you decide to add a debug message for each mapping you define. With # 2, you add an operator to the loop, and it is still easy to read. With # 3, you need to create lambda or something else. Nothing wrong with lambdas - I adore Lisp as much as anyone, but I think that I will still find # 2 easier to read and modify.

But this is a close call, and your taste may be different.

0
source

itertools to the rescue again! Try using starmap - here's a simple demo:

 list(itertools.starmap(min,[(1,2),(2,2),(3,2)])) 

prints

 [1,2,2] 

starmap is a generator, so you need to use a list generator to actually call methods.

 import itertools def define_many_mappings_4(self): list(itertools.starmap( self.define_parameter_mapping, [ ("status", "current_status"), ("id", "unique_id"), ("location", "coordinates"), ] )) 

I'm usually not a fan of using a list of dummy object constructs to invoke a sequence of functions, but this diagram seems to affect most of your problems.

If define_parameter_mapping returns None, you can replace list with any , and then all function calls will be made, and you will not have to create this dummy list.

+1
source

I think that # 3 is not bad, although I could choose a slightly longer identifier than d , but often this type of thing becomes data-driven, so you can use variation # 2, where you loop the database query result or something from configuration file

0
source

There is no right answer, so you will get opinions on all sides here, but I would rather see # 2 in any code for which I was responsible for maintaining.

# 1 is verbose, repetitive and difficult to change (for example, you need to call two methods for each pair or add a log - then you must change each line). But often this happens with the development of the code, and this is a fairly familiar and harmless model.

# 3 suffers the same problem as # 1, but with a slightly more concise price, requiring what is basically a macro and, therefore, new and slightly unfamiliar terms.

# 2 is simple and clear. It displays your displays in the form of data, and then repeats them using basic language constructs. To add new mappings, you need to add a string to the array. You can load your mappings from an external file or URL into a line, and that would be easy to change. To change what has been done with them, you only need to change the body of your for loop (which itself can be turned into a separate function if necessary).

Your complaint number 2 on the "object before the verb" does not bother me at all. When scanning this function, I would first suggest that the verb does what it should do, and focuses on the object, which is now clear and immediately visible and supported. Only if there were problems, I would look at the verb, and it would be immediately clear what he was doing.

0
source

All Articles