Tuesday, September 19, 2017

Stubs, Mocks, and Spies in Rspec

There's a number of different terms we use in testing to describe how we're setting up the tests. Are we stubbing? Mocking? Spying? All of the above? What do they even mean?

1. Stubs

These are just canned responses. You stub out methods so that when they're called, they just return something (anything you want). If they're not called, nothing happens. 

Rspec stubbing: https://relishapp.com/rspec/rspec-mocks/v/2-14/docs/method-stubs

Example

allow(obj).to receive(:message).and_return(:value)

You can do this either both real objects and doubles.

2. Spies

These are objects that you set up with canned responses (like stubs) that also record information about the calls made to that method (was it called? what was it called with? How many times?). 

Rspec

Example

allow(Invitation).to receive(:deliver) 

or

invitation = spy('invitation')

Followed by the assertion

expect(invitation).to have_received(:deliver)

3. Mocks

These are objects that have already been instrumented with expectations. They're like spies in that actions are recorded but they also go a step further to automatically verify the behavior when the test is exercised.

Example

logger = double("logger")
account = Account.new logger

expect(logger).to receive(:account_closed)

account.close

State verification vs Behavior verification 

Verification is the act of verifying that something occurred in some manner. In testing, we rely on either state verification or behavior verification to ensure that objects are behaving in the way we expect them to. 

In the testing world, state verification is verifying the test through the state of an object. What's the current value of variable X? In other words, what's the current status of this object? Does it match up with expectations? 

Behavior verification takes a different approach. Behavior verification is not concerned with what state the object is in - it's only concerned with the fact that certain actions occurred in some manner (regardless of how they changed the objects state). 

According to Martin Fowler, only mocks insist on behavior verification. In other words, unlike stubs and spies, only mocks are preprogrammed to perform behavior verification. With mocks, you don't really have a choice to do state verification. 






Sunday, September 10, 2017

Spinning up a rails app using Heroku in < 5 min

It's really amazing how you can have an app running in production in < 5 minutes using Heroku. Below are the minimal set of required steps to serving a basic static page to Heroku.

Pre-requisites
  • Heroku Account
  • Heroku CLI
  • Rails CLI
Create and and commit the app

rails new app-0 -d postgresql && cd app-0

rails generate controller welcome

touch app/views/welcome/index.html.erb && echo 'Hello World' > app/views/welcome/index.html.erb

Add root 'welcome#index' to the config/routes.rb file 

git add . && git commit -m 'first commit'

Deploy app to Heroku

heroku login

heroku create

git push heroku master

heroku ps:scale web=1

heroku open

Topics:

  • GIT
  • PostgreSQL
  • Rails
    • Routing
    • Code generation
  • Heroku
    • create
    • ps
    • open
    • Default Rails Server: WEBrick
      • Single threaded server vs multithreaded server


Sunday, August 20, 2017

Rspec doubles - normal double, instance double, class doublea

Test doubles are any object that are suppose to stand in and represent real objects during testing. Rspec offers three types of doubles - ordinary doubles(just double), instance doubles, and class doubles.

All doubles are strict by default. What that means is that if any un-allowed or unexpected methods are invoked, the test will fail. For example:

x = double()
a.bar // error because `bar` was not allowed.

However, you can make any double loose by appending `as_null_object`.

Now lets look at differences.

Ordinary doubles

x = double()

These doubles are super barebones. You can allow any messages on these methods.

Instance doubles

x = instance_double('ClassName')

These doubles are aware of the instance methods of class 'ClassName' - you can only allow messages that are defined.

Class doubles

x = class_double('ClassName')

These doubles are aware of the class / module methods of any class or module named 'ClassName'. Just like instance doubles, only defined messages are allowable.

In short, instance and class doubles go a step farther than verifying the state of an object (was 'X' called?). They also verify behavior (is 'X' a thing that this object does?).

When do you use one over the other?

I see ordinary doubles as good for creating dummy objects during a test. For example, if you need to fulfill a parameter requirement for a method where you know the object isn't being used. However, you generally want to use instance and class doubles for the stricter check.

Saturday, August 12, 2017

New Smoothie I'm trying this week

So the avocado coconut smoothie I mentioned last week is more complicated to make than I prefer.

This week I'm going to give this a shot: https://iquitsugar.com/recipe/liver-detox-smoothie/

