About a year ago, I wrote out some principles for web programming in PHP. I called it the MicroPHP Manifesto. The thing is, what I talked about wasn’t really specific to PHP. So, I’ve decided to explore the concepts again in the context of the other languages I work with.
What follows are some principles I try to keep in mind.
I like PHP, Python, and JavaScript, and I like making things in PHP, Python, and JavaScript. I’m not a Symfony developer, or a Django developer, or a jQuery developer.
I think this is an important distinction. It’s entirely possible to be a jQuery developer, but not a JavaScript developer. It’s possible to be a Django developer, but not a Python developer. Those are all certainly valuable and useful tools, but if I only know how to use one framework, my options for using the right tool for the job get pretty limited, and in my experience, large, full-stack frameworks are often not the right tool, particularly if flexibilty and performance are major concerns.
My experience has been that I become a better, more versatile developer when I focus on learning a language first. Diving head-first into a full-stack, complex framework when I’m starting out has allowed me to build finished products more quickly, but it also becomes a detriment when I need solutions outside of the framework’s scope. I often end up with a “plug and pray” approach to development, where I find a library or plugin that sounds like it will meet my needs, cross my fingers, and shove it in. That might get my app launched faster, but it makes stuff a lot harder down the road.
Additionally, learning a full-stack framework can be as complex as learning a new programming language. They often have complex architectures and nomenclatures — parts that don’t carry over to other frameworks and tools. I’d rather spend my time learning more about the language itself, knowing the skills that I learn will apply to anything I build in the language, no matter which libraries I use.
Small units of code are good. The smaller it is, the easier it is to understand. It’s harder to screw it up — and I screw stuff up a lot, so limiting that is really important.
So, I strive to build small modules of code with a single purpose, or at most a few closely-related purposes. They should be self-contained pieces that solve individual problems. These pieces then work together to solve larger, more complex problems.
With simpler, modular code, fixing bugs is easier, because I can look at an individual piece and see clearly what it’s doing. And, if the modules are self-contained, testing my code is much easier.
To paraphrase Biggie Smalls, “more code, more problems.”
I want to manage less code. Larger codebases get harder to manage. Searching across the codebase takes longer. Navigating through complex file structures takes longer. Tracing execution through dozens of files is hard. Keeping it all straight in my brain gets challenging.
Bigger libraries and longer code seem to overflow my brain buffer. I have trouble keeping track of code flow when the source gets too long, or when execution is jumping between several source files, and visual noise really affects me, too. This is why I love syntax coloring so much, and consistent whitespace really helps. I use the code folding feature in my editor a lot, just to hide things, so I can focus better on the task at hand.
I also want to support less code. I’m responsible for all of the code that my app uses, not just the stuff I wrote — every single line of it. This means that bugs and security holes are my responsibility. How often do we see a WordPress or Drupal plugin get abandoned after a year or so? Am I sure I want to use a piece of code I don’t really understand, when a year down the road I may have to fix an exploit in it?
This is not to say that I would never use code that I didn’t write — I’d be hard-pressed to get much done that way, and frankly there are better programmers out there than me — but every line of code in my app matters, so I need to justify each one.
I want code that is easy to understand. Understanding things quickly means getting stuff done faster. My time to productivity is shortened. My time to fix bugs is shortened.
I also want code that is easy to verify. My code should be testable, whether or not I get around to actually writing those tests, and I’ve consistently found that simpler, more modular code is more testable.
Readability should be a feature. Code should be simple and terse, but clear. Value clarity over cleverness. When I’m writing code, I try to consider how quickly another developer will be able to understand it at first glance. Alternately, will I be able to understand it when I come back to it in two months? The less time I waste trying to figure out how things work, the more there will be for getting things done.
I’d be lying if I said I always follow these principles. Sometimes, I just get lazy. Sometimes, time constraints mean I write hacky, complex code as fast as possible to get something working, or I pull in a library without reviewing it carefully, and hope it works. In the short term, writing simple, clear code is harder — it requires more discipline and frequent reassessment of technique. Particularly with time-sensitive projects, it’s hard to ever feel like I ever am entirely happy with the results.
But, when I make the time and put the effort in, it always pays off down the road — not just for myself, but for the other members of my team and people who use the code I’ve written, and that’s a really good feeling.
What follows are some principles I try to keep in mind.
Learn languages, not frameworks
I like PHP, Python, and JavaScript, and I like making things in PHP, Python, and JavaScript. I’m not a Symfony developer, or a Django developer, or a jQuery developer.
I think this is an important distinction. It’s entirely possible to be a jQuery developer, but not a JavaScript developer. It’s possible to be a Django developer, but not a Python developer. Those are all certainly valuable and useful tools, but if I only know how to use one framework, my options for using the right tool for the job get pretty limited, and in my experience, large, full-stack frameworks are often not the right tool, particularly if flexibilty and performance are major concerns.
My experience has been that I become a better, more versatile developer when I focus on learning a language first. Diving head-first into a full-stack, complex framework when I’m starting out has allowed me to build finished products more quickly, but it also becomes a detriment when I need solutions outside of the framework’s scope. I often end up with a “plug and pray” approach to development, where I find a library or plugin that sounds like it will meet my needs, cross my fingers, and shove it in. That might get my app launched faster, but it makes stuff a lot harder down the road.
Additionally, learning a full-stack framework can be as complex as learning a new programming language. They often have complex architectures and nomenclatures — parts that don’t carry over to other frameworks and tools. I’d rather spend my time learning more about the language itself, knowing the skills that I learn will apply to anything I build in the language, no matter which libraries I use.
Build small things
Small units of code are good. The smaller it is, the easier it is to understand. It’s harder to screw it up — and I screw stuff up a lot, so limiting that is really important.
So, I strive to build small modules of code with a single purpose, or at most a few closely-related purposes. They should be self-contained pieces that solve individual problems. These pieces then work together to solve larger, more complex problems.
With simpler, modular code, fixing bugs is easier, because I can look at an individual piece and see clearly what it’s doing. And, if the modules are self-contained, testing my code is much easier.
Less code is better than more
To paraphrase Biggie Smalls, “more code, more problems.”
I want to manage less code. Larger codebases get harder to manage. Searching across the codebase takes longer. Navigating through complex file structures takes longer. Tracing execution through dozens of files is hard. Keeping it all straight in my brain gets challenging.
Bigger libraries and longer code seem to overflow my brain buffer. I have trouble keeping track of code flow when the source gets too long, or when execution is jumping between several source files, and visual noise really affects me, too. This is why I love syntax coloring so much, and consistent whitespace really helps. I use the code folding feature in my editor a lot, just to hide things, so I can focus better on the task at hand.
I also want to support less code. I’m responsible for all of the code that my app uses, not just the stuff I wrote — every single line of it. This means that bugs and security holes are my responsibility. How often do we see a WordPress or Drupal plugin get abandoned after a year or so? Am I sure I want to use a piece of code I don’t really understand, when a year down the road I may have to fix an exploit in it?
This is not to say that I would never use code that I didn’t write — I’d be hard-pressed to get much done that way, and frankly there are better programmers out there than me — but every line of code in my app matters, so I need to justify each one.
Create and use simple, readable code
I want code that is easy to understand. Understanding things quickly means getting stuff done faster. My time to productivity is shortened. My time to fix bugs is shortened.
I also want code that is easy to verify. My code should be testable, whether or not I get around to actually writing those tests, and I’ve consistently found that simpler, more modular code is more testable.
Readability should be a feature. Code should be simple and terse, but clear. Value clarity over cleverness. When I’m writing code, I try to consider how quickly another developer will be able to understand it at first glance. Alternately, will I be able to understand it when I come back to it in two months? The less time I waste trying to figure out how things work, the more there will be for getting things done.
I’d be lying if I said I always follow these principles. Sometimes, I just get lazy. Sometimes, time constraints mean I write hacky, complex code as fast as possible to get something working, or I pull in a library without reviewing it carefully, and hope it works. In the short term, writing simple, clear code is harder — it requires more discipline and frequent reassessment of technique. Particularly with time-sensitive projects, it’s hard to ever feel like I ever am entirely happy with the results.
But, when I make the time and put the effort in, it always pays off down the road — not just for myself, but for the other members of my team and people who use the code I’ve written, and that’s a really good feeling.
0 nhận xét :
Đăng nhận xét