Now THERE’s real conviction…

I find myself amused by the anonymous poster(s) who continually berate me for my dual Java/.NET stance; this most recent comment is just but a precious sample of the accumulated levity (and high technical persuasiveness) of those who refuse to even put their name to their opinions:

    yeah, keep bitching. Dude, you should get over Java and concentrate on .net since you’re an annoyance in our space.

Precious.

Don wants to know how Indigo can avoid EJB’s fate

Don recently asked,

I’d love to hear from the EJB alternative camp what they’d like to see from us in Indigo to keep them from reinventing the wheel over here in .NET land.

which was in response to his earlier comments of

I’ve spent some time thinking about whether we’ve taken adequate steps in Indigo to stem the need for dozens of alternative "containers."

Based on what I’m seeing, I think we’re on a good path. Here’re a few things that make me believe that:

  • We don’t mandate a process/appdomain host, so you can host Indigo services in any AppDomain or process you chose.
  • Our dispatch and instancing pipeline is fully pluggable (and replacable) and is wired up to our metadata/contract engine.
  • Most important data structures are extensible without resorting to subtyping.

 

Philosophically, we’ve done a good job at building simple and reliable mechanisms and not imposing a lot of policy on top. This is similar to the approach taken by .NET Remoting (albeit in a somewhat different domain) and quite the opposite of the approach taken by MTS, COM+, and EJB.

So I thought I’d take a stab.

 

One of the critical flaws of the EJB Specification as it stands, and the principal benefit behind the lightweight containers (until they start to get too heavyweight, anyway) is that of composability, the ability to "pick and choose" which parts of the container you want to apply to your particular project. For example, under the current regime, if all you wanted was the ability to start a transaction and kick off some processing each time a message comes in, you either have to write the host yourself, complete with JTA code (which means bringing in some kind of open JTA framework), or else you install EJB and write Message-Driven Beans. There’s no "middle ground" until you start to consider the lightweight frameworks, but even there, there’s a growing tendency to want to be all things to all people. I want a container that gives me the very basics of container-managed inversion-of-control and then gets the rest of the way out of my hair. No automagic pooling (unless I ask for it), no automagic resource management (unless I ask for it), no automagic transaction management (unless I ask for it), and so on.

Proponents of the current crop of lightweight containers will be very quick to pipe up and say "but that’s exactly what we do!", but there’s a difference–in several of the formerly-lightweight containers, they started out this way but have grown to encompass almost all of what an EJB container does, with similar complexity involved. Give me a very basic container-managed relationship, and a raft of services that I can pick-and-choose from, but let the traditional C++ mantra: "Don’t pay for it if you don’t use it" be the guiding principle here. Sometimes all I really want is a simple container in which to put a remote object, and sometimes I want the full nine yards of a middleware container (a la COM+ or EJB). Build a simple container with a ton of hook points, then give me things built on top of those hookpoints that I can take or leave as I wish–not stuff already built in that I can choose to use or not (but still have to pay for in terms of code loaded, processing steps taken and so on), but things that don’t ever get referenced or used unless I explicitly call or configure for them.

That’s the pipe dream, anyway. 🙂

Richard Monson Haefel waves farewell to books… and describes how authors offer up their soul

Richard Monson Haefel, the author of one of the first (and best-known) books on EJB, has announced that he’s getting out of the book-writing business:

    I’ve been writing technical books (and some articles) for seven years and I’m ready to move on. Its been a lot of fun and my books have done a lot for my career, but they are a lot of work and at this point in my life they are not worth the effort.

He goes on, though, to say something that I think deserves underscoring and support, because he calls it "corny" but I think is very very true and needs to be reinforced:

    Of course this wasn’t an easy decision for me. As corny as it sounds, each book and every edition is a part of me. Think about it. An author (or at least me) spends as much as two years writing a book, not including subsequent editions. I’ve been working every year (over four editions) since 1998 on the EJB book!. There is a lot of blood sweat and well ? sweat (I’m not big on crying over work) in those books. When you buy one you get a chunk of my soul. Sorry. I warned you that this would be corny.

