Connect 4 – illustration of Matrix rotation in js

Once in an interview, I was asked to determine whether a somewhat filled in connect 4 board has a winner. Here’s an elegant solution using an arbitrary rotation function: Rotate the board 0°, 45°, 90°, 135°, and check for 4 in a row in each of those rotations.

Since I couldn’t find a good rotation solution online I decided to post a solution here (javascript):

var _ = require('underscore');

var rotateArray = function(array, degrees) {
    var radians = degrees * Math.PI / 180;
    var round = (f=>parseFloat(f.toFixed(13)));
    var coordinates = _.flatten(array.map((row,y) => row.map((value,x)=>({value,x,y}))));
    var translatedCoordinates = coordinates.map(spot=>({value: spot.value, x: round(spot.x*Math.cos(radians) - spot.y*Math.sin(radians)), y: round(spot.x*Math.sin(radians) + spot.y* Math.cos(radians)) }))
    var rows = _.chain(translatedCoordinates).groupBy(x=>x.y).values().sortBy(x=>parseFloat(x[0].y)).value();
    return rows.map(x=>_.pluck(x,"value"));
}

var hasFourInRow = function(array){
    var vectors = [0, 45, 90, 135];
    var matrixToString = (m => (m.map(r=>r.join("")).join("\n")));
    var versions = vectors.map(degrees => rotateArray(array, degrees)).map(matrixToString);
    return _.any(versions,(b=>b.indexOf("****")!==-1));
}

And to illustrate the use, here’s sample test cases:


var testCases = function(){
    var win1 = [['*','*','*','*'],
                [' ',' ',' ',' '],
                [' ',' ',' ',' '],
                [' ',' ',' ',' ']];
    var win2 = [['*',' ',' ',' '],
                ['*',' ',' ',' '],
                ['*',' ',' ',' '],
                ['*',' ',' ',' ']];
    var win3 = [['*',' ',' ',' '],
                [' ','*',' ',' '],
                [' ',' ','*',' '],
                [' ',' ',' ','*']];
    var win4 = [[' ',' ',' ','*'],
                [' ',' ','*',' '],
                [' ','*',' ',' '],
                ['*',' ',' ',' ']];
    var lose1 = [['*','*','*',' '],
                 ['*',' ','*','*'],
                 [' ','*','*','*'],
                 ['*','*',' ','*']];

    console.log([win1,win2,win3,win4, lose1].map(hasFourInRow));
    //outputs true, true, true, true, false
}

testCases();

Stories, and Meaning [at work]

Tl; Dr: All people are motivated by meaning of their work. The ability to shape the “stories” that we tell ourselves gives meaning and thus is an essential motivational tool. This meaning is also key for personal satisfaction.

Let’s consider a standard engineer. There are a lot of “outlooks” this engineer might have. I’ll go over 5 out of thousands of possibilities just to illustrate some variety:

  • I’m the star engineer here, and I’ll turn this place around. Others might not quite see it yet, but it’s only a matter of time.
  • I’m a great engineer but nobody appreciates my work. How come that other engineer got promoted, I don’t think their work is as good as mine. I should run the company, the CEO is only CEO because he has blue-blood 1% investor friends. The world is rigged against me.
  • I’m so excited to be an engineer. I earn multiple times the median household income and I get perks too, while my other friends are still paying off their college debt.
  • Work’s good. It’s just a job though.
  • Why am I always the one under pressure? Nobody ever thanks me no matter how hard I work. Why do I get mistreated? I’m such a victim. It’s not right.

What I’m proposing is that the same engineer having the same experiences could retell that same experience in any of the ways I listed above.

In fact, you’ll find that a lot of people gravitate towards common narratives. I have a friend, let’s call him Fry who always sees the same story: The big guy is mistreating the little guy. One thing I learned quickly was that he liked and actively chooses (if not entirely consciously) to see the world in these terms. And if I want his help, I can motivate him by giving him a rebel story he can play a part in.

For example, if I’m trying to create a new tool, I could tell it in a way that plays up the opposition, especially if it’s an entrenched “senior” group that’s cautious about new ideas, and it’ll make him want to help.

