What I did after taking over a negative iOS project

What I did after taking over a negative iOS project

Half a year ago, I joined a startup team that had just received Series A funding to be responsible for the iOS project. In the early days, the company was uncertain about its survival, and they only pursued rapid iteration to find the right direction. This kind of early unknown team did not have much engineering pursuit, just writing fast was good. However, after determining the direction, they need long-term development and cannot grow wildly.

Based on my practical experience in this project over the past six months, I would like to share it with you.

Code hosting: self-built Gitlab

The easiest way for grassroots teams in the early days was to use GitHub. But as the number of team members increased, the cost of using GitHub became very high. The average team package costs $9 per person per month. Another problem is that GitHub is deployed abroad, and the domestic access network is often unstable. I heard that the code of a multinational team was hosted on GitHub, and GitHub could not be accessed normally during an important meeting. It was really a sudden fatherly love. Another disadvantage is that it is not convenient for the server to configure the CI service by itself. If it is deployed on your own server, some other service scripts are also deployed together, which will give you a lot of autonomy. After comprehensive consideration, I chose the mainstream Gitlab.

Engineers' time is more valuable than machines

Many short-sighted teams think that the equipment provided to engineers is too expensive, so they just pick a cheaper one. Although a good computer is more expensive, the compilation time saved by engineers in the long run is much more expensive than the machine. In terms of equipment, I suggested to the company that they should equip it with the latest 15-inch rmbp and a dell 4K monitor. Later, I found that keyboard and mouse are also important, so each person was subsidized with a keyboard and mouse quota of 500 yuan. I saw that many engineers are still using air for development, and some are using mac mini. I really feel sad for such stupid companies. A team I used to be in used the same computer for 4 terminals. Every time I compile, I go for a walk on Nanjing Road. If I have to go online at night, I can go to the movies and come back.

Hire people early

Recruiting is a very important part of the team development process. Many early teams underestimate the difficulty and cycle of recruiting. This is because there are two disadvantages for less well-known teams to recruit people:

Can't offer too high a salary

Excellent talents will of course compare the salaries in the market. Companies like BAT, which have been well-known for a long time, will naturally have salary advantages. Although startups have options, the future of the company is uncertain after all. Many engineers are also worried that the company will go bankrupt in the near future.

The team has many and complicated tasks

After a project matures, iterations are mostly carried out step by step with a steady rhythm. Each link has a dedicated staff. For early projects, since the project is still in the growth stage, it is very likely that we will see that live streaming is popular halfway through, so we will add a live streaming requirement. Or we may find that a competitor has a function, and we will just release it in the next version without worrying about it. Or the CEO may suddenly have an idea when he passes by, and the launch time will be postponed again.

In addition to the technical hard indicators, there is also the issue of engineering team culture in the early stages of recruiting. For a project with dozens of people, the enthusiasm of a particular person is actually not very important to the project. He just needs to complete the work that should be completed. Even if he doesn't talk to others, it doesn't have much impact. A large project cannot stop running just because any one person is gone.

But in the early stage of the team, there are only a few people. If one person has a different understanding of the team's mission, there will be a lot of friction in daily behavior.

I have thought about what team culture is and how to describe it. Later, I saw a saying that seemed quite appropriate. Culture is like air, it is everywhere. The company does not require you to respond to user feedback on social platforms after get off work, nor does it require you to ignore or communicate with people in other departments when you find problems with products in other departments, or whether you should raise a better suggestion with the company. The support behind these behaviors is team culture. The people in the team determine the values.

To sum up, if you are lucky, you can find a matching technician in a few days, but more often it may take several weeks. Of course, if you hire someone in a hurry, and find that he is not suitable after working for a few months, it will also cause great damage to the morale of the team.

Therefore, considering the future progress of the project, you should start the recruitment plan in time. If you start recruiting when you find that the progress is too busy, you will have to take time to prepare for the interview and take into account the progress of the project, which will be very stressful.

Transition to Swift

The other three colleagues in the team had no experience in writing Swift before. However, considering the future development trend and the fact that our business type does not require dynamic development, I insisted on promoting the use of Swift programming in the team.

One question I am often asked is if you want to use Swift but other people in the team don’t know how to use it, will it cause difficulties in advancing the project? In fact, if someone in the team guides them correctly, helps them solve problems in the process of getting started, and gives them some time to transition, they will soon be unable to turn back.

Here is my process of migrating from OC to Swift.

First, write the network layer library in Swift. Then bridge several commonly used OC Models and Swift objects. It should look like this:

  1. class SwiftUser {  
  2. init(ocUser: OCUser) {  
  3. }  
  4. func convertOCUser() {  
  5. }  
  6. }

After this transformation, a new module can be written completely in Swift. At the beginning, Swift code must be written with OC thinking. But after getting familiar with Swift syntax, you can slowly suggest a more Swift way of writing during the review process. Some functions require OC and Swift to call each other, which is really troublesome. If a person with no Swift experience is asked to solve these problems, it must be very discouraging. Therefore, a certain amount of time must be allocated during the project to rewrite the old OC code. Fortunately, the original code is very messy and needs to be rewritten. In this way, as the business progresses, the proportion of Swift is getting higher and higher.

In this way, after one or two months, everyone will gradually become familiar with Swift, and then we can promote the use of frameworks such as RxSwift.

Streamlining development workflow

In the early stages of a project, there were thousands of requirements. How many functions should be developed in one iteration? The product manager instinctively relied on his intuition. After listing a page of requirements, he said that this was the version. Programmers tended to estimate the time optimistically, and half a month passed by. The requirements for the next iteration, UI design, and pre-delivery testing were all in a mess.

After discussion, we decided to have an iteration cycle of two weeks. During the development process, if we found that a certain requirement could not be completed in this iteration, we would move it to the next iteration. Everyone was clear about what to do in each cycle. It was also a good rhythm to release it every two weeks based on user feedback.

What needs to be emphasized here is the preparation work in the early stage of the development process. Mainly refers to requirements and UI diagrams. Most of the requirements design is developed around a certain requirement, but there are many surrounding tasks to be done to integrate this requirement into the existing system. For example, the product proposes that user information should be tagged. So a sketch was drawn with labels. For him, this requirement may be described very clearly, but when it is actually implemented, there will be other work to be done. For example, how to delete a label? Is there a word limit for labels? What if labels are repeated? If these issues are not clearly expressed in the early design of the product, they can only be communicated back and forth during the development process. Having an experienced developer participate in the discussion of requirements in the early stage and raise questions is of great help in later development.

A designer who doesn’t use Sketch is not a good designer

I see many designers stick to the tradition and keep using PS. However, in fact, the use of vector design tool Sketch is already very common in the industry. Nowadays, the screen sizes of mobile phones are more different. If you design with bitmaps instead of vectors, it will be very inconvenient to do responsive layout design. In fact, if you are used to Sketch for mobile UI design, it will definitely greatly improve your productivity.

But like most people, many designers feel that PS is quite easy to use, and have never used Sketch. In fact, leaders have the obligation to push some people to make good things happen.

In my previous team, I kept hinting that only mediocre designers use PS. After a few weeks of prodding, he said that he could also use Sketch. Later, as all the symbols for the project were gathered, PS was used and he couldn't go back.

Of course, there are also very old-school designers. This kind of people can only be pressured to change passively. At that time, there was a designer in his forties in our team, and we were also in a difficult situation. I thought, forget it, if you can't use Sketch to produce drawings next month, you should prepare to change your job. Of course, as a team, we can't just give instructions and leave it alone. The designers who are already proficient in Sketch will pay special attention to his learning status and provide timely guidance. In the end, we got a good result. After being forced to change, he found that Sketch is indeed more useful.

Here is a very useful software for outputting design drawings: Zeplin. It would be very rigid to use annotations directly on the design drawings. The efficiency will be greatly improved if the programmer can view all the source information of the design drawings during the viewing process.

Access CI

Many teams change the macros in the code to distinguish the environment in the app, and change the macros before each submission.

Sometimes, someone forgets to change the environment macro, and the app connects to the test environment. What I want to say here is not to check carefully before publishing, but that this situation should not happen.

In fact, manually submitting through Xcode packaging is also a risky process, because from time to time, a few lines of code are changed locally, and the local code is also submitted when submitting, which brings unknown risks.

I differentiated the environments by configuring the scheme and target in Xcode. I used fastlane to complete the automatic packaging and uploading. I combined it with Gitlab's CI and configured Gitlab runner. From then on, packaging only required clicking a button. This reduced the risk of manual operation in publishing.

Our components use cocoapods to manage dependencies. After configuring Gitlab runner, the component version update is also done remotely instead of locally. After configuring webhook, everyone in the slack channel will receive a message after each job is completed.

Make good use of Testflight and pay attention to beta feedback

In the early days, the business changed frequently and there was no automated testing. We could only rely on manual testing to ensure stability. At the beginning, the team chose to release the enterprise version package for testing. Of course, enterprise version users can easily download and install it, but it also has many disadvantages. The biggest disadvantage is that this package and the App Store package are two packages with different bundle ids. This will cause some functions bound to the package to fail to be tested normally, such as WeChat login and jump after payment.

Our business has a chat function, and the chat history is only stored locally. And we believe that an account can only be logged in on one device on the same platform. This results in the account being logged out from the App Store version during user testing, and the chat history is lost. Enthusiastic users are willing to try our beta version, but they also bear an unnecessary price. Based on this consideration, under my leadership, we gave up the method of releasing the enterprise version package for testing. Instead, we used testflight testing.

Testflight has a high threshold for use. You need to collect the user's email address, and then enter the invitation code sent by Apple in testflight to start testing. Many users quit because they find it troublesome. Operations believe that this will cause great inconvenience to the test. But after calming down, things are not that bad. Users who are really interested in this product will not give up just because they have to fill in an email address. Those who are lost are just ordinary users. After users use Testflight, they will also receive updates for subsequent test package releases. Unlike the enterprise version, we can only manually tell users that we have a new test package. When the number of active users in the beta test exceeds 100, there will be a qualitative change. These are all active heavy users. A group of heavy users using your new version for a few days can at least ensure that the core business logic is flawless.

Someone asked us before if using Swift would cause a lot of problems if we couldn't dynamically fix serious bugs online. In fact, because of the beta testing process, serious accidents rarely occur. One accident happened when we upgraded our Swift version to 4.0, and an enumeration was incompatible with iOS 8 devices (Xcode didn't remind us, it was Apple's fault). That version also happened to be the last version that supported iOS 8. None of our test users used the iOS 8 system.

It is also very important to allow users to give feedback in a timely manner during beta testing. If I give you feedback on a problem, I will ask you to check the app version, which page it is on, and my user ID. Users are very good-tempered. We have integrated the function of shaking to report bugs in the app. All effective information, such as operation steps, network requests, device information, etc., will be collected together. It can be easily viewed in the background. Tell users to shake the app and describe the problem when they encounter a problem. We will receive an email after the user gives feedback, and timely feedback to users will also make them feel involved.

The shake function is not open to all users, but only to certain specific users we can contact. After all, engineers need to follow up on every feedback. If it is open to all users, we will receive too much invalid information. I often see engineers discussing where to hide the entrance to these developer functions. Some say to enter specific characters in a text box, and some say to click a few times in a corner. I choose to configure the entrance to the developer panel in the universal link. In this way, users will not accidentally reach it anywhere in the app, but can only reach it by jumping through the link we tell them.

Adhere to Code Review and Enhance Technical Communication

Code review is a magical thing. All qualified engineers think code review is good. As far as we know, many excellent IT companies abroad pay great attention to code review, but in China, it is rare to see teams performing code review. Or code review is rarely seen in small and medium-sized teams.

But I value code review. From a sentimental perspective, it is a kind of inheritance of engineering skills. Even if a method name is not good, from the company's perspective, the project will still work. But from the engineer's perspective, if you have the ability, why not help those who are just starting to write code with some guidance?

As a leader, helping members grow during the review process will lead to different results than just checking whether the code can complete the function. I have read a very touching sentence: many leaders now know that they need to manage others in their work, but they ignore the need to lead.

To be honest, I did encounter a lot of resistance in promoting code review. There were resistance from both inside and outside the team. People outside the team believed that code review slowed down the progress of the project. As a core development member, I had no visible work output for more than 20% of my time every day. Sometimes I had to send other people's work back for revisions due to problems, and a completed feature took a few more hours. The problem encountered within the team was that many members did not understand the value behind this work. It was easy for them to think that I did not advance the project progress in the morning, but was just sitting there not knowing what I was looking at. They felt that I did not commit much code. In the end, I won the team's "Minimum Code Output" award.

Personally, I would be more relaxed if I didn't do the review. I can definitely control all the details of this feature. It's just not good to write it this way, but it's not unusable. I don't need to explain to them why it's not good. I just need to ask them to change it according to my comments.

But what is the point of persisting in such a thankless task?

When I first started working, I met a university professor on my way to travel. We chatted and asked him a question. In ancient China, people would embroider flowers on the soles of shoes. Others could not see the soles of the shoes. What was the meaning of doing this? He replied that we do not do things for others to see. In the end, we still have to pass the test in our hearts. Flowers are embroidered on the soles of shoes, which others cannot see. You know it yourself.

<<:  Record an APP transfer process

>>:  King's Counterattack: Use AI to play WeChat Jump Jump, automatically brushing points to break 10,000 points

Recommend

They are both iced coffee, why is cold brew more expensive than iced Americano?

In the hot summer, many people often drink a cup ...

Where will WeChat go in the second half?

[[243547]] Image source: Visual China In the firs...

Swift social app text input optimization "hodgepodge"

1. Input-related optimization issues In most appl...

Google's three magic weapons to maintain its search dominance

On January 18, the American website medium.com pu...

The future is here: face the era of self-driving cars

With the development of technology, self-driving ...

How to choose bidding software for bidding promotion?

When we do bidding promotion, we will come into c...

5 tips to help you end "impulse buying" and save 100%

Today is 618, and those who like online shopping ...