ecobee Co-op

iOS Developer

Winter & Summer 2019

ABOUT ECOBEE

ecobee is a Canadian tech company based out of Toronto. Founded in 2007, the company was the first in the world to release a smart thermostat that provided energy-saving features. Recently, ecobee has continued to invest in the "Smart Home" concept and has released room sensors (that complement the thermostat) and a smart light switch.

There is also an iOS and Android app that acts as the "hub" to control all the devices a user may have in their home.

In addition, ecobee offers a service called SmartBuildings which provides solutions for managing several thermostats in a commercial building.

          

© ecobee

© ecobee

 
 

ABOUT THE JOB

After spending a combined total of twelve months working at Tulip as an iOS Developer and Software Developer, I decided that iOS development was my true passion and therefore wanted to return to an iOS Developer position for my final two co-op work terms but at a new company (to try something new!).

I have divided this section of my report into different topics which are all related to my experiences while working at ecobee.

Storyboards vs Code

Prior to working at ecobee, I had done very little work that involved creating user interfaces and adding constraints through code. The iOS team at ecobee had been using Storyboards but recently made a decision to begin using "components" to build new features in the app.

For example, the screen to the right has a total of 6 unique components. The last 5 rows on the screen are all actually one type of component, just reused. This allows us to create and modify screens in the app quickly and easily since it is just a matter or choosing which component we need and passing in its content (such as a title, subtitle, image, etc).

If you are an iOS Developer yourself, you are probably thinking what I just described sounds very similar to a UITableViewCell. Your are correct, except the components we created are written to be much more generic than a UITableViewCell. The technical reasons why are besides the point of this work term report so I won't waste your time.

What does this have to do with me not having much experience creating user interfaces and using constraints through code? Components do not use storyboards, they are all created through code. When creating a screen that includes a group of user interface elements, you need to tell iOS where to place each user interface element on the screen (that is the purpose of constraints).

 

Prior to working at ecobee, I had used constraints through Storyboards but I'll admit that I got into a bad habit of using Storyboards' ability to auto-generate constraints. Doing this prevented me from actually understanding the different types of constraints and how they actually work together. Therefore, I had to learn how to do all of this manually and in code. It wasn't easy to understand at first, but I was able to use existing components as a guideline and with the help of some of the more senior developers on the team, I was able to make components on my own within my first month on the job and I would feel comfortable moving away from Storyboards in my personal projects.

GraphQL

Huh? What the heck is GraphQL?

That was my reaction when I found out that the iOS and Android apps use GraphQL to communicate with the mobile backend. Back when I was working at Tulip and worked on personal projects, I had dealt with RESTful and CRUD API's so GraphQL was an entirely new type of API for me to work with. At first glance, I thought it was just a fancy way to make an API call but then I was told about its main benefit; only returning the data you need. For example, lets say the following properties exist for a thermostat in the backend:

type Thermostat {

    id: ID

    name: String

    currentTemp: String

    setTemp: String

    fanOn: Boolean

    heatOn: Boolean

}

Being the mobile app, if all I need to know is currentTemp, a "traditional" API would have one GET endpoint that returned all the properties of a thermostat whether you needed all that info or not. With GraphQL, I can create a query that only asks currentTemp be returned:

thermostat(id: $id) {

   currentTemp

}

Having the ability to request exactly what I need is appreciated because it decreases latency when making network requests allowing for a more responsive user interface.

In addition to being able customize my request, I also learned how to use fragments which allow the same properties to be shared between multiple queries. Using the same Thermostat type from above:

fragment temperatures on Thermostat {

    currentTemp

    setTemp

}

query ThermostatTemperature($id: ID!) {

    thermostat {

        ...temperatures

    }

}

query AllThermostatFields($id: ID!) {

    thermostat {

        id

        name

         ...temperatures

        fanOn

        fanOff

    }

}

Both queries will include currentTemp and setTemp in their responses.

Overall, I found GraphQL to be a great tool to use and would definitely use it in any future personal projects I work on.

Scrum vs Kanban

ecobee is a company of many teams which include: iOS, Android, Mobile Backend, Thermostat (Hardware), Thermostat (Firmware), Switch+ (Hardware), Switch+ (Firmware), and feature specific teams (for example, eco+ had its own team to to create the backend for that feature). The company is currently working on a lot of new "stuffthat I can't quite mention yet but making sure all the teams are in sync with each other can be a challenge.

Though I wasn't directly part of the eco+ team, I did go to meetings that involved me representing the iOS team. When I first starting working at ecobee, most of the teams used Scrum as their software methodology of choice. With this in mind, one of the features in eco+ is that you can toggle on and off the five settings (see screenshot of the app above). In order for this feature to be implemented, the eco+ team needed to implement their backend logic, then the Mobile Backend team needs to update the GraphQL schema to include new types and mutations that allow the iOS team to actually update the settings.

Sounds straight forward enough right? Well, the iOS team and eco+ team operated on two week sprints whereas the Mobile backend team worked on one week sprints.

What happened was the eco+ team committed to implementing the backend logic in Week 1, but when the Mobile Backend team was planning their sprint in Week 2, the eco+ team had not completing their ticket yet. This meant the earliest that the Mobile Backend team could start their work was in Week 3; in turn meaning we (the iOS team) could not start our work until Week 4. Everyone agreed that a 4 week timeline to implement a API call end-to-end was a little excessive.

One possible solution was to have all the teams work off of the same sprint duration; however, with the amount of work all the teams were juggling, our Agile Coaches suggested several teams to transition to the Kanban methodology. Kanban allowed us to consistently re-prioritize all the tickets in our backlog and begin working on the most important tickets as soon as they are ready (instead of having to wait until the next sprint).

Using the same eco+ example, as soon as the eco+ team finished their work, the Mobile Backend team would be able to begin working on their ticket as soon as they have the bandwidth (since Kanban does not have a concept of "sprints", rather "continuous integration"). Then, when they are done, we can start our work. After the teams started Kanban, our end-to-end implementation never reached four weeks.

Prior to this work term I had never actually worked with push notifications (I have only ever worked with local notifications). One of the new features we were working on required push notifications and I volunteered to be the point-person for the iOS team. Since I didn't know how Apple Push Notification Service (APNS) worked, I conducted my own Spike to create a Proof of Concept app.

When I was reading through the APNS documentation I found that there are two main ways to send the contents of the push notification.

 

The first way is that the server sends the title and body of the push notification in the payload; however, even though the iOS app does not support multiple languages, we do have the infrastructure in place so that when we do want to support multiple languages it should be relatively easy from a coding perspective. Therefore, if the server was to send us the strings, the server would need to know what language the users device is using. For this reason, this solution was not favoured by anyone.

The second way to handle push notifications is to have the title and body strings stored locally on the device in the localization file. In iOS, every language that app supports has its own localization file that contains a key for a specific label in the app and a value (which is the text that gets displayed to the user in the appropriate language). For example, say the localization key is "ECOBEE_NOTIFICATION_TITLE". If the server sends the same key in the payload of the push notification, iOS is able to use the key to find the correct text to display. This was clearly the best solution in my opinion.

I reported my findings to all the stakeholders involved in creating push notifications and presented a demonstration of my Proof of Concept. They all agreed that the second option was the best. I then wrote the code for the iOS app to receive and display push notifications.

At the 2019 Apple Worldwide Developers Conference, Apple announced that Xcode 11 would include deeper integration with Swift Package Manager. For our app, we use Carthage to manage our dependencies. We also have several private frameworks (created by us) that we import into the app. For example, we have our own dependency injection framework.

 

In the spirit of learning, I wanted to figure out how I could refactor that framework to use Swift Package Manager. To be honest, it blew my mind how easy it was. All I had to do was create a file that specified which platforms the framework should be built for and any dependencies that the framework required which then Xcode automatically downloads. To then add the "package" into the main app was a simple as a couple of clicks in Xcode.

When I was done exploring Swift Package Manager, I talked to my team about how it works and possible advantages of using it. They acknowledged that they are also interested in transitioning to Swift Package Manager and will take a deeper look into when Xcode 11 is released in September.

GOALS

LEARN
GRAPHQL

Given that the iOS app used GraphQL to communicate with the backend, I didn't really have a choice to learn how to use it. However, at the time I started working, the app had only used simple queries and mutations so there was room for me to learn about some of the more advanced features of GraphQL.

As our team implemented more and more queries for new features, we began to have several queries that contained the same fields. As a result, I began using "fragments" in an effort to make some of our queries contain the equivalent of reusable code.

At one point I also encountered a situation where I had to use "inline fragments" (which was the first time any query in the app had to use it). The GraphQL schema can specify interfaces and in order to use the interface within a query, you need to use an inline fragment.

Overall, I was able to quickly understand the advantages of GraphQL and use queries, mutations and fragments with ease to request data from the background. For this reason, I accomplished this goal.

CONDUCT
SPIKES

In my previous co-op jobs, I never had an opportunity to conduct a formal spike. I always try to improve my technical communications skills in both written and verbal formats; doing at least one spike was therefore a great way to continue to improve these skills in my opinion.

When developing new products and features in the mobile apps, ecobee has Employee and Customer Field Trials. When employees and customers give us feedback we usually ask them to record their screens and manually send us the video. In January, the iOS team was wondering if there could be a way that we could automate the screen recordings so we can see videos from all of the people involved in the trail.

We decided to look into third-party frameworks that would record the users screen and provide detailed analytics regarding their interactions (such as heatmaps).

I took the initiative to conduct the spike and decided to look into two third-party frameworks. I created two branches (each using one of the frameworks), tested their functionality and documented any limitations I found or features that we could leverage.

Once I was complete, I presented my findings to the team during a meeting. My presentation included the pros and cons of the two frameworks and how we could use them to accomplish certain goals.

At the end of the day, we never implemented any form of screen recording due to privacy concerns; however, I still believe I have accomplished this goal since the point of it was to conduct at least one spike and I also completed the Push Notification spike I explained in the previous section.

COLLABORATE WITH OTHER TEAMS

When I worked at Tulip as an iOS Developer, I worked with a small team that include another developer, a UX designer, a Project Manager, and stakeholders from Indigo. At ecobee, there are teams for each product and feature that is being built.

Given this structure, I believed that this would be a great chance to work on both my technical and non-technical communication skills during cross-team discussions.

 

Near the beginning of my work term, I was assigned to be the point-person for the eco+ feature on the iOS app. Every week the entire eco+ team (including UX designers, backend developers, and project managers from different "sub-teams" (you can think of iOS as being a sub-team)) would get together to talk about how the feature was progressing and address any concerns. It took me a little bit to get comfortable in my position but eventually I was comfortable enough to "challenge" (in a good way) people's thoughts on how certain aspects of eco+ should work. Giving my opinion sometimes required me to provide technical reasons as to why we should do something one way instead of another; sometimes I just pretended I was a user and acted as if I was using the feature for the first time.

Even though my ideas didn't always turn out to be the best ones, because I was able to work in cross-team environment and work together to create the best feature we could, I have accomplished my goal.

SLOWWW DOWN

In the first four months of my work term, I would often get into the mentality that I need to complete as many tickets as I can, as fast as I can. Doing this would lead to situations where I would miss an edge case while testing which means I've created a bug that I probably could have caught if I had took my time.

Therefore, this goal was a pretty straight forward one; take my time and spend time writing proper unit tests to ensure that I catch bugs before they make it into production (the app store).

To accomplish this goal there wasn't much to do other than keep reminding my self to spend time writing good unit tests after I completing what was asked of in a ticket.

By the end of my work term I think I did a better job thinking through the edge cases in my code. Though there were definitely times where I sometimes may have "sped up" again, I was able to remind my self to slow back down.

CORE PROBLEM SOLVING

We are using a third-party library called MagazineLayout that helps manage the layouts of the user interface elements on each screen of the app.

In most apps, there are scenarios where you may need to update one row on the screen with new content. However, when the iOS team first started using MagazineLayout, the app contained mainly "static" content. As a result, in the few scenarios where content did need to be refreshed the developers simply opted to refresh the entire screen rather than just the rows that needed to be refreshed. In iOS, refreshing certain rows requires specific logic which if not implemented correctly, could lead to the app crashing; whereas, if you tell iOS just to refresh everything on the screen, the chance of crash happening because of the reload is close to zero.

During my work term, we began working on screens that were much more dynamic than the existing screens. We technically good get away with the existing "refresh everything" logic, however, it is not very performant and actually led to some bugs with MagazineLayout.

Therefore, I decided to explore how we could begin introducing the concept of reloading by row (instead of everything). I initially made a proof of concept which then a full-timer used to create a full solution.

Because I didn't end up implementing the full solution (not because I couldn't do it but because our Kanban methodology required the full-time employee to take the next item on the TODO list), I would still like to be able to actually implement an improvement to a core aspect in the codebase.

 

CONCLUSION & ACKNOWLEDGMENTS

The eight months I worked at ecobee was a very rewarding experience. Not only was I able to solidify my iOS development skills but also learn about other agile methodologies and API query languages.

 

I would like to thank the entire iOS team; Vince, Colin, Miwand and Yo for helping me talk through problems I was trying to solve and always proving me with constructive feedback regarding the code I wrote.

I would also like to thank my manager, Joe, for sharing his previous developer experiences with me in order to help me become a better developer.

I would also like to thank the countless people I've worked with from other teams including the Mobile Backend team (for helping me understand how GraphQL worked), eco+ and User Experience teams (for valuing my suggestions on how to make the eco+ feature better and improve the iOS user interface designs).

For any co-op students looking for their next job, I would strongly suggest you consider ecobee for any team. I believe ecobee has a bright future and I enjoyed my time so much that I will be returning full-time once I graduated next year.

Engineering&PhysicalSciences_SoCS_versio
ecobee_logotype_Pantone.png
Experiential-Learning-Hub_co-op.png
 
This site was designed with the
.com
website builder. Create your website today.
Start Now