Everybody has a narrative or two that resonates with them. I have another coworker, Bender, who always promotes the story: People are stupid. I know not to try to change his story, because it’s a choice and likely inspired by some very frustrating life experience (I imagine those frustrations are valid, albeit rather long-lived). If I need him on a PR I can ask it in a way that implies I need his expertise. That way he act can out his fantasy of undoing the damage of incompetent/indifferent through the act of improving my code. A win/win.

Sometimes these narratives are just plain counterproductive. I can think of experiences when teammates were annoyed that some “undeserving” party “stole credit.” In these situations you can try to rewrite the narrative, though it takes a certain skill. One way to accomplish this is to bring up an opposing narrative like, “Yeah so his name was mentioned in a meeting big deal… I don’t do great work so some manager can mention my name, I do it because there are literally millions of users who are experiencing what I make and I think I’m lucky to be able to be in a position to help so many people. That’s something I can be proud of.” [And as an aside their is no duplicity in this. It is our choice whether to aim to “do good” or to accrue material. Each philosophy has its upsides.]

And the fact that people are choosing to live these stories is an important fact. For a long time, I would have thought doing this type of thing was “manipulative” or “tricking” people into work when I could instead explain to them why their underlying narrative was too black&white. But knowing that these narratives are choices, with symbolic importance, that give meaning to the individual who holds them, I see now that people choose to live these stories hoping to “play them out.”

And most importantly, we all have narratives. Mastering other peoples narratives is a great tool, but mastering your own is probably more important.

———

Part 2.

If you’re a leader in an organization, you need to be aware of the stories that occupy the minds you oversee. Do people see themselves as battling each other for recognition? Do they see themselves as allies against a great evil? Do they see themselves as victims of your rule?

People within the company all have their narratives, and those attitudes are contagious. Your actions will have a great role in deciding which attitude wins out.

I’ve seen organizations torn apart by leaders who were out-of-touch with the effects of their actions. The cultural effects you have are of supreme importance. Actions like requiring engineers start an hour earlier, for example, are incredibly dangerous, because they give room for the narrative “We are seen as code monkeys” to thrive.

To win this battle you must understand the narratives that you are battling against. You must truly understand them, you must know and appreciate the day-to-day of your workers. For example, you must know that your Office Manager Lela is frustrated, sleep-deprived, is wondering where her life is going, and is starting to feel like the “manager” in her title is meaningless. When you know the people you work with you’ll know what stories are compelling to them. When you understand, you will be capable of offering the service of arming them with a better story, a brighter story, a more compelling story. Because as bad as Lela’s life is, it’s better for everyone if she feels like her work matters at the end of the day.

This is your value.

The Professional Web Codebase

One of the major advantages of the high career mobility in SF … Cross pollination. Yet each new codebase I comes to seems to lack a few of the following. So I figured I’d list out the essentials that every web codebase should have.

  1. The Obvious: Git, IDE, MV*, relational DB, 3 environments that match production.
  2. Language regularization:Each language has its own idiosyncrasies. Learn your languages weakness and make helper functions to accommodate. In PHP, these weaknesses include single-threaded, bad undefined index default behavior.My preferred solution to PHP’s single-threaded limitations is to make use of a job queue. This will emulate additional threads for heavy tasks (e.g. sending emails to all of your user base) or high-latency tasks that ideally should be asynchronous (e.g. certain API calls). I’ve seen this done well, and I’ve seen it done poorly. From experience, I’d point out the following lessons: don’t use a message queue as a job queue and the DB is a great place to store a home-grown job queue [because it provides great visibility, resilience, can be controlled programatically, can be exported to disk, is atomic, etc].

    In PHP, out-of-bound reads on arrays return null and log a notification to the event log. As this is never the engineer’s intent, I always write two helper functions. One that looks up an key and returns a specific value if the key isn’t found (for cases where you’re using the array as a set). The other function looks up the key and returns an exception if the key is not found (for normal cases where the key should always be present).

    I strongly believe once you handle these edge cases most popular languages are pretty interchangeable (javascript, java, php, python, ruby).

  3. A powerful, generic staging environmentOne of the most impressive and useful technologies I saw was something we called humblebrag. It was a script that caught all requests to *.company.com/…. It then took the *, checked-out the corresponding git branch, and mapped the request to that particular branch. Thus in effect, we had a zero-effort way to have all branches usable simultaneously on a single server, even by non-engineers.Doing this can be a little harder in more complex environments with versioned services listening on ports, if you don’t plan for it early.
  4. A circuit breaker. Download one from github.
  5. An ability to do cross-server mutexes.
  6. A simple, generic read-through-caching function.
  7. A powerful logging system connected to an alerting system
  8. An A/B test system. Even if you’re not doing A/B tests on user-experience, it can be a great way to rollout to a small portion of users or internal-testers to ensure stability on a new environment.

 

 

Understanding engineers by understanding authors

I’ve written before about the challenge it can be for non-engineers to understand engineering work. I’m not the the first to observe that the non-technical need a metaphor to understand invisible and often abstract output an engineer creates. Traditionally, that metaphor has been physical engineering/construction. Others have already, and rightly, criticized the physical labor metaphor.

Instead of ridiculing the wrong metaphor, I offer a substitute. I posit this: To understand engineers, think of them like writers.

to understand engineers, think of them like writers.

Why is this a good analogy? It explains several aspects about engineering that otherwise seem downright unreasonable.

  1. Emotional attachment to work
    Like an author, many engineers see a work project as an opportunity to exercise their creativity and build something the take pride in. Like an author, engineers develop a sense of owning what they create. If the project gets cancelled, handed-off, or drastically changed (especially without notice), compromising their artistic vision, the engineer may experience frustration. But this is natural, how would an author feel in such situations?
  2. Difficulty in measuring progress and estimation.
    If software were physical construction, it might be reasonable to have an easily-predictable timeline. One might confidently answer “how far along are we?” But like writing, and unlike construction, everything one makes in software is new. And like writing, progress can’t merely be measured in the amount typed, refinement and reduction are actually an important and lengthy part of the process.
  3. Ambiguity and subjectivity of excellence
    Every week somebody writes a blog post on how to find out in an interview who’s a good engineer. And every week it gets (rightly) torn to pieces by commentators. The fact of the matter is that there are many independent components that comprise engineering talent and measuring them is very difficult. Even among the very best stylistic difference might mean two greats may not appreciate each others’ virtues, like Faulkner and Hemmingway.
  4. Challenges of collaboration
    And on that note, collaborating can be hard. Like writing, there are an indeterminate number of ways to write software, but each engineer has a style. I can tell you from personal experience that writing software with other people is hardBoth want a sense of ownership and freedom to express their creativity, but must now answer to the confines of the project itself as well as their partner (or team’s) creation. Imagine a group of professional writers trying to work together, of varying cultures, varying talents, varying dispositions, and varying skill-levels. With no objective answer to many issues, engineers reviewing one another’s code is a touchy topic.
  5. A need for freedom
    As a creative endeavor, software’s workflow can be unpredictable. A creative solution may come at any moment, often in the shower or a dream. Sometimes, when all the factors align, answers comes pouring out at a great pace. During such times, the absolute worst thing that could happen would be an interruption (or a required meeting). Compromising on artistic process will compromise the product.
  6. It’s not work
    One of the most persistent and most damaging misunderstandings I have witnessed is the erroneous perception that engineers will avoid work if they can “get away with it.” Perhaps those who feel this way think of engineering as labor, as if it were physical construction. But writing code, like other writing, is a passion that cannot be avoided. When I go on vacation from work I always end up recreationally writing code within a week. I can’t generalize for every engineer, nor every project. Like a writer, if an engineer really doesn’t believe in her work for moral reasons or is so constrained she has no space for creativity then she may lose motivation.
  7. Can we rewrite?
    Another commonality is that due to stylistic differences, every individual prefers their own way of writing things. (And to be clear, in software there is a lot of room for styles, styles that are often so unique that one can often tell who wrote code just by reading it). Each considers her own style clearer, cleaner, or better; often because it aligns so directly with her own thought process. Learning to compromise on this a key skill.
  8. Some produce more than 10 times another
    Is there any number of E.L. James that could produce the Great Gatsby? For specialized work (e.g. advanced problem solving, revolutionary user experiences) there’s just no substitute for a prodigy. On the other hand, if what you’re making is the software equivalent of a gossip magazine, having Shakespeare on your team might actually be a recipe for failure.