Ingredients

 small green apple, diced and frozen.
1 zucchini, diced and frozen.
1/4 avocado, diced and frozen.
1 cup mixed greens like broccoli florets, watercress, beetroot greens, silverbeet, kale or spinach.
1/4 cup coriander or parsley (or both!).
1 teaspoon chia seeds.
1/4 teaspoon turmeric, ground.
1/2 lemon, juiced.
2 cups coconut water.

My Grocery List

  • 1 - 2 green apples
  • Zucchini
  • Avocados
  • broccoli florets 
  • Almond Milk

Reflections on Sublime so far - quotes and projects

I switched over to using Sublime from Vim this past year and it's been an absolute joy to use. In fact, I liked it so much I even made a cheatsheet for others to get the most out of this editor. However, there's were still a couple of actions that have been a source of frustration: changing quote types and navigation across multiple projects. In this post I'll discuss what they are, the solution I've adopted to address them, and how I still felt about the solutions after a week of use.

Problem 1: Quotes


Replacing single quotes with double quotes or double quotes with single quotes using multiple selection. If you select both quotes, typing in a single quote will simple quote the double quotes themselves. 

For example:

"hello world" becomes '"'hello world'"' when what I really want is 'hello world'. This isn't a problem if I'm trying to actually quote selections, but very rarely do I (or anyone) want to be quoting the quotation marks. 

Solution

The most promising solution I found to this problem is the ToggleQuotes sublime plugin. I just installed it and it works pretty well. I'm considering adding tests to this and adding support for quotes around multi-line strings. 

Problem 2: Project navigation


When I have sublime opened for > 1 projects, it's difficult to go from one to another. Right now I just use the basic mac application switcher and it works fine for two projects but once I have > 3 applications open it becomes a nightmare.

Solution

Turns out Sublime has a built in projects feature to deal with this issue. I just learned that every window you open is either a named project or anonymous project (if you open sublime in any directory not associated with a project). You can define project specific sublime settings and switch between them quickly using sublimes Project feature. You can also add folders from other projects into the current project.

Update after a week of using ToggleQuotes and sublime projects features

  • The project feature for sublime is absolutely indispensable. I've been able to switch from one project to another seamlessly and this has been a tremendous boost for my workflow. I will also say that I continue to advocate for keeping the project files in the same place - no need to pollute your repos if you don't have to. 
  • Toggle quotes is awesome. Thank you @spadgos.






Saturday, July 29, 2017

Smoothie breakfast diet

I'm currently experimenting with a low-sugar, nutrient-dense breakfast smoothie diet that's easy to make. This is a list of three smoothies that I will be having throughout the week along with a grocery list of ingredients you'll need to buy to make them. 


Banana Peanut butter 

http://www.youmustlovefood.com/banana-peanut-butter-cinnamon-smoothie/
http://allrecipes.com/recipe/221261/peanut-butter-banana-smoothie/A
  • Peanut butter 
    • has protein as well as potassium — which lowers the risk of high blood pressure, stroke and heart disease. It also contains fiber for your bowel health, healthy fats, magnesium to fortify your bones and muscles, Vitamin E and antioxidants.
  • Bananas
    • They contain several essential nutrients, and have benefits for digestion, heart health and weight loss.
    • Bananas are among the most popular fruits on earth.
    • Bananas contain a fair amount of fiber, as well as several antioxidants.
Grocery List 
  • banana 2x
  • milk (2 cups)
  • peanutbutter (1/2 cup)
  • Cinnamon powder
  • Cacao powder 
    • https://iquitsugar.com/raw-cacao-vs-cocoa-whats-the-difference/
Apple Strawberry

http://gimmedelicious.com/2015/07/16/apple-strawberry-smoothie/
  • Apples are 
    • extremely rich in important antioxidants, flavanoids, and dietary fiber. The phytonutrients and antioxidants in apples may help reduce the risk of developing cancer, hypertension, diabetes, and heart disease. This article provides a nutritional profile of the fruit and its possible health benefits.
  • Strawberries are no exception to this rule; 
    • in addition to antioxidants, they have many other nutrients, vitamins, and minerals that contribute to overall health. These include folate, potassium, manganese, dietary fiber, and magnesium. It is also extremely high in vitamin C!
Groceries
  • Apple (1x)
  • Frozen strawberries (1 cup)
  • Milk (1/2 cup)
  • Strawberries / banana (1 cup)


Avocado Coconut

https://iquitsugar.com/recipe/avocado-coconut-dreamboat-smoothie/
  • Avocados are 
    • Health benefits and nutritional information. Also known as an alligator pear or butter fruit, the versatile avocado is the only fruit that provides a substantial amount of healthy monounsaturated fatty acids (MUFA). Avocados are a naturally nutrient-dense food and contain nearly 20 vitamins and minerals.
  • Coconut oil
    •  is high in natural saturated fats. Saturated fats not only increase the healthy cholesterol (known as HDL cholesterol) in your body, but also help convert the LDL “bad” cholesterol into good cholesterols. By Increasing the HDL in the body, it helps promote heart health and lower the risk of heart disease.
Groceries
  • Coconut oil (2 tablespoons)
  • Blueberries (1 / 2 cup)
  • Banana (frozen) ( 1) 
  • Avocado (1)
  • Coconut cream (500 ml)
Toppings
  • Gogi berries
    • https://www.downtoearth.org/health/vitamins-supplements/ways-to-use-goji-berries
  • Chia seeds
  • Cacao nibs 
  • Mulberries 
Final grocery list
  • 2 Apples
  • 4-5 Bananas 
  • Cacao powder
  • Coconut oil 
  • Coconut cream (2 cups)
  • 1 Avocado 
  • 1 container Blueberries
  • Strawberries 
  • Frozen strawberries
  • Almond milk 

Tuesday, May 16, 2017

How to run Cinemania 96 on Windows 10


  1. Install Virtualbox 
  2. Create a windows 7 VM using free IE8 windows 7 virtual machine from microsoft. Create it with at least 1GB of RAM so it's no super slow.
  3. Download virtualbox guest addition and extension pack
  4. Add the extension pack to VB
  5. Start windows 7 VM and install guest additions. Reboot.
  6. Connect CD to USB port
  7. Add a USB device in the VM
  8. Copy files over to the hardisk 
  9. Run cinemania.exe

Sunday, April 30, 2017

Career Development Plan

In our last post, we established the key skills that make up the value of an engineer working in an organization. However, knowing the generalities is not very actionable. 

In this post, we'll delve into the key sub-skills that make up the top level skills as well as accompanying specific actionable tasks that you can start implementing immediately increase your skillfulness in that area and thereby increase your overall value as an engineer. 

Technical Expertise (clean and efficient code, language mastery, editor mastery, etc)
  • Core CS Fundamentals
    • Algorithms and Data structures
  • System Design
    • Learn Programming Paradigms 
      • Object Oriented 
      • Functional 
  • Programming Language
    • Learn Ruby
  • Text editor
    • Learn Sublime Editor (for host machine development tasks)
    • Learn Vi / Vim / Emacs (for general editing tasks)
  • Shell
  • Testing
  • Debugging
  • Source Control
    • Learn GIT
Qualities (leadership ability, general problem solving ability, communication ability, maturity level, etc)
  • Communication
    • Writing and Speaking
  • Analytical / Problem Solving Ability
  • Maturity 
    • Growth Mindset
    • Honors commitments
    • Seeks and Integrates Feedback
    • Treats others with respect
    • Actively Identifies problems
    • Self awareness
    • Proactive about future / career
Execution (planning ability, ability to get shit done, hitting goals)
  • Estimation
  • Project Planning / XP
  • Time Management
  • Getting Unblocked
  • Simplest thing that could possibly work

Scope (area of impact, sub-component, component level, sub-system, system, business unit value)

As your skill sets grows (technical, quality, and execution), so will your scope. If it doesn't, then you need to seek out more responsibility yourself. 

Dedicate entire branches of improvement for each area and track your progress overtime. Identify sticking points (tasks that are on B) and master them (move them to C). 

Saturday, April 29, 2017

Framework for Assessing value of Software Engineers

How does the industry differentiate between a junior software engineer from a senior software engineer? What are the set of attributes we use to assess the value of an engineer so that they're compensated appropriately? 

These are important questions with answers that seem to vary wildly, but having some method of approaching these questions are crucial for arriving at a mutual agreement between the hiring manager and the engineering employee on the value that the engineer brings to the organization. That shared understanding is really important for initial salary negotiations and for maintaining a amicable business relationship overtime. 

As an engineer, even if the companies you're applying for jobs for or are currently working at have no structure for compensation, it's still in your best interest to know what your metrics are for measuring your value so you can improve more effectively. For example, if "leadership quality" is a valuable attribute in your system, then you can very intentionally seek out ways to acquire that trait. 

But what does this value structure for engineers look like? What are the metrics? 

It's easy to come up with a list of things that you think are most important, but they're not helpful if they don't align with what a company or the industry as a whole deems most important. You can't approach companies asking to be paid a million dollars a year just because you can recite methods in the C++ standard library. Impressive? Maybe. Valuable? Not necessarily. 

One way to approach this question is to simply ask hiring managers at top companies. Luckily, many great engineering teams have shared their views on this publicly. After looking at the engineering ladders / compensation structures for these companies and identifying commonalities, I arrived at this general structure for engineers:
  • Technical Expertise (clean and efficient code, language mastery, editor mastery, etc)
  • Qualities (leadership ability, communication ability, maturity level, etc)
  • Execution (planning ability, ability to get shit done, hitting goals)
  • Scope (area of impact, sub-component, component level, sub-system, system, business unit value)
Some companies also mentioned "experience" and "public artifacts" such as Github projects. However, I left those out because those only serve as signals for the traits we're looking for. When you look at someones experience, you're trying to get a sense of where they're at in terms of things like leadership ability or technical expertise. 

The specifics of each and how they're prioritized will vary by company and by industry. You don't have the time to evaluate every attribute that could fall under technical expertise, so as a hiring manager you need to identify which ones you value and come up with strategies to measure how different candidates stack up on that metric.

I highlighted scope in a different color because it's not so much a skill as it is an area of responsibility. Skillfulness in other areas does lead to expansion in the scope of responsibility for an individual within an organization through promotions, but they're still quite distinct from one another since it's not inherently a skill. Nonetheless, it's a key metric because increasing scope does have a significant and direct effect on your value. You can have flying marks in all three areas of technical expertise, qualities, and execution but work on relatively small system compared to other members of the organization with very little business value. 

How this generic structure helps engineers

You can use this list as a framework for thinking about your skill set in the context of your domain / industry. How do you think you rank on technical expertise? On your personal qualities like communication ability? Do you want to become knowledgeable about other critical parts of the system to expand your area of responsibility? If you find a weak area, start working on it. 

Admittedly, this structure isn't very actionable if you can't fill in the specifics. One particular area where finding the set of important skill seems daunting is in the area of technical expertise. A million things can qualify as technical expertise. For example, if you work in embedded systems, having knowledge of Angular.JS isn't as valuable even though it certainly qualifies as a technical expertise. The solution here is to focus on durable skills. 

Durability is a trait that exists for each skill and across skills. First, we'll look at an example of two different skills that differ in durability.

1. Knowledge of classic computer algorithms
2. Knowledge of the API of a brand new AWS web service

#1 is not likely to change. #2 is more likely to change. Whether or not #1 is directly useful to you is a different story. But it is knowledge that is more durable because the most efficient sorting algorithms don't change in a matter of weeks or even years. 

Lets take one skill: editor mastery. 

Durable skill: Mastery over a popular, mature, productive editor that is available across systems. 
Non-durable skill: Mastery over an editor that is buggy and works on a single platform.

Every time you decide to learn something, keep durability in mind. You're making an investment and you want to make sure you're investing in something that will pay dividends for years to come. 

Resources


Wednesday, March 22, 2017

Sublime Selection

Select a character

SHIFT + LEFT / RIGHT

Select from cursor to end of word

SHIFT + OPTION + RIGHT

Select from cursor to beginning of word

SHIFT + OPTION + LEFT

Select a word

CMD + D

Select a line

CMD + L

Select between parenthesis

CTRL + SHIFT + SPACE

Select everything in file

CMD + A

Sublime Cursor Motion

Here's basic cursor motion commands you should know.

Move by character

UP / DOWN / LEFT / RIGHT

Move by word 

OPTION - LEFT / RIGHT

Move to the end of the line

CMD + RIGHT

Move to the beginning of the line

CMD + LEFT

Move to a matching brace

CTRL + M

Move to the top of the file

CMD + UP

Move to the bottom of the file

CMD + DOWN

