The thread ‘Group commonly used application-wide methods in unit-test friendly way’ has given me a lot to think about, maybe I’m stuck in procedural mode. But how to get out of the rut? How to think about objects? A “button” is an object, you can do things to it and it will respond in certain ways. An email address is not an object, it’s value, a property of the account owner just like a telephone number or a name.
An email address can be valid or invalid. There are many methods of validating an email address, from less precise to more precise: you can check the formatting, you can look up the MX record, you can send an email to see if it bounces, you can confirm the email address if you get a reply from that address.
If you are dealing with a member, a subscriber, or an account, the email address is their property and you can use all the methods outlined above to verify the email address. If you have a mailing list the email address is still a “property” of the list but not as “proprietary” as in the first case and you can’t use all the validation methods. If you are dealing with a contact form, the visitor’s email address is still a “property” but even less “proprietary” that in the case of a mailing list but at least you have received direct authorization to send mail to that address.
For discussion purposes let’s call the validation anyone can do “secondary” because it’s not entirely conclusive and let’s call the validation that the membership scripts can do “primary” because they get owner feedback. If there are better terms for these things, please let me know.
According to the thread mentioned above, the email validation methods should be part of the membership class that really owns the email address property. But there can be many versions or variations of the membership class and the validation methods should be in some ancestral membership class which can be used by contact class and mailing list class as static methods, for example:
Though, to be clear, an email address could be an object. More generally, any noun could be an object. Whether we choose to make it a plain value or an object depends on the complexity of the value and on whether any logic needs to follow that value.
You could create a separate class called, for example, EmailValidator. That way the logic is contained in one placed and can be reused by both your membership and contact classes.
Having Validation under its own object allows you to change the validation preformed without changing the objects that use it. Thus if there is a bug in the email validation you only have to change it in one place instead of a dozen. Validating an email is a single responsibility which does make an object. Having a single method makes it no less an object.
Shortly after reading your reply I realized that it makes perfect sense to have an ‘EmailAddress’ class capable of validating the address and providing other Email Address related services. Now other objects have the choice of properties, either the EmailAddress object or the EmailAddress string.
Having the choice is important because, for example, a mailing list with a 1000 addresses would take for ever to check each MX record.
This also solves the dependency issue since only the EmailAddress class needs do validation. Other classes only need to ask the EmailAddress object if it is valid or not.
It is also easy to localize or customize the verbose feedback by extending the EmailAddress class. For example EmailAddress_es would have the verbose feedback in Spanish.
BTW, I made a curious discovery, you can use variable variables to handle multiple email addresses:
$myEmail = 'mySelf<email@example.com>';
$$myEmail = new EmailAddress($myEmail);
$myEmail = 'my very own Self <firstname.lastname@example.org>';
$$myEmail = new EmailAddress($myEmail);
The above creates two objects that can be accessed by setting $myEmail to the email address itself. I fear this is likely confusing in practice.
Yes, they are weird! First I tried to see if I could use the email address as the variable name and that is not allowed because it is a badly structured variable name. Then I tried the variable variable and, to my amazement, it worked. :magic:
The question is, when, where and why would you want to use it. :scratch: