Wednesday, March 23, 2016

The "Nice Guy" Core Belief

Robert Glover defines a "nice guy" as a man whose behaviors are driven by the following belief paradigm:

"If I hide my flaws and change my self to be what others want me to be, then I will get my needs met, be happy, and live a problem free life"

This belief comes out of childhood abandonment experiences. To someone who did not experience frequent forms of abandonment as a child and does not carry this type of belief, this line of thinking might seem illogical. However, if we look at it in terms of the psychological principles of childhood development, it starts to make a lot more sense. 

A child's greatest fear is abandonment. Think about it - you can't really survive on your own if you're five or six years old. To be abandoned is pretty much the same as being left to die. That fear is also not limited to fear of physical abandonment, it also includes emotional abandonment and feeling like your feelings are unimportant or even undesirable. Since most children are aware of the fact that they're mostly helpless on their own, they rationalize any abandonment experience they have as being caused by their behavior. It's their fault. When they get yelled at, they believe that they're wrong because to say otherwise is to risk having their greatest fear (abandonment) come true. 

As a result, any kind of behavior that carries the risk of abandonment are usually assigned the value judgment of "bad" by the child. Some children are abused when they speak up to authority, or if they do don't do well in school, or if they express their needs like wanting to talk about their day. Whatever those behaviors are, when those behaviors are shunned by people close to them over and over - especially their parents - they become viewed as flaws. At first, maybe one specific behavior is viewed as a flaw. But when a pattern emerges, an entire category of behaviors becomes viewed as flaws. For example, "asking for new toys is bad" evolves into "asking for things I like is bad" if similar expressions of need are met with rebuke. The child then believes that these flaws must be hidden or eliminated if they want to survive. That belief acts as an effective survival mechanism for young, helpless children. By believing that they're the ones who are wrong and need fixing, they're able to stay out of trouble with their parents and other adults who have tremendous power over them.

This belief also doesn't just magically disappear after puberty. For most men, it becomes a core, underlying, and subconscious belief that drives all of their behaviors as adult. The difference is that as an adult, it's no longer a survival mechanism. If anything, it's the opposite. A man that continues to operate under the belief system of a small, helpless and abandoned child still experiences the power differential of a child and his parent with most people he interacts with. For example, the man might not get what he ordered at a restaurant and rather than speaking up and calling over the waiter to have his order corrected, he decides to let it go because the idea of telling the waiter that he got his order wrong made him scared and anxious. In this scenario, even though the waiter actually has very little power over his survival, he fears the confrontation to the same degree as he would fear confrontation with an abusive mother or father. 

There are two common outcomes due to this behavior, driven by a belief that took seed from a very young age:

1. The man does not get his needs met. 
2. The man experiences helplessness and deep resentment. 

In the scenario above, the man at the restaurant will sit there unsatisfied, eating something he did not order. He may also be muttering curses under his breath and vowing never to eat at the restaurant again, even though he's may no effort to speak to the staff about the mistake. 

So does that mean that these children and men never express their needs and instead just keep quiet like the man in the restaurant? I mean, wouldn't that always be the case since their primary reaction is to suppress or eliminate these needs? No, of course not. Hiding a need doesn't cause it to disappear - especially if it's a very intense need. It's just hidden from other people. 

This creates a dilemma. The strong needs don't disappear, yet the belief prevents the person from expressing it. So in situations where the person operating under this core belief has a very strong, unshakable need and experiences great fear and anxiety at the idea of openly expressing it, he usually takes one of two approaches:

1. He does nothing and keeps quiet and faces the same two outcomes as the man in the restaurant. He does not get what he wants and feels resentment. 
2. He expresses their need indirectly. 

If he does nothing, he doesn't really cause the world much harm. He's just silently fuming and doing nothing about it. The damage usually comes from the second approach - when rather than asking directly for what he needs from the world, he tries everything but ask directly for what he wants. In most cases, that means lying, cheating, or manipulating. 

This is the reason why people in general - especially women - cannot stand "nice guys". Nice guys are fundamentally dishonest. They're not necessarily mean people - they're humans that are very afraid of being open about their thoughts and feelings. As a result, a lot of what they do has strings attached because there's almost always an ulterior motive. As a "nice guy", rather than asking you to share that delicious cheesecake you've got there with me, let me tell you how much I love cake. And maybe I'll also share some of my food with you in hopes that you'll get the hint. 