That’s not corny, Richard, that’s the author’s life. For those who’ve never written a book before, you have to understand the dynamics: you spend at a minimum six months (in my case, more like two years) trying desperately to figure out how to best convey the material, beating it and hammering it in various ways to make it clear, precise, accurate, and so on. You carry this thing with you everywhere you go: it’s on your laptop, at a minimum, sometimes it’s in your notebooks and your scribble notes on napkins and most of all, it’s floating there in your head, demanding attention. And then, when you finally publish them, they’re out there for the world to take potshots at. It really is a piece of you out there, and it’s terribly vulnerable because there’s nothing you can do once the book hits the shelves; somebody didn’t like the way you explained a particular concept? You can’t call it back, you can’t try to spin "what you meant" that didn’t come off correctly, you can’t edit it (unlike a web page) once it’s in dead-trees format. The best you can hope for is a second printing and the chance to fix a few errata.

Leon Uris once said, "Becoming an author is easy: just get out some paper, and open a vein." Each book becomes your baby, a little piece of you floating out there for all the world to take a whack at. And man, it’s tough the first time, like parents watching their first kid go off to kindergarten.

That’s not corny, Richard. That’s just being an author. Best of luck to you at the Burton Group.

Can’t let Floyd get the last word… More EJB history

Floyd and I are in a jenn-yoo-ein blog war now, as he responds to my post accusing him of EJB revisionism. This can only mean that I must now respond with vigor and extreme hostility, ripping his arguments to shreds and leaving no doubt in anyone’s mind about our respective ability in blogging, Java, or technology in general.

Not. (Gotcha, Floyd. 🙂 )

Truthfully, Floyd was right when he said

    While Ted phrased his points as corrections to my own, for the most part I don’t think they are, two people of different backgrounds can certainly see and interpret different aspects about why things are, especially historically. We are talking about history, not code. 🙂 …. Perhaps I should have been more upfront on my last entry, but the perspective I was giving was based on how things would have looked like to the developer at various points in history, and how that then affected adoption and growth, etc. It perhaps should have been phrased "a brief history of EJB adoption from the developer’s perspective", not the spec designer, book author, or specification implementor’s perspective. If I am being revisionist, then so is Ted, as we are both revising history with our own interpretations. 🙂

Exactly. I read Floyd’s post to mean that he was describing the development of EJB from its creators’ intent, rather than an interpretation of how developers saw–and largely misinterpreted–what its intent was. After all, it’s fairly obvious in hindsight, I think, that developers, and their management too for that matter, really really screwed the pooch when it came to EJB. Using it when it wasn’t really called for, and expecting that simply using EJB in of itself would provide the scalability and performance desired, will leave any development project pretty grossly screwed up.

Floyd’s also right when he says

    … it is obvious that people reading Ted’s blog will think that every point I made is wrong (Hani certainly did), so I feel compelled to respond …

        Unfortunately, Floyd seems to have fallen into the same trap that everybody else did back then, which was to assume that since EJB built itself on top of RMI (or so it seemed), then EJB must essentially be a distributed object framework just as RMI was, just as CORBA was before it, just as DCOM was over in the Microsoft space.

    I suppose that I invited this by saying early that EJB was designed to be distributed object framework, but take alone that sentence is out of context – as I mentioned later on in the blog, the distributed object framework was just one of the three major categories.

Yes, Floyd, you DID invite my blog-wrath when you said that, because unfortunately I think that’s a mistake that people continue to make unto this day, not just with EJB, but with some of its intended successors, too, the principal one being Spring.

The problem I have with the industry right now is stated rather simply: Not every problem we face lends itself to an object-oriented solution. For a large percentage of developers working today, that is an uncomfortable feeling, and thus gets repressed with a brutality normally reserved for hideous personality defects that we don’t want to own up to. Whether we like it or not, however, the design space that EJB–and Spring–operate in is a space that doesn’t lend itself to the object-oriented paradigm, and trying to pretend otherwise can lead us into all sorts of dangerous places.

Consider another technology whose major architectural principles also don’t follow an O-O slant, that being the HTTP and Servlet space. When you consider the major tenets of object-orientation, usually consisting of polymorphism, encapsulation and a methodology that demands fine-grained methods and objects ("No method should be longer than a page in your editor" and "No class’ responsibilities should exceed what can be written on an index card" being two of the common aphorisms used to describe proper O-O design and implementation), it slowly dawns on you that servlets don’t really follow that approach at all. In fact, if we were to compare a servlet’s overall design, it smacks much more of a 3270 session, which is essentially a procedural space: requests are processed, per-session data used as part of that processing, generating results that are returned. We can put an object-ish veneer over the whole thing, as frameworks like Tapestry or JSF try to do, but the underlying driving forces are still the same, essentially procedural in nature. The Servlet API, then, is an object facade over a fundamentally procedural task, and the way in which we write servlets reflect that: we don’t generally access fields in servlets (that creates a synchronization concern), for example, but instead access data stored in an entirely separate object that the container manages for us (that still has synchronization concerns), that being the Session, of course. We don’t expect to be able to inherit one servlet from another, since each servlet tends to be single-purpose and single-minded; we don’t usually look to polymorphically substitute one servlet in the place of another. (Note that this isn’t to say that servlets aren’t devoid of polymorphism entirely, only that we as the development community using them don’t make use of polymorphism in our usage.)

I find it particularly telling that, for all intents and purposes, the Servlet API looks astonishingly like the ISAPI or NSAPI APIs that predated them, which were intended for procedural languages (by which of course I mean C) instead of object-oriented ones. In fact, to a large degree, they’re identical. The .NET HttpHandler API, the logical equivalent is even less object-oriented:

public interface IHttpHandler
{
  void ProcessRequest(HttpContext context);
  bool IsReusable { get; }
}

You don’t get much more object minimalist than that.

(For the Java developers in the crowd, the Java translation would look like:

public interface IHttpHandler
{
  public void ProcessRequest(HttpContext context);
  public boolean getIsReusable();
}

where HttpContext is an object that contains methods to access HttpServletRequest, HttpServletResponse, Session, ServletContext, and a few other interesting tidbits. The IsReusable property is just whether or not instances of this thing can be pooled, something which the Servlet API defines on its own terms; I suppose you could see returning false from this property as the equivalent of implementing SingleThreadModel. Sort of.)

All of this isn’t to say that the Servlet API isn’t useful or interesting, but simply to say that we pretty much silently rolled with the fact that it was a procedural space, and adjusted our use of the object-oriented approaches accordingly.

Enter EJB. And MTS/COM+, for that matter. Web services guys, listen up–you’re likely headed down the same path if you’re not careful. Ditto for anybody contemplating Indigo.

EJB and MTS/COM+, unfortunately, were perceived to be object frameworks that required a usage model that followed the object tenets. And in each case, as time went on, patterns emerged that sought to debunk that idea and show that taking a strict object interpretation was doomed to failure. Effective COM and Transactional COM+ led the charge here in the MTS/COM+ environment. I hope I did the same with Effective Enterprise Java, but others came before me (in a much less "effective" style, of course 😉 ) saying much the same thing. And before us all came Deutsch’s "Fallacies of Distributed Computing" and Waldo and Wollrath’s "A Note on Distributed Computing" as basic foundation for the later works. (Hint: if you want to make a name for yourself, write an "Effective Web Services" book and say pretty much the same thing. You’ll be hailed as a hero.)

Herein lies my concern: Spring, as well as the other POJO-based containers, tend to lead developers back to an "objects-first" approach, and that tends to encourage object-oriented behavior, such as fine-grained methods, small-scale classes, inheritance, polymorphism, and so on. While I won’t go so far as to say that such things *can’t* be done in a Spring container, my worry is that developers will seek to do it both within the container (which I couldn’t care about in the least) as well as across container instances, which has Badly-Ending Story written all over it, as developers make the same mistakes that the CORBA crowd made, which is the same mistakes that the DCOM crowd made, the same mistakes the RMI crowd made, the same mistakes the OSF RPC crowd made, and so on.

Eventually, some day, we as an industry will recognize the truth of the statement "There is no such thing as a good distributed object model", but until that day, we have to remain on our guard against technologies that will–either by intent or by accident–lead us down that dark and stormy path. And thus the virulence of my reaction to Floyd’s comment; by characterizing EJB as a distributed object framework, even just to say that this was how it was perceived, reinforces that perception and puts us back in the danger seat all over again. So Floyd, maybe you weren’t wrong, per se, but you walked into an area in which those of us who’ve had to try and rescue EJB projects from themselves are a little sensitive, perhaps overly so.

Where Floyd and I do still disagree, however, is in this bit (him quoting me first):

        The hard choice is to realize that EJB’s "heavyweight" or "lightweight" factor isn’t in the API at all, but in the implementation of that API. And frankly, the big vendors have ALWAYS competed, at least with one another, on their "transparent middleware" services. That story doesn’t change.

    As mentioned before, I think the implementation is also a factor, but the entire light weight container / Dependency Injection / POJO "movement" directly contradicts the point that the weight of the API isn’t a factor "at all".

Au contraire. Just as JNDI is lookup via explicit method call, Dependency Injection is lookup via implicit method call (we’ve just reversed the direction)–effectively the same thing, just changing the API, reversing the direction of the invocation. The Spring interfaces that are available for implementation (for lifecycle control, etc) are pretty much equivalent to the EJB interfaces, it’s just that Spring makes them optional where EJB required them (admittedly an error in design). Spring’s major innovation wasn’t the POJO-based design model, or even the Dependency Injection approach, but in the lightweightness of the container. Think about it this way: would Spring developers be so excited about Spring if they had to run it as an external process, a la WebSphere or WebLogic? My casual anecdotal experience suggests no, thus leading me to believe that the API isn’t the major issue here. (Is implementing the SessionBean or MessageDrivenBean interface really THAT costly? If you truly dislike having to implement the methods you don’t care about, write a GenericSessionBean class that does the same thing the GenericServlet class does–provide common-sense NOP defaults. Message-Driven Beans are even simpler, and probably don’t even need a GenericMDB class, but your mileage may vary here.)

Floyd and I will probably disagree on Spring’s contributions, and this wouldn’t be the first time he and I have disagreed, nor would it be the first time I’ve clashed with people on the subject of Spring. Bruce Tate and I have had this discussion on a number of occasions, as have Justin Gehtland and Mark Richards (at the most recent NFJS show, in Des Moines). My point isn’t that Spring isn’t useful–far from it, I find Spring to be entirely useful–but that the efficacy of the tool is in its in-process nature, not its API. To more deeply understand this point, I strongly suggest anybody in the Java space play with COM+, which offers both an in-proc and out-of-proc model (known as "Library" and "Server" applications, respectively) as well as an annotation-based configuration scheme that will likely be similar to how EJB 3 works. (COM+ Queued Components are a bit like MDBs, and in this case, I prefer the EJB approach, but that’s neither here nor there.)

Oh, and by the way: welcome to the blogosphere, Floyd. 🙂

Spring, objects, and scalability

Keith Donald has picked up on the Floyd-and-Ted discussion, and weighs in on a few of the points that I raised. In particular, he goes into some of my assertions regarding Spring:

    I believe it is accurate to say that Spring leads developers back to an internal, in-process "objects-first" approach. I think it is wrong to say Spring encourages a "distributed-objects-first" approach, or even the use of distribution in the first place. I imagine anyone working with Spring for any length of time will back me up on this. Surely anyone who has read J2EE Design and Development by Rod Johnson…

I wish that were the case, Keith, but too often I run into developers who are of the "objects uber alles" mindset, and any technology that allows them to go back to their basic O-O principles is obviously a Good Thing. Will Spring developers suffer from this same mindset? Possibly not, but I’m not worried about the guys who learned Spring from Rod and/or his immediate camp directly. I’m more worried about the folks who pick up Spring second-hand and use it after reading a few tidbits about POJOs and such. THEY’re the ones who’re going to give Spring the bad name… because in many respects they’re the same ones who did it to EJB.

    First of all, the Spring container itself does not address the problem of distributing objects at all, period. The container has always been about providing a solution for the management of the internal structure of a software system. It is a sophisticated factory for local, in-process application objects (services) based on POJOs. This factory lets you develop the internal components of your app in a object-oriented, test-driven fashion, yes. You can easily have finer-grained strategies that execute polymorphically, you can develop in parallel and you can test in isolation. You use Spring to manage the assembly of these local components into a working system by providing it instructions about what implementations it should instantiate and how those implementations should be configured and wired. You do all of that before you even start thinking about which services you’ll export over remote transport and how you’ll export them…

ALL containers have been about providing that same solution. They manage a variety of resources on your behalf, including (but not limited to) threads, network resources, database resources, messaging resources, object lifecycle, and so on. The fact that Spring chooses to express its application code via POJOs is dangerous, moreover, because it leads people down the slippery slope that distributed object models can become. (Don’t believe me? Go re-read the Distribution chapter of Fowler’s PEAA book–it’s not just me saying this.) Fact is, Keith, YOU may think of Spring in that fashion, but that’s actually a fairly distribution-oriented way of approaching the problem, and wasn’t the point of Spring to get developers back to thinking in objects, because EJB clearly wasn’t an object-oriented system?

    Most good software developers I know care most about building business components that contribute to solving a domain-specific problem: that actually carry out business-differentiating work. With a POJO-based approach, you can focus on building and testing that core business logic first. You don’t need any container to do that–Spring or otherwise. Just give us JUnit and the new operator. We like that.

