Blog: Philosophy

  • How to Become a Better Developer: Straight Talk

    Jan 21, 2013

    Being a good engineer is a matter of experience, knowledge, and personal philosophy / attitude. Each of these things can be individually improved upon. Intentionally analyze where you are in your career and in the predispositions of your personality. Understand where you're most lacking and always work towards improving that area.

    A developer who is constantly growing is a happy developer that other people want to work with and learn from. A depressed developer stuck in a dead-end learning cycle is a liability to their team and to any project in which they’re involved.

    You are not just some code-monkey. You're a problem-solver whose influence significantly impacts (for better or worse) the quality of your organization.

    Here are some tips on how to become a better developer. (Special thanks to the developers on FreeNode for contributing to this list of ideas.)

    Learn from advanced engineers.

    I come from a time pre-internet. My friend Jeremy was the only other person that I knew who was interested in creating software. We were starved for information. We’d scour bulletin-board systems to find source-code that we could read and learn from. Much of it was too advanced for us, but that’s what we had.

    Now, the internet is full of guides, documentation is easy to find, and we have screencasts that show us step-by-step how to make new applications. These are great resources and we’re lucky to have them. But, many developers forget about the value of directly learning from the work of others.

    Read the code of experienced engineers and aspire to truly understand WHY they made the choices that they have. Work with others to understand. Put away your ego and just study. You’ll be surprised at how quickly you change your tactics.

    Fabien Potencier is a PHP heavyweight and he’s a big name in the Symfony scene (consequently the entire PHP scene). The Symfony source is some of the best material to learn from this is available in the world of PHP. Say what you want about Symfony (or better yet, just don’t say anything about it) but there’s a lot that can be learned here.

    Taylor Otwell is the engineer behind the upcoming framework Laravel 4, which has been modularized into a suite of components entitled Illuminate. He’s utilizing the power of Composer to put real control into the hands of PHP developers and to improve the quality of the codebase and communities by refusing to lock developers into a specific set of functionality. The Illuminate source is a superb resource.

    Take special care to look at unit-tests as well. There’s just as much to be learned here. Unit-tests can function exceptionally as documentation for the capabilities of a project.

    Learn technologies that are specifically different from those that you already know.

    Do you only know how to develop with PHP? Learn Python or C#.

    Only ever use traditional server-side application development techniques? Learn a JS MVC framework like EmberJS. Only use MySQL? Learn ElasticSearch or PostgreSQL.

    You don’t need a use case to learn a new technology. Chances are that once you learn them you’ll discover opportunities to use them. More importantly, if you have only used a couple of programming languages, then your mind is simply not thoroughly primed to understand the variety of solutions that you have the power to implement.

    If you’re relying on a specific stack (LAMP, for example) then you are literally unable to use the "right tools for the right job." The saying is, "If you only have a hammer, you tend to see every problem as a nail."

    An added benefit of learning new technologies is that with every bit of knowledge gained, the next becomes increasingly easy to acquire. This is why experienced developers can pick up a new technology in a day, where a beginner could spend months. Their brains are already primed with all of the concepts necessary in much the same way that learning a 3rd spoken language is often much easier than learning your 2nd.

    Join a community by attending user group meetups and IRC.

    This is one of the most important aspects of becoming a better developer. You’ll be exposed to new ideas via presentations, etc. But, most importantly you’ll be exposed to intelligent and motivated individuals that fill you with the kind of fuel that propels you through the next couple of weeks of enthusiastic learning. The more regularly you attend, the larger gains you’ll see.

    Maintaining a high level of motivation and energy is one of the most important aspects of improving yourself as a professional engineer. If you feel like you don’t have the time to do this sort of thing then YOU are who I’m talking to. With proper management of your brain’s chemicals and natural human tendencies you can be a lot happier and a lot more productive doing what you do.

    Take an interest in design patterns and agile development.

    While it’s not necessary to buy the Design Patterns bible, it’s necessary to appreciate what design patterns are and what control they give you.

    Design patterns teach you both solutions and problems. There’s a good chance that with each new design pattern learned you’ll realize problems that you never considered. You’ll realize how tightly-coupled your code has been and you’ll start to realize that good software design can significantly lower the cost and THE BUSY WORK associated with long-term maintenance of an application.

    The best developers are able to quickly adapt their software to changing requirements without having to deal with a bunch of the most mindless and boring types of development.

    Becoming a better engineer means being less bored, solving problems faster, changing codebases faster, and being able to do more without being as exposed to the negativities of the crunch.

    Don’t create ignorant self-serving opinions.

    How often do you hear things like, "I hate Symfony, it’s too bloated.", "I hate ORM because it’s not as fast as my raw SQL implementations.", "I hate Rails for all of the magic." or, "I really just don’t see the point of Coffeescript?"

    Frankly, someone designed these technologies for a reason. They all have their advantages and disadvantages. There's a good chance that the decisions that define these projects were based on solving problems that you haven't yet encountered and don't yet know how to plan for. They may also have philosophical differences that lead them towards a different kind of solution than you. This doesn't make their solutions wrong.

    The reality is that we have different opinions not only because of the differences in our knowledge and experience but also because of the differences in the problems that we have to solve.

    It’s important for engineers to have experience with a wide array of tools and to understand why to use one over another. As stated earlier, if you don’t know more than one software stack then you have no way to use the best tool for the job.

    It’s certainly reasonable to dislike a technology because of it’s negatives. But, unless you’ve real-world experience then it’s possible that you just have the opinion because someone that you trusted has it or because you want to give yourself the opportunity to not feel compelled to change. Either way, this is a really bad practice.

    Realize what you don’t know and embrace it. Ignorance is a problem to be solved like any other. We're professional problem-solvers, after all.

    Rely on your own intelligence.

    I have been a provider of IRC / forum support for various technologies for over 3 years now. This is an important point that I feel very strongly about.

    You don’t install a technology, play with it for a few minutes, hit a problem, then immediately rely on the help of people on IRC or forum. The people on IRC or the forums that have the knowledge to help you have time as a limited resource. When you’re being helped by someone, they’re not able to help someone else.

    Have you ever gone into an active IRC channel for a technology, asked a basic question, and have been simply ignored while other people are around asking more complex questions and getting help? It’s because these people believe that you’re plenty competent enough to solve your own problem without too much trouble and that you shouldn’t be in IRC asking and waiting for a solution. You should be studying the documentation and codebase and creating one.

    The hard and fast rule is that you must ask yourself "have I really tried?" and if the answer is "no" then start there.

    The real advantage of having access to these experienced individuals is in gaining perspective. If you’re new to development and an experienced developer teaches you her approach to development over the course of a few hours a week that is SIGNIFICANTLY more important than them teaching you something rudimentary like how to use the authentication system or pass variables to a view.

    Anyone can learn how to do that by reading the documentation, or diving into the source, or reading the code of other people’s applications.

    Documentation is a great resource when it’s available. You can usually learn the API from the API documentation and you can usually get some important perspective on how to think about application development with a particular technology from a ‘getting started’ guide or a more general documentation format.

    These resources are here and they’re important. It’s important that you read through the entire documentation for a technology before asking questions in IRC, maybe even multiple times.

    If you can’t find what you need then read the API documentation. EmberJS has a good example of API documentation. Here you can see classes and methods and understand what each do.

    Source code itself is good documentation. Maybe if you’ve read through the guide-based documentation, api documentation, and other people’s source and question / answers on stackoverflow.com and you’re still having routing problems then you can ask for help from someone else. But, if you’re asking how to make classes load from different folders or something similarly fundamental, you should be heading directly to the source to find your answers.

    The source is far more accurate at answering questions than anyone in IRC, on forums, or anywhere else. The source is the part that actually means something.

    Don’t short-circuit your intelligence. You’re an engineer. Some aspects of the source etc may be difficult for you to wrap your head around but you can do it and it’s not going to take the rest of your life to understand the code either.

    You may say that it just takes too long and that you’re under a deadline. You may well be under the deadline because for much of your career you’ve relied on other people to do your work for you. If you dig in and learn things on your own then you’ll have real knowledge built-up and that knowledge will be yours forever, more or less.

    How to Get Help

    Now that you've tried to do a good job and have exhausted the other resources it may be time to ask for some help. When doing so it's important to realize that it's rare to find experienced people that are willing to answer your question. Respect the time that these people provide as a free service.

    Prepare a list of things that you've tried, all relevant source code, and the exact errors or problems that you're seeing. Read the resources that you've compiled and make sure that they all make sense. It's rude to force someone who is providing free help to do all of the discovery work necessary to be able to sufficiently answer your questions. Give them the best possible set of information from which to work and you will be appreciated and respected by everyone involved. A combination of your work and the work that others expend trying to help you can help people who are otherwise unrelated to you and your problem learn new things.

    You should read What Have You Tried?.

    Never call anything technical "magic".

    We’re engineers. We’re supposed to be the people who denounce witchcraft and explain the unknown with rational answers and utilize thorough analysis to provide pragmatic solutions to complex problems.

    We have no business being afraid of the truth. Am I the best programmer? Are you? Are either of us even CLOSE? The answer is no, not by a long-shot. But, we’re professionals. We push forward and improve our philosophy and our toolkit. That’s our job.

    Computer Science is too big a field for any of us. As time moves on, specialization becomes increasingly granular and we become increasingly specialized. However, in the end we ALL benefit from a healthy philosophical approach.

    We must not be afraid of the unknown. We must embrace it. That is the only way forward and in this profession, if we’re not moving forwards then we’re steadily moving backwards.

  • Introduction to the Form Model

    May 22, 2012

    Forms are often used to interact with a specific model such as a user or a blog post. However, in many circumstances a form may collect data that is related to multiple data models.

    It may also have special validation requirements that have little to do with the underlying data, such as captcha and password confirmation. Consequently, it often makes sense to create a form model.

    A form model represents the data needs of a form. This may be validation alone, storing values for form select drop-downs, having custom methods to generate data for the form, or managing persistent data in a session to make multi-page forms simple.

    In this video I discuss modeling forms and introduce a form base model for Laravel.

    More documentation and information can be found on the project's Github page.

  • Why CodeIgniter is Dead

    May 6, 2012

    I've written many CodeIgniter tutorials, recorded a dozen screencasts, and participated in the #codeigniter IRC support channel for years. Consequently, many people ask me why I no longer use it. I realize that this article is not particularly flattering. But, I've answered this question enough times to warrant a post, so here it is.

    CodeIgniter has been the go-to framework for programmers new to PHP frameworks. It is relatively easy to use, the documentation is widely considered to be good, and there is a large support community (there are currently 140 people in the CodeIgniter IRC channel). It has stood as the most popular PHP web-development framework for years. Consequently, there are many screencasts, written tutorials, and third-party libraries available. CodeIgniter is built around the concept of legacy support. So, its design is structured around the capabilities of PHP4.

    However, CI has aged poorly due to a combination of legacy support between major versions and a virtually complete lack of leadership. Despite the emphasis on legacy support, recent versions of CI require PHP 5.2. PHP 5.4 is the most modern stable release and 5.3 is now available on any reasonable host. (If your host doesn't support PHP 5.3 then jump ship as soon as possible.) By providing legacy support (changes to the framework rarely require any changes to your code-base) CodeIgniter has been unable to implement any of the features available in 5.3 that give developers more flexibility to create elegant solutions to problems.

    Since CI doesn't use any of the new features, best-practices suggest that its users should avoid them in order to provide standardized code. It should be easy to find and hire a PHP developer who is versed in CodeIgniter and mismatching a bunch of code-styles is a bad way to approach that goal.

    When it comes to code modularity CodeIgniter is one of the worst performers in the industry. CodeIgniter is not built using any modular design pattern so all solutions are after-thoughts that were developed by members of the community. Out-of-the-box CI supports libraries (basic classes), helpers (global function declaration), and plugins (the same as helpers, these are not used). These are all different versions of the same concept separated by intent.

    There are some third-party modularity solutions available. The oldest and most powerful of these is Modular Extensions by wiredesignz. It allows the implementation of HMVC modules. Unfortunately, in order to implement this he was forced to permanently alter core system files and this makes the code brittle. Issues can easily arise from upgrading CodeIgniter. As a long-time member of the #codeigniter IRC support team I can attest to the amount of issues that users end up running into as a result of this implementation. The fault is not so much on the code that drives Modular Extensions. But, on the fact that it's essentially a hack designed to expand a system that fundamentally rejects modular code.

    Another third-party system released for CodeIgniter is Sparks (getsparks.org). I was a big proponent of Sparks at first and made a number of screencasts that encouraged its use. But, it quickly became apparent that Sparks is the worst form of code modularity currently available for popular PHP frameworks. The core concept seems reasonable enough. It's a command-line tool for installing packages that pulls from git repositories, supports server caching (removal of the original repo doesn't kill the spark), and versioning. These are all good things. However, it falls flat on its face due to the fact that it can't offer more than CodeIgniter itself does. Sparks can only provide libraries, helpers and config files. This limits its function to a central repository for CodeIgniter libraries. Unfortunately, it fails at that as well due to the fact that CI developers cannot rely on the libraries that they need being available within the Sparks system. A Google search ends up being the go-to method in the end, rendering Sparks useless. It is now apparent that modular code solutions have no place in the world of CodeIgniter. These are symptoms of a greater problem.

    CodeIgniter was conceived by Rick Ellis of EllisLab. It is now community supported to some extent, but still seems to wilt under its creator's needs. CodeIgniter is the platform on which EllisLab's flagship product (ExpressionEngine) is built. In part due to the preoccupation of EllisLab with ExpressionEngine change to the CodeIgniter framework has come infrequently and the magnitude of the changes have been insignificant.

    CodeIgniter Reactor was released so that the community could make changes and improve the framework. Unfortunately, due to the fact that there is no strong or dedicated leader, improvement to the framework has not occurred. One could easily argue that CodeIgniter 2.0 brought only minor usability improvements at the cost of dropping PHP4 support entirely. The CodeIgniter development team is either too busy with their other projects or just not sure what CI should become. It's no longer the framework for legacy support and it begs the question, "what was the purpose of dropping that support?" as users have seemed to have gained little in exchange.

    When it comes to community participation only the most daring need apply. CodeIgniter is not well unit tested. This means that there is no way to responsibly make pull-requests as you're unable to test whether or not your changes have unexpectedly broken something. There was a time when this was the standard in PHP but as a community and as an industry we're past the point where that is acceptable. The community has been trying to catch up and to create tests for CI but in the last few years very little real progress has been made as the task of retrofitting CodeIgniter with unit tests is Herculean.

    In summary: CodeIgniter has proven its inability to change and it can no longer compete with the feature-set or practices found in any other modern PHP framework. When I say that CodeIgniter has died. I don't mean that nobody is using it. I'm saying that CodeIgniter has nowhere to go and can become nothing more than it is.

    Solution: Don't be content exploring only a single framework. CodeIgniter is lauded to be easy to learn. It is that. But, so are other frameworks. Do your due diligence and find what best serves you and your organization. Without experimenting we can't truly understand what we prefer. It's far easier to identify strengths and weaknesses when you have something with which to compare.

    I use Laravel.


    UPDATED 5/21:

    There has been a lot of response to this post, some of it negative. I'm going to take some liberty to clarify my position.

    I made a few key mistakes while constructing this post. The first is that the title distracts from the actual information in the post. The second mistake was to advocate Laravel in this post as some have assumed political motives, which is simply not true. These mistakes have distracted and confused the issues.

    The assumption that I simply became bored with CodeIgniter isn't the case, and it ignores the issues that I discuss in the post.

    I acknowledge that there is responsibility inherent when one provides and promotes educational resources. However, I disagree that responsibility should embargo unpopular ideas.

    I'm not interested in intellectually or emotionally strong-arming anyone. I express my ideas because I believe that there is value in that. I believe that the otherwise warm response to this post is due to many users having similar experiences and perspectives on the subject.

    I value the perspectives of others and you should feel free to contribute to the lively discussion in the comments.

  • A Walk Through Laravel's Folder Structure

    Mar 12, 2012

    In this video I walk through the Laravel folder structure and share some of my thoughts about Laravel.

  • Are You Developing with Your Clients' Best Interests in Mind?

    Sep 16, 2011

    Software and Database engineering / architecture are difficult jobs. It's absolutely necessary to constantly learn more design patterns and to keep up with new developments so that one can implement best-practices. Frequently, web developers who are under-qualified for database architecture jobs end up in that role due to team size constraints or due to management not realizing that there is a need for experienced professionals. We end up with developers obsessing over every small performance hit while remaining somewhat oblivious to the big picture.

    It's important to choose the right tools for the job. By observing basic practices such as reducing the number of queries per page, reducing the number of hits to the server per page, and intelligently caching our data we can keep performance quite high under a heavy load. Should the site become a massive success and performance starts to become an issue then that is a GREAT problem to have. We're building successful web applications and we're making some money. You can then start load balancing your web servers and using data storage patterns such as the "data warehouse" in order to kick your system's performance back up to the top.

    The biggest issue that our clients come against tends to NOT be performance. Instead, it tends to be their ROI (return on investment). The less money that our clients spend developing (or paying us to develop) and paying for maintenance (adding features and generally just making changes to keep up with their business) the more income becomes profit. I submit to you that our primary goal should be to reduce the lifetime cost of the products that we're either building in house for a company or are turning over to clients.

    We can reduce the lifetime cost of our products by:

    1. Using industry standards across all aspects of our development (from database architecture to variable naming conventions).
    2. Keeping our code small and easy to read (code should read like a sentence, variable names should be easy to understand).
    3. Using technologies that are established and have strong community support.
    4. Properly refactoring code when the need presents itself.

    Your Choices Directly Influence Your Clients' Costs

    It's important to remember that code you write is going to eventually enter into the hands of another developer. You may hand a product off to a client who then hires an internal development team. The experience level of that development team is an unknown. It's quite possible that they hired inexperienced developers in order to reduce their costs. The more difficult it is for these developers to understand and maintain your code the more likely the modifications that they make will be of the "hacked up" persuasion. This can violate the integrity of the project's conventions, reduce performance, and reduce readability and maintainability. This turns your product into a long-term challenge for the company involved. It's easy to blame your client for not having hired experienced development, but our profession is one that is easy for amateurs to enter into and is difficult for many business people to understand. Sometimes the budget for an experience developer simply does not exist. It is not our job to predict or judge the failings of our clients but to improve their experience with the product that you created for them.

    By developing your code by standards and intentionally making sure that your code is self-documenting (easy enough to read that you don't need to generate as much documentation) you're reducing the lifetime cost of the software for your client. By using established technologies you're giving yourself and others access to free community support.

    This is the philosophy that leads Big Name's web development decisions. Do you agree with us or does your organization subscribe to a different philosophy?

  • The N+1 Problem and ORM Data Modeling Performance.

    Sep 14, 2011

    A Brief Explanation of N+1

    N+1 is an expression that represents a popular pitfall in data modeling for web applications. I'm going to briefly explain N+1 using an example involving the following database tables:

    mysql> describe songs;
    +----------+--------------+------+-----+---------+----------------+
    | Field    | Type         | Null | Key | Default | Extra          |
    +----------+--------------+------+-----+---------+----------------+
    | id       | int(11)      | NO   | PRI | NULL    | auto_increment |
    | album_id | int(11)      | NO   | MUL | NULL    |                |
    | name     | varchar(128) | NO   |     | NULL    |                |
    | filename | varchar(128) | NO   |     | NULL    |                |
    +----------+--------------+------+-----+---------+----------------+
    
    mysql> describe albums;
    +-------+--------------+------+-----+---------+----------------+
    | Field | Type         | Null | Key | Default | Extra          |
    +-------+--------------+------+-----+---------+----------------+
    | id    | int(11)      | NO   | PRI | NULL    | auto_increment |
    | name  | varchar(128) | NO   |     | NULL    |                |
    +-------+--------------+------+-----+---------+----------------+
    

    In this example you need to loop through the albums, creating a container, then loop through the songs providing links to each of them.

    How do you approach this from a data modeling perspective?

    You could query to pull back all of the albums, then, loop through them. For each album you could query to pull back the songs for it. Consequently, you'd have the initial album query (+1) and then add another query to the pile for each album in the database (N). This means that the number of queries that you need scales with the amount of content in the database. To pull back songs from 10 albums you'd do 11 queries. To pull back songs from 100 albums you'd do 101 queries. This is not good.

    select id, name from albums
    select id, name, filename from songs where album_id = 1
    select id, name, filename from songs where album_id = 2
    select id, name, filename from songs where album_id = 3
    select id, name, filename from songs where album_id = 4
    select id, name, filename from songs where album_id = 5
    

    An alternative would be to select all of the albums, then aggregate the returned album ID's. Then, you can query for all of the songs like so:

    select id, title, filename from songs where album_id in (1, 2, 3, 4, 5)
    

    With 2 queries we have pulled back all of the data that could have taken us anywhere between 2 queries and (total database album count + 1) queries.

    The problem here being that you must now arrange the data in a format useful for you development. You might do something like this:

    $album_songs = array();
    
    foreach($songs as $song)
    {
        // create array container
        if(!isset($album_songs[$song->album_id]))
            $album_songs[$song->album_id] = array();
    
        // push to array
        $album_songs[$song->album_id][] = $song;
    }
    

    This will allow you to do something that more or less does this in your view:

    foreach($albums as $album)
    {
        echo "<h3>$album->name</h3>";
    
        // loop songs if they exist
        if(isset($album_songs[$album->id])
            foreach($album_songs[$album->id] as $song)
            {
                echo anchor('download/' . $song->filename, $song->name);
            }
    }
    

    There's a bit of extra processing as you're combining everything into an array that is indexed by album id.

    Compare and contrast this with using an ORM ActiveRecord model.

    You'd have a model called Albums and a model called Songs. You could do something like this:

    $albums = Album::find('all');
    
    foreach($albums as $album)
    {
        echo "<h3>$album->name</h3>";
    
        // loop songs if they exist
        if($album->songs)
            foreach($album->songs as $song)
            {
                echo anchor('download/' . $song->filename, $song->name);
            }
    }
    

    We pull back a list of all albums as one query. However, then we take the amount of records returned and instantiate that many album model objects. In this case $album is an array of Album model objects. Each of those objects contains the member variables and methods defined in the model as well as those in the model's parent class (ActiveRecord\Model).

    As you look through them you call if($album->songs). If there are no songs tied to an album then using the foreach() loop without this if() statement will result in an error. The error is that foreach expects an ARRAY and we're sending a boolean (false). So, we simply check to see if it's set at ALL, and if it is we know it's populated as an array of Song objects, so we can pass it into the foreach() loop.

    Well, at this point the ActiveRecord model has not yet run any queries relating to songs. This is due to a pattern called 'lazy loading'. There is no reason to populate every relationship in an ORM model by default (and indeed, you'd sometimes create infinite loops by doing so). Only when you make a call against $album->songs does the model then query against songs.

    It goes something like this:

    1. Query for all albums
    2. Start to loop through all albums
    3. Query for all songs belonging to an album
    4. Start to loop through all songs

    As you can see, we're dealing with N+1 here again. However, It's actually much easier to resolve with PHP-ActiveRecord.

    $albums = Album::find('all', array('include' => 'songs'));
    
    foreach($albums as $album)
    {
        echo "<h3>$album->name</h3>";
    
        // loop songs if they exist
        if($album->songs)
            foreach($album->songs as $song)
            {
                echo anchor('download/' . $song->filename, $song->name);
            }
    }
    

    By passing the additional parameter to include the songs models we're telling the ORM that we want "eager loading" for the albums to songs association. This means that instead of waiting until we make a call against $album->songs to pull back the data, we'll just go ahead and do it right now. Since the model has far more information about how you're going to want to use the data it can take steps to make the entire process more efficient. In this case, it'll query for albums, then query for all songs that have the returned album_ids. 2 queries, much like our solution above. We are avoiding N+1 and we can easily and cleanly loop through the results.

    An Argument Against ORM

    Here is where opponents of ORM argue that you're introducing unnecessary overhead into your application. It's true that we're adding additional memory requirements and some amount of additional processing requirements. Each returned record will require an instantiated model object, after all. The data still loops in the background to assign the values (as we did manually earlier in the article), so that's pretty much the same. So, in the end we're dealing with the overhead of the ORM model's infrastructure (sanity checks, etc) and then we're dealing with the instantiation of returned result objects. It is true that the ORM data model pattern has these extra costs.

    In my opinion ORM data models should be used by MOST projects on the web as it reduces the complexity of development, makes avoiding unpleasant challenges (N+1) easier, and improves readability and maintainability.

    What is your opinion on this topic?