On Software Frameworks

From Zanecorpwiki

Jump to: navigation, search

TODO: talk about research time.

When I saw the title 10 Ways to Cut your Web Development Timeref group=noteThe more general point of the article is discussed in Efficiency vs. Shortcuts./ref I just emknew/em that the first thing they'd say was Use Frameworks! and when I clicked through, sure enough the first title was exactly Use frameworks. (Kudos to them to leaving off the '!' I'd imagined.)

Frameworks are the bugaboo to my technical philosophy. I've spent years researching, using, and developing frameworks. The more time goes on, the more disenchanted I become.

This is the account of my apostasy.

Contents

Lexicon

Since there are not generally accepted precise definitions of the terms necessary to discuss these issues, I'll begin giving the best summary I can (some terms are my own).

  • A 'library is a collection of related functionsref group=noteFor our purposes here, we don't make a distinction between functions, methods, procedures, etc./ref grouped by usage or domain.
  • A framework is a library that imposes assumptions on usage, environment, replaces core functionality, or has a largeref group=noteLarge relative to the average minimal functional size./ref minimal functional setref group=noteThe minimal functional set refers to amount of library code which must be adopted in order to do work. In other words, a library/framework with a large functional is internally highly interconnected--for any one function/code fragment to work, the developer must adopt many large amounts of code from the library/framework./ref Frameworks are characterized by inversion of control (though in some cases this may be a result of the prior characteristics as much as a fundamental intent).
  • An application or comprehensive framework is the skeleton of an application that can be customized by an application developerrefRalph E. Johnson. Frameworks = (components + patterns). Commun. ACM, 40(10):39--42, 1997./ref
  • A functional framework is a framework dealing with one or more infrastructure verticals in such a way as to cause minimum interference with code outside the covered verticals; i.e., within the vertical a functional framework has the characteristics of a framework but outside the vertical, it interacts as a classic library.
  • Framework coverage refers to the functional areas handled by the framework. Coverage may be exclusive meaning that it is difficult to use other libraries or frameworks within the covered area, or non-exclusive meaning that the framework does not impose undue barriers to combinations

By way of example:

  • Ruby on Rails is a relatively comprehensive framework.
  • Hibernate is a functional framework covering persistence.
  • Struts is a functional framework providing non-exclusive covering flow control and supporting user input authentication and error handling.

A final note: an expansive reading of the framework definition above could be read as applying to programming languages. This would be correct were it not for the hallmark of inversion of control. A programming language redefines how you talk to the machine, but it never inverts control.

Fundamental Pros and Cons of Frameworks

Inversion of control is the hallmark of frameworks. Regular, non-inverted control means the developer is going to tell the computer what to do. Libraries ease the developer-machine communication, but are passive. Frameworks define the communication itself.

In other words, with a framework, the developer doesn't talk to the machine, they talk to the framework. This can be a good thing. Machines are hard to talk to, so the idea is that talking to the framework is easier than talking to the machine. To the extent that the framework exclusively covers a functional area, the developer can no longer directly talk to the machine regarding that area of functionality. Even when coverage isn't exclusive, it's usually harder to talk to the machine because most frameworks assume that you're not going to be talking to the machine.ref group=notesAt least, if you use the framework for that area. Some frameworks, like Struts, cover multiple functional areas, but their inter-function bindings are not tight, meaning the framework doesn't assume that you'll use all the areas together./ref

To the extent that the developer cannot talk directly to the machine, the developer is limited by the framework. Depending on what you're doing, this limitation may be anything from inconsequential to annoying to simply unacceptable.

This give in take of increased simplicity versus decreased control is the basic pro-con of the framework decision. The value of each must be evaluated in context. For instance, if the framework simplifies things you don't care about, there's little gain. If it restricts things you need access to, then there's a lot of pain.

Using the wrong framework for the task can easily increase rather than decrease problems. All frameworks expose some underlying model of how things are done. When that model doesn't jive with how the developer(s) intend or need to do things, it creates conceptual dissonance. On the other hand, when the model matches closely, then the framework can greatly simplify application conceptualization and speed development.

Implied Pros and Cons

The final analysis is not so simple as simplification, limitations, and dissonance. There are at least three other considerations to take into account before selecting a framework.

