Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like Abstract 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
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.
While breaking up the class, it is a good idea to analyze how other classes use Abstract, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
22 | abstract class Nexcessnet_Turpentine_Model_Varnish_Configurator_Abstract { |
||
23 | |||
24 | const VCL_CUSTOM_C_CODE_FILE = 'uuid.c'; |
||
25 | |||
26 | /** |
||
27 | * Get the correct version of a configurator from a socket |
||
28 | * |
||
29 | * @param Nexcessnet_Turpentine_Model_Varnish_Admin_Socket $socket |
||
30 | * @return Nexcessnet_Turpentine_Model_Varnish_Configurator_Abstract |
||
31 | */ |
||
32 | static public function getFromSocket($socket) { |
||
33 | try { |
||
34 | $version = $socket->getVersion(); |
||
35 | } catch (Mage_Core_Exception $e) { |
||
36 | Mage::getSingleton('core/session') |
||
37 | ->addError('Error determining Varnish version: '. |
||
38 | $e->getMessage()); |
||
39 | return null; |
||
40 | } |
||
41 | switch ($version) { |
||
42 | case '4.0': |
||
43 | case '4.1': |
||
44 | return Mage::getModel( |
||
45 | 'turpentine/varnish_configurator_version4', |
||
46 | array('socket' => $socket) ); |
||
47 | |||
48 | case '3.0': |
||
49 | return Mage::getModel( |
||
50 | 'turpentine/varnish_configurator_version3', |
||
51 | array('socket' => $socket) ); |
||
52 | case '2.1': |
||
53 | return Mage::getModel( |
||
54 | 'turpentine/varnish_configurator_version2', |
||
55 | array('socket' => $socket) ); |
||
56 | default: |
||
57 | Mage::throwException('Unsupported Varnish version'); |
||
58 | } |
||
59 | } |
||
60 | |||
61 | /** |
||
62 | * The socket this configurator is based on |
||
63 | * |
||
64 | * @var Nexcessnet_Turpentine_Model_Varnish_Admin_Socket |
||
65 | */ |
||
66 | protected $_socket = null; |
||
67 | /** |
||
68 | * options array |
||
69 | * |
||
70 | * @var array |
||
71 | */ |
||
72 | protected $_options = array( |
||
73 | 'vcl_template' => null, |
||
74 | ); |
||
75 | |||
76 | public function __construct($options = array()) { |
||
77 | $this->_options = array_merge($this->_options, $options); |
||
78 | } |
||
79 | |||
80 | abstract public function generate($doClean = true); |
||
81 | // abstract protected function _getTemplateVars(); |
||
82 | |||
83 | /** |
||
84 | * Save the generated config to the file specified in Magento config |
||
85 | * |
||
86 | * @param string $generatedConfig config generated by @generate |
||
87 | * @return null |
||
88 | */ |
||
89 | public function save($generatedConfig) { |
||
106 | |||
107 | /** |
||
108 | * Get the full path for a given template filename |
||
109 | * |
||
110 | * @param string $baseFilename |
||
111 | * @return string |
||
112 | */ |
||
113 | protected function _getVclTemplateFilename($baseFilename) { |
||
117 | |||
118 | /** |
||
119 | * Get the name of the file to save the VCL to |
||
120 | * |
||
121 | * @return string |
||
122 | */ |
||
123 | protected function _getVclFilename() { |
||
128 | |||
129 | /** |
||
130 | * Get the name of the custom include VCL file |
||
131 | * |
||
132 | * @return string |
||
133 | */ |
||
134 | protected function _getCustomIncludeFilename($position = '') { |
||
141 | |||
142 | |||
143 | /** |
||
144 | * Get the custom VCL template, if it exists |
||
145 | * Returns 'null' if the file doesn't exist |
||
146 | * |
||
147 | * @return string |
||
148 | */ |
||
149 | protected function _getCustomTemplateFilename() { |
||
156 | |||
157 | |||
158 | /** |
||
159 | * Format a template string, replacing {{keys}} with the appropriate values |
||
160 | * and remove unspecified keys |
||
161 | * |
||
162 | * @param string $template template string to operate on |
||
163 | * @param array $vars array of key => value replacements |
||
164 | * @return string |
||
165 | */ |
||
166 | protected function _formatTemplate($template, array $vars) { |
||
174 | |||
175 | /** |
||
176 | * Format a VCL subroutine call |
||
177 | * |
||
178 | * @param string $subroutine subroutine name |
||
179 | * @return string |
||
180 | */ |
||
181 | protected function _vcl_call($subroutine) { |
||
184 | |||
185 | /** |
||
186 | * Get the Magento admin frontname |
||
187 | * |
||
188 | * This is just the plain string, not in URL format. ex: |
||
189 | * http://example.com/magento/admin -> admin |
||
190 | * |
||
191 | * @return string |
||
192 | */ |
||
193 | protected function _getAdminFrontname() { |
||
205 | |||
206 | /** |
||
207 | * Get the hostname for host normalization from Magento's base URL |
||
208 | * |
||
209 | * @return string |
||
210 | */ |
||
211 | protected function _getNormalizeHostTarget() { |
||
225 | |||
226 | /** |
||
227 | * Get hosts as regex |
||
228 | * |
||
229 | * ex: base_url: example.com |
||
230 | * path_regex: (example.com|example.net) |
||
231 | * |
||
232 | * @return string |
||
233 | */ |
||
234 | public function getAllowedHostsRegex() { |
||
245 | |||
246 | /** |
||
247 | * Get the Host normalization sub routine |
||
248 | * |
||
249 | * @return string |
||
250 | */ |
||
251 | protected function _vcl_sub_allowed_hosts_regex() { |
||
261 | |||
262 | /** |
||
263 | * Get the base url path regex |
||
264 | * |
||
265 | * ex: base_url: http://example.com/magento/ |
||
266 | * path_regex: /magento/(?:(?:index|litespeed)\.php/)? |
||
267 | * |
||
268 | * @return string |
||
269 | */ |
||
270 | public function getBaseUrlPathRegex() { |
||
276 | |||
277 | /** |
||
278 | * Get the path part of each store's base URL and static file URLs |
||
279 | * |
||
280 | * @return array |
||
281 | */ |
||
282 | protected function _getBaseUrlPaths() { |
||
301 | |||
302 | /** |
||
303 | * Format the URL exclusions for insertion in a regex. Admin frontname and |
||
304 | * API are automatically added. |
||
305 | * |
||
306 | * @return string |
||
307 | */ |
||
308 | protected function _getUrlExcludes() { |
||
313 | |||
314 | /** |
||
315 | * Get the default cache TTL from Magento config |
||
316 | * |
||
317 | * @return string |
||
318 | */ |
||
319 | protected function _getDefaultTtl() { |
||
322 | |||
323 | /** |
||
324 | * Get the default backend configuration string |
||
325 | * |
||
326 | * @return string |
||
327 | */ |
||
328 | View Code Duplication | protected function _getDefaultBackend() { |
|
343 | |||
344 | /** |
||
345 | * Get the admin backend configuration string |
||
346 | * |
||
347 | * @return string |
||
348 | */ |
||
349 | View Code Duplication | protected function _getAdminBackend() { |
|
364 | |||
365 | /** |
||
366 | * Get the grace period for vcl_fetch |
||
367 | * |
||
368 | * This is curently hardcoded to 15 seconds, will be configurable at some |
||
369 | * point |
||
370 | * |
||
371 | * @return string |
||
372 | */ |
||
373 | protected function _getGracePeriod() { |
||
376 | |||
377 | /** |
||
378 | * Get whether debug headers should be enabled or not |
||
379 | * |
||
380 | * @return string |
||
381 | */ |
||
382 | protected function _getEnableDebugHeaders() { |
||
386 | |||
387 | /** |
||
388 | * Format the GET variable excludes for insertion in a regex |
||
389 | * |
||
390 | * @return string |
||
391 | */ |
||
392 | protected function _getGetParamExcludes() { |
||
396 | |||
397 | protected function _getIgnoreGetParameters() |
||
404 | |||
405 | /** |
||
406 | * @return boolean |
||
407 | */ |
||
408 | protected function _sendUnModifiedUrlToBackend() |
||
412 | |||
413 | /** |
||
414 | * Get the Generate Session |
||
415 | * |
||
416 | * @return string |
||
417 | */ |
||
418 | protected function _getGenerateSessionStart() { |
||
422 | |||
423 | /** |
||
424 | * Get the Generate Session |
||
425 | * |
||
426 | * @return string |
||
427 | */ |
||
428 | protected function _getGenerateSessionEnd() { |
||
432 | |||
433 | |||
434 | /** |
||
435 | * Get the Generate Session |
||
436 | * |
||
437 | * @return string |
||
438 | */ |
||
439 | protected function _getGenerateSession() { |
||
443 | |||
444 | |||
445 | /** |
||
446 | * Get the Generate Session Expires |
||
447 | * |
||
448 | * @return string |
||
449 | */ |
||
450 | protected function _getGenerateSessionExpires() { |
||
454 | |||
455 | /** |
||
456 | * Get the Force Static Caching option |
||
457 | * |
||
458 | * @return string |
||
459 | */ |
||
460 | protected function _getForceCacheStatic() { |
||
464 | |||
465 | /** |
||
466 | * Get the Force Static Caching option |
||
467 | * |
||
468 | * @return string |
||
469 | */ |
||
470 | protected function _getSimpleHashStatic() { |
||
474 | |||
475 | /** |
||
476 | * Format the list of static cache extensions |
||
477 | * |
||
478 | * @return string |
||
479 | */ |
||
480 | protected function _getStaticExtensions() { |
||
484 | |||
485 | /** |
||
486 | * Get the static caching TTL |
||
487 | * |
||
488 | * @return string |
||
489 | */ |
||
490 | protected function _getStaticTtl() { |
||
493 | |||
494 | /** |
||
495 | * Format the by-url TTL value list |
||
496 | * |
||
497 | * @return string |
||
498 | */ |
||
499 | protected function _getUrlTtls() { |
||
520 | |||
521 | /** |
||
522 | * Get the Enable Caching value |
||
523 | * |
||
524 | * @return string |
||
525 | */ |
||
526 | protected function _getEnableCaching() { |
||
530 | |||
531 | /** |
||
532 | * Get the list of allowed debug IPs |
||
533 | * |
||
534 | * @return array |
||
535 | */ |
||
536 | protected function _getDebugIps() { |
||
540 | |||
541 | /** |
||
542 | * Get the list of crawler IPs |
||
543 | * |
||
544 | * @return array |
||
545 | */ |
||
546 | protected function _getCrawlerIps() { |
||
550 | |||
551 | /** |
||
552 | * Get the regex formatted list of crawler user agents |
||
553 | * |
||
554 | * @return string |
||
555 | */ |
||
556 | protected function _getCrawlerUserAgents() { |
||
562 | |||
563 | /** |
||
564 | * Get the time to increase a cached objects TTL on cache hit (in seconds). |
||
565 | * |
||
566 | * This should be set very low since it gets added to every hit. |
||
567 | * |
||
568 | * @return string |
||
569 | */ |
||
570 | protected function _getLruFactor() { |
||
573 | |||
574 | /** |
||
575 | * Get the advanced session validation restrictions |
||
576 | * |
||
577 | * Note that if User-Agent Normalization is on then the normalized user-agent |
||
578 | * is used for user-agent validation instead of the full user-agent |
||
579 | * |
||
580 | * @return string |
||
581 | */ |
||
582 | protected function _getAdvancedSessionValidationTargets() { |
||
601 | |||
602 | /** |
||
603 | * Remove empty and commented out lines from the generated VCL |
||
604 | * |
||
605 | * @param string $dirtyVcl generated vcl |
||
606 | * @return string |
||
607 | */ |
||
608 | protected function _cleanVcl($dirtyVcl) { |
||
617 | |||
618 | /** |
||
619 | * Helper to filter out blank/commented lines for VCL cleaning |
||
620 | * |
||
621 | * @param string $line |
||
622 | * @return bool |
||
623 | */ |
||
624 | protected function _cleanVclHelper($line) { |
||
630 | |||
631 | /** |
||
632 | * Format a VCL backend declaration |
||
633 | * |
||
634 | * @param string $name name of the backend |
||
635 | * @param string $host backend host |
||
636 | * @param string $port backend port |
||
637 | * @param array $options options |
||
638 | * @return string |
||
639 | */ |
||
640 | protected function _vcl_backend($name, $host, $port, $options = array()) { |
||
659 | |||
660 | /** |
||
661 | * Format a VCL director declaration, for load balancing |
||
662 | * |
||
663 | * @param string $name name of the director, also used to select config settings |
||
664 | * @param array $backendOptions options for each backend |
||
665 | * @return string |
||
666 | */ |
||
667 | View Code Duplication | protected function _vcl_director($name, $backendOptions) { |
|
703 | |||
704 | /** |
||
705 | * Format a VCL backend declaration to put inside director |
||
706 | * |
||
707 | * @param string $host backend host |
||
708 | * @param string $port backend port |
||
709 | * @param string $descriptor backend descriptor |
||
710 | * @param string $probeUrl URL to check if backend is up |
||
711 | * @param array $options extra options for backend |
||
712 | * @return string |
||
713 | */ |
||
714 | View Code Duplication | protected function _vcl_director_backend($host, $port, $descriptor = '', $probeUrl = '', $options = array()) { |
|
741 | |||
742 | /** |
||
743 | * Format a VCL probe declaration to put in backend which is in director |
||
744 | * |
||
745 | * @param string $probeUrl URL to check if backend is up |
||
746 | * |
||
747 | * @return string |
||
748 | */ |
||
749 | protected function _vcl_get_probe($probeUrl) { |
||
783 | |||
784 | /** |
||
785 | * Format a VCL ACL declaration |
||
786 | * |
||
787 | * @param string $name ACL name |
||
788 | * @param array $hosts list of hosts to add to the ACL |
||
789 | * @return string |
||
790 | */ |
||
791 | protected function _vcl_acl($name, array $hosts) { |
||
804 | |||
805 | /** |
||
806 | * Get the User-Agent normalization sub routine |
||
807 | * |
||
808 | * @return string |
||
809 | */ |
||
810 | protected function _vcl_sub_normalize_user_agent() { |
||
825 | |||
826 | /** |
||
827 | * Get the Accept-Encoding normalization sub routine |
||
828 | * |
||
829 | * @return string |
||
830 | */ |
||
831 | protected function _vcl_sub_normalize_encoding() { |
||
847 | |||
848 | /** |
||
849 | * Get the Host normalization sub routine |
||
850 | * |
||
851 | * @return string |
||
852 | */ |
||
853 | protected function _vcl_sub_normalize_host() { |
||
861 | |||
862 | /** |
||
863 | * Get the hostname for cookie normalization |
||
864 | * |
||
865 | * @return string |
||
866 | */ |
||
867 | protected function _getNormalizeCookieTarget() { |
||
871 | |||
872 | /** |
||
873 | * Get the regex for cookie normalization |
||
874 | * |
||
875 | * @return string |
||
876 | */ |
||
877 | protected function _getNormalizeCookieRegex() { |
||
881 | |||
882 | /** |
||
883 | * Get the allowed IPs when in maintenance mode |
||
884 | * |
||
885 | * @return string |
||
886 | */ |
||
887 | View Code Duplication | protected function _vcl_sub_maintenance_allowed_ips() { |
|
926 | |||
927 | /** |
||
928 | * When using Varnish on port 80 and Hitch listen on port 443 for HTTPS, the fix will set X-Forwarded-Proto to HTTPS to prevent redirect loop. |
||
929 | * |
||
930 | * @return string |
||
931 | */ |
||
932 | protected function _vcl_sub_https_proto_fix() { |
||
940 | |||
941 | /** |
||
942 | * When using Varnish as front door listen on port 80 and Nginx/Apache listen on port 443 for HTTPS, the fix will keep the url parameters when redirect from HTTP to HTTPS. |
||
943 | * |
||
944 | * @return string |
||
945 | */ |
||
946 | protected function _vcl_sub_https_redirect_fix() { |
||
973 | |||
974 | |||
975 | protected function _getHostNames() { |
||
997 | |||
998 | protected function _stripHost ($baseUrl){ |
||
1001 | |||
1002 | /** |
||
1003 | * Get the allowed IPs when in maintenance mode |
||
1004 | * |
||
1005 | * @return string |
||
1006 | */ |
||
1007 | View Code Duplication | protected function _vcl_sub_synth() |
|
1042 | |||
1043 | /** |
||
1044 | * vcl_synth for fixing https |
||
1045 | * |
||
1046 | * @return string |
||
1047 | */ |
||
1048 | protected function _vcl_sub_synth_https_fix() |
||
1076 | |||
1077 | |||
1078 | |||
1079 | /** |
||
1080 | * Build the list of template variables to apply to the VCL template |
||
1081 | * |
||
1082 | * @return array |
||
1083 | */ |
||
1084 | protected function _getTemplateVars() { |
||
1179 | } |
||
1180 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.