I want it to be clear that I’m not saying all engineers automatically deserve to have any project that they work on adapted to conform to their artistic whims. I am advising all to be sensitive to the pride and passion that people put into work.

But most of all I’m trying to help people understand engineers. It can be hard to relate to an engineer who expresses slight negativity about meetings, blows off people who check-in on them, never knows how long their work will take, doesn’t like standard schedules, might prefer to work alone, gets disappointed when their work is shifted, or thinks they’re amazing. So if you care to understand and relate, I’ve given you the tools.

Select vignettes of a tech company

Underneath the “machine” of an engineering company is ultimately emotions. I’ve selected a few vignettes I think most engineers could relate to that highlight common themes of misunderstanding in software engineering.

  • Thinking to motivate people, an executive names a select employee for an award. One employee gets motivated, the rest get demotivated
  • Eager to prove his place a product owner fantasizes about his project that will prove him great like his idol, Steve Jobs. When talking to his team about his product he patiently listens through their objections before ignoring their opinions and making proceeding with his initial plan. The rest of the team no longer feels like this project is a good outlet for personal creativity (since their input gets ignored) and withdraws.
    [This exact same behavior is done just as much by engineers who are equally prone to wanting to take full control of a project]
  • A manager picks an employee who’s already been labeled as a “problem,” and decides to prove they can turn the situation around. The manager gets increasingly involved with day-to-day decisions of the engineer suspecting it will force the engineer to work harder. The engineer, who’s just as likely to be as good as any other engineer, then comes to resent the manager at a personal level, to see treatment as inhumane, and refuses on principal to participate with the tactics. One of the two, and not too unusually both, get fired.
  • Seeking to engage with engineers a manager tries to have a conversation about a project. Bringing up, “firing on all cylinders,” “endzone,” “deliverables,” and “grand slams.” Having no interest in cars, football, or baseball (nor analogies for that matter) engineer gets a sense the person he’s talking to couldn’t ever understand him.
  • Manager wants to present an air of knowing, so pretends to understand things he does not, and honestly could not. His direct reports immediately pick up on this and lose respect for him. Nonetheless they are patient and respectful to his face.
  • Blindly mimicking the culture of management, a manager refers to Sally as a “resource.” With this analogy material resource manager encourages his tendency to think of engineers as fungible. Also, Sally  now hates this manager guy who keeps objectifying her!
  • Seeking to create an objective way to numerically rank candidates and assign bonuses, a 360 review process is put into place. Immediately friends give each other great scores.

All unfortunate situations.

Disclaimer: none of these are inspired by employers past nor present.

Solving rush-hour

For those who’ve been inspired by last programming challenge, I thought I’d give annotations on a programming exercise I’ve created.

The challenge: code an AI to solve Rush Hour, you can play Rush Hour online if you aren’t familiar with how the game works. If you want to follow along, you can find my solution on github.

The game of Rush Hour
The game of Rush Hour(tm) – The objective is to get the red car to the exit. The above picture illustrates one possible board.

Let me start with the high-level thought process.

How to solve it?

The most naive approach is a brute-force solution, trying every move, filtering out backtracking. Some simple math will let us rule this possibility in or out.

The only state in Rush Hour the positions of the cars. Thus the number of possible game states is equal to the number of possible arrangements of cars. We can approximate an upper bound of the latter by multiplying the number of possible spaces each car could move to (this ignores cars being on top of each other, hence upper-bound). In the above board we see 8 vehicles, and each vehicle can only ever occupy 4 or 5 squares [they can’t turn ever] depending if their size). Some boards have more vehicles, so if we estimate 10 vehicles at 5 positions that’s 5^10 < 10 million.  So yes, brute force is in.