Framework Lifespan

Framework do not last all that long. 3-10 years is probably the activeref group=notesI define this as the time between the time a framework is finalized to the time that it ceases to be used in a significant number of new projects./ref lifespan for the majority of frameworks. That means if a framework has been around for awhile, and you're just starting to implement a new project in it, you're project will probably be dated by the time it's done.

The lifespan consideration has implications for long lived applications as well. It's often the case that the most abundant (and some would argue the most talented) development resources are usually available for the hottest platform of the day. But what about when that platform's not so hot? As I write this, you can't throw a brick without hitting a Ruby on Rails developer, but good luck finding a someone good to work on your a site built with JSP, Struts, Velocity, Turbine, ColdFusion etc. developer. I remember when all these where the talk of the town. For the most part, the only developers working on this stuff either stopped caring, didn't have the capacity to learn something new, or charge an arm and a leg to bother to work in something so outdated and uninteresting.

The same thing will (and already is) happening with Rails and Django (or anything else you could name that's currently mainstream). It'll also happen to whatever frameworks follow.

Cognitive Cost

The cognitive cost refers to the cost of learning the framework. Part of what makes frameworks good is their conceptual chunking. Conceptual chunking is a term used in the modern understanding of how we think. The mind, for example, can only hold a few... like 5-7 things in conscious thought at any one time. Our ability to handle complex tasks is defined by our ability to chunk.

For instance, when designing a house you don't think it terms of boards, sheet rock, nails and brick, you think in terms of walls, doors, and windows. You can hold wall, door, window, stairs, bathroom, closet in your mind, and that's enough to lay out a house. Those ideas form a conceptual framework of what a house is. The idea of wall composes all things that make up wall into a single conceptual chunk which can then be consciously manipulated.

Chunking is the process of learning where these lines are drawn. Sometimes this process is natural and transcendent. Like music... it's the same tones on every instrument even if you do different things to get the tones. That's why people that learn to play a couple of instruments really well can often get by on many instruments, sometimes even never having played them before.

With frameworks--perhaps because they conceptualize what is almost entirely an imagined thing--these boundaries are rarely so natural.ref group=notesSometimes we find a framework that just fits; fits both our task and our own mental model. If one continues to investigate frameworks, then this will always be the exception in the long run. We also have to understand that just because it fit this project and our model doesn't mean that it'll fit the next project or someone else's model. That, BTW, is why people specialize and narrow their focus: so that the tools and frameworks that they invest in can be leveraged. Again, it's a gain of abstraction and efficiency but at the cost of limitation, and it almost always dates and puts a limit on ones usefulness in the long term./ref

Conceptual Dissonance

Conceptual dissonance has already been discussed in terms of evaluating a particular framework, but it's also a consideration when looking at frameworks in general. Frameworks are, by definition, encodings of conceptual metaphors; confining abstractions of the Turing machine.ref group=notesEven when a framework does not interfere with Turing completeness, they are always limiting due to inversion of control. They make some things easy, but others awkward or tedious./ref

If we think of software as an expression of what's possible to do with a computer and define the standard conceptual topography in these terms, then we can think of frameworks as functions that remap this conceptual space. The things that the framework was built for become very easy. These functions are placed in more easily accessible locations. Everything else gets relegated to less desirable areas, or in some cases dropped altogether.

When we're trying to do something relatively original and unique, then it becomes unlikely that we'll find a comprehensive framework that fits our new view of things. If we did, then the framework would already be expressing that view and we wouldn't be doing anything unique. Functional frameworks, which are much closer to libraries anyway, may be combined with new ideas so long as the coverage and minimal functional set don't interfere with the area of innovation. Even with comprehensive frameworks, if the innovation is occurring at a different level--usually at the application level--then no problem.

Frameworks Don't Evolve Well

Refactoring and code evolution are powerful tools. They are necessary tools in making the best systems, and keeping those systems the best. You lose both almost entirely when you adopt comprehensive frameworks. This is a necessary result of inversion of control and conceptual dissonance.

To be clear, a system built on a framework may evolve easily in ways in which the framework was built to evolve. One of the much lauded features of Rails is the ability to upgrade and transition data models.

But what if you want to move into a new framework? Inversion of control pretty much guarantees that there'll be technical interference and cognitive dissonance guarantees there'll be conceptual incompatibilities. For these reasons it's almost always easier to rebuild a system from scratch than to migrate in an evolutionary way from one framework to another.

Cognitive Cost Increases as Frameworks Age

It is inevitable that whatever frameworks were hot when the app were built will not be hot at some point down the road. Because work on the system isn't constant, people--even those that worked on the original system--move on. They have to, at least partially, relearn whatever framework the system was developed in. The cognitive cost gets paid many times over.

What's worse is when the guy working on it wasn't the original developer... or the original developer has moved on so far that they don't really remember the framework anymore. Now the cognitive cost is magnified by the fact that there's no incentive to pay it. It becomes troublesome and tedious because the framework is dead and useless in terms of career or what it may have to teach. Under these circumstances, you're very likely to get hackish code that decreases system integrity and makes the app that much more confusing and difficult for future changes.

Considering that better developers tend to be exactly the ones that move on as soon as frameworks start to age, it means that the probability of new developers unused to old frameworks goes up... unless you hired sub-par developers to begin with (and that has it's own set of problems). On average good developer isn't generally paid that much more than a bad developer.ref group=notesThis is a concept I've discussed a lot... should have or should write an essay on this. TODO: find or write and link./ref Good developers compensate by taking the better jobs. Working on old stuff that no one uses is not the better job. This means that as time goes on, you either have to pay more and more to compensate good developers for taking increasingly uninteresting work, or accept worse and worse developers on the project.

How I Avoid Frameworks

If you haven't guessed my bias is generally anti-framework. Not because frameworks are bad, but because I don't believe frameworks are right for the kind of work I do. The point of this section isn't so much prescriptive as it is descriptive. In other words, I'm not saying, Do this! but This is how I avoid frameworks, and by the way, it's not that hard.

Understand that Chunks Aren't Frameworks

It's fully possible to do object oriented programming with a purely functional languages using nothing but calling and library conventions. You don't need an OOP language to do OOP programming. That isn't to say that doing OOP programing in an OOP language isn't easier or better, it just isn't necessary, but you get the benefits of OOP from doing OOP, not from using an OOP aware language.

In the same way, you can get much of the benefits of frameworks without using a framework if you understand and implement the concepts that underlie the frameworks. Well, you may ask, but don't isn't it stupid to implement what a framework already implements? If using a framework is appropriate, then yes. But if a framework is going to get in the way, then it makes perfect sense.

It all comes down to scale. For small systems, it really doesn't matter what you do. No matter how you go about implementing the system, it's not going to take much time because the system itself is small.

For big systems, the overhead of implementing your own chunking is small compared to the size of the system itself. In such cases, even if a framework only causes a small amount of cognitive dissonance and future drag, you're still going to be better off making a perfect match.

Making your own chunks for a moderate system may not be worthwhile.

Service Oriented Systems: Abstracting at a Different Level

When Frameworks Can be Useful

Despite everything else, there are times when a framework is worthwhile. First off, frameworks are great as learning and teaching tools. A good frameworks chunk things in useful ways. It's useful to learn what good chunks are and using frameworks is one of the best ways of doing that. Use a bunch of different frameworks and make a few of your own and you'll eventually be like the guy who can play a jingle many musical instruments first time out. What's more, you'll get to the point where you don't need the frameworks for chunking anymore.

Another instance would be a situation where you do a lot of prototyping. Prototype systems take longevity completely off the table. They also take a lot of functionality of the table (like security, sometimes persistence, etc.) so cognitive dissonance is not so pronounced.

Notes

references group=note /

References

Bibliography:

references /

Further Reading:

  • Blurring of MVC lines: Programming the Web Browser: Focuses on Javascript and MVC, and has some interesting points. The article was important to the development of my phrasing, but I don't put weight in the author's arguments. Analyzing Javascript/straight AJAX from an MVC/pro-framework point of view just isn't useful. It's a given it won't stand up well from that standpoint... that's kind of the point. I also question his endorsement of Django. I've had occasion to use Django once, and it was far from impressive.

TODO: link more influencees.

Personal tools