Agreed. So, then, what I hear you saying is that Spring doesn’t directly enable easier building and testing, because the focus here is for people to build POJOs and front it with… whatever. And thus the actual container into which the POJO is deployed is more or less irrelevant, yah? After all, if it’s socially acceptable for people do this for Servlets or Spring, why not for EJBs? But again, I’ll say we need to be careful here, because once again we’re approaching this via the "objects uber alles" approach, and I submit that in a number of scenarios, you can’t start with your internal data structures (which we both agree that your object model is, unless you’re advocating that it’s OK to expose that object model across processes, at which point we disagree).

    But that’s only one half of the puzzle and without mentioning the other half I’m being completely naive. You still need the ability to apply enterprise services to your POJOS as (if) needed. You may need to secure them, make them transactional, selectively export them to the server for remote access or management (perhaps over a variety of mechanisms), etc. Spring’s container, using the techniques of 1. Dependency Injection and 2. proxy-based AOP, combined with 3. its service abstractions, gives you a mechanism to do that in a externalized, decorative fashion without impacting your mainline business logic. In addition, you can execute first-level integration tests that exercise the interaction of much of this stuff without having to deploy to a full-blown J2EE container–essentially, you fail faster.

Dependency injection *only* saves a single function call, that of the JNDI lookup, and unfortunately you cannot control when the dependency gets injected, unlike in the JNDI case where you control when the dependency gets resolved. This means that if the system administrator changes the JNDI entry (yes, they can and should be able to do that, at runtime, without you knowing!), the next JNDI lookup pulls back the modified entry. When, exactly, do you ask for Spring to re-inject your dependencies? Plus, proxy-based AOP is essentially what CORBA, RMI, DCOM, and other remoting tools do already–Spring simply joins a handful of other technologies (unfortunately NOT EJB prior to 3.0) that expose that interceptor stack to you. Guys, I hate to say this, but .NET even builds this in, via ContextBoundAttribute and friends. (Frankly, doing interception really isn’t AOP, as I’ve said before, but people seem determined to take the term and co-opt it into whatever they want, so I’m about to give that up as a lost cause. Sure. Interception is AOP. Go ahead. And VB was object-oriented, too. Whatever you want.) As to the "integration tests that exercise the interaction of much of this stuff without having to deploy to a full-blown J2EE container", dude, that’s a failure of the open-source community to write an in-process EJB engine. If JBoss were embeddable (hint, hint, Marc Fleury) or if OpenEJB were more popular (hint, hint, Keith–there is one), then we could mock the EJB parts up around it and do exactly the same kind of in-proc integration testing that Spring can also do.

    As an aside: Ted, I agree with you to a point regarding API. If an object is a MessageListener, you better believe it should implement a MessageListener interface! The Spring team does not subscribe to this belief that everything in the world should be abstracted away. We believe an object’s non-core concerns are a good fit for externalization. So the API is important to us from that point of view: we don’t want our application code full of extraneous non-core concerns that clutter our main-line logic or introduce hardcoded dependencies on expensive resources. Also from an API perspective it needs to be easy to test application code in isolation: a heavyweight API that bakes in a first class dependency on a expensive-to-setup deployment environment is not acceptable.

Now you’ve lost me–an interface is good, but EJB is somehow a "first class dependency"? Dude, an interface is an interface is an interface! If you’re going to argue that JNDI or JTA/JTS is somehow that "first class dependency", then I’m afraid that I’m going to have to turn around and argue the same for MessageListener and the rest. If MessageListener is "a good fit for externalization", then I’m going to have to suggest that the SessionBean or MessageDrivenBean interfaces are the same–you can’t have your cake and eat it too. But more importantly, it *is* possible to do your testing without the heavyweight container. And let’s call that out more carefully, that the J2EE interfaces are NOT heavyweight APIs, because by definition they are interfaces, and interfaces are no more heavyweight in EJB or JMS or Servlets than Spring’s are.

    Bottom line: Spring enables a non-invasive, scalable up+down POJO-based design model and that is the major innovation that has brought agile J2EE into the mainstream.

Sorry, no. Spring is a reinvention of the EJB concept designed to run in-process, more or less a reinvention of the old JavaBeans model. It is no more scalable than the code that’s written to run inside of it (as is EJB, quite frankly), and the major design emphasis of Spring–that being the POJO and all of its object-orientedness–are a slippery slope that will, if Spring achieves the kind of mainstream deployment that EJB achieved, eventually come back to bite us all.

