Conditions | 61 |
Total Lines | 215 |
Code Lines | 165 |
Lines | 0 |
Ratio | 0 % |
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 sqlite3.convertAssign 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 | // Extracted from Go database/sql source code |
||
26 | func convertAssign(dest, src interface{}) error { |
||
27 | // Common cases, without reflect. |
||
28 | switch s := src.(type) { |
||
29 | case string: |
||
30 | switch d := dest.(type) { |
||
31 | case *string: |
||
32 | if d == nil { |
||
33 | return errNilPtr |
||
34 | } |
||
35 | *d = s |
||
36 | return nil |
||
37 | case *[]byte: |
||
38 | if d == nil { |
||
39 | return errNilPtr |
||
40 | } |
||
41 | *d = []byte(s) |
||
42 | return nil |
||
43 | case *sql.RawBytes: |
||
44 | if d == nil { |
||
45 | return errNilPtr |
||
46 | } |
||
47 | *d = append((*d)[:0], s...) |
||
48 | return nil |
||
49 | } |
||
50 | case []byte: |
||
51 | switch d := dest.(type) { |
||
52 | case *string: |
||
53 | if d == nil { |
||
54 | return errNilPtr |
||
55 | } |
||
56 | *d = string(s) |
||
57 | return nil |
||
58 | case *interface{}: |
||
59 | if d == nil { |
||
60 | return errNilPtr |
||
61 | } |
||
62 | *d = cloneBytes(s) |
||
63 | return nil |
||
64 | case *[]byte: |
||
65 | if d == nil { |
||
66 | return errNilPtr |
||
67 | } |
||
68 | *d = cloneBytes(s) |
||
69 | return nil |
||
70 | case *sql.RawBytes: |
||
71 | if d == nil { |
||
72 | return errNilPtr |
||
73 | } |
||
74 | *d = s |
||
75 | return nil |
||
76 | } |
||
77 | case time.Time: |
||
78 | switch d := dest.(type) { |
||
79 | case *time.Time: |
||
80 | *d = s |
||
81 | return nil |
||
82 | case *string: |
||
83 | *d = s.Format(time.RFC3339Nano) |
||
84 | return nil |
||
85 | case *[]byte: |
||
86 | if d == nil { |
||
87 | return errNilPtr |
||
88 | } |
||
89 | *d = []byte(s.Format(time.RFC3339Nano)) |
||
90 | return nil |
||
91 | case *sql.RawBytes: |
||
92 | if d == nil { |
||
93 | return errNilPtr |
||
94 | } |
||
95 | *d = s.AppendFormat((*d)[:0], time.RFC3339Nano) |
||
96 | return nil |
||
97 | } |
||
98 | case nil: |
||
99 | switch d := dest.(type) { |
||
100 | case *interface{}: |
||
101 | if d == nil { |
||
102 | return errNilPtr |
||
103 | } |
||
104 | *d = nil |
||
105 | return nil |
||
106 | case *[]byte: |
||
107 | if d == nil { |
||
108 | return errNilPtr |
||
109 | } |
||
110 | *d = nil |
||
111 | return nil |
||
112 | case *sql.RawBytes: |
||
113 | if d == nil { |
||
114 | return errNilPtr |
||
115 | } |
||
116 | *d = nil |
||
117 | return nil |
||
118 | } |
||
119 | } |
||
120 | |||
121 | var sv reflect.Value |
||
122 | |||
123 | switch d := dest.(type) { |
||
124 | case *string: |
||
125 | sv = reflect.ValueOf(src) |
||
126 | switch sv.Kind() { |
||
127 | case reflect.Bool, |
||
128 | reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, |
||
129 | reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, |
||
130 | reflect.Float32, reflect.Float64: |
||
131 | *d = asString(src) |
||
132 | return nil |
||
133 | } |
||
134 | case *[]byte: |
||
135 | sv = reflect.ValueOf(src) |
||
136 | if b, ok := asBytes(nil, sv); ok { |
||
137 | *d = b |
||
138 | return nil |
||
139 | } |
||
140 | case *sql.RawBytes: |
||
141 | sv = reflect.ValueOf(src) |
||
142 | if b, ok := asBytes([]byte(*d)[:0], sv); ok { |
||
143 | *d = sql.RawBytes(b) |
||
144 | return nil |
||
145 | } |
||
146 | case *bool: |
||
147 | bv, err := driver.Bool.ConvertValue(src) |
||
148 | if err == nil { |
||
149 | *d = bv.(bool) |
||
150 | } |
||
151 | return err |
||
152 | case *interface{}: |
||
153 | *d = src |
||
154 | return nil |
||
155 | } |
||
156 | |||
157 | if scanner, ok := dest.(sql.Scanner); ok { |
||
158 | return scanner.Scan(src) |
||
159 | } |
||
160 | |||
161 | dpv := reflect.ValueOf(dest) |
||
162 | if dpv.Kind() != reflect.Ptr { |
||
163 | return errors.New("destination not a pointer") |
||
164 | } |
||
165 | if dpv.IsNil() { |
||
166 | return errNilPtr |
||
167 | } |
||
168 | |||
169 | if !sv.IsValid() { |
||
170 | sv = reflect.ValueOf(src) |
||
171 | } |
||
172 | |||
173 | dv := reflect.Indirect(dpv) |
||
174 | if sv.IsValid() && sv.Type().AssignableTo(dv.Type()) { |
||
175 | switch b := src.(type) { |
||
176 | case []byte: |
||
177 | dv.Set(reflect.ValueOf(cloneBytes(b))) |
||
178 | default: |
||
179 | dv.Set(sv) |
||
180 | } |
||
181 | return nil |
||
182 | } |
||
183 | |||
184 | if dv.Kind() == sv.Kind() && sv.Type().ConvertibleTo(dv.Type()) { |
||
185 | dv.Set(sv.Convert(dv.Type())) |
||
186 | return nil |
||
187 | } |
||
188 | |||
189 | // The following conversions use a string value as an intermediate representation |
||
190 | // to convert between various numeric types. |
||
191 | // |
||
192 | // This also allows scanning into user defined types such as "type Int int64". |
||
193 | // For symmetry, also check for string destination types. |
||
194 | switch dv.Kind() { |
||
195 | case reflect.Ptr: |
||
196 | if src == nil { |
||
197 | dv.Set(reflect.Zero(dv.Type())) |
||
198 | return nil |
||
199 | } |
||
200 | dv.Set(reflect.New(dv.Type().Elem())) |
||
201 | return convertAssign(dv.Interface(), src) |
||
202 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: |
||
203 | s := asString(src) |
||
204 | i64, err := strconv.ParseInt(s, 10, dv.Type().Bits()) |
||
205 | if err != nil { |
||
206 | err = strconvErr(err) |
||
207 | return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err) |
||
208 | } |
||
209 | dv.SetInt(i64) |
||
210 | return nil |
||
211 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: |
||
212 | s := asString(src) |
||
213 | u64, err := strconv.ParseUint(s, 10, dv.Type().Bits()) |
||
214 | if err != nil { |
||
215 | err = strconvErr(err) |
||
216 | return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err) |
||
217 | } |
||
218 | dv.SetUint(u64) |
||
219 | return nil |
||
220 | case reflect.Float32, reflect.Float64: |
||
221 | s := asString(src) |
||
222 | f64, err := strconv.ParseFloat(s, dv.Type().Bits()) |
||
223 | if err != nil { |
||
224 | err = strconvErr(err) |
||
225 | return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err) |
||
226 | } |
||
227 | dv.SetFloat(f64) |
||
228 | return nil |
||
229 | case reflect.String: |
||
230 | switch v := src.(type) { |
||
231 | case string: |
||
232 | dv.SetString(v) |
||
233 | return nil |
||
234 | case []byte: |
||
235 | dv.SetString(string(v)) |
||
236 | return nil |
||
237 | } |
||
238 | } |
||
239 | |||
240 | return fmt.Errorf("unsupported Scan, storing driver.Value type %T into type %T", src, dest) |
||
241 | } |
||
300 |