A Trip to the Met

Surrounded in a sea of options, I felt an urge to head to the Met.

Software development is art

On the way there, I tried to explain this urge. It became readily apparent as I walked through the halls of Egyptian wing that software development is as much an art as these. One can only hope to be in a museum some day. Though, any dreams that my software creations will outlast me may be overly optimistic.

Art requires repetition and experimentation

Looking at the Madame Cezanne exhibit, with it’s many renditions of the same lady, I am reminded that many versions were made before the final product was complete. This is an inherent part of the process of experimentation and exploration. Bad art has to be made before they can be judged bad and discarded to made room for good. This exhibit was only just a peek. Many shitty drafts were made that will never be on seen except by the artist.

Artists are judged on the height of their greatest accomplishment, not the first thing they make

Another thought that occurred to me was that people are judged on their greatest contributions or indiscretions. People only care at all about the early work when your best work has already been accepted as great. In the hindsight of a career, only highlights make it and most first moves are necessary to build the foundations of a great career. It’s really only by building a lot that one builds great things.

Let’s delay no further. Let’s get started.

Flatiron School Week 12 – iOS Full time Report

For notes on the first half of the program, check out the halftime report.

The End of the Beginning

These three months have been a tremendous experience. I recall other three-month periods where nearly nothing has changed. In stark contrast, I didn’t know anything about making apps three months ago and now I can make 80% of the good ones out there and I will soon be able to make the last 20%.

Amidst celebration, the feeling of the real world seeps in. The realities of finding a job are readily apparent. These three months have been a working vacation, a sabbatical, with no need to worry about worldly concern, just code. Yet, this search feels so much different from the post-college job hunt. That felt like gauntlet of hurdles, where the goal was to shape myself into the candidate that would be hired. This feels like a dating process. Maybe it’s always been that way, and I’ve only now grown mature enough to see it as such. I go into each interview, each conversation with as much thought about how much I like them as I do with how much they may like me.


Flatiron School Placements

This week, there’s been a lot of job advice, most of which I agree with wholeheartedly.

  • The placements team tell us how to prepare for the technical interview.
  • They tell us how to think about the long term (your career) not just your first job.
  • They tell us how to network.
  • They help us practice mock cultural and technical interviews.
  • They host talks to connect us with alumni and industry people.
  • They help us with our individual situations and questions.
  • All these things are meant to help us get a get a job.

Note: If you’re an international student, it may be hard to find a company to sponsor your work visa. 

Note 2: iOS developer make slightly more than Ruby on average.

I’m expecting the job finding process to go through a few iterations and take at least 2 months.

My advice: 1. Just like dating, you have to go out there, meet people and build relationships. 2. Keep coding to keep improving yourself. 3. Stop when you’ve found a place you’re excited to work for at least a year or two.


iOS Client Projects 

In interviews, people like to see that you’ve worked on projects before and especially if you’re worked with clients before.

One of the things that no one told me was that iOS students have client projects for the last four weeks. Ruby students work on their own projects.

I worked with a team for a client called HireCanvas, which makes the college campus recruiting process easier (how appropriate for my situation).  We helped them build out a iOS version of their web app.

Half of your time will be spend figuring out where to go

  • For the first eight weeks of labs, objectives and deadlines were established for us. Coding as a career gets real when I sit in front of a computer and spend half the time figuring what needs to be done when and what should be done next. Not having this structure makes me appreciate the time and thought put into designing a curriculum. On the project, we also have to make choices that will determine whether the project will be done in time. Do I use a cocoa pod or build my own?

Git only gets real in groups

Teamwork helps you figure out what makes good teammates

  • The other thing about working with people is that it helps you develop an intuition for who you would want to work with and who you wouldn’t. Sometimes people surprise you. You might think that an experienced programmer would be great to have on a team until you realize that commitment was a more important trait to look for.

Communication Communication Communication

  • As with any type of project, communication turned out to be key. When communication breaks down, people assume the worst and death spirals are started. Talking through it, you realize that the thing you were worried about was not that important to the other person.

A note on legal agreements

Read before you sign. Try to change what you don’t like.

Unlike software agreements, employment contract and non-disclosure agreements should be reason to pause. People will pressure you to sign, so you can get the job. They will tell you that it’s standard practice. That’s a whole lot of bs.

If they’re never going to use a part of the agreement, you shouldn’t have to agree to it.

Make sure you understand what you’re signing and if you don’t like it. Ask if you can change it. A lot of times it’s so boilerplate that the people you’re working with don’t even know what’s in it. If it can’t be changed, ask whether it’s worth taking on the work. I’d rather forgo a project than sign something I’ll regret later.

One thing the school could have done better was show us the legal agreements we would need to sign for the client projects and for attending the school before money and time was spent.


Overall Lessons

1. The number one goal for coming to Flatiron School is to learn how to be self-sufficient as a developer

Use the time to learn to fish and you will have skills for a lifetime. Use this time to try and fail, not produce a portfolio or kickstart your startup. The real world is not as forgiving.

2. Flatiron School brings together very nice, talented people. Build relationships with them.

For most of college, I didn’t appreciate the diversity of human talent and what I could learn from others. At Flatiron, the side projects I’ve seen really brings out people’s passions. I appreciate being around so many talented people (students especially).

3. Have enough living expenses for 6 months before you come to Flatiron

People who only had four months are now scrambling to find the first jobs they can. That’s an unenviable position to be in. Give yourself the time to think about what you want to do after Flatiron. You might be a different person by then.

4. Learning to code will make you feel more empowered than ever before

Not only can you make other people’s dreams come true, you can make your own reality.

Flatiron School Week 11 – Week in Review

Week 3 of Client Project

One of our teammates have been dealing with an emergency for most of the last two weeks, so we’re down to three people.

The Science Fair is Wednesday and we want to have something to showable, so we scoped down our project to just what needed to be shown.

From Monday to Tuesday, our team and our app really came together. We are in the performing stage of the team “form, storm, norm, perform” process. I’m glad that my investment of time paid off. Everyone pulled their own weight.

I’m really impressed why what we were able to do in 2 weeks. People were really impressed at the Science Fair.

I’ve been so focused that I haven’t really been paying attention to how the other client projects were going. It looks like they had bigger clients and bigger expectations. That’s the benefit of having a younger client.

We ended the week with a huge celebration over at Sammy’s. So much fun.

Flatiron School Week 10 – Week In Review

Week 2 of Client Projects

Notes to Self

This week felt like I was reliving my first year out of college when I was working as a paralegal/project manager in a client facing team. That year, I learned more about communication and relationship building than anything else, themes that came up this week.

  • Giving feedback is one of the most difficult conversations between people. Admitting that you’re wrong is another. All difficult conversations are best done promptly.
  • On a small team, having a team member that isn’t able to contribute at the same level is a productivity killer because it means that productive people need to stop and invest in that team member. (Sam Altman has more on this topic)
  • Communication is key. When communication breaks down, trust erodes and people assume the worst.
  • As much as possible, it’s good to talk directly with the people involved. You build trust this way.
  • Don’t hesitate to pick up the phone.
  • Teams should have a single point of contact when working with clients to provide updates.

Flatiron School Week 9 – Resolving my first real git merge conflict

This week we started our client projects. 19 people broke down into teams of 4 or 5. There were four clients and our team had four people. This was the first time that I really needed to deal with git merge conflicts and develop a workflow.

It wasn’t long before I had a conflict.

There were three files that I conflicts with:

  1. AppDelegate.m
  2. the .pbxproj file
  3. a xccheckout file

1. AppDelegate.m

I knew how to resolve the first one, but as I tried to do that, my file directory on the left side of Xcode disappeared. It was time to ask for help. Zach, one of our TAs, helped me put together a plan to resolve the conflicts.

I had to back out of the merge, so I used

git merge --abort

and then reset the head to the last commit because there some uncommit changes that I didn’t want anymore.

git reset --hard <commit id>

2. the .pbxproj file

Apparently that file directory is stored in the .pbxproj file. The way that we resolved this was by telling git to just join the two versions together in the .gitattributes file by adding:

*.pbxproj merge=union

Another way to resolve this is to choose one version of the pbxproj.

git checkout --ours <directory/file>

Replace “ours” with “theirs” to get the version being merged into the current branch.

I had to add in some files that were no longer referenced by the pbxproj file after the merge using this second method.

3. a xccheckout file

For the .xccheckout file, this was a file that should have been ignored. I added this to the .gitignore file.

*.xccheckout

The problem was that both versions that I was trying to merge still had this file in tracked files. I had to remove this file from both repos by running:

git rm --cached <directory/file>

Once the .xccheckout file was removed, I could merge the two repos.

Both the .gitignore and .gitattributes files should be set up at the beginning of a project.

Update

Since that week, we’ve had to resolve conflicts many times. Following Github’s workflow has been pretty useful. I’ve found that the best way to resolve conflicts is prevention. We designed our workflow so that each person worked on a different part of the app and that minimized conflicts.

Flatiron School Week 9 – Week in Review

Mistakes and Lessons

Symptom: With custom UITableViewCell xibs, I was getting key value coding-compliant errors.

Mistake: When I was dragging over the views from my xib to my custom UITableViewCell class, the object chosen was “File Owner” and not the cell.

Lesson: Make sure there are no connections in the xib’s File Owner connection manager.


Symptom: Multipeer connections were not being made.

Mistake: The MCServiceType was too long.

Lesson: The MCServiceType has to be 15 characters or less.


Symptom: [self.tableView reloadData] was not reloading cells.

Mistake: I was calling the reloadData method inside a notification.

Lesson: NSNotifications are run on the background queue by default.

Notes to Self

Message syncing between servers and devices is a pain.

Reading code is a whole other skill.

I need to use CocoaPods more.

Flatiron School Week 8 – Week in Review

Topics: ScrollViews, views without storyboard, xibs/nibs, NSOperationQueue

This week was the last week of lecture, so we covered a grab bag of advanced topics.

Notes to Self

ScrollViews are sexy.

Bad public speakers (an anti-pattern)
  • don’t bring the audience with them and just start talking. Don’t explicitly say what questions they will address and how those are relevant to the audience.
    • Shouldn’t be thinking “what are we talking about?” “why are we talking about this?”
  • don’t speak loud enough.
  • don’t provide context for what they are saying and what problems they are trying to solve
  • go way too deep into things that the audience neither has context for or cares about
  • don’t paint a picture

Flatiron School Week 7 – Week in Review

Topics: APIs + Core Data, Authentication, Multithreading

Mistakes and Lessons

Symptom: API calls don’t tell you a lot when they don’t work. I wasn’t getting anything out of an internet request. Debugging API calls can feel like a text based adventure.

Mistake: Errors in strings are hard to debug. Apparently, when I had made the url, there was an extra “%”.

Lesson: Copy and paste urls that work from Postman, or use an encoder to convert strings to urls.

Symptom: When I changed the colors in my bocce game, the logic for choosing the next team to go broke.

Mistake: I had changed my colors away from the default colors (e.x. blueColor) to RGB values and had used == to compare the objects. The correct way to compare the objects is using an isEqual. Turns out that when you use [UIColor colorName] using == to compare is ok because they are at the same memory location.

Lesson: Use isEqual with objects and == with primitives.

Notes to Self

There are some times when I just have to slow down and plan out how something works. I was making a tableView that updated an API and a Core Data store. This very quickly got too complicated to keep in memory and I had to write down the interactions step by stem.

My partner and I decided to divide and conquer a lab. It became very hard for me to test along the way, because I was dependent on his piece to make mine work.

“If You Want To Go Fast, Go Alone. If You Want To Go Far, Go Together”

Flatiron School Week 7 – BocceGame built with UIDynamicAnimator

UIKit Dynamics

In my spare time, I wanted to look at animating physics collisions so I found UI Dynamics. It’s a part of UIKit that has some build-in functionality to animate physics based interactions. It’s generally not used for games, but rather for transitions and cool UI tricks.

A bocce game is a simple way to demonstrate this functionality. In bocce, there’s a target ball called the jack and two teams try to get their ball as close to the jack as possible. The team gets points for the number of balls that are closer to the jack than the nearest opponent ball.

Bocce Game Demo

Github Repo

How to use UIDynamicAnimator

You have an animator.

Animators can add behaviors.

Behaviors can add items that they affect.

My animator

    self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

One behavior is the UIDynamicItemBehavior behavior that allows the ball to continue moving after released by the hand with the add

self.linearVelocity = [[UIDynamicItemBehavior alloc] init];
[self.linearVelocity addLinearVelocity:velocity forItem:gesture.view];
[self.animator addBehavior:self.linearVelocity];

Another behavior is the collision behavior that collides with either a wall or another item.

//initialize collision behavior
self.collision = [[UICollisionBehavior alloc] init];
[self.animator addBehavior:self.collision];

How to make this game

Dragging a ball

Set up a UIPanGestureRecognizer that calls the dragged: method.

    UIPanGestureRecognizer *draggable = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(dragged:)];
    [self.currentBlock addGestureRecognizer:draggable];

The dragged method has the form:

- (void) dragged:(UIPanGestureRecognizer *)gesture
{
switch (gesture.state) {
case UIGestureRecognizerStateBegan:
//save the starting location
break;

case UIGestureRecognizerStateChanged:
{
CGPoint translation = [gesture translationInView:self.view];
 
//calculate the new location with the starting location and the translation
//set the location to the new location
 
break;
}
 
case UIGestureRecognizerStateEnded:
{
 
//figure out the velocity when the ball is released and add it to the item with the UIDynamicItemBehavior
}
 
break;
}
 
default:
break;
}

}
}

Continue a ball moving after release

Right now, the ball would stop when I let go of it. To keep it going at the same speed, get the velocity in view from the gestureRecognizer and add it to the UIDynamicItemBehavior with addLinearVelocity: forItem:

//Inside the case UIGestureRecognizerStateEnded
CGPoint velocity = [gesture velocityInView:self.view];
[self.linearVelocity addLinearVelocity:velocity forItem:gesture.view];
[self.animator addBehavior:self.linearVelocity];
 
//necessary to make the motion smooth, otherwise it will be jumpy if you hold down the 
[self.animator updateItemUsingCurrentState:gesture.view];

Stopping the ball

The ball will keep going on for a long time, so I needed to stop it somehow.

Stop the ball by adding friction. In UIDynamicItemBehavior, friction is the resistive force between two objects. I wanted resistance to simulate air resistance. Angular resistance was needed to stop the balls from spinning too.

self.linearVelocity.resistance = 8;
self.linearVelocity.angularResistance = 8;

Only allow one animation to run at a time

I found that trying to flick a ball before another had finished moving was making a really jumpy animation, so checked if the animation is running with each gesture recognized and only let the new block move after the other was finished moving.

