SitePoint Sponsor

User Tag List

Results 1 to 7 of 7

Thread: Literal values vs class constants in method parameters

  1. #1
    SitePoint Guru bronze trophy
    Join Date
    Dec 2003
    Location
    Poland
    Posts
    736
    Mentioned
    7 Post(s)
    Tagged
    0 Thread(s)

    Literal values vs class constants in method parameters

    Do you think it's a good idea to use class constants as parameters to a method when the parameter is used to indicate an option out of a few choices? Look at the two classes below:
    PHP Code:
    // class 1
    class MyDocument {
        public function 
    getContents($format) {
            switch (
    $format) {
            case 
    'txt':
                
    // ...
                
    break;
                
            case 
    'html':
                
    // ...
                
    break;
                
            case 
    'pdf':
                
    // ...
                
    break;
            }
            
            return 
    $contents;
        } 
    }

    // usage:
    $document->getContents('html');


    // class 2
    class MyDocument2 {
        const 
    FORMAT_TXT 1;
        const 
    FORMAT_HTML 2;
        const 
    FORMAT_PDF 3;
        
        public function 
    getContents($format) {
            switch (
    $format) {
            case 
    self::FORMAT_TXT:
                
    // ...
                
    break;
                
            case 
    self::FORMAT_HTML:
                
    // ...
                
    break;
                
            case 
    self::FORMAT_PDF:
                
    // ...
                
    break;
            }
            
            return 
    $contents;
        } 
    }


    // usage:
    $document->getContents(MyDocument2::FORMAT_HTML); 
    I know the second method has become popular recently, even in many built-in php libraries. Some time ago I've read a comment by an experienced programmer that the use of constants for parameters is not a good idea but I can't remember the reasoning. I'm always split between which method to use since neither of them has big enough advantage over the other. Basically, I like literal values because they need less typing but I also like the more structural look of the constants. Performance differences are irrelevant to me in this case. I can annotate both using phpdoc so my IDE will give me appropriate prompts, however with constants it is very slightly more elegant.

    Which is better?

  2. #2
    SitePoint Member
    Join Date
    May 2013
    Location
    Richmond VA
    Posts
    12
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I prefer the use of constants. They can be more verbose, but to me the major benefit is better error reporting for typos. If you do $document->getContents('htmk'); The error that will appear because of this will be further away from the source of the problem than if you do $document->getContents(MyDocument2::FORMAT_HTMK);. The later the error will be reported right where the error is - the misspelling of the constant.

  3. #3
    SitePoint Addict SitePoint Award Recipient captainccs's Avatar
    Join Date
    Mar 2004
    Location
    Caracas, Venezuela
    Posts
    376
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    I read recently that the constants should be defined in the class interface, not in the class itself. Constants make for better error checking as th3mus1cman pointed out.
    Denny Schlesinger
    web services

  4. #4
    SitePoint Guru bronze trophy
    Join Date
    Dec 2003
    Location
    Poland
    Posts
    736
    Mentioned
    7 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by th3mus1cman View Post
    I prefer the use of constants. They can be more verbose, but to me the major benefit is better error reporting for typos. If you do $document->getContents('htmk'); The error that will appear because of this will be further away from the source of the problem than if you do $document->getContents(MyDocument2::FORMAT_HTMK);. The later the error will be reported right where the error is - the misspelling of the constant.
    Thanks, it makes sense that with constants the error will be reported right where it occurs, which is a clear advantage.

    Quote Originally Posted by captainccs View Post
    I read recently that the constants should be defined in the class interface, not in the class itself.
    Interesting, I've never thought of it this way. And I think I can see why this would be logical. But we would need to always define interfaces - some argue that we should define an interface for every class.

  5. #5
    Hosting Advisor silver trophybronze trophy
    SitePoint Award Recipient cpradio's Avatar
    Join Date
    Jun 2002
    Location
    Ohio
    Posts
    2,770
    Mentioned
    44 Post(s)
    Tagged
    0 Thread(s)
    I agree that constants are the better approach (in my opinion). However, I think a slightly different approach to what you seem to be doing would be the following:

    PHP Code:
    interface IDocument
    {
      function 
    getContents();
    }

    class 
    TextDocument IDocument
    {
      public function 
    getContents()
      {
      }
    }

    class 
    PdfDocument IDocument
    {
      public function 
    getContents()
      {
      }
    }

    class 
    HtmlDocument IDocument
    {
      public function 
    getContents()
      {
      }
    }

    // class 1 
    class MyDocument 
        public function 
    getContents(IDocument $format) { 
            return 
    $format->getContents(); 
        }  


    // usage: 
    $document->getContents(new HtmlExtension()); 
    Why? Because 1) it requires you to only provide something that is implemented (meaning you can't pass an integer to replace a constant, or a string for that matter) nor can you pass a misspelling and 2) It allows you to use DI to separate logic that may be different for each extension, thus making your MyDocument class less crowded.

    Quote Originally Posted by Lemon Juice View Post
    Interesting, I've never thought of it this way. And I think I can see why this would be logical. But we would need to always define interfaces - some argue that we should define an interface for every class.
    I'm a HUGE fan of interfaces, but you need to use them where it makes sense. Most base classes should have an interface, beyond that, when you extend a class you usually lose the purpose of the interface at that level. So in my prior example, I created an IDocument interface that TextDocument, HtrmlDocument, and PdfDocument all utilize. If I ever needed a base class (Document) to provide something common among the three classes then I'd only have Document associated to the interface and TextDocument, HtmlDocument, and PdfDocument would inherit Document (which allows them to utilize the Interface too, I wouldn't build an Interface for each of them unless there was a specific implementation I needed it to conform to) -- I hope that makes sense.

    Edit:

    I like how oddz kept his named Document, so I've updated my example to be similar
    Last edited by cpradio; Yesterday at 04:40. Reason: Renamed Extension to Document for IExtension, TextExtension, PdfExtension, and HtmlExtension

  6. #6
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    3,843
    Mentioned
    11 Post(s)
    Tagged
    3 Thread(s)
    I would argue that the document doesn't need to know anything about how it is converted. Instead pass the document into a separate instance of a class that knows how to convert the document.

    pseudo code:

    PHP Code:

    // Create base document
    $doc = new Document();

    // Create format
    $format = new PDFDocumentFormat();

    /*
     * Convert document to pdf format 
     * All document formats implement an interface containing the convert() method accepting 
     * a single argument that is the document to be converted
     */
    $pdf $format->convert($doc); 
    Is document some type of domain object with fielded data that is stored in some of persistent storage mechanism such as a relational database?

    or

    Is document big data and the objective is to create strategies that convert it between several different formats?
    The only code I hate more than my own is everyone else's.

  7. #7
    SitePoint Guru bronze trophy
    Join Date
    Dec 2003
    Location
    Poland
    Posts
    736
    Mentioned
    7 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by cpradio View Post
    I agree that constants are the better approach (in my opinion). However, I think a slightly different approach to what you seem to be doing would be the following:

    PHP Code:
    interface IDocument
    {
      function 
    getContents();
    }

    class 
    TextDocument IDocument
    {
      public function 
    getContents()
      {
      }
    }

    class 
    PdfDocument IDocument
    {
      public function 
    getContents()
      {
      }
    }

    class 
    HtmlDocument IDocument
    {
      public function 
    getContents()
      {
      }
    }

    // class 1 
    class MyDocument 
        public function 
    getContents(IDocument $format) { 
            return 
    $format->getContents(); 
        }  


    // usage: 
    $document->getContents(new HtmlExtension()); 
    Why? Because 1) it requires you to only provide something that is implemented (meaning you can't pass an integer to replace a constant, or a string for that matter) nor can you pass a misspelling and 2) It allows you to use DI to separate logic that may be different for each extension, thus making your MyDocument class less crowded.
    Quote Originally Posted by oddz View Post
    I would argue that the document doesn't need to know anything about how it is converted. Instead pass the document into a separate instance of a class that knows how to convert the document.

    pseudo code:

    PHP Code:

    // Create base document
    $doc = new Document();

    // Create format
    $format = new PDFDocumentFormat();

    /*
     * Convert document to pdf format 
     * All document formats implement an interface containing the convert() method accepting 
     * a single argument that is the document to be converted
     */
    $pdf $format->convert($doc); 
    cpradio, oddz, these are good alternative solutions to the problem, I admit. I didn't mean to go as far as this since I was asking about a simplest scenario where just a flag parameter is enough. Maybe my example with the document was not the best one in this case because converting to different formats may well be a task for separate classes. Nevertheless, it was useful to see these implementations.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •