Conditions | 11 |
Total Lines | 51 |
Lines | 0 |
Ratio | 0 % |
Tests | 0 |
CRAP Score | 132 |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like OptionService.update() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | from plugin.api.core.base import Service, expose |
||
50 | @expose |
||
51 | def update(self, changes, account=None): |
||
52 | scope = 'account' if account is not None else 'server' |
||
53 | |||
54 | # Validate changes |
||
55 | changed = {} |
||
56 | ignored = [] |
||
57 | |||
58 | for key, change in changes.items(): |
||
59 | if 'from' not in change or 'to' not in change: |
||
60 | raise InvalidUpdateError |
||
61 | |||
62 | if key not in OPTIONS_BY_KEY: |
||
63 | raise UnknownOptionError |
||
64 | # Retrieve option |
||
65 | option = OPTIONS_BY_KEY[key] |
||
66 | |||
67 | if option.scope != scope: |
||
68 | raise InvalidScopeError |
||
69 | |||
70 | # Retrieve option details from database |
||
71 | option = option.get(account) |
||
72 | |||
73 | if option.value != change['from']: |
||
74 | raise UpdateConflictError |
||
75 | |||
76 | # Ensure option has changed |
||
77 | if change['from'] == change['to']: |
||
78 | ignored.append(key) |
||
79 | continue |
||
80 | |||
81 | changed[key] = change |
||
82 | |||
83 | # Update options |
||
84 | updated = [] |
||
85 | |||
86 | for key, change in changed.items(): |
||
87 | if key not in OPTIONS_BY_KEY: |
||
88 | raise UnknownOptionError |
||
89 | |||
90 | value = change['to'] |
||
91 | |||
92 | # Update value |
||
93 | option = OPTIONS_BY_KEY[key] |
||
94 | option.update(value, account) |
||
95 | |||
96 | updated.append(key) |
||
97 | |||
98 | return { |
||
99 | 'updated': updated, |
||
100 | 'ignored': ignored |
||
101 | } |
||
102 |
If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example
could be written as