Jump to content
Larry Ullman's Book Forums

Antonio Conte

Members
  • Posts

    1084
  • Joined

  • Last visited

  • Days Won

    126

Posts posted by Antonio Conte

  1. Caching. Object orientation IS slow, but that was however never the problem it tried to solve. Readability and abstractions (high-level vs low-lever code) is OOPs biggest strength, and the reason why people use Java, C# or even PHP. If speed is all that matters, write assembly or C++, because PHP will never be able to compete with that.

     

    If you don't implement the interface, the Sorter won't accept that object. It's a contract, and it's other developers job to abide to it. If all their method return "LOL" that's on them really. Nothing is fool-proof, but an interface is communicating it's intent way better than anything else currently available. If you don't abide to the contract as a develop, an exception will be thrown.

     

    Why I'm choosing to participate in it? Because it works. It's proven time and time again that procedural code ends up as messy spaghetti code that is unmaintainable and ends up labeled as "legacy". Sure, as a one-man team you'll be able to make it work, but no way for larger organizations

    • Upvote 1
  2. First off, it's been an eventful night out with some drinks, so please excuse me if I don't make much sense.

     

    To take you first question, implementing an interface is the only real way for a Sorter class to trust the object has sorting capabilities. This is even more clear in a fully object-oriented language like Java where you need to define return type from a method. Because a class implements an interface like "Sortable" we can trust it to be sortable. This is a contract more than anything else, but it defines expected behaviors.

     

    A session object might not need to be sortable (because it doesn't make sense in itself) but what about JSONStructurable, Serializable, Hashable or Expirable? These are all acceptable actions to do to a session, and the interface would be an reinforcer of that. The interfaceces would of course return the session as JSON, in serializable form, as an identifiable hash or communicate that is possible to expire through interfacing.

     

    ----------

     

    To move on to your next statement. While we are not building amazon, every programmer have a different style of coding. Object orientation is goos at defining where the task we need solved happens and where we solve it. Separation of concern is one of those buzzwords that describes object orientation. OOP is all about mapping programming problems to a real world domain, and helping us to simplify code.

     

    While you describe OOP as advanced, abstracted and hard to understand, I would argue that is plain and simply wrong. Badly coded OOP is even worse than any procedurally coded project, but properly designed, sensible OOP simplifies any programming problem you might have into human-readable, plain simple english. While this may sound like an Utopian dream world, this is what the programming world is working towards.

     

    I believe very much in readable code. The perfect example in that regard is the Laraval PHP framework. While being a 100% OOP web development framework, you get your logged in user by calling Auth::user(). To send an Email in the background using a queue (pageload finished and job executing in the background) all you got to do is call Queue::push('SendEmail', array('message' => $message)); This is similar to human-readable language, and works like expected. While lots of logic is dispensed in the background, the incredible Facade pattern eliminates any object instantiation or similar that is irrelevant to the task. Still, in the core system, everything is made simpler by the fact that the system relies in real objects. 

     

    My point here is that while OOP might seem like an obstacle to "code that simply works", OOP is about hiding complexity where it belongs. OOP "client code", as the code I exemplified by Laravel is, should be no harder to understand than procedural code. If it is, it's simply shitty object-orientation, and shitty code exists for both procedurally and object-oriented code without a doubt.

     

    Sorry again for the long intoxicated ramble. I hope I'm able to explain myself clearly here. Have a great night (or day) everyone.

  3.  

    I'm curious why you would separate session handling functionality into a separate class?

    Testability for one. The problem you discovered and similar loop holes in logic could get caught by that. Also, in larger teams, you'll not see regression, i.e the same problems comming back. Another point is that everything $_REQUEST-related in PHP is so similar it could benefit from inheritance, exactly why I made a class in the first place.

     

     

    Why in the world would you want to write an interface

     

    Due to composition. Wouldn't it make you happy to pass your whole Session object into a JSON parser, being able to foreach a Session object, sort session values internally or similar? By providing interfaces, you Sorter class doesn't give a damn if it gets a Session or a Dog object. (It would probably like a dog better thought) A key concept here is seperations of concerns, and that is also why you'll see loads of classes for something as simple as a session.

     

     

    This kind of unnecessary abstraction is the exact reason why sites using frameworks are generally slow!  I`m not trying to be hard on you, but I really want to know what I am missing here.

     

    That's what caching is for. While it takes time to generate object-oriented object graphs (or threes, or list) it gives you power to focus on your domain. When you application is no longer simple CRUD work, but you need to verify something like that rules and algorithms for car parking does what it's supposed to, you don't want procedural code that's hard to understand. Maintainability, extensibility and other fancy words are very much more important from a business perspective. eZ Publish takes 12 seconds to load in dev enviroment (mainly due to logging) on a project I'm working on, but throw Varnish on top of it, and it can serve millions upon millions of requests a day. Best part? Load is BETTER the more traffic the site gets.

     

     

     What are the drawbacks of using static functions?

     

    They can reach from huge to non-existing. There's so many good explanation online, so I won't bore you with mine. In a setting like Sessions, they aren't really important if you ask me, as sessions are a very specific thing. That's why I've also gone that pretty much the same road as you did in your Session class above.

     

    Nice job, Matt.

  4. Absolutely. It makes sense to me to have methods for adding, updating, getting and setting stuff, but not necessarily in the manager. Those kind of things would be better suited to a Session object. To make it sweeter, I would also have the Session object implement some interfaces for handling stuff like serialization and etc.

     

    In the real world though, I've usually cheated by writing some quick wrapping around the stupid globals. Usually, you don't want error messages or similar when say a session key isn't found, so I've focused more on that kind of stuff. I don't think I actually have that code readily available, but I would link you a Gist if I did.

     

    Quick usage example:

    Session::start();
    Session::add('key', 'value');
    Session::exists('key');
    Session::get('key'); // Return null, throw exception? Your choice
    Session::remove('key'); // Why must $_SESSION['key'] exists for me to "delete" it? No errors on non-existing keys
    Session::regenerate();

    I've almost stupped doing this kind of stuff myself. No matter what kind of project you work on, you usually need this kind of functionality. Due to that, I tend to build on Laravel or even the Symfony2-stack itself. The latter we also implement custom systems on at work, so that's a bonus.

     

    Let us know how it works out, Matt.

    • Upvote 1
  5. If your php binary is not aliased available in /usr/bin/php, you need to specify a more explicit path. If you can't run "php -v" from everywhere in your terminal, that's the case. Try running 'which php' and use that path.

     

    Example:

    $ which php

    /usr/bin/php

     

    Now use that path to run yiic.

    $ ls -lah

    ... (A lot of folders)

    $ cd PATH_TO_XAMPP/htdocs/YII-FOLDER/

    $ ls -lah

    ... see YII contents

    $ /usr/bin/php yiic.php (run commands here)

  6. No script is too simple if you display output from users. I can make my own form and set your URL as the action. Therefor, no input should ever be trusted.

     

    As this is number based, I would instead look at something like intval(). As much as you need to think security, you also need to assure input type here. Because if that, you'll often want to parse and check input before you work with it.

     

    Your main problem here is that you assume your users will only input numbers. Try using text and see the result then. Your script will give error messages and not work as intended.

    • Upvote 2
  7. You could look at some Javascript libraries. Geolocation is maybe something you could look into. When you have an exact location, country names are no issue. On another note, setting a country is maybe something your users won't be really hesitant to share with you directly? You could consider implement a splash screen version asking visitors their country.

     

    Another way is maybe to look up their IP-adress. As this tread says, looking up IPs might be a way to go. Keep in mind that a user might sit behind a proxy, though, so that's not a guaranteed way to get their country...

     

    ... And that's also pretty much the point here. You cannot guarantee 100% a user's country, so I would recommend you to think about what suit your needs. Asking the user directly might get you more a better answer than looking up the IP, but social "cleverness" like asking their language might be even more accurate. It all depends on how import an exact location is to you.

    • Upvote 1
  8. Change you mysql credentials as fast as possible. You shared all details publicly on this forum, so they are no longer safe to use. This is a much bigger problem than a user changing a few columns!

     

    Other than that, I'll bet the issue is not related to your connection, but instead has to do with one or more of your queries. You're most likely not effectively cleaning user input somewhere so a user can change your query in some way. We need to see some of those queries.

  9. Very good. That's a lot more to work with. The problem seems to be missing DateTimeZones in your database. Here's a thread describing the very same problem. Here's also some tips on how to install timezones yourself.

     

    That said, doing this using mysql is not the only available method. If you are using timezones for other purposes than learning, you might instead consider doing this using PHP instead. After all, a user will often be able to set his own timezone, so using something like DateTime instead might make sense.

    // Some logic for getting user's timezone. Could be stored in a cookie/similar. 
    $timezone = 'America/New_York';
    
    // A slightly altered query
    $query = "SELECT message_id, subject, date_entered, messages ORDER BY date_entered DESC LIMIT 1";
    
    // Run query
    $result = mysqli_query($dbc, $query);
    
    // Get result
    $data = mysqli_fetch_array($result, MYSQLI_ASSOC);
    try {
       $date = new DateTime($data['date_entered'], new DateTimeZone($timezone));
       echo $date->format('Y-m-d H:i:s'); // TimeZoned dateTime.
    }
    catch ( Exception $e )
    {
       echo $e->getMessage(); // An error occured.
    }
    

    Hope that either solves your problem or gives you some idea of creating an alternative version.

    • Upvote 1
  10. You could look at the function ini_get(). It's the getting equalient of ini_set(). The basic thought is something along the lines of:

    
    $file = "./testfile.pdf";
    
    try {
        assertUploadSize($file);
        // Safe to work with $file
    }
    catch ( Exception $e )
    {
        // Exceptional state
        echo $e->getMessage();
    }
    
    
    function assertUploadSize( $file )  
    {  
        // Could not work with file
        if ( ! file_exists($file) )
            throw new Exception("Error: File is not readable, or does not exists at path.");
    
        // Get sizes
        $fileSize = filesize($file);
        $POSTRequestSize = convertPHPSizeToBytes(ini_get('post_max_size'));
        $fileUploadSize = convertPHPSizeToBytes(ini_get('upload_max_filesize'));
    
        // Post size is too small
        if ( $POSTRequestSize < $fileSize  )
            throw new Exception("Error: Filesize is larger than allowed POST size.");
    
        // Upload size is too small
        if ( $fileUploadSize < $fileSize  )
            throw new Exception("Error: Filesize is larger than allowed file upload size.");
    }
    
    //This function transforms the php.ini notation for numbers (like '2M') to an integer (2*1024*1024 in this case)  
    function convertPHPSizeToBytes($sSize)  
    {  
        if ( is_numeric( $sSize) ) {
            return $sSize;
        }
        $sSuffix = substr($sSize, -1);  
        $iValue = substr($sSize, 0, -1);  
        switch(strtoupper($sSuffix))
        {  
            case 'P':  
                $iValue *= 1024;  
            case 'T':  
                $iValue *= 1024;  
            case 'G':  
                $iValue *= 1024;  
            case 'M':  
                $iValue *= 1024;  
            case 'K':  
                $iValue *= 1024;  
            break;  
        }  
        return $iValue;  
    }
    

    I've based my answer on This Stack Overflow. One of the main problems is parsing PHP ini's values into something we can work with. I've then based the main checking function on Exceptions, as this is absolutly exceptional state. The function should display errors when a file is not readable/does not exists, or when your settings are beneth the filesize.

     

    I haven't tested the code, so it might not work at the moment. That's a basic outline to solving the problem, though.

  11. Some versions of mysql doesn't support stored procedures. That might be your problem here. Larry also a wrote a post on how to change from stored procedures (they are a hassle, really) some time ago.

     

    http://www.larryullman.com/2010/12/07/rewriting-the-e-commerce-stored-procedures-with-standard-php-mysql/

     

    You said you used the first edition, but the same pricinple applies to your case too.

     

    Edit: I might have found the same article for the first book:

    http://www.larryullman.com/2010/12/28/rewriting-the-e-commerce-stored-procedures-with-standard-php-mysql-3-chapter-10/

  12. Quote types work a little bit different. If you want a variable to work inside quotes, you eighter needs to use double quotes or use concatination.

     

    $var = "HERE";

    echo "You can echo out '{$var}' using double quotes"; // You can echo out 'HERE' using double quotes

    echo 'But you can't echo $var using single-quites'; // But you can't echo $var using single quotes

    echo 'Unless you concatinate. Then ' . $var . ' will work'; // Unless you concatinate. Then HERE will work.

     

    The reason why $response is wrapped in single-quotes in your example is that he wanted to display the single quotes in the output itself. The {}-tags are only a precaution on my side, btw. They explicitly states it's a variable.

  13. It depends. If all you want to do with the automobile is to represent a specif model of a make, the answer would be no. If you create anything where an automobile can exist with differences (i.e a truck, suv, etc) then an abstract base class could absolutely make sense.

     

    Some principle like SOLID can probably help your understanding a bit. As for your question about interfaces, this should clear up some of those questions you have. As an example, all automobiles can drive. Implementing the interface Drivable thus probably make sense. If a group of similar object share other such similarities, another interface is probably the way to go. Steerable or GearShift (excuse my clumsy examples) could therefor also be viable interfaces.

     

    So... It depends on your needs. There are no overarching non-breakable rules in software engineering, only best practices and different models for your data and behaviors.

    • Upvote 1
  14. Glad you got it working. :)

     

    Notice that Larry also assumed this kind of issue right from the start. This comes from experience. By learning how to isolate each part that can go wrong in a program, it's a lot easier to do debugging. You PM-ed me and asked for help with solving the problem, so I offered an elaboration. I want you to notice that my post only elaborated on how to do the steps Larry asked you if you had done earlier. Debugging is a very simple process, but it needs to be done.

     

    I'm glad you're saying this is helping your process moving forward. That's pretty much what anyone can help you with in these cases. Any program that is to difficult to understand can be simplified until each part is simple to understand on it's own.

     

    Good luck!

    • Upvote 1
  15. You still need to break down the problem you are working on and make sure each part works as expected. Ignore everything related to error messages and logic beyond actually querying the data before you have solved that problem. You need to make sure of a few things:

     

    1. The SELECT query is working.

    - Write and execute a new query outside any other logic. Magic sure you can output all emails and hashed passwords currently stored in the DB.

    2. When that is working, add conditions. Try fetching the specific row that matches the email address.

    3. When that is working, fetch the row matching both the email and the hashed password.

    4. When that is working, make it dynamic by adding variables. When that is working, you can be pretty sure everything is good.

     

    Every programming task can be broken down into smaller parts. It makes for easier development.

×
×
  • Create New...