Go to a line

CTRL + G (preferred) or CMD + T + :

Go to a symbol

CMD + R

Touching Typing Numbers and Special Keys

When I learned to touch type, I learned how to type letter properly but never properly learned numbers and special characters.

Here's how the keys map to fingers:

left hand
1 - pinky
2 - ring
3 - mid
4 - index
5 - index

right hand
6 - index
7 - index
8 - mid
9 - right ring
0 - pinky

tab - left pinky
caps lock - left pinky
shift - left pinky
fn - left pinky
control - left ring finger
option / alt - left mid
command - left thumb

http://apple.stackexchange.com/questions/47293/what-fingers-do-i-need-to-use-for-hitting-control-option-and-command-buttons-on
http://www.typing-lessons.org/preliminaries_4.html

Tuesday, March 21, 2017

Database Indexes

Premature optimization is the root of all evil.

Database indexes are all about optimization. Using indexes prematurely is unnecessary in most cases. However, knowing what it is and how to use it will save your ass. 

So lets talk indexing.

When you do things to some set of data in a relational database, the db has to retrieve that data. And if that data is retrieved based on some value (get every row where column C equals 5), then the db has to go through every single row in a table containing that data and decide whether or not that row should be used. 

Unless you use indexes. 

If you use indexes, the db does NOT have to go through every single row. Instead, it will find the rows it needs by using a special data structure. That special data structure is the index. 

Most database indexes are B-Trees which allow for logarithmic time operations. In other words, it can change O(N) lookup to O(log n). If you have a lot of data, that can be a huge difference. Instead of looking at every row and checking if a specific column equals a certain value. If there's an index for that column, then the database can do a O(logn) time look up for the value in the B-Tree, then follow the pointer to the row! 

Using an index is not always an optimization.

There are times when using an index can actually hurt you. An index is just used to do a look up for a row, but if a lot of those rows are being returned, then all an index adds is extra overhead for the lookups because when the matching rows are found using the index lookup, they still need to be scanned!


Monday, March 20, 2017

Relational Databases

So there's data that we want to store, access, and manipulate. Relational databases are tools that enable us to do just that.

With relational databases, you have to define the structure of the data before you can do anything with it. This structure is expressed as tables that have columns. And those columns represent a specific type of data (numerical, date, text, etc).

Tables are the types of things that you have information about. Columns are information about those types of things. Rows are information about the actual things. For example, if I'm interested in working with medical data and I need a database of patient (a type of thing) information, I might have a table called patients and the patients have information like name, and social security number, and insurance.

The blueprint of a database, which is just a set of table definitions, is called a schema.

Here's an example:

Doctor (
   name CHAR(20)
   id PRIMARY KEY
)

Patient (
   name CHAR(20)
   social_security_number INTEGER(9) PRIMARY KEY
   doctor_id FOREIGN KEY REFERENCES doctor
)

Tables can also have keys which are a special type of information that is unique to every row in the table. In the case of patients, that might be their social security number since no two people will have the same social security number.

Using SQL to manipulate data in a relational DB

Now for this database to be us useful, it needs to contain data. We can create a db and manipulate data in that db by using SQL (structured query language) which is a language that you can use to define what you want to do with that data that the database understands.

> CREATE DATABASE example_hospital;

Adding a doctor

> INSERT INTO Doctor VALUES("Dr. Phil")

Get all the doctors!

> SELECT * FROM Doctor

Get all the names of all of the patients of Doctor with name "Dr. Phil" (this involves data from more than one table!)
To select data in multiple tables that are related, we have to join them by running JOIN statements.

> SELECT patient.name FROM Patient, Doctor WHERE patient.doctor_id = doctor.id AND doctor.name="Dr. Phil"

This is known as the inner join. There are no rows with a key value in a table that does not match up with the key value of of another row in the corresponding table. In other words, it excludes rows from both tables that do not link up.

Left outer - retain all the rows in the left table but exclude rows on the right if they don't match. The values in those rows are replace with the value NULL. This would include all the patients even if they don't have a doctor seeing them.

Right outer - retain all the rows in the right table. This would include all the doctors even if they don't have patients.

Full outer - retain rows in both tables! This would include all the patients and doctors.

Get the number of patients

> SELECT count(*) from Patient

Get the number of patients per doctor!

> SELECT doctor.name, count(patient.id) as num_patients FROM Patient, Doctor WHERE patient.doctor_id = doctor.id AND doctor.name="Dr. Phil" GROUP BY doctor.name

Maintaining Data Consistency

Databases also prevent you from trying to do things that it thinks is nonsensical. For example, if you say that a patient has a doctor and you insert a bunch of patients that reference doctors. Then you can't just delete doctors because then there will be foreign keys in the patients table that point to nothing. That violates referential integrity (which says that every row in a table with a foreign key must have that key point to an actual row in another table).

DB's also support features like transactions, where you can specify a series of operations that are treated as atomic. The changes only persist if every operation succeeds. Otherwise, no changes persist.


Sunday, March 19, 2017

Jalapeno Popper Sandwich with Bacon


Ingredients
  • bacon strips
  • sliced bread
  • jalapeno peppers
  • cream cheese 
  • shredded cheddar cheese
Instructions

Pepper prep
  1. cut the jalapeno peppers in half
  2. broil the peppers
    1. preheat to 400 and let it cook for 10-15 minutes until slightly charred
  3. let it cool for 10 - 15 minutes because you'll need to touch them next
  4. remove the skin and seeds
Cheese prep
  1. mix the cheese in a bowl
  2. or not. up to you.
Bacon prep
  1. if frozen, put it in the fridge and let it thaw
  2. bake the bacon
    1. preheat to 450 and let it cook for 15 minutes. longer if you like crispier bacon.
Bread prep
  1. toast the bread!
Assembly
  1. Put the cheese on the bread. Then the peppers. Then the bacon. 
Microwave for 1 - 2 minutes (to melt the cheese into everything else mmmmm) and serve :) 


Saturday, March 18, 2017

Migrating a wordpress.com site will take you longer than thirty minutes

A couple of weeks ago my girlfriend told me that she wanted to install Google Analytics on her wordpress.com blog. Unfortunately, you can't install analytics without upgrading to the business plan which is a whopping $24.92 a month. She had plans to monetize her site in the future (ads?), which isn't possible with the personal plan.

So I told her that she should consider a self-hosted site. In fact, it's so easy I could do it for her in less than an hour.

I just finished.

It took over a week.

Here's what I had to do:

  1. Create an account on a new hosting service 
  2. Install wordpress through cPanel using a temporary domain name
  3. Import content from old wordpress into new wordpress
  4. Install Jetpack after realizing that none of the shortcodes were working
  5. Install Google Analytics (FREE)
  6. Transfer current domain name registrar over to new registrar (This process takes FIVE days)
  7. Buy a SSL certificate (got it for a dollar/year thanks to discount holla)
  8. Update DNS nameservers for domain (Takes about a day to propagate) to point to new host
  9. Update hosting plan to use current domain name and turn on SSL
  10. Replace WP database references to temporary domain using 
  11. Optimize the site with the help of Google PageSpeed because the site was slow AF. Went from a page speed score of 40 (ah!) to 96 (yay) by using a combination of plugins:
    1. autoptimize
    2. wp super cache
    3. wp asset cleanup 
    4. speed up javascript to footer
    5. speed up optimize css delivery 
Finding the right combination of plugins was a bit of trial and error. Some claimed to work but didn't. So I had to keep inspecting the page source and running page speed to test whether or not the plugins were making any difference to the site performance. 


Done! 

Design Patterns

Humans are great at seeing patterns. When a programmer solves a lot of problems, he starts to see solutions that seem generally applicable to a wide category of problems. When those problems are design problems (how to manage the objects and the relationship between objects), those solutions are known as "design patterns".

There are different types of patterns:
  • Creational
    • ways to manage the creation of objects
  • Behavioral 
    • ways to manage the communication of objects
  • Structural 
    • ways to organize objects
A common structural pattern is known as the decorator or wrapper pattern. You use it by wrapping an object with another object that has the same interface which then modifies the behavior of the inner object. You're basically creating an onion :)

Decorator pattern in the wild

If you've ever build a rails application, you've probably run into situations where the controller is filled with code responsible for formatting your data for presentation. There's a library called draper that allows you to write decorator models that wrap your models with functions that will do the formatting, which removes an additional responsibility from your controllers.

Why not just use inheritance?

Less flexible. With decorators, you can decorate your objects at run time by wrapping them with other objects. With inheritance, you lose that flexibility.


