Quantcast
Channel: code – getiblog
Viewing all articles
Browse latest Browse all 3

Teaching: Convergence and Divergence

$
0
0

This post isn’t about JS code. It’s observations about the goals we have when we teach JS development (and really any programming language).

By teaching, I don’t mean only when you’re standing in a classroom with students. I mean all teaching / advocacy, like when you tweet a “protip”, or write a blog post about some dev pattern, or write a book, or give a meetup or conf talk, or a “brown bag lunch” at work, or a code review, or …

In all these ways, we teach others things about ways we think they should and shouldn’t write code.

A good friend of mind recently pointed out to me that you can’t properly talk about how effective (or quality or suitable) something is for a certain task until you define the purpose/goal. So it got me thinking: what are my purposes/goals when I teach JS, and what about for other teachers I’ve observed.

It occurs to me that these purposes/goals can fall into two buckets: convergence and divergence.

Convergence

Converge: “gradually change so as to become similar or develop something in common.”

At first glance, you’re probably going to assume that convergence is the more virtuous of the two categories.

We’re all familiar with the idea that “best practices” tend to lead to a general increase in the quality of code. By propagating a set of well-tested, battle-hardened, broadly accepted approaches to code, we create a sort of “shared vocabulary” that improves communication across all sorts of boundaries.

For example, one of the value propositions of frameworks is that they create clearly paved cowpaths that make it easy for new developers to learn a smaller set of “right ways” to do things, and then also make it easy to add developers to an existing team without significantly re-teaching them to get them up to speed.

Shared wisdom avoids wheel reinventing. If an approach has helped many developers before to avoid common pitfalls, your chances of using that same approach and getting similar positive results is high. All boats rise with the tide, right?

Convergence Breeds Familiarity

Let’s talk about code readability for a moment. Code readability is often asserted as being heavily subjective opinion. But that’s not a unanimous position.

Researchers have studied (PDF) if the idea of automating a metric for code readability is practical. At first glance, I didn’t even think such a thing would be possible. But I found the read to be fascinating.

One of the interesting take-aways for me from their study is that the most impactful characteristic that led to participants rating code as readable was familiarity. The more familiar the code looked to what they’d seen before, the more readable it was.

Convergence reinforces familiarity. The more we all agree on how to do something, the more times we’ll see that thing, and the more times we see it, the easier it will be to read, and write again the next time.

Some frameworks embody the convention over configuration mindset for exactly this reason; we establish conventions and we repeat them over and over, and that makes it easier to keep building. Some even suggest that languages should have only one way to do any operation, because the more different ways there are to do it, the more someone has to learn to gain familiarity for readability sake.

Convergence Improves Efficiency

I bet the team of developers you work with has a style guide, and I bet you all use a specific framework for your application. I also bet that most of you use the same set of tools (editors, browsers, etc), and maybe even the same machines and OSs.

These are pretty good bets because it seems pretty obvious that the way we get a team to work most effectively together is through homogeneity. It’s far easier to fix issues if the environment is consistent, so we can eliminate most of the potential sources of the problem before we start.

Shared configurations mean that developers can interoperate and communicate better. Pairing is easier when the code looks exactly the same regardless of what workstation you’re at. Tests are easier to write, and later audit, when the code being tested has a narrower set of paths to consider.

I’ve even taught before in my classes, many times: the easiest way to spot when bad code (bugs) are being introduced is if everyone agrees on the right ways to do things so that the bad stuff stands out more obviously.

This is all entirely pragmatic and understandable. We all just want to get shit done. We want to ship features faster so our bosses and clients are happier, and we keep getting paid. Whatever helps us do that, sign us up.

A few years from now, some smart group of folks is going to reinvent all these “best practices” with some new platform or framework or build process or acronym, and at that time we’ll all move with the crowd. But for now, things are safest and most efficient if we just churn on what’s working immediately in front of us.

It seems no matter how we slice things, convergence makes our lives easier.

Local Maximum

The most obvious problem with convergence is that we can all end up converging on a maximum that’s only locally a maximum, while missing out on a nearby maximum that’s much better.

If you’re not familiar with this idea of local and global maximums, consider this diagram:

If most people accidentally end up gravitating to that local maximum, probably because someone particularly popular did it first and others were just pulled in as a result, we all might not even notice that we missed out on something that could well have been better.

“Not really a big deal”, I hear some of you thinking right now. “A bird in the hand is better than two in the bush.” The standard we have all agreed upon is better than the standard we could have agreed upon had things played out different. The fact is, it’s the one we have, it’s good enough, and changing to a new standard has heavy switching costs that probably aren’t worth it.

We’re not actually sure that the switch wouldn’t be worth it. We can’t accurately gauge how much better that other maximum could be unless we made the switch.

This effect produces a “gravity” that keeps us near the local maximum, because the farther we stray away, the more risky and time consuming those explorations get.

Convergence Produces Dogma

There’s something interesting about our collective psychology as developers. When we see others flocking to a common centralized set of practices, we’re very tempted to draw near to them too, and then become prohibitively unwilling to break off and explore, or let others around us do so.

It’d be nice if this were true:

But how commonly practiced is this view? I know we’d all like to claim this maturity and level-headedness, but in reality, I’m not so sure we see much evidence. Let’s just be honest.

Even if you are someone who feels confident enough to break out of best practices after learning them first, you probably think of it as a “necessary evil” rather than an ideal. The “best practice” is the rule, and any other path(s) are the exception, right? You may break those rules from time to time, but you certainly teach others that they’re better off, the vast majority of the time, sticking with the pack.

Have you ever stopped to consider how elitist this sounds, to a new learner? Do as I say, not as I do, because you don’t know enough yet to do as I do.

It produces a tone in our industry that encourages convergence and adherence, and disapproves, even if smirkingly, at those who color outside the lines.

And besides, if your overall ethic is that “what’s best for the majority is best for everyone”, then of course you’re going to treat movements away from the convergence as less preferable. You’ll spend the majority of your effort and energy on your staying power, and any of your explorations will get far less of your time and attention.

It’s not enough that you academically claim “use common sense” in a tweet, if in practice the overwhelming majority of the messages that learners receive are pushing them towards the center. I bet you’ve defended your own “common sense” breaking of best practice before, but when was the last time you concretely praised or encouraged someone else doing so, not just abstractly nodding at such virtues?

Anti-Convergence

Those who know me know I have a pretty well-established pattern of swimming upstream. I regularly post or tweet about things which go off the well-tread beaten path into other possible ways of thinking about things.

When I do so, I have a pretty clear expectation of what I’m going to get in response. Those with similar or more experience than me almost always disagree or push back. Those who follow me with less experience than I have are equally likely to be in one of two groups. One group will simply echo what they’ve heard from others, which is to say they’ll disagree-by-proxy.

The other group, the smallest of them, is the group of developers who’ll be intrigued that I presented a new way of thinking. They may very well end up disagreeing, but they don’t criticize me for the exploration. They debate and discuss and explore, too.

If I was newer to this industry, with thinner skin, it’d be far too easy for me learn that if I don’t want to get scolded by others, I should just fall in line. If 90% of the people I encounter will dislike such explorations, that remaining 10% supporting group is not enough to overcome.

My experiences may just come from the fact that I’m seen sometimes as harsh and stubborn. People may just disagree with me systemically because they have to tear down the wall of dogma they think I’ve built up to even get a point across. It might just be that I can be seen as an asshole when I challenge and question and push back on the crowd. Nobody wants to follow what an asshole says, even if he might have a good point.

And let’s be honest, I’m not particularly adept at making people feel good in their debates with me. I have strong opinions, and I hold them pretty strongly. I’m more an obstruction than a facilitator.

But I think this is bigger than myself. Far bigger. I think it’s about our industry, not about individual personalities and conflicts.

Convergence is a force that acts for good in many respects, but the downside is that it’s a mindset that tends to nourish a sense of threat when any non-convergence crops up.

When you teach others, what are you teaching and why are you teaching it? Are you teaching others to fall in line with the crowd, or are you teaching others to think for themselves? Since the answer is probably inevitably “both”, how exactly are you figuring out how to balance?

Divergence

Divergence generally sounds like the opposite of convergence. But it’s much more than that. If convergence is all movements toward a single target, divergence is more than just movements away from a single source.

Divergent: “using a variety of premises, especially unfamiliar premises, as bases for inference, and avoiding common limiting assumptions in making deductions.”