You cannot do a "good distributed object model", because if you build a good object model, you are creating a model which requires a great deal of cross-object communication and therefore spends a great deal of its time over the wire. If you build a good distribution model, however, you find yourself making serious compromises on your interface design, passing DTOs instead of making property-set calls and so on. The two are logically at diametrically opposite ends from one another from a design perspective.

The evilutionist site is a sham

OK, OK, enough people have pointed out to me that my earlier rant about the "evilutionist" site is a sham and a satire, that I feel morally obligated to admit that I was snookered and take my lumps accordingly. But, in true weblog fashion, I admit my guilt even as I defend my reasons for reacting so. 🙂

Why did I fall for it so completely? Because this is the direction our society (at least here in the US, can’t speak to the rest of the world) seems to be headed: a greater and greater polarization of people around specific hot-button topics that appeal to them. This in turn motivates them (because they are surrounded by people who are obviously "right-thinking people", namely, that think like they do) to act on their beliefs, in whatever fashion seems appropriate or "right", justifying it against some kind of "higher moral order". Look at the Ellie Nesler case of a number of years ago: a mother, whose son was sexually molested, watched as the molester went through his trial, and when it looked like he was going to be found innocent of the charges, she up and kills him. The community around her cheered her actions, because in their minds, the man was already guilty despite having not yet reached a legal verdict. This woman, this vigilante killer (whose motivations, I admit, I can completely understand) was hailed as a hero, because her moral beliefs happened to coincide with those of the community around her. What if those moral beliefs change to mean, "Anybody who wears a turban on their head must be Muslim and therefore must be allied with that stinkin’ Osama Bin Laden, so let’s round ’em all up and kill ’em all before they get to us!". Remember, it happened once before in this country, when we socked away the Japanese-Americans in "detainment camps" (leaving the German-Americans to mingle freely around us, despite FDR’s and Churchill’s agreement early in WWII that Germany was the greater threat). Think it couldn’t happen again?

The problem is, quite frankly, the greater communication we have worldwide, namely, the Internet. Believe me, I wouldn’t give it up for anything, but the Internet allows for widely-scattered people to congregate and spew their favorite brand of weirdness. Google for "white supremicist" sometime if you’re stomach is feeling strong to your stomach but you feel need to throw up. Or pick some equally ugly topic and just watch the links scroll across the page as your skin starts to crawl with them. Christian fundamentalists looking to find abortion doctors to kill off "in the name of God". Militia groups looking to meet and train against the day when the government steps on their "rights" too much (remember TerryTimothy McVeigh?). Anarchists who believe that the government needs to be destroyed so we can all go and leave in peace with nature in grass huts. Hell, there’s probably an activist Communist site out there still hawking the old Communist party line advocating violent overthrow of bourgeoisie governments. And so on, and so on, and so on.

And for that reason, I bought into the hoax, hook, line, and sinker, because to me, it’s entirely too credible that there would be a group motivated to try and shift the material taught in schools to something that’s more "right-thinking", in their mind, and the best way to do it is (still) spin the topic.

Look, this is a sensitive issue for me, particularly the material taught in schools; kids are wide-open sponges, with no filters installed, ready to absorb whatever is fed to them. And once they leave for kindergarten (home-schoolers aside), they spend more time in the company of their teachers–and the approved school curriculum–than they do their parents or family. (Which reminds me–when’s the last time you took a look at your kids’ history books? Or their reading materials lists? When’s the last time you looked into that curriculum at all?) What the school teaches them is what they will believe, until such time that they’re able to form their own opinions (assuming their schools teach critical-thinking skills at all, which some don’t). It’s our responsibility as parents and citizens to protect the material in schools from becoming politicized. If not, we risk being torn into lots of little groups that viciously cling to half-formed half-baked ideals that lead us into stupid conflict, and there’s so much we could do together if we just learned to respect others’ ideas and opinions. But that’s not going to happen if we don’t actively seek to protect against the politicization of school materials.

And that’s all I have to say about that. Next couple of posts will be technical in nature, I swear. 🙂

Update: … and if any Java or .NET commenter DARES to suggest this or this as an example of that polarization of "right-thinking people" into a rabid political action group, I swear, I will do something truly nasty to you…. 🙂

Further update: Typos corrected. 🙂