The general solution:

Because “brute force” is such a general mechanism, there really is a lot of reusable code in the solution. In my solution I’ve pulled out the reusable logic into genericSearch.js. The idea is that a whole host of puzzles follow the same form: Given an Initial state try to get to End State.

The docblock below is the interface to genericSearch that is used by the solver, but this same search function could be used by any number of puzzles (triangle peg game, sudoku, etc).

Screenshot_2
Any brute-force can be represented with only these params.

Thus, to write the program (after having written genericSearch.js) all I must do is to make those 5 parameters [and any helpers to go along].

Initial state – Brain Dead Simple

I know a lot of engineers who would be tempted to represent the game of rush hour with at least a half dozen classes (“so we have vehicle base class, which has car or truck subclasses, and we’d need a class for the board and legal moves”).

And that is a valid way to go about it. I went with a minimalist solution– a nested array 36 characters. Brain dead simple.

 

 

 

It seems that perfection is attained, not when there is nothing more to add, but when there is nothing more to take away. — Antoine de Saint Exupéry

Because every car is at least 2 in size, this string notation suffices to convey both the position and bearing of vehicles, everything we need. Since the exit is always in the same spot, that needn’t be represented in state. Adjacent characters of the same value represent the same car.

We have our first parameter, initial state. However, we have skimped in our state, by not defining what a vehicle is or orientation in the state object we’ll have to define that logic later.

Some of the advantages of representing the board state as an array of characters:

  • It’s trivial to serialize. Serialization is key to making sure we don’t backtrack when searching for solutions.
  • It’s very easy to input.
  • It’s very easy to output and debug. At the end to see the solution found I can simply “play” the states and watch the characters move.
  • At any given moment it’s trivial to determine if a space is vacant of any vehicles.
  • Certain impossible board-states are prevented automatically (e.g. a misconfigured initial state could not result in overlapping vehicles).

Some of the disadvantages:

  • We must determine every car on the board and which direction it’s facing. This is non-trivial (let’s call “trivial” something that I code correctly on my first try).
  • Moving a vehicle is kind of “dirty.” By moving vehicles by overwriting the board state it’d be easy make bugs that create weird board states (vehicle with size one).
  • Certain impossible board-states are prevented automatically (e.g. a misconfigured board state could not result in a vehicle with no bearing)
Parameter 2 – Possible moves

Each vehicle may move forward, or backward (assuming its path is unobstructed). To keep things simple, we can say a vehicle can only move 1 square at a time and represent longer travels as multiple moves.

Get all possible moves from this state
Get all possible moves from this state

This definition introduces a few more functions (getVehicles, canGoForward, canGoBackward), which I won’t put into the post. See the full code for that. The reason I exclude them is because I don’t have any particularly elegant solution to those tasks.

Parameter 3 – Apply move

Again I have no magic to work on this one so I won’t show the 15 lines. In fact, it feels like the least dry piece of the code to me, and it makes me want to refactor the most. The number of occurrences of -1 are too numerous (6) and speak to casual coding.

So don’t get me wrong, I don’t want to say anybody should hold this code up as an amazing example of good code. What I hoped to illustrate is how a problem that seems daunting can actually be broken down into 19 functions, the longest being 23 lines.

The Gimmes

I have two functions left. One is how to uniquely represent the state as a string. The other is win condition. The former is easy: JSON.stringify. The latter is easy as well.

Screenshot_6

And we’re done! Now I’ve left our the genericSearch.js, which honestly was perhaps the most fun, but this post is long enough. If your thirst isn’t quenched try playing around with it yourself.

Takeaways
  • Keep the pure & reusable code in a separate file (or separate function) from your 1-time, implementation-dependent code
  • Maybe 2 classes would have come in handy. Despite being small, the code doesn’t seem as friendly as I’d want. If I had kept state as an object of objects I would never have to define string -> state mapping.
  • Unit tests would have been a good way to allow such a refactoring to be less painful.

Don’t be an Architecture Hipster – A guide

