[oop] hoe consante terugkrijgen?
In sommige gevallen is het handig om de ISO normering aan te houden. Waarom? Omdat andere programmeurs dat ook doen, en omdat je dan precies weet wat een bepaalde waarde inhoudt.
Er zijn heel veel ISO-lijstjes en één daarvan is bijvoorbeeld een lijstje voor iemands geslacht: http://en.wikipedia.org/wiki/ISO/IEC_5218
Dat lijstje ziet er ongeveer als volgt uit:
0 = unknown
1 = male
2 = female
9 = not_applicable
Nu is dit op zich niet een heel groot lijstje, maar toch heb ik geen zin om die getallen te moeten onthouden. Dus leek het me handig om hier een interface van te maken, als volgt:
Code (php)
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
<?php
interface gender {
const unknown = 0;
const male = 1;
const female = 2;
const not_appicable = 9;
}
?>
interface gender {
const unknown = 0;
const male = 1;
const female = 2;
const not_appicable = 9;
}
?>
Het idee is nu dat als ik weet dat iemand een man is, dat ik dan dit kan doen:
Dit lijkt me namelijk een stuk duidelijker dan dit:
Zijn jullie het met deze gedachte eens?
Nu is echter mijn vraag... stel dat ik deze persoon opsla in de database, dan staat er in de database bij "gender" dus een 1. Dat is prima, want dat willen we ook. Echter, stel nu dat ik een tijdje later de gegevens van die persoon op mijn scherm wil tonen, dan staat er dus bijvoorbeeld:
name: Ozzie
gender: 1
Is het nu mogelijk om in plaats van 1 daar dan de naam van de constante, dus "male", te tonen? Dus:
name: Ozzie
gender: male
Weet iemand of, en zo ja hoe, dat kan?
Alvast bedankt voor de reacties.
http://stackoverflow.com/questions/1880148/how-to-get-name-of-the-constant .
Maar kan je dit niet beter in je view regelen?
Hier staat beschreven hoe je dat kan doen Maar kan je dit niet beter in je view regelen?
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<?php
class Gender
{
const UNKNOWN = 0;
const MALE = 1;
const FEMALE = 2;
const NOT_APPLICABLE = 9;
private $gender;
public static function __construct($gender)
{
if ($gender < 0 || $gender > 9) {
throw new \InvalidArgumentException('Invalid gender.');
}
$this->gender = $gender;
}
public function getGender()
{
return $this->gender;
}
public static function parse($name)
{
switch (strtolower($name)) {
case 'male': $gender = 1; break;
case 'female': $gender = 2; break;
case 'not applicable': $gender = 9; break;
default: $gender = 0; break;
}
return new self($gender);
}
}
class GenderToTextTransformer
{
public function transform(Gender $gender)
{
switch ($gender->getGender()) {
case 0: return 'unknown'; break;
case 1: return 'male'; break;
case 2: return 'female'; break;
case 9: return 'not applicable'; break;
}
}
}
$genderToText = new GenderToTextTransformer();
$wouter = new Person('Wouter', Gender::parse('male'));
$nienke = new Person('Nienke', Gender::parse('female'));
$robot = new Person('WuutWuut', Gender::parse('unknown'));
echo 'Wouter is a '.$genderToText->transform($wouter->getGender());
echo 'Nienke is a '.$genderToText->transform($nienke->getGender());
echo 'The gender of WuutWuut is '.$genderToText->transform($robot->getGender());
?>
class Gender
{
const UNKNOWN = 0;
const MALE = 1;
const FEMALE = 2;
const NOT_APPLICABLE = 9;
private $gender;
public static function __construct($gender)
{
if ($gender < 0 || $gender > 9) {
throw new \InvalidArgumentException('Invalid gender.');
}
$this->gender = $gender;
}
public function getGender()
{
return $this->gender;
}
public static function parse($name)
{
switch (strtolower($name)) {
case 'male': $gender = 1; break;
case 'female': $gender = 2; break;
case 'not applicable': $gender = 9; break;
default: $gender = 0; break;
}
return new self($gender);
}
}
class GenderToTextTransformer
{
public function transform(Gender $gender)
{
switch ($gender->getGender()) {
case 0: return 'unknown'; break;
case 1: return 'male'; break;
case 2: return 'female'; break;
case 9: return 'not applicable'; break;
}
}
}
$genderToText = new GenderToTextTransformer();
$wouter = new Person('Wouter', Gender::parse('male'));
$nienke = new Person('Nienke', Gender::parse('female'));
$robot = new Person('WuutWuut', Gender::parse('unknown'));
echo 'Wouter is a '.$genderToText->transform($wouter->getGender());
echo 'Nienke is a '.$genderToText->transform($nienke->getGender());
echo 'The gender of WuutWuut is '.$genderToText->transform($robot->getGender());
?>
>> Maar kan je dit niet beter in je view regelen?
Hoe bedoel je dit?
Toevoeging op 30/04/2014 13:44:41:
Edit: Wouter, ik had je reactie nog niet gezien... ga nu even lezen. Zo dadelijk reactie.
Toevoeging op 30/04/2014 13:49:09:
Wouter, mooie aanpak... maar nogal complex lijkt mij. Ik denk dat de aanpak (zie link van LedFan) met een reflection class een stuk efficiënter/universeler is?
Efficiëntie gaat het niet om in OO hè :) In mijn voorbeeldje heb ik even wat Domain Driven Development toegepast. Daardoor heb ik een Gender Value Object geintroduceerd. En 1 van de regels van Value Objects is: "Don’t use _toString() for presentation." Dus daar heb ik weer een nieuwe klasse voor geïntroduceerd. Op deze manier kun je het gender op verschillende manieren presenteren. Je zou een PresentGender interface kunnen maken en dan krijg je mooie dingen als:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
interface PresentGender
{
function present(Gender $gender);
}
class AsText implements PresentGender
{
public function present(Gender $gender)
{
switch ($gender->getGender()) {
case 0: return 'unknown'; break;
case 1: return 'male'; break;
case 2: return 'female'; break;
case 9: return 'not applicable'; break;
}
}
}
class AsUnicodeSymbol implements PresentGender
{
public function present(Gender $gender)
{
switch ($gender->getGender()) {
case 0: return 'U+26A8'; break;
case 1: return 'U+2642'; break;
case 2: return 'U+2640'; break;
case 9: return 'U+2205'; break;
}
}
}
?>
interface PresentGender
{
function present(Gender $gender);
}
class AsText implements PresentGender
{
public function present(Gender $gender)
{
switch ($gender->getGender()) {
case 0: return 'unknown'; break;
case 1: return 'male'; break;
case 2: return 'female'; break;
case 9: return 'not applicable'; break;
}
}
}
class AsUnicodeSymbol implements PresentGender
{
public function present(Gender $gender)
{
switch ($gender->getGender()) {
case 0: return 'U+26A8'; break;
case 1: return 'U+2642'; break;
case 2: return 'U+2640'; break;
case 9: return 'U+2205'; break;
}
}
}
?>
Maar het toepassen van DDD is vaak erg overdreven en DDD experts staan zelden met beide beentjes op de grond. Je kan ook gaan voor een simpele KISS (Keep It Simple Stupid!) of YAGNI (You Aren't Gonna Need It) aanpak.
Wat ik eigenlijk wil voorkomen is dat die unknown, male etc. op verschillende plekken terugkomen. Het lijkt mij handiger als ik dat gewoon kan doen aan de hand van die constanten in de interface. Met die reflection class zou dat moeten lukken. Ik denk dat dat valt onder de noemer van de KISS aanpak :)
@ozzie wat ik bedoelde met die view is iets zoals Wouterj zij.