Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Real-world applications are complicated. There are three ways to handle this problem.

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.



I find that when I work with a framework for a while, I do start to understand it very well. I find myself looking at the implementation more and more as I learn the subtleties about how it is written. After a while I start to feel as familiar with it as code I have written myself, if not more so because I interact with it so often. At that point, it's basically free code. You get the benefit of all those lines of code, but you get to outsource a lot of testing, debugging and development.

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 say that, beautiful or not, these two options are the best way to write unmaintainable code that doesn't ever work."

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."


>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.

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.


Please explain reasoning behind CakePHP having a poor design. I'm curious as most people that say a framework or tool sucks actually are just using the framework/tool in an incorrect way, and there is frequently an elegant way to tackle their issues. This applies to more than just CakePHP, mind you.


Sure, but you don't always have the time to figure out what that elegant way is. This is the reason people complain about the complexity of frameworks.


symfony2 (which the OP picks on a little bit) has taken exactly this approach, there's much more emphasis on the components than the framework as a whole.


Even better, other PHP projects, like Drupal, are planning to use Symfony2 components. Symfony2, with its "bundle" concept, holds huge promise for the PHP community and eco-system.


The problem I see with this is that it only has benefits for huge apps. If you're just getting something off the ground, debugging a 100-line stack trace for every little issue starts to kill your flow real fast.


    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.


Real-world applications are complicated.

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.


Often, it's because the real world is complex.

"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.


Sure, there are complexities like that in the world. However, where programmer A writes an if-else statement or, maybe, a 5-line dynamic dispatch, programmer B installs some "enterprise" framework or a rules engine, instantly making the entire system an order of magnitude more complex.

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.


Well we're talking about different things, now. Per Brooks, I was talking about essential complexity, you're talking about accidental complexity.

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.


The fourth option is to break your problem up. Not all problems should be handled in one pass by one giant program.


Yeah, i vote for that one; i try to code in little modular pieces; and if a connection is needed i try to make it as short and simple as possible.


I mostly agree with you, but a program that fails on uncommon cases is not a complete failure. I mean, do all your websites work with IE 5.5?


I don't think the article "suggests that you eschew option three" at all.

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.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: