The MicroPHP Manifesto
funkatron.com
funkatron.com
The first is to not handle the problem. Implement something "simple" that doesn't work in uncommon cases. This seems nice because there isn't much code and there isn't much complexity. But that's because your program doesn't actually work, which is usually considered a bad thing. (This program right here -> "" <- is the easiest way to solve problem X. It only fails in 100% of the cases, that's all.)
The second way is to "refuse complicated frameworks" and write an application with a framework inside. This is what most people do, but believe that they aren't using a framework because they didn't download one. But, the same problems come up again and again: rendering data, handling AJAX requests, building database queries, managing users and passwords, the list goes on forever. When you do a half-assed job of handling this stuff right in your application code, you're using a framework. It's just a bad one. You had to write it from scratch, it's not well-tested, and you can't reuse it.
A third option is to use well-written libraries (or frameworks) to manage the implementation complexity, leaving your application as a concise shell around the core components. This means your application code only describes the problem that your application is trying to solve. The dirty work of dealing with the real world (HTML, JSON, SQL, etc.), is all handled in other code. (You can write this yourself, of course; you just have to understand that JSON parsing is not what your application does, and when you want to write that code, you need to "switch gears" and implement it outside of your application du jour. And sometimes, "you" is not you, it's someone else on the Internet.)
This article suggests that you eschew option three in favor of option one or two, because the code is "less beautiful". I say that, beautiful or not, these two options are the best way to write unmaintainable code that doesn't ever work.
The third strategy may feel unclean because you did not get to fully control every aspect of the interface and implementation. But most of the time, that doesn't matter. Yes, you'll have to do some configuration. Configuration is easier to test and maintain than the logic that you're configuring, and that means your application is actually simpler. The world is complicated. Your software doesn't have to make it more complicated.
In short, after working with the framework a little, I have thousands of lines of code that are better tested than my application, better vetted by more programmers, and many edge cases handled I might not even realize I have. I might only use half the code, but I'm glad it's all there, and I'm glad I can focus on getting down to work instead of writing yet another framework.
I agree that for big jobs, you can't prioritize pretty over featureful, but, respectfully, I think you are overstating your point here: "doesn't ever work." That's simply not true. Have you really never written a working program without a full featured framework?
I think one of the points that isn't clearly enough articulated in this article, but is very significant for me, is code understandability. Probably my biggest issue with CakePHP (what I use) is that when you step outside the standard use cases you fall down a rabbit hole of complexity and peculiar idioms. The result here is that one becomes a "Cake developer" rather than a "PHP developer"; there is a high degree of lock-in and switching the entire toolset becomes difficult and impractical. So the idea being suggested is allow people to switch out tools one by one rather than start over with a new, incompatible set if they need some lower level change.
What I see in this post that I agree with is the idea that PHP tools should be more modular and decoupled, so you can grab a full stack bundle if you want, but can use modules piecemeal if you don't. Currently, the latter option is lacking in PHP. I don't think anyone's saying "down with frameworks" as much as "hey, let's get some do-one-thing-well tools as well, so the piecemeal/modular option is also there."
Totally agree. But that's because of poor design in CakePHP (I used it too).
>What I see in this post that I agree with is the idea that PHP tools should be more modular and decoupled, so you can grab a full stack bundle if you want, but can use modules piecemeal if you don't. Currently, the latter option is lacking in PHP.
Actually, it's not. Take a look at Zend Framework and you'll see that you have a TON of modules for doing all kind of stuff and if you want you could use just the core ones and ignore the rest. It works so well that I even use components in non-Zend Framework projects.
The author recommended several microframeworks. He's arguing against large, monolithic frameworks and pointing towards a more pragmatic, YAGNI approach.
Use a small framework that gives you simple things -- URL routing, JSON parsing, etc. Maybe a base application structure to keep things sane.
You can do a lot of very useful things in a small, reusable microframework that don't have the level of complexity of a larger framework like Zend.
edit: I knew your name was familiar. Good work on Catalyst. My choice in framework really depends on the project.
If it looks like a nail and feels like a nail, don't use
a sledgehammer.
We should all be pushing for "the right tool for the right job"; a concept that is both language and framework agnostic. When you start your next project, take a moment to think about all of the core components and modules that will be necessary to complete said project.Many of us (including me, at times) have forgotten our primary role as an application architect. We need to take a giant step back to look at the project from a bird's eye view to gain some insight into how to solve the problem(s) in an efficient and timely manner.
Often, it's because people make them so. Often, it's because people recycle broken solutions instead of really thinking about what they're trying to do. Most code out there solves trivial problems, but is insanely complex. Web frameworks are especially bad at that.
"Deliveries are not made on Tuesdays, unless it falls on the 9th day of the month, but not in June for tax purposes in 2013, 2014 and 1998. Our Nowheresville office is excluded from the above rule."
You get rules like this. And there's reasons for most of them. Sometimes very good reasons.
Often, what simplifies a business process on the surface actually doubles (or worse) the underlying code. Because managers don't want you to throw away old data because it doesn't fit the new schema.
The "happy path" is always simple. And it tends to wind up being a fraction of the actual, evolved production code.
Unless you work in large organisations with long-lived systems, this will never be part of your worldview.
What programmers like B often doesn't realize is that they push core logic of the application from their source code (Turing complete, expressive, versioned, benefiting from static and dynamic analysis and all the testing/refactoring tools available for the language) into an obscure XML notation or even some proprietary rules database, worked upon by a complicated blob of 3d party code that has nothing to do with the original business problem.
The point is that in web frameworks, the two are often confused or at least blurry. So we need to extend the essential/accidental dichotomy to deal with global versus local views.
Take for example parsing emails. In a universal sense the complexity is accidental, it arose from the technology decisions of the authors of RFC822 (which partly arose from previous decisions).
But locally, for a web programmer, the email address format is an immutable, irreducible fact of reality. I can no more wish away that complexity than I can wish myself a million dollars. To me it is an essential complexity.
Where web frameworks of the entirely-made-out-of-code variety really shine is in facing up to these locally essential complexities. It may seem superfluous now. It may not seem so in six months.
Black Flag made a lot of junk because they couldn't get the band to cooperate. They had to keep re-doing the same songs over and over because their lead singer kept changing. Talk about a good analogy for unnecessary rewrites! At one point, when the artistic direction and ego situation became especially dire, one side of an album was all spoken word, and the other side was all instrumental. In the end, they just ended up becoming another "metal" band with albums like "Slip it In" towards the end of their discography. Black Flag is a great band, but this post completely misrepresents what they did and what it means, if anything for software development. If it's the story of anything, it's the story of an entrepreneur who kept paying for all the corners he cut.
Rush wanted to write complex albums that dealt with a lot of layered meaning. There was a lot more planning and attention paid to what got laid onto their tracks. In exchange for their hard work, attention to detail, and planning, they were well compensated. They played arenas and sold a ton of albums. Black Flag played VFW halls, and I'll be damned if most of their fans these days didn't just torrent their discography and be done with it. What would you want for your business? There will be no hipsters to fondly nostalgize your unsuccessful web application.
Programming in today's world means working with other people's code. All a framework does is provide a set of design patterns and standards that a group of programmers can adhere to. This encourages code reuse and allows you as a programmer to create "black boxes" - components with a well defined programming interfaces that behave in a consistent & predictable manner.
Real-world example: I'm currently working with a custom-built CMS programmed in PHP. I'm the second man on a what began as a one-man project. The CMS author wrote a bunch of database functions (essentially wrappers for the deprecated mysql_* functions) and dumped them into a file. Now, the author wasn't aware that you can (and should) lazy-load database connections - so every time you need to talk to the database, you have to manually connected using `cms_db_connect()` AND select the database with `cms_db_select(CONST_DATABASE_NAME)`. As pretty much every page initiates a database connection this code is EVERYWHERE.
And this is only the tip of the iceberg. There's also a half-assed MVC implementation, ubiquitous usage of inline CSS, un-encapsulated code, and a butt-load of quirky behavior. Now if the original author had take a little bit of time at the beginning and researched a proper framework or used an existing CMS our project would not be behind schedule - and it would be far easier to add another developer into the mix. All this meaningless complexity because the original author took the "simple" route of not working with a framework authored by third parties.
Choosing simple tools for complex jobs can get you in just as bad of a place as choosing complex tools for simple jobs.
I am glad Ed/Funkatron is forging ahead and voicing these concerns and suggestions nonetheless. As a PHP dev, I look over the fence at python & ruby examples and wonder why my application/framework is so complex and ugly (obv. examples and production applications are apples and oranges, but the contrast is stark). I hear "PHP is supposed to be ugly." Seriously? This is a selling point?
It's good to hear others call attention to these issues and suggest a path forward that keeps PHP competitive with other languages on the web.
some of the best elements of RoR (gems/bundles)
I program in Ruby a lot, have done for a long time, and love it, but I've also lost weeks (months?) of my life to fighting gem interdependency problems and watching 'bundle install'. It's almost certainly my least favourite part of the job.That's not to denigrate the efforts that go into RubyGems, Bundler, etc. - they're doing a good job, and they make life much easier than it would be without them, but in some ways they're playing with a lousy hand for historical reasons that are too late to change now.
I'm largely ignorant of Symfony2, but I hope it's learning from the flaws of the RubyGems ecosystem as well as its strengths.
Thanks!
I don't use (or need) RVM on servers, and I don't use it on a daily basis, but I find it useful for testing gems across multiple interpreters before I release them.
Why wonder? Have a look at the source of the different frameworks and try to understand how they work. Maybe there's some inherent characteristic of the languages that makes it this way. Maybe it's just that one is better thought-out than what you're using and you could propose or contribute a change.
Unless you're a contributor to a language or framework, it's probably not a great use of your energy to hope that it competes well with others. A better use of your energy might be to learn a few so you can pick the most appropriate tool for a given job.
When you roll your own, you have to either document it yourself (ha!) or become the point man on all questions about how things work.
My last company underwent a painful conversion from roll-your-own to Zend Framework. It slowed us down in the short term, but there was a huge payoff in developer productivity in the long term.
At my current job we're working with our own framework. I think it has two main downsides for my employers: 1) Employees are difficult to replace - they invested a lot of time in me, to teach me their stack. 2) New employees are difficult to introduce - fresh developers keep asking questions, disrupting the workflow.
For me it's a mixed situation. In short term I know I'm safe - why should they sack me? But in the long run I'll end up with untransferable skillset.
> I want less code, not more
If been coding web apps since the mid-90's, and I've pretty much had it with either re-inventing the wheel or scouring the internet for bits and pieces of libraries. Big fat frameworks allow me to focus on the code I need to do something new.
I have no time to fuck about trying to compensate for all the bits and pieces those lightweight frameworks conveniently left out in order to be lightweight. The end result is inevitably just more code to maintain instead of less.
I get my punk rock kicks from writing shell scripts and the odd quick & dirty hacks, not complex web applications.
It seems to me that what he is trying to do is something like setting up a simple contact form using Java, Spring and Hibernate, and by this I don't mean that he codes silly stuff at all, but that if he feels this way he's just picking the wrong tools for the job.
I don't know anything about music but I also think that the analogy he used is wrong. Black Flag may do great music with much less equipment, but I doubt that with that drum kit the drummer would be able to do the same sounds or have the same precision as the drummer with the huge kit would.
Does OP know why Neil Peart needs all that stuff? I assume Neil wouldn't be able to play the same things in a minimalistic set up.
If you don't know what all the framework's "boilerplate" is for and you just want to get your application running, why are you using a framework in the first place? A framework is supposed to do stuff for you that you would have to otherwise do manually. If you don't normally do the stuff the framework does for you, don't use it.
There are plenty of quotes in there that I strongly disagree with (the commitment stuff mostly), but I think I can sum it up with saying that just because you can do great things with less it doesn't mean that having more is bad. Just learn to pick the right tool for the job.
edit: jrockway is spot on regarding code quality.
The movement toward smaller, decoupled and interoperable libraries in the PHP community is in general a good thing.
But without a widely adopted PHP package-management system using many micro libraries becomes more complex to manage than a big all-in-one framework. We need something like NPM for PHP. Maybe PEAR 2 can get us there.
Indeed it will not always be that easy, because the project has to be structured in a way that the autoloader could work with.
Maybe even merely giving the heads up to library developers would be enough to get them to accept it; worth a shot, right?
"It doesn’t mean that stuff is bad, in the grand scheme of things. It doesn’t mean it has no value or is the wrong approach for many. But it’s the wrong approach for me, for sure."
Let's face it, the differences among Zend Framework vs Symfony vs Limonade vs Rails vs Django aren't really that big of a deal for most of our projects. In fact, I don't know if I've ever worked on a project that any of those frameworks couldn't solve effectively. The fact is that for the simple database web apps that most of us are writing, these decisions are not very critical.
It seems to me that Ed recognizes something that no one talks about as much as they should. The important consideration is not "Which tool is right for the project?". Most of the time "Which tool is right for the developer?" is the question that the success of a project hangs on.
Ed and his coworkers at http://gimmebar.com recognize this. They have adopted Javascript as the lingua franca that allows their frontend and backend developers to work together harmoniously. Developers working in harmony can achieve great things. The 5 Days of Gimmebar are proof enough of that (http://blog.gimmebar.com/post/12793742161/5-days-of-gimme-ba...).
Ed says that a simple framework with useful single-purpose third-party components is the right choice for him. Maybe it is for you too, maybe it isn't. I think the important takeaway from this post is that we should all strive for the self awareness that allows us to recognize what will let us work most effectively. I know I've been giving that question a lot of thought lately myself.
i'd actually say the Rush vs Black Flag analogy does not do Neil Peart or micro concepts justice. ideally, small tools can be used together, much like a drum kit. each of Neil's drums performs a very specific function, and he uses them as he sees fit. if he only played one song a night, his kit would look very different. extending the analogy, if you give Neil Peart a 5 piece, he can still make great music.
When you look at a large framework like Zend, it's a lot to swallow. There are a lot of parts, and just like the tools in a tool box, each plays a different part. You might just need a hammer today, but tomorrow, you might need a screw driver, and then a saw, and then a sander.
So, I appreciate larger frameworks. Sure, SOAP or XML-RPC might not be fun, but when that's the way you connect to the bank, it being apart of the framework makes it so much easier.
Anyways, the point was I saw your post, and it reminded me of Stephen's story.
Reading "quick" start tutorials like this (http://packages.zendframework.com/docs/latest/manual/en/zend...) is just depressing, and it's a big reason why droves of developer continue the exodus to other languages. PHP libs and frameworks should not emulate Java.
Sometimes I think PHP needs a _why to add some whimsy to the community and encourage people to break the mould, but they'd probably be dismissed as someone who "doesn't understand design patterns" or some other BS...
Thank you for writing this.
In that way I guess a four piece kit reminds me of lisp - just some parenthesis and a few other things, but endless possibilities nonetheless. But I've never used lisp for anything really and in software I always like to shoot for a happy medium of scale and pragmatism. Also Neal Peart's setup is part of the entertainment value. EJB or some overgrown PHP thing, on the other hand, not very entertaining.
His "punk movement" is more of a "I don't want to use things I have to learn" complaint. I defy any PHP developer to assert that the majority of development is made faster by spending your days bolting together that which already exists.
Our third-party library stack for the (very complex) chartboost.com architecture is made up of simple, modular parts: Paraglide as micro-MVC (one class, and a handful of folder for the base structure), MongoModel (one class, as MongoDB ORM), etc. Most of our third-party libraries are very simple and manageable, the way all PHP should be.
As for code verbosity: everything is auto-loaded on the fly when needed. Our code has practically no `require` statements. We just follow a simple conventions of where to place files and how to name classes, and everything works smoothly and painlessly.
Most importantly in this setup, none of the libraries depend on the framework of choice or on anything architectural. The framework doesn't even require being run in a web environment. This lets us do powerful and flexible things like use Facebook's `phpsh` library to open up a shell that will have our entire environment available and loaded on the fly. We can also switch between dev, production or local environments on the fly.
First, "building small things" isn't what many of us do from day to day. I don't think many of us sit down and try to create bloated, overly complex systems, but oversimplification isn't helpful either. If you're wild-westing it or reinventing wheels for your next web project, I can't help but think you've only got serious pain in your (near) future.
I think there's an important difference between complex and complicated. I wonder if you asked Neil about his set if he'd describe it more as an organized toolset that's evolved over time or a sprawling mess of a ball-and-chain he's involuntarily tied to.
I'm no fan of the verbose, Java-like implementations (ZF and SF, I'm looking at you) you've highlighted, but there are more options out there.
Secondly, I take issue with the abrasive tenor a lot of these posts seem to take. All critique and no solutions, especially no code to show for great ideas. While a good F@$* that S@#% helps everyone see the problem, the lack of action or offering of concrete ideas for improvement leaves me with the feeling that it's just complaining.
I wish more of the leadership in this community was contributing in an open-source, here's-the-code sort of way. At least contributing as much as they critique.
=C=
Just look at perl6.
Use the parts of PHP that matter most to you.
Frameworks do require a bit of initialization code, but the whole point is that once initialized they save you tons of writing. They take care of boring stuff like authentication, basic code organization, certain security issues, etc.
There's nothing wrong with deciding not to use any frameworks, but to do so because it seems "cleaner" or "simpler" I think it misguided.
This is the reason I ended up writing my own micro-framework, Flight (http://flightphp.com/). The goal is to be as flexible and extensible as possible, while providing a tiny footprint.
Poor_programmer = 'Overcomplicated code'; If (You == programmer) { stop(); }
EDIT: I change die() to stop() because die felt a little too dramatic, even if thats the correct function in php. =)
If you have more tools in the box, then you can start to consider whether to go full-stack with PHP (I'd no longer consider this route a viable option), or whether to modularise your project. Maybe for a lot of things that's too much and a PHP framework that does it all is totally fine. No point doing something just because you can, but you have the flexibility to think outside of the box when refactoring.
This is exactly what I did when it came to generating an image and manipulating the output. In PHP it was convoluted, buggy, impossible to understand the library it depended upon, and offered no flexibility. It took months of procrastination and avoidance before we had to get the feature working, so I ditched the lot and re-did it in Python, using Cyclone and a couple of lightweight libs. It took a day and a half to implement, with no knowledge beforehand, and it does absolutely everything we wanted (without any hacks).
It was at that point I realised that it was much more beneficial to look beyond the one-size-fits-all solution of a massive framework, which may be appropriate to some, but just as often isn't. And as has been said - very well indeed I must add - I don't want to be a [framework]-developer who knows not so much the language, but an individual or group's abstraction of it; I want to be a developer who knows what to do when that framework doesn't fit.
Why? Configuration/Bootstrapping is needed, with simple, small and loosely coupled components even more, because you don't want to tie a some configuration monster to it. But it would indeed turn out to be a simpler configuration, usually a nice little array with few keys bootstraps any simple component nicely. On framework level it can be more DRY. Downside, every "framework" solves bootstrapping and configuration on it's own. Which would me make always feel bad about running multiple frameworks side by side.
For components (objects) configuration we could solve a lot of problems if the php community could agree about an plain array configuration protocol to set them up. At least it would be interesting if it's doable.
Most mega-frameworks pat themselves on the back with examples that declare "See, you can write an entire CMS in 10 lines of code!" That's impressive except you can't write anything else and extending the CMS requires that you read and understand 100 pages of framework API entangled with assumptions and design tradeoffs that expertly fit the author's needs and not necessarily yours.
The problem is that the ideal framework requires zero lines of code because it already solves your exact problem. The worse framework requires more lines of code than coding your application from scratch. So, the key is finding a framework that satisfies 80% of your needs easily and doesn't get in your way for solving the other 20%.
Then you're probably using the wrong language. :-)