| Conditions | 11 |
| Total Lines | 51 |
| Lines | 0 |
| Ratio | 0 % |
| Tests | 0 |
| CRAP Score | 132 |
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