- (void) dragged:(UIPanGestureRecognizer *)gesture
{
    if (![self.animator isRunning]) {
        switch (gesture.state) {
...

Detecting when the ball was stopped

To find out when to make the next block, I needed to know when the ball had stopped moving. I used the

- (void)dynamicAnimatorDidPause:(UIDynamicAnimator *)animator

method. It’s a delegate method so I had to set the

    self.animator.delegate = self;

Making the target ball bounce off the walls

I didn’t want the target ball to go off the screen, so I set the screen boundaries as walls,

[self.collision setTranslatesReferenceBoundsIntoBoundary:YES];

made the ball bound off all objects including boundaries (referenceBounds being those of self.view because the animator has self.view as the reference view),

[self.collision setCollisionMode:UICollisionBehaviorModeEverything];

and added another invisible wall, so that the ball would not end up on the top edge of the screen.

[self.collision addBoundaryWithIdentifier:@"end" fromPoint:CGPointMake(0, self.view.frame.size.height*0.1) toPoint:CGPointMake(self.view.frame.size.width, self.view.frame.size.height*0.1)];

Take the target ball out of collision

I wanted to make the target ball immovable, so I just had to remove it as an item of the collision.

[self.collision removeItem:self.currentBlock];

I also wanted future object to be able to go off the screen, so I removed the “end” boundary and the window boundaries.

[self.collision removeBoundaryWithIdentifier:@"end"];
[self.collision setTranslatesReferenceBoundsIntoBoundary:NO];

Ignoring most the call to dynamicAnimatorDidPause after a ball is made

After a new object is added, dynamicAnimatorDidPause is called, so I had to add a BOOL property justMadeBlock to ignore those calls.

Stop the moving block when it goes offscreen

If a ball was flicked too hard, then it would go off the screen and I would have to wait for it to stop before the next ball would load. To shorten that time, I made another boundary outside the edge of the screen and overwrote a delegate method to make the ball stop moving and not able to collide with other blocks.

[self.collision addBoundaryWithIdentifier:@"outOfBounds" forPath:[UIBezierPath bezierPathWithRect:CGRectMake(-90, -90, self.view.frame.size.width+180, self.view.frame.size.height+180)]];

Delegate method for the UICollisionBehavor

self.collision.collisionDelegate = self;
- (void)collisionBehavior:(UICollisionBehavior *)behavior beganContactForItem:(id<UIDynamicItem>)item withBoundaryIdentifier:(id<NSCopying>)identifier atPoint:(CGPoint)p
{
    if ([((NSString *)identifier) isEqualToString:@"outOfBounds"]) {
        //not allow it to move
        [self.linearVelocity removeItem:item];
        //not allow it to interact with future blocks
        [self.collision removeItem:item];
    }
}

Calculate the nearest ball and marking the nearest ones

Once a colored ball had been thrown, there is now a winning ball (closest to the target).

I took all the balls on screen.

    NSArray *blocksOnScreen = [self.collision items];

Got their locations

Sorted the array of balls by location

And found the balls of the same color that were closest to the target ball

With those “winning balls”, I added a CALayer to them to mark them as winning.

The next to go would be the team further away from the target.

At the end of the game, a UIAlertController asks if you want to play again.

Adding indicators for the number of balls remaining per team

I used CAShapeLayers and added them to the self.view.layer. They would update as balls were made.

Adding a flashing turnIndicator

The alpha controls the opacity of the text label, so setAlpha:1.0 means make it appear.

UIViewAnimationOptionAutoreverse makes it disappear again.
UIViewAnimationOptionRepeat makes the animation keep going until you stop it.
UIViewAnimationOptionAllowUserInteraction allows you to remove the animation later on.

[UIView animateWithDuration:1.5 delay:0 options:UIViewAnimationOptionAutoreverse| UIViewAnimationOptionRepeat | UIViewAnimationOptionAllowUserInteraction  animations:^{
        [self.turnIndicator setAlpha:1.0];
    } completion:nil];

Stopping animations

When I tried to reset the game, setting all the properties back to nil worked well, except for stopping the turnIndicator animation.

There I found that the animation is in the layer of the animated object.

[self.turnIndicator.layer removeAllAnimations];

Choosing a more attractive color scheme

Adobe’s color wheel was really cool. I like pastel colors, so this is what I chose.

Notes to Self

Writing code takes way longer than expected

I didn’t think that it would take very long to make this, (just slap some blocks on a screen right?) but building features takes time and focus. Really quickly, seeing jumpy animations makes you want to fix them and that’s the 20% that takes the most time. Writing blogs about code also takes hours…

User testing is super important to do throughout

I knew how the game was played, but it wasn’t obvious to people I showed it to. I really wouldn’t have known if I hadn’t had someone use the game.

Don’t let sidetracked on super advanced features when the basics are not done

The flip side of asking for feedback is that people start giving you really good suggestions, but I think you have to finish one phase before hacking away at the next thing.

Hacking is fun with something quick, but it’s no fun with a big project

This is the second project that I’ve hacked to together. It’s been fun, but I really would have liked to have classes for the data model. This game was made over three weekends and I was finding that when I wanted to add new features, I had to recall the mental model that I had for the project. Instead I should have had a game class that remembered the model for me.