For humans, intimacy cannot coexist with dishonesty. Honesty is essential. This shouldn't be a surprise. So when you learns that a guy is a "nice guy" because on more than one occasion he's tried to manipulate or lie in order to get what he wants from you, you no longer trust him. Not only that, but you will also likely experience repulsion because dishonesty is also a sign of fear. We do not respect cowards. Now if that's true generally speaking no matter what relationship we're talking about, then the manifestation of dishonest, cowardly behavior in very intimate relationships (usually between man and woman) must be the most destructive.

Sunday, March 20, 2016

OO Bootcamp: Day 4 + 5

The Cynefin Framework

Dave Thomas created this framework to as a way of classifying different types of problems and the approach to finding solutions to those problems. We know that different problems require different approaches. What's unique about this framework is that Dave buckets all problems into one of four main types: obvious, complicated, complex, and chaotic.



We went through each type, discussed the characteristics and approaches as well as used examples of real problems that fit that type. 

Obvious
  • Cause and effect in this system is well defined. The approach to solving these problems is to understand what the problem is, categorizing the problem, and then responding by using a best practice associated with that problem. 
An example of a problem that is obvious is how to convert celcius to farenheit. The rules for performing such a conversion is well defined. It's just an equation and one in which the causes and effects are clear. Each input produces a unique output. 

Complicated
  • The cause and effect in this system is complex and requires analysis by an expert. We can understand the problem but it requires analysis to understand what solutions are appropriate. There is no clear best practice because because the set of solutions depends on the analysis. Instead, there are good practices.
Building a ordinary house. There is no one way to build a house. Someone with expertise needs to assess the environment and offer a number of solutions. Given the solutions, it's usually clear what the effects are even though they may not be very obvious. 

Complex
  • The causes may be defined but it's not clear what the effects are in advance. The best we can do is to probe the system to look for patterns. Once the problem is identified, we can move towards devising solutions for it. Even with the solutions, the effects are not defined. 
Netflix recommendation engine. How do you know if person A will like the movie you recommend based on the new recommendation algorithm? You don't. There's no guarantee. The same is true for stock picking. Which stock will yield the highest return this quarter? Given any solution, the effects (gain? loss?) cannot be predicted consistently.

Chaotic 
  • We don't know what the problem is. The problem can be anything. It's unforeseen and unexpected. Causes are not clear and the effects are not clear. Our only option is to act when the problem occurs in the system and then respond.
Emergency and crisis situations. When a power plant blows up, there may be a million different problems. Our job is to do what must be done and then work on identifying the problems that need to be addressed. 

Fred argues that most software projects are of the complex type because we're ultimately writing software for people to use. People change. Not only that, but the use often occurs in some business domain which often comes with a great degree of uncertainty. 

The software development approach that best exemplifies the probe-sense-respond approach that Dave argues is best suited for complex problems is the task cycle. By keeping design and coding short, we're able to iterate quickly and learn a lot about a domain. This is the world of A/B testing. Because we're able to ship rapidly and change rapidly, we are more likely to approach a moving target than if we just spend a huge amount of time upfront (waterfall model) with the design and then implementing it in one go. That's treating software projects like complicated or obvious problems, which Fred argues is ineffective.  




Saturday, March 19, 2016

OO Bootcamp: Day 3

We kicked off the day with a post-mortem. Why did we struggle so much with designing am elegant solution to the metric conversion problem?

  • We lacked the vocabulary. We didn't know about the quantity pattern.
  • We were not familiar with the language and framework. Pairs that did not know ruby spent half the time googling how to write in ruby. 
  • Not all pairs were familiar with the tools. Not every uses Vim. Even those who used Vim did not use the same key bindings.  
  • We did not have a good sense of code smell so we spent more time implementing crappy designs that we should. 
What did we learn?

1. Don't just pass around strings and other primitive data.

Having random primitive data floating around is a clear indication of encapsulation violation. They're raw data - who's using them? Who's responsible for them? Having a number 1 floating around in your system without it being represented as a symbol anywhere or a Boolean that just floats around in and out of objects indicates that it has meaning and that it's part of a behavior that may change over time. Isolate it in a single entity so that it doesn't fly all over the place.

2. Don't continue on a design you think is shaky.

If you do not have a solid base, things just get worse - much worse. If the design is bad, create a new design and refactor so that the next task is easier. 

3. Don't bother creating a new class if it has no behavior.

Someone created an NoArithmeticException class and it had no special behavior (like telling us how to resolve the error). Why be a class? Just use a built in one! Sometimes even if it makes sense conceptually, the code you'll end up writing may not justify it. If you do it too early you may also not really understand what the base needs to have as you haven't seen enough of the differences yet. Another example is the rectangle and square. Why create a new square class? There's no special behavior. It's just a special rectangle.

4. Stop writing "create" in the procedure name if it's returning an object.

The absence of create should imply that something is being created and returned. We use create_builder because it actually didn't return anything and only created new instances. Just call a.quantity versus a.create_quantity

5. Minimize branches of logic in code.

More logic branching the more complex the software because more paths means more cases to test and eventually if there are lots of path it grows exponentially! For example if A has 10 cases and B has 10. A passes B data. Well, for each type of input there are 10 possible paths. The measure of this complexity is commonly known as the McCave Cyclomatic Complexity which measures the number of possible paths through a programs source code.

One technique to avoid creating too many logical branches is to put your guard clauses up top and avoid else statements. Why? Because else statements are signs of unique behavior. Move them to a different place to reduce the complexity in the current object.

6. Only use inheritance under these two conditions

Humans are great at seeing inheritance everywhere. We look at the code and our first instinct is to make some is-a relationship . Here's a test to help you guard against that intuition which is often wrong:

1. You're using almost all the code in the superclass and it has its own specialized classes (otherwise why bother creating it at all). No need to rewrite over and over. 
2. The grand mother test. Be able to explain to grandma why X is a type of Y. For example, saying that a stack of poker cards is a type of array makes NO sense. 

7. Don't spend too much time upfront on design.

You can create really elaborate models during the design process that result in unnecessary code. That's why we keep design short because we know it's inherently flawed (combined with our tendency to jump to inheritance). . 

Polymorphism Exercise

We all went outside and were told we could be asked one question "are you better than the person next to you (right / left?) and were told what to say based on some criteria of better (first it was month of year and then it was number of show lace holes on one side of our shoe). Then people would ask us these questions  to sort us.

How did this demonstrate polymorphism in action?

We were all different people with different data. However, we had the same interface (same question you could ask all of us). The sorter then interacted with that interface and was able to sort us accordingly. This is the key of polymorphism - where we have different objects that conform to a common interface so that they could be use interchangeably / treated the same / interacted the same way by other objects. One useful concrete example: a sort object that can sort any object as long as they have X, Y methods. In Java, this is implemented through the Comparable object.

Same interface, different underlying forms.

OO Bootcamp: Day 2

We spent most of the day 2 pairing. We started the day off by learning the vocabulary of pairing, went over a few key object to object relationships, and then we were off to the races implementing a program that performed unit conversions that took up most of the day.

Pairing

Fred is a huge proponent of pairing. We only started pairing on our team fairly recently. The two main arguments I've heard for why pairing is important are

1. Reduced business risk because it leads to knowledge transfer on a team. More than one person will know how to perform a specific task.

2. Higher quality product as a result of combined intellect and greater accountability.

Not all pairing is made equal, however. Effective pairing requires an understanding of pairing dynamics and adherence to some basic rules and guidelines.

Pair Types
  • Expert + Expert
  • Expert + Beginner
  • Beginner + Beginner

In reality, software expertise can't be represented by either "expert" or "beginner". Consider the types above as the most extreme combinations you can have for completing any given task given a group of people with varying levels of expertise relevant to that task. 

From a getting shit done perspective, it's ideal to have a team of A players / 10X programmers. That's how amazing products get built. For most companies, that's not the reality. This doesn't mean beginners should never pair. Quite the opposite. Everyone should pair because that's the only reliable way to bring everyone up to the same level. 

So what are the advantages of the expert + beginner pair and the beginner + beginner pair?

Advantages of the Expert + Beginner pair:
  • Expert gets a fresh perspective on problems
  • Beginner can learn a lot about existing systems and programming techniques in a short period of time. Rapid ramp up.
Advantages of the Beginner + Beginner pair:
  • Both beginners can hone their problem solving and team work skills by relying on themselves and each other.
Pairing Protocol
  • Let me drive = "Give me the keyboard"
  • Trust me or Trust me I know what I'm doing  = "Be quiet and let me finish this and I'll explain afterwards"
Pairing Tips
  • Less experienced pair should drive. More likely to retain information. 
  • Talk, talk, talk. By talking, you clarify your thoughts and let your pair know what your intentions are. If you walk into a room of pairs and its quiet then that's a bad sign. 
Pairing Models
  • Pair programming ping pong. Pair A writes a test. Pair B writes code to pass the test. Pair B writes the next test. Pair A writes code to pass the test.

Object relationships

There are fundamentally three types of object relationships.

  • Inheritance (is-a relationship)
  • Buying / Composition (has-a relationship)
  • Collaboration (bi-directional has-a)
If you've ever taken an OO class in college before or read a design patterns book, you've probably head of the phrase "prefer composition over inheritance". The main reason is that our human brains are biased to see inheritance relationships where there does not exist any. In other words, we're prone to creating inheritance hierarchies that do not make sense behavior wise. To avoid making the error of having a class inherit a bunch of behaviors it does not need, we should only consider inheritance if and only if the sub class uses most of the methods in the base class and the sub class has specialized behavior. Fred calls this specialized behavior a "kick". If a class has no "kick", it should not exist as a stand alone class.

The Quantity Pattern

We were asked to write a program that checked if any quantity of a given unit on the metric system is equal to any quantity of the same or different unit. For example, one question we would be able to ask this program is: "Is 5 teaspoons equal to 10 tablespoons?".

Our initial design was a quantity object whose job was to understand units and quantity of a unit. We then created sub-classes for each type of unit to perform the necessary conversions. We got this to work, but it produced a lot of duplication and it looked impossible to extend with new behaviors like adding quantities of different units or worst, adding an entirely new set of units.

The solution was a common pattern called the Quantity Pattern. Essentially, the quantity pattern sees two main players in this problem domain: a unit object and a quantity object. What happened in our design was that the logic of unit conversion was duplicated across multiple objects. In the quantity pattern, the unit object is responsible for understanding the concept of a base unit and the size of other units in the same system relative to that base unit. The quantity object understands the notion of size / magnitude given a unit and how to compare sizes. This greatly DRY'ed up the code and was by far the most elegant solution.

Afterword

Becoming a truly expert programmer requires developing a vocabulary in all of the following areas:

  1. Language / Key frameworks
  2. Tools / Text editors
  3. Coding patterns or programming style
  4. Code smells or signs of bad design 
  5. Design patterns or patterns of software design
  6. Analysis patterns or patterns that exist across domains
Getting language and tools down will make you go fast. However, just going fast isn't enough. As we've learned, having a bad design leads to ugly code. Mastering the others will allow you to become a true craftsman. In this course, we'll be focusing mostly on language, code smells and a couple of design patterns. 

Thursday, March 10, 2016

Hard writing, easy writing

My girlfriend shared two quotes with me today that I thought perfectly reveal the essential responsibilities between the reader and the writer.
Hard writing makes easy reading 
                                         - Wallace Stegner

Easy writing makes hard reading 
                                          - Earnest hemingway

Most ideas in the mind are often ill-defined and non-linear. As an author, making those ideas clear on paper requires that she makes an effort to clarify and organize her thoughts. That's hard work. So when the author fails to put in that work, some of that responsibility is shifted to the reader.

In How To Read A Book, Mortimer J. Adler describes this relationship in the exchange of information between the reader and the writer using a pitcher and catcher metaphor. Easy writing is a lot like being a lazy pitcher - the throws lack control and therefore also precision and accuracy. As a result, the catcher can't reliably predict the trajectory of the ball and fails miserably.

This is the same with face to face communication. It's obvious when someone makes the effort to gather their thoughts because you don't have to struggle to understand what is said. What's funny is that my girlfriend shared those quotes with me after calling me out for being a lazy communicator. I was blabbering and made her do all the hard work to figure out whatever the hell I was trying to say (sorry babe). It's not fair or productive for one person in a conversation to be doing most of the work - we should strive to keep our communication balanced in effort. Otherwise, just be quiet.

Monday, March 7, 2016

OO Bootcamp: Day 1

My company is sponsoring a two week object orienting programming boot camp led by Fred George, who's a well known programmer and instructor. Today was the first day and we learned a lot. I'll be sharing the most important lessons on my blog over the course of these two weeks. I think it's an amazing opportunity for us to learn from someone with so much experience so I'm going to do my best to make sure I get as much as I can out of this as well as share as much useful information as I possibly can.

The primary goal of the boot camp? 

To teach us the fundamentals of modeling effectively. No, not this kind of modeling:



Data modeling. Defining conceptual models of some domain. Why is this important? Because how a system is modeled sets the groundwork for everything else that follows in building the system.

What's your job?

In OOP, we design systems that are based on objects and their behaviors. To understand what those behaviors and how they interact with other objects in the system, we need to clearly understand the jobs of these objects.

So our first lesson was this: learning to identify an objects job. He posed a basic question: what is the job of a rectangle? We all struggled to come up with an answer he was satisfied. Our answers were so off that he created a list of criteria that disqualified a job definition.

For example:

  • Circularity. Saying that the rectangles job is to understand itself or rectangles is a circular definition. No good. 
  • A list of data or methods. An object contains data and procedures that allow it to do its job. You can't really define what they are without knowing what its job is! 
The problem was that a lot of us were stuck on defining its job in terms of the behavior and knowledge that were implied by our subconscious knowledge about its actual job. You could say that we were getting a little ahead of ourselves. We were defining its job it terms of things like length, width, area, and perimeter. Sure, it may be useful for a rectangle object to have knowledge of those things - but we needed to get deeper. What job does it have that makes sense for it to have knowledge of those things?

The answer turned out to be something we all understood but took for granted: the job of the rectangle is to understand opposing sides that are right angles to each other. Now, that's not a very precise definition but it does establish the primary job of the rectangle that is not tied to any ideas we had in regards its behavior in the system. Once you know what the job of an object is, the rest will follow. For example, now that we know it's job we can then say that having knowledge of its area and perimeter is useful information. 

Tips

  • Keep the job as simple as possible. Break it down to its bare essentials. What's the job, really?
  • Come up with jobs for the object by role playing(anthropomorphism). What is your job? What are you expected to know for your job? How will you work with others?

The Task Cycle

Once we have an object modeled in our heads, we want to actually test our model against reality by building it and seeing how it performs. 



The most important thing to keep in mind about this cycle:
  • We want to keep our test & code cycle short (less than or equal to 15 minutes) because that leads to code that can be quickly integrated into a code base. Small changes integrated quickly leads to less bugs. 
  • A short test & code cycle depends on not spending too much time on design. A design is useless until you actually implement it and get feedback on how it actually works in a system. 
OO Principles

Encapsulation is a very important software technique to use when building your models. Code that is not well encapsulated is leaky and can lead to rapid software deterioration. If an object is not encapsulated, its data ends up being pulled into other parts of the system which creates unnecessary coupling that can make change very, very difficult. 

There are some common signs of violating encapsulation:
  • -ER / -OR class names
    • Classes that end in -er are usually violators because they are grabbing data out of other objects to perform some action. For example, controllers are notorious for acting as a middle man between the view and the model. It knows a lot about the views and knows a lot about the models in order to manage the flow of data between the two.
  • Many instance variables (> 2)
  • Law of demeter .... or your object is looking at too many other objects: a.b.c.d()
  • Presence of getters & setters. Having getters and setters is just ASKING for other people to violate you. 
    • Chances are, the object you're trying to grab data from knows how to use that data better than you do. You can learn to avoid this by role playing. Have someone ask you to give up your data. Then ask why. In most cases, you'll know how to do that with less duplication.
How do you know when you're done? 

In order of priority,
  1. The code works. You're confident that it works because you've seen it work, it meets the requirements, and the tests are green. 
  2. It's clear what the code does. Is it clear what the job of your objects are? Are there comments where the code is not clear?
  3. There is no duplication. Is this code duplicated anywhere else? Duplication can happen even on a single line of code - an expression that accidentally gets repeated. Dry up your code!
  4. It's implemented with as few logic, method, classes as possible.
Why is this priority order important? Well because if you optimize for #4 without following this priority, your code can get very unreadable very quickly :D