Divergence is not merely moving in the opposite direction of convergence, but rather starting in different place(s), and moving in many different directions at once. As such, its value propositions, its pros/cons, are not strictly opposite of those in convergence. This bears more analysis, too.

Let’s start with the obvious bad stuff.

Divergence Wastes Effort

If a developer on your team came up to you and said, “Ya know, I think a feature like goto would really create better code…”, how would you respond?

Good chance most of you collectively laughed, cried, sighed or rolled your eyes. Come on. We’ve already fully explored the perils of that thinking. The vast majority of us now willingly accept that goto is one of the deep evils of programming, in terms of creating hard to follow code. There’s no question that it’s sometimes convenient, but as they say, the “road to hell is wide and paved with gold.” The convenience purchased is not worth the cost.

We don’t need to waste effort rethinking this stuff. Enough smart people have already thought all these thoughts, and their conclusions are so unanimous now that they might as well be law: Never use goto.

Nothing is more frustrating that seeing a developer rediscover all those same mistakes and conclusions, and wasting your team’s time to do it. We don’t need your divergent thoughts here, friend.

Wisdom is learning from the mistakes (and successes) of others. Divergence from the common norms in programming is just throwing away all that experience and making all the same mistakes, again and again.

Besides, “there’s nothing new under the sun.” You’re not going to suddenly discover the amazing untold narrative of how goto is the missing cornerstone of our code. If there was merit there, one of our many smart developer ancestors would have found it.

Divergence Costs Efficiency

Every time the development team has to learn a new way of doing things, that costs a lot of time and effort. And even more than that, the complexity will keep costing over time, as there’s more places for bugs, more places for misunderstandings, more test variations needed, etc.

Divergence generally means that there won’t be one right way of doing any thing, but could at any moment be many acceptable ways. That means it’ll be harder to spot when someone does something dumb, because it might just be they’re using some “new” smart pattern you haven’t seen yet. It’ll take a lot more time and effort and mental focus to separate the good from the bad.

Divergence Bounces Between Local Maximums

If you’re stuck in a rut, it’s going to take some serious rethinking to break out of it. You’re going to need some divergent thinking that moves away from the crowd if you’re going to find a newer and better way of doing things.

Unfortunately, it’s impossible to predict, until you fully get there, whether the new maximum you find is truly better than the old one you left. You may spend a lot of effort switching, and end up with basically the same overall quality (for whatever metrics you use to measure that).

It’s possible you may indeed arrive at another local maximum, and not actually at the best global maximum.

Divergent Noise

Constantly questioning the status quo produces an awful lot of unnecessary noise. That noise distracts us from what we need to be focusing on to get our jobs done. That noise causes us to miss the important signal hidden in the churn.

Ever had that developer on your team, who all they ever seem to do is question and push back? Annoying, right? Teams need team players. Teams need people to fall in line with the consensus direction and support everyone getting to their most productive.

No football team wants, or would tolerate, the running back arguing in the huddle that a different play should be run. The coach and/or the quarterback made the call. Run the play. Do your job.

Divergence Can Be A Dogma, Too

Sometimes, doesn’t it seem like those who challenge the status quo only do so as a matter of habit, for the sake of debate, or just for attention?

In a sense, there’s a dogma here, too. A dangerous one. The dogma that the status quo must be wrong, because whatever the crowd settled on must be sub-optimal. Divergent thinkers obstruct sometimes for seemingly no other reason than to stop reinforcing that which is already the accepted standard. In other words, they may not know what path we ought to take, but they definitely know the path we’ve been taking isn’t good enough.

Divergent thinking sometimes also leads to splitting hairs on semantics. You’ve seen this before, haven’t you? When the argument becomes about the words in the argument, rather than the topic? Divergent thinkers also annoyingly tend to introduce new, sometimes nuanced, meanings for words we all thought we commonly understood.

Dogma is dangerous just like most -isms are dangerous: when the bigger principle at play becomes more focused on than the people or things that make it up. Dogma moves from pushing back on an issue on its merits to pushing back on all issues on some principle. Religions and politics and many other areas of life exhibit these undesirable, and moreover unhelpful, patterns of interaction.

One thing we can all agree on: we don’t need more dogmatic obstructionists. No thanks. Move along.

But, Divergence Fights Dogma

The interesting thing is that divergence can also be a force for good. Divergence can sometimes slap us enough to wake up from our dogma-induced slumber and realize the things we glossed over before.

