What is a Web Framework?
jeffknupp.com
jeffknupp.com
And it really doesn't help when more experienced devs, or non-web programmers shame people about web dev being dead simple because it's not. It's a different kind of programming, it may even be easier than writing C and managing memory explicitly and not having garbage collection. But if it is easier, it's only easier once you've mastered it and have a really strong grasp of what is happening at all times. Until you get there, it's easy to get lost in the endless list of technologies you must be familiar with to write even a simple web application. And I know this because I see it in beginners that I have taught and/or worked with.
Also, the distinction of semantics and styling should be cleared up a little. Less emphasis on how elements are styled by default, and more on what they represent.
I like the approach of assuming no knowledge, but this requires extra care to introduce concepts without using improper or misleading terminology. As a beginner, there's not much worse than hearing simplifications and thinking they're the whole story.
Good luck with continuing your series!
Anyone reading or writing these sorts of fundamental web programming tutorials should look at Philip Greenspun's books Philip and Alex's Guide to Web Publishing and Software Engineering for Internet Applications, both available free online (The latter is a stripped down version of the former, written for goal-oriented MIT students who don't want anecdotes or pretty pictures). They are around a decade old, so they aren't a good source for copy-paste-ready code, but the ideas in the books have aged quite well (from simple things like using "abstract URLs"--URLs without extensions like .aspx and .php, to focusing on the website's data model and user interaction instead of the programming language).
The most interesting part of these books is that they explored creating web applications for a purpose, not as an end in themselves. They were written for the sort of people who evaluated their past year not on what their manager wrote in some HR form and the raise they got, but on what they were able to accomplish, like creating http://scorecard.goodguide.com/. (What's funny is that in Greenspun's ITConversations interview (around 4:20 http://web.archive.org/web/20130729213414id_/http://itc.conv...), he said that the parts of Phil and Alex's Guide that aged were not the technology, but the rampant idealism in the book that web applications would unleash a new age of enlightenment, like the academics who had believed television would be used to broadcast Harvard lectures around the world).
Here are the chapters on HTML: http://philip.greenspun.com/panda/html http://philip.greenspun.com/seia/html
And the closest to describing HTTP and frameworks: http://philip.greenspun.com/panda/server-programming http://philip.greenspun.com/seia/basics
(It just occurred to me that Philip's interview above is one day short of being 10 years old, and his assessment might be worth revisiting. The internet still contains volumes of crap, but the internet as only grown as a teaching and community building tool, with sites like Meetup and Facebook organizing learners and teachers, Khan Academy and Udacity doing organized classes, and StackOverflow collaboratively solving specific problems).
You don't, and I've recently been encountering a LOT of very confused would-be devs who get stuck behind some tangled mess of django installation.
The "simplest" web application could look like this:
#!/usr/bin/python
import cgi
form = cgi.FieldStorage()
name = form.getvalue("name", none)
print "content-type:text/plain\n"
print "Your name is %s" % (name)
Or maybe you want to get fancy: #!/usr/bin/python
import MySQLdb
db=MySQLdb.connect(user=user,passwd=pass,db=test)
c.execute("select something from sometable")
results = c.fetchall()
print "content-type:text/plain\n"
#hey look, CSV data!
for line in results:
print ",".join(line)
etc. etc.I encountered a dev the other day (I guess I'm a shitty dev, then?) who asked me how my application handled URLs.
uhh...apache?
"No, how does it handle URLs, though"
"Apache. WTF are you talking about?"
"No, like if you go to example.com/foo/bar/, how does it know what to send me?"
"...?"
I swear half the devs I meet lately are more concerned with javascript frameworks and rewriting their own webserver than they are about actually serving content to users.
Imagine a baker who was more concerned with building ovens than baking bread.
Keep in mind what your goals are when you're working: are you looking to write a javascript framework, or are you looking to write a web application? Then evaluate what path you want to take from "not having an application" to "shipping a product".
Sometimes (probably many times), you don't need to make it as complicated as you're making it, and apache will work just fine.
I'd imagine that at some point, it's hard to make enough bread without considering the ovens.
If "baker" denotes an individual whose job is to bake bread in a small bakery, then perhaps.
But we're more like industrial chefs, hired to "make" bread at scale (e.g. for Tesco or Walmart). As a software engineer, our roles may be much more about combining, improving, or making our own ingredients, machinery, and processes.
Then, when it comes to baking the bread, we're able to produce much more with less effort, or even hand off the final production to others.
But my point is that sometimes people get caught into pre-mature optimization. The baker analogy, within the context of what I'm saying, is about a baker who never bakes any bread, because they spend all of their time iterating on ovens, and not bread.
Having some super fancy bread-making-machine is totally vital...eventually, or if you're doing something very cutting-edge, or out of the ordinary.
But not when you're writing a personal blog.
That said, I have worked with/for a lot of bakers who have literally given no time thinking about the oven (I've done a lot of cheap PHP freelancing), and occasionally ruminate on finding a better oven and the choice that led to my current situation in the kitchen.
There are a fair number of folks out there who bake plenty of bread, but who could do so in more sanitary conditions with easier to reproduce recipes if they were open to some different methods.
I agree that a personal blog is probably not the right point for that kind of methodology, but there are also a lot folks who need to learn the difference between yeast and random fungii that they found by googling "free wordpress themes".
Basically, frameworks are a way to work on a team without everyone reinventing solutions to problems that are almost beneath notice when trying to get dynamic content on the web.
The reason we don't have single CGI scripts for each url, and instead route everything through a single bootup script is to centralize things like session management, database initialization, memcache, configuration... etc. Things that you could do on every page, but that would be too cumbersome, repetitive, and generally don't change often.
When working with django, or zend, or cake, or whatever the framework of the day is I've often just wanted to go back to the simplicity of plain WSGI. But then I see the mess that people still make when everything is done for them and realize that would just create a new hell.
It takes discipline to program at a lower level, and understanding. Both of those qualities are in short supply.
Why don't we train developers for this instead of constantly telling them they need to learn flash-in-the-pan-framework.js?
This is not to say that understanding web at a low level isn't useful, it certainly is. However, in my opinion it is better to for example build a simple mvc framework as learning experience and use something battle tested in production.
There's a certain sort of intellectual deference that is given to these frameworks (much of it has to do with how readily people accept things said by famous/rich people). For example, is MVC really the best way to write traditional webapps?
We need more iconoclasts.
Of course you can attempt to add those things yourself, but the best code you'll often write is that code you don't write at all because someone already did. Don't reinvent square wheels.
For many "developers" these days the job consists of trawling the Internet looking for a "framework" that matches their project, then tweaking it.
While it may not appear to be the case, developing secure web applications is rather complicated, that's why we have frameworks and that's why these frameworks can be somewhat complex. That doesn't make not using them the simpler solution.
Looks like it does to me. The content-type is printed with a \n and then Python implicitly adds a second newline. Or did you mean something else?
In any case having to manually make sure to print newlines in the right places and escape user input in headers correctly is insane.
I disagree. The more complexity you introduce, the more code is needed, the greater the chance of bugs, and the greater the chance of those bugs not being discovered sooner.
Seems messy to say the least.
Deployments are still easy. Either symlink the web server config, or (in our case) deploy an RPM which copies the config to The right location. Then it's just a matter of a graceful restart.
These days, with Mojolicious behind nginx, it's much cleaner. (But it is good to have used a less abstract setup.)
But a good URL router allows for code separation, and to a lesser extent, separation of concerns, which directly speaks to the ability to deliver, uhhh, baked goods.
If you're just building static HTML files, then sure, your URL routing is, and probably should be handled by Apache, because each page is its own destination. In modern web development though, you have an application, and that application would likely get big and unruly if you didn't make some efforts to modularize the application into URL addressable resources.
"Handling URLs" then, is as much a part of baking a cake as sifting the flour, or measuring the baking soda.
This is part of the problem, though: most websites should just be collections of static files, but copious kool-aid swallowing has led to heavyweight frameworks being the default architecture.
With apps, even if I build a single-page app, I have to build an API to power it, and that API needs to know the difference between "customers" and "customers/customer_id", and the easiest logical way to manage that is through URL routing.
Even in static apps, URL routing is kind of a burden, unless you never link to internal pages and never grow your content beyond what you can keep in your head.
Apache? Python? Why!?
Nginx maybe?
http {
upstream database {
postgres_server 127.0.0.1 dbname=test user=test password=test;
}
server {
location / {
postgres_pass database;
postgres_query "SELECT * FROM cats";
rds_json on;
}
}
}
I'm actually using it... (and planning to use for much deeper things tho).https://github.com/FRiCKLE/ngx_postgres/
https://github.com/agentzh/rds-json-nginx-module
edit: reformated code block
Also, you could use LUA with nginx to increase the flexibility (if the lack of it was what you mean).
I think this is what Taobao uses/used: https://github.com/alibaba/tengine
It's a bit much, too, to say "All frameworks are too complicated to be worth the effort because Django!" Even Django's partisans acknowledge that it's on the very high end of the complexity curve; indeed, it's the only framework I know of which requires more up front from the developer than Rails. I'm lately more and more of the opinion that, in almost all cases, most of that up-front investment is wasted; you can get 90% of the benefit from a microframework such as Ruby's Sinatra or Python's Flask, either of which can be mastered from a standing start inside a weekend, and save the suffering involved in Rails or Django for when, if ever, you actually need that last ten percent.
Basically, you want to choose the right tool for the job. If you're putting in two screws, just grab your trusty Apache-brand screwdriver and go to it. If you're putting in forty, you're better off breaking out the Flask power drill and a screwdriver bit; sure, you can put in forty screws with a hand driver, but you won't do your wrists any favors in the process. And if you're putting up a frame for a two-story house, you're really going to need something like Django's powder-actuated, magazine-fed nail gun, but for anything smaller, it'd be overkill.
I found the article informative. I can understand what their 'simplest' example does knowing only what sockets are. However, I have no idea what cgi is. Your example is magic to me. The the things the example is supposed to teach are hidden behind its abstraction.
Yep, it's quite simple to do GCI by hand... But you'll want all your pages to look the same, so you'll need to add some template functionality to your code. Also, you'll certainly need to handle data, so add some data validation there. You'll also benefit from some better abstraction over your database, and connection pooling... and while we are talking about finite resources, you'll want to limit the number of threads Apache launches.
There is certainly more. I'll certainly not remember all the troubles of reinventing that wheel, as I don't do it since the 90's.
Or if my questions aren't making sense, that would be good to know as well.
The old school default was to put executable in the cgi-bin folder (wherever that had been configured to be) and make them executable. That would run the script and return the output.
[1] - http://bottlepy.org/
So if you write a solid library with just the right number of features, then it might get less consideration because you're not always duct-taping over poor design choices.
This is what happens when we glorify Internet Time. It becomes more about shipping and less about quality.
This is one of the reasons that I find the Golang package management philosophy refreshing in theory. "Master should never break" really prevents feature creep from coming in and promotes the use of solid packages that aren't always being actively worked on. Of course there are some major drawbacks wrt lack of versioning in Go, but I think the philosophy there overall is a very good thing for open source development.
Please continue to push Golang away from fashion-oriented 'engineering.' I hope you take marketing seriously; it seems very possible for someone to create the next ultra-coupled-hack-of-a-Go-framework to rile everyone up and consequently forget all the lessons of minimalism.
The biggest disservice that Industry does to working class programmers is when it tells them that all of these 'old' practices of modularity/coupling are outdated/can't possibly work/too hard to learn/too academic/require writing too much code. They free developers to work faster and better, rather than shackle them to fashionable technology, keeping them in a perpetual state of engineering amateurism.
Worse, Industry has the gall to proclaim each small step as progress. It's all hype and bullshit, including your favorite framework.
JavaScript frameworks seem to be another matter.
-- Some way to parse URLs coming into the system and route to the correct code that handles the response to that request. -- Some way to marshal and unmarshal form, request parameters, and more recently JSON. -- Some way to return HTML, after we have done what we need to considering the inputs we received. -- Some way to handle cookies. We probably also want a convenience layer so that we can have some sort of session to make authentication and authorization easier. -- Some way to interface with a more fixed storage, usually some form of a database. It would be nice to have a set of convenience methods to handle prepared statements. -- It would be nice to have some sort of way to escape text going to and from the fixed storage to help prevent XSS attacks. -- It would be nice to have a way to conveniently handle CSRF attacks.
Now, we could have a library for each one, or maybe 20. But that means every new project, we're making 7 (at a minimum) libraries, evaluating them for security, keeping on top of security updates for 7 projects, and learning 7 (or more) fundamental libraries each time we come on to another team because someone made different choices. On top of that, we've written glue code on top of this all to make our lives livable. The current state of code ownership means that we probably can't take this from employer to employer, so we'll have to write it all over again, or learn someone else's glue code with its own idiosyncrasies.
All for things that matter quite a bit, but I'd prefer a single good implementation over having to search for the 7 best. Further, what happens when one of these projects goes dormant? It's easy to rip everything out if you've written your code modularly, but what about that junior programmer's code from before you were there?
And are we supposed to thrust this all on a junior programmer who is just starting out? That's how PHP happened. ;) Not every programmer is gifted with a good sense of architecture, and most frameworks at least enforce a Not-Terrible architecture. When taking over someone else's code, this can be a very good thing.
Frameworks, as massively coupled as they are, have some distinct advantages for getting things done in 95% of systems. If you're running a system for which the defaults don't work, a framework isn't right for you. That's fine. Depending on how far out you are from the opinions, you can either cobble together your own solution or write it from scratch. But for most use cases, there are more advantages to that massively coupled system than disadvantages.
In short: java, inspired by flask, uses the http server included in the JRE. Perfect for embedding a small webapp in a java program (jar size < 20k, no external deps). Probably not suited for big scale apps.
Edit: homepage
http://www.tcpiputils.com/browse/ip-address
108.168.209.242
I was expecting some enlightenment at the end or something useful for me, but nothing. This stuff is mandatory for each and every programmer who writes web-apps and I wouldn't call them web-programmers if they wouldn't know these basics.