One of my more popular HN comments was a teardown of an all-too-common engineering subculture. The article in question sought to teach “Software Architecture,” but ultimately annoyed me and many other HN readers.

Tl; dr:
Software architecture discussions are so polluted by software-hipsters that the majority of software engineers are disinclined to discuss and study architecture at all.

Know-it-all / hipster

  • Probably studied philosophy, english, film-studies, or engineering.
  • Lurks around discussions, hoping to overhear a mistake, any mistake. 
  • Uses an unnecessarily complex vocabulary
  • Has a self-righteous and loud tone of voice, especially when correcting people.
  • Enjoys correcting people, even on minor/irrelevant points.
  • If asked him a question you can be sure of two things:
    1) he will never admit he doesn’t know
    2) he will answer with so many niche terms that you will end up more confused than when you began
  • He may be likened to Dwight Shrute, or the comic-book guy.

Architecture  Hipster

  • Loves UML making diagrams. Gladly presents them without a legend to people who don’t know how to read UML diagrams.
  • Love creating new unintuitive names for very simple ideas (e.g “Broker topology”). Proceeds to use these niche names in discussions and judges other people for not knowing what a “Broker Topology” is.
  • Gets really into programming fads that are hailed as panaceas but later get tossed out for a new panacea (e.g. microservices, Layered Architecture, REST).
  • Gets very emotionally attached to programming decisions, even if they will have no effect on the user.
  • Loves engineering around unlikely “what ifs…”.
  • Prefers creating abstraction through classes instead of functions, even if no state is needed.
  • Is bored by “practical details” like logging, debugging, convenience, fail-safes, and delivering quickly.
  • Maximizes the number and obscurity of patterns used, leading to classes named things like EventLoopListenerFactory.
  • Only cares about performance if obscure (e.g. tail-call optimization)
  • Isn’t actually very capable creating software (hasn’t won any coding competitions, has trouble with git reset, hasn’t written any software that people enjoy using)

Thus:

Know-it-all / hipster
 = Architecture  Hipster 
+ software architecture 

I don’t dislike architecture. Architecture is a beautiful study. However, the complexity of the discipline makes an fertile ground for phonies; a space for phonies to use miscommunication as a tool to create an illusion of their own competence.

The “Hello” World

Have you ever been searching for a song on your favorite music service and scrolled through all the songs that matched your search. All of them?

For example, top of the pop billboards at the time of this writing is Adele’s “Hello.” I scrolled for a while and got to at least 1,962 songs named “Hello,” before I stopped scrolling.

It feels like looking into the grand canyon.

A few things are immediately apparent-

  1. All comes to pass. To illustrate, Madonna too is in the Hello list, but her Hello didn’t last; I can’t see why Adele’s would.
  2. The top dog takes it all. Adele’s variant has 250 million spotify listens. Most of the Hellos have < 2,000 listens. Adele’s Hello very well may have more (spotify) listens than all of the other 2 thousand combined.
  3. It’s  harder than it seems. When all the songs you know of are big hits, it can be hard to realize just how many unpopular songs are out there.
  4. This goes deeper than “Hello.” I just picked the top song on the billboard at the moment, but it could have been any songs. Or any poem, or book, blog, or famous person.

And a few things are less obvious-

  1. Why does the top dog take it all? Why do 99% of songs never reach the radio? Are most of these songs just bad? Is it simply that it’s ten times easier to write a bad song than a good one? Or is it that the music industry builds pop celebrities for profit, and radios buy in? Or is it that audiences don’t want so much choice, that we only like a song the 3rd time we hear it so we focus on a few new ones?
  2. So two thousand people chose the same word for their title. Is unique art only a fantasy? From the pool of a million english words, two thousand artists all picked the same one as the title of their song. I know this because I searched by title. How many of these songs share the same key chords? How many of these songs are about the same thing? Artists, like the rest of us, like to think they are doing the unique, but maybe the pool of possibilities split among all of humanity isn’t big enough to allow us each a distinctly unique idea, song title, or life story.
  3. So where do they all end up? There must be at least 80 hours of “Hello,” on spotify. Which makes me think there must be enough music on spotify that I couldn’t listen to it all if I dedicated the rest of my waking life to it. And people are still writing music. Is it just a never-ending cycle of new genres with a small fraction surviving into each new generation with the vast musical history resting in peace at the bottom of our searches? Or do we someday exhaust the unique musical possibilities?

 