Object Oriented Programming

OOP is just one approach to creating computing abstractions that's very popular because it's based on how we already think and perceive. We see the world in terms of things (objects) doing things (methods), and thus a programming language that allows us to define computing processes using that way of thinking feels much more familiar than, say, writing ones and zeros. OOP languages are all just variants of how to formally define those abstractions to a computer. 

When I learned about object oriented programming in college using Java, I first learned a bunch of weird buzzwords like encapsulation, inheritance, polymorphism and that you need to make classes of things before they can do things. Oh and that in order to share the same set of behaviors in one class in the definition of another you have to use the "extends" keyword. So boring.  

This kind of introduction to OOP that starts with the unique terms of OO and language specific keywords makes it harder to grasp the essence of the why behind OOP. Students don't need to know the difference between an abstract class or an interface to "get" OOP. 

Regardless of what OO language you use, you'll always be dealing with objects and data structures. They're both data, but objects are a higher level abstraction that also comes with actions whereas data structures is just pure data. All the other terms surrounding OO that are language specific are just ways that that language allows you to define the behavior of those objects and their relationships with other objects. 

Concepts like "polymorphism" and "encapsulation" are just things that are made easier by OO programming, but are not exclusive to OO programming languages. I think it's much more effective to teach how to model processes with OO first, then introduce more specialized concepts once the basic big picture understanding is cemented. Things like "encapsulation" starts to make perfect sense once you start seeing the benefits of hiding the details of how a thing does something. 


Friday, March 17, 2017

Concurrency

Why do one thing at a time if you can do many things at a time? That's what multi-core processors allow computers to do - do many things in parallel. Even in single processors, from the users perspective it still seems as if things are running in parallel because operating systems are so damn good at context switching.

A thread is the fundamental unit of execution in a computer. It starts somewhere and ends somewhere. Once you introduce multiple threads of executions, you can open up a whole can of synchronization problems if you don't synchronize your threads!

For example, lets say Sally and Bob share a bank account. The way the system works is that there is a number of ATM machines in different locations that are connected to the central banking system. When someone initiates a transaction, a new thread of execution is initiated in the program that runs in the central system.

In this program, lets say there are accounts (one of which is shared by Bob and Sally).

The code involved in updating the balance as a result of a deposit is as follows:

newBalance = userBalance - amount (the calculation)
userBalance = newBalance (the update)

Now lets say Bob and Sally both attempt to withdraw at the same time. Lets say Thread A is the thread initiated by Bob and Thread B is initiated by Sally.

1. Bob and Sally both initiate a withdrawal of $100 from a starting balance of $500.
2. Thread A calculates the new balance to be $400 and then gets suspended while Thread B is run. At this point, the user balance is still $500.
3. Thread B ALSO calculates the new balance to be $400 and then goes to completion.
4. Tread A finishes with balance of $400.

They both withdraw $100, but the final balance is $400 :)

Luckily, there are several ways to synchronize threads so that things like this don't happen. A common construct is a semaphore which basically protects shared resources. So if one was used in this situation, it would be used to protect the account resource. If someone is already using the account to withdraw or deposit, don't let anyone (any other thread) access it.

How should you sort in this situation?

A master directory server receives a list of accounts, ordered by user ID, from each of several departmental directory servers. What's the best approach for this server to create a master list combining all the accounts ordered by user ID?

Questions you should ask:

  1. Are the list of accounts from each individual server already sorted?
  2. Can all the id's fit in memory?
Scenarios:
  • Individual lists are not sorted 
    • extra memory available
      • You can pretty much just pick a sorting algorithm based on speed. Quick sort will do.
    • extra memory not available
      • You're still fine with most sorting algorithms as long as they're in-place (such as quicksort or selection sort). 
  • Individual list are sorted
    • extra memory available
      • Merge sort can be very efficient here since the merge operation is O(n). Since we have extra memory, the auxiliary memory it needs may not be an issue. 
    • extra memory not available
      • You can still use merge sort if you lazy load the sublists. So instead of loading O(N) records in memory that will require an additional O(N) extra memory for the temporary buffer, you'll just have the O(N) temporary buffer and read the values of the sublists as you need them from either the disk or server. 
As you can see, there's no such thing as the"best" general sorting algorithm because it depends on what the constraints are!