It’s not necessary that divergence goes overboard in the ways we’ve just looked at. Sometimes divergence is actually a force for conservatism, drawing back to fewer assumptions than we are typically extended to. Divergence can suggest that some of our typical assumptions should be re-tested.

Instead of thinking of divergence as looking for entirely different paths, sometimes it’s just asking us to pull back from our dogma of assumption and re-examine where we’ve already walked. Maybe we missed something, maybe we didn’t. But certainly it can’t hurt, from time to time, to just take a look, right?

That’s a level-headed and conservative brand of divergence. It’s anti-dogma. Or it’s the dogma of no-dogma. Or something like that.

Divergence Promotes Creativity

Have you ever seen a solution to a problem that ended up being the negation of solving the opposite problem?

For example, consider the problem of trying to figure out if two rectangles overlap. Thinking about the four corner points of each rectangle, there are quite a few different configurations where they could overlap (one being entirely inside the other, or overlapping only one side, or two sides and a corner, etc).

Convergence tells us to solve the problem at hand. Divergence wonders if maybe there’s a different problem that’s easier to solve and maybe that solution can answer our question?

So, it’s well known that another way of testing if two rectangles overlap is testing if they don’t overlap and then negating the result. The question of if they don’t overlap is actually much easier to express. For example, the right-hand side of a rectangle being less than the left-hand side of the other, means no matter what else, they don’t overlap. There’s fewer cases (only four) to consider here. The negation of this solution gives the solution to the other.

Divergence Finds Other (Better) Maximums

It’s true what we said earlier, about the risk of just finding other maximums that aren’t actually reasonably better.

But what’s equally true is that convergence never, ever, ever finds other maximums. You don’t stumble upon another maximum while headed toward the one where the crowds are.

So your only hope of finding something better is if you take on a divergent mindset, at least occasionally.

Remember, divergence doesn’t mean going in the opposite direction of convergence. It doesn’t mean just starting where you’re already converged and going outward or backward. It actually means starting in an entirely different location, and going in some other direction.

Mathematically speaking, you have a statistically higher chance of finding a global maximum more quickly through these divergent techniques than through purely convergent techniques.

Ever heard of the “traveling salesman” problem? The problem is known as “np-complete”, that it’s too hard (takes too long) to calculate the actual best answer brute-force (for sufficient problem sizes). So we have to develop other practices, algorithms, for trying to “find” the solution.

One class of these algorithms is called “hill climbers”. Think about the curves of that graph above as hills on a mountain range line, where the minimums are valleys and the maximums are mountain tops. If one climber cannot climb and descend all hills, how do we find which mountain is tallest? We drop a bunch of climbers in random places (divergence) and have them all try to converge on their nearest maximums. If we drop enough climbers and have a good enough spread of them, we’re pretty well assured that at least one of them will find the highest peak.

It’s possible in that scenario, most of our climbers will converge on one peak that’s pretty good, and only one lucky/unlucky climber will be an outlier enough to have found the global maximum.

Convergence From Divergence

Let’s try to draw this down to some sort of take-away. Remember, I started the beginning of the post talking about what goals/purposes we have for the things we teach others (in all various ways).

Am I suggesting our goals for what we teach should be to encourage all/mostly convergent “best practices”? Yes and no. Am I suggesting our goals should be to encourage divergent, creative, out-of-the-box thinking? Yes and no.

Let’s ask ourselves: if this climbing metaphor above represents us finding, and ultimately teaching, best solutions or best practices as developers, which climbers provided the most value in that effort?

We needed climbers which converged and didn’t just randomly run around changing directions willy-nilly. But we also need a better practice of distributing our climbers — not just talking about divergence but actually doing it — where we encourage and challenge members of our team to start from sometimes wildly different places.

Bottom line: we need to be strategic about our divergence (distribution of thought and assumption) and tactical about our convergence (seeking to build consensus for pragmatic reasons).

I’m serious about teaching. It’s an obsession. How we act as developers is teaching other developers who are watching us. When I question the status quo, and push back on the crowd and hype, I’m doing so because I think we need to drop climbers in other places and look for new mountains to converge on.

I hope you’ll be brave enough and disciplined enough to do the same with your own mountains.


Viewing all articles
Browse latest Browse all 3

Latest Images

Trending Articles





Latest Images