My programming challenge

 

TRY IT OUT -> Zennish <- TRY IT OUT

A programming puzzle inspired by a programming career

Professional programming involves balance between the opposing philosophies of architecture (GRASP, SOLID) and pragmatism (KISS, YAGNI). Over-architected code front-loads difficulty to solve problems that won’t necessarily ever come. Under-architected code causes exponentially more pain with each new requirement, like a house on a bad foundation. Finding the middle ground consistently, our job, is hard. 

But in the real world the changes you have to make over your code are so spaced out and forgotten. Thus the feedback loop on your coding decisions may be months or years. Welcome to the garden of practice. When you make choices in this low-stakes sandbox it’ll only take minutes to reap what you have sewn. 

I also see this an alternative to traditional coding challenges (e.g. codility, google code jam) that challenges the traditional valuation of engineers on academic math-intensive skills. Expert engineering is not about plugging a sequence of numbers into the OEIS; it’s creative composition.

Try it out

Quote

Readable Code: Name Everything

Consider the following code samples.

// Specimen A 

if ($forceClose !== ' ' && $forceClose !== NULL && $issues['forcedClose'] && $forceClose > 0) 
     { 
     //ONLY SAVE IF 1, NEVER TOGGLE BACK
     $this->saveAttrForUser($user, 'forced_close', $forceClose);
     if ($forceClose == '1') 
         {
         Log::saveWrite("App killed");
         }
    }
// Specimen B
// note the prefix 'b' indicates type Boolean, the prefix 's' indicates type String
$bGotValidMessageFromClient = !($sForceClose !== ' ' && $sForceClose !== NULL);
$bAppPassedExitMessage = $aIssues['forcedClose']; 
$bExitWasForceful = ( (int)$sForceClose > 0);
$bAppWasForceClosed = $bExitWasForceful && $bGotValidMessageFromClient && $bAppPassedExistMessage;

if ($bAppWasForceClosed) 
     { 
     // A comment here that would mean something...
     $this->saveAttrForUser($sUserId, 'forced_close', $sForceClose);
     $bForceCloseWasAKill = ($sForceClose == '1');
     if ($bForceCloseWasAKill) 
         {
         Log::saveWrite("App killed");
         }
    }
These two samples contain the exact same logic. The former is more direct, essentially it inlines all of the variables in the latter. And that is why it is worse. A variable serves as a unit of abstraction, and a well-named variable is a comment; thus having more variables is better. In fact, all if conditions should the form if ($bSomeVariable) {, that is, never put a complex expression within the parentheses of the if. If the logic is particularly complex then use multiple variables, as seen in the sample above.

All if conditions should the form if ($bSomeVariable) {

At first glance, the bottom example is longer and may look intimidating. But it is superior because it exposes its internal logic. Try deciding what the top code does, and what ‘1’ indicates in that code. Then consider the bottom code. The top is an actual code sample.

And while we’re adding in these extra variables, let’s name our variables clearly. Programmers seem to have some unspoken assumption that variable names need to be less than 10 characters and not have prepositions… Maybe this made sense when you had an 80 character wide monochromatic screen with no form of autocomplete, but technology has made that trend obsolete.  I suspect most people would try to turn the variable name $sLinkToUniversalDownloadPage into something like $sUniversalDownloadLink which is inferior because it is ambiguous (is the link universal or the download universal?).

Or, for example, what would a function named “OpenFileLock” do? Is it opening a lock on a file? Is it filing a lock (in some kind of lock registry)? Is it locking an open file? Each of the three words in the title can be read as a multiple parts of speech (i.e. verb, noun, adjective, etc). Or perhaps FileLock is an existing class in this codebase. Prepositions here would make all of the difference.

Name everything; name it well.