1

I am trying to build my own MVC framework (of course to learn it better) by following latest OOP design pattern. I was wondering, what is the best practice for placing repeatable codes (which are used to stay in the utility classes as static methods, which is consider not a good patterns).

For example, we want to traverse an multi dimensional array using dot separated string, and I have to utilize this algorithm in several classes (which are subclasses from other base classes). How can I do that without using utility class and without repeating the same code multiple times?

Md Monjur Ul Hasan
  • 1,705
  • 1
  • 13
  • 36

4 Answers4

4

If those are utility functions, then define them as such in a separate namespace. Something akin to

<?php
namespace Utils;

function array_query($array, $query) {
   // code for traversing the array 
}

Put them in one or multiple files and you will be fine. Just remember to include that file in the boostrap stage of your app.

Bottom line: stop abusing static classes, we have namespaces for that sh*t now.

But, not all of what you think of as "utility functions" are actually. Some of the code, if you start using OOP code, should go in the associated classes. For example "email validation" should not go in a "utility function" but in a class:

class EmailAddress {

    private $emailAddress;

    public function __construct($emailAddress) {
        $this->assertValidEmailAddress($emailAddress);
        $this->emailAddress = $emailAddress;
    }

    private function assertValidEmailAddress($emailAddress) {
       if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
           throw new DomainException("Not an email address");
       }
    }

    public function __toString() {
        return $this->emailAddress;
    }
}

And these kind of repeated "domain logic" fragments should go in separated entities, which then you can type-hint for other classes. Then you utilize it somewhere as:

public function register(EmailAddress $email, SafePassword $password): User
{
   // your user registration logic
}

This way various services of yours can perform activities and you use try-catch for improved validation.

P.S.
You might need to take a hard look at what you are doing. That dotted access utility is neat (I had it too like 10 years ago), but actually is is a "temporary fix" for a deeper problem: you shouldn't be dealing with so deep array, that you need to simplify accessing them.

tereško
  • 58,060
  • 25
  • 98
  • 150
3

There's nothing wrong with a utility class, just don't lump all your unrelated utility functions into a single giant class. Separate (and namespace) them by what they do. For example, see Zend Filter or Symfony Filesystem.

Alternatively, if the classes that need this function all have a common parent, you can put the function in the top-most class or abstract.

Or if the classes do not have a common parent, you could create a Trait with a method called extractArrayFromDottedString() or similar.

Alex Howansky
  • 50,515
  • 8
  • 78
  • 98
  • 1
    If you have problem, that can be solved by traits, you probably are solving the wrong problem. Also, just extending from a shared parent to just isolate duplicate code (while very tempting, indeed) is a bad idea. More often it is an indication, that the code should refactored and you should extract a common dependency for all those specialized classes. – tereško Nov 11 '17 at 18:06
1

Laravel does this by defining standalone "helper" functions. CakePHP and Yii do it by defining container utility classes (i.e. "Text" or "Xml") with static methods. Programming languages do similar things (i.e. PHP's implode(), Java's Math.round, C's strcpy, Python's sum(), etc.). Pretty much everything uses either standalone functions or static class methods.

Ultimately, the best choice is subjective. It depends on how you want to structure things. Research common design patterns in PHP, and get a feel for how different frameworks feel in practice. Then pick an approach and stay consistent.

John Ellmore
  • 2,209
  • 1
  • 10
  • 22
0

Utility class is an anti pattern

Really not.
In OOP, designing the whole application with utility classes is very probably an anti pattern but defining utility classes wit static methods that provide routine/transverse tasks may make sense.

Not mixing utility methods with methods of existing classes that consume them may also provide a better cohesion and reusability of the utility class and consumer classes.

Of course as alternative you could define a class with instance methods.
This is valid, more verbose but has as advantage to improve the class testability. If you need to mock the invocations or to switch to other implementations for utility methods, instance methods have to be favored.

davidxxx
  • 125,838
  • 23
  • 214
  • 215