The title is a bit scary, please don't be afraid, but this is not a literacy post, and you need a certain foundation in iOS development. In my many years of career as a programmer, most of the time I worked on small projects, and the larger ones might be about a million lines of code, which is nothing compared to the tens of millions of lines of source code of the Windows system. However, a source code of an iOS project with millions of lines is quite large. What I want to say is that people will always grow, take on greater responsibilities and accept greater challenges, and one day the organization will give you important tasks. However, software development is not a one-day or one-night stand, nor will it be so grand and vigorous, but more about countless details in the ordinary. Doing large projects does not necessarily require advanced technology, perhaps it is the scientific processing of details and standardized management. First of all, let's talk about the choice of programming language, Objective-C or Swift? I haven't used Swift in the project yet, because I can't convince myself to use it. What are its advantages? You can't force your teammates to learn Swift. Of course, not using it doesn't mean you can't. People who use Swift to develop meaningless products as soon as they enter the industry are not qualified to look down on their peers who don't know Swift with tinted glasses. Do you know how many pitfalls there are when mixing Objective-C and Swift? Do you know that Swift also shares a Runtime environment with Objective-C? Do you know that using Swift will make the ipa package more than 10M larger? Swift represents the future, and Objective-C is the present. Everything that Swift can do in Objective-C can be done, such as Closure can be completely replaced by Blocks, and Tuple can be completely replaced by structures. Use Objective-C in production environments, and watch Swift as an amateur. This is my attitude. Raywenderlich has already released a bunch of Swift tutorials. China is always a step behind in the use of cutting-edge technology. To a large extent, that wall has hindered the development of domestic IT practitioners. The developers of the wall (including my information security engineering teacher) will one day be judged by history. Let's talk about application architecture. It is true that MVC is the key to success and failure. If you let the kids in the team develop according to their understanding of MVC, the bad result will generally be high coupling between classes, and the Controller will be so fat that it will become a treasure box... Every version iteration will be painful. If there are not many functions, it can be barely maintained, but if there are too many functions, it will inevitably collapse. For example, the China Pavilion in the World Expo Park, try to build 5 more floors in proportion, haha. In the end, if the developers can't stand it, they can only choose to refactor or run away. Everyone knows that the latter is more realistic, especially in enterprises where business is king. Code quality is nothing as long as it can work. However, good programmers have dignity. Deadlines or political tasks that are done on a whim usually make programmers exhausted, and they will leave when they are tired of it. Let's get back to the point. Since MVC seems bloated, it is time to slim it down. Usually, the slimmed-down MVC is called MVCS or MVVM in the iOS world. Of course, these two are not the same thing. Whether to choose MVCS or MVVM for a project depends on your business characteristics. Are MVCS and MVVM so different? Of course not. MVCS needs to pay attention to the abuse of Service/Store and whether the data in it will be polluted by different modules. Improper use of MVVM will also increase the difficulty of project maintenance. I am talking about the loose binding relationship between View and ViewModel. In iOS development, when MVVM is mentioned, everyone thinks of ReactiveCocoa. In fact, it is okay without ReactiveCocoa. It's just that ReactiveCocoa has many advantages, such as code convergence without having to write everywhere. Other benefits can be explored by yourself. Regarding the organizational structure of project files, many people classify them as Controllers/Views/Models/Vender... Actually, there is a problem. For example, if you want to find the cellB class used by TableView of ControllerA, you have to find it one by one in Views. It is too painful. Even if you search, it is still painful because what you see is what you get. I usually divide it by Module. Each Module has Controllers/Views/Models/Stores/API. API is the encapsulation of each interface request for Store to call. The obtained data is parsed and instantiated into Model and then passed to Controller through block to refresh View. Is it very confusing? Using RAC, Controller can also subscribe to RACSignal created in Store. You can make a try. There are also Helper and Utility, which have nothing to do with the business and have object properties. The code that provides support functions is placed in Helper, such as creating an encapsulation of a custom object. If it is just a function or algorithm, not an object and can be used in many places, put it in Utility, such as sorting/encryption algorithm. Project file organization structure Regarding the design of the network communication module, I personally think that each HTTP request should be independent and not interfere with each other. That is, the POST/GET method you encapsulate will create a temporary object, and the long connection generally only maintains one instance object and is created in a singleton manner. I will create an API object for each HTTP interface request and request data in it. Of course, in order to avoid repeated writing of request codes, a BASE API class can be established, and the subclass can call the request method of the parent class. The only difference is the interface and parameters. This is the idea. I will talk about the design of the API class later when I have time. Regarding multithreading, GCD and NSOperation are the most commonly used in iOS development. In most cases, GCD is sufficient. However, NSOperation also has its advantages, such as the ability to set the number of concurrent threads, the dependencies between threads, the ability to pause and resume, and it is more flexible. It is often used in multithreaded downloads. In interviews, you will often be asked about the difference between GCD and NSOperation. You can check it yourself. There is a lot of information. There is also a reference link about NSOperation below. Although GCD is powerful, there are still many people who use it blindly. I am really worried about them. Here are a few points: 1. Abuse of dispatch_after as a timer causes crash! Don’t you know there is something called dispatch_source_set_timer? Countdown 2. Don't use dispatch_sync easily. There are so many thread synchronization methods. Why do you fall in love with it? Especially don't use dispatch_sync in dispatch_async. Don't ask why. Just google it in Baidu! 3. dispatch_once is only used when creating a singleton, don't use it randomly. dispatch_once is executed only once in the entire app life cycle, not in the object life cycle, brother! 4. What! You don't know how to use GCD to create serial and parallel threads! Serial parallel Regarding multi-team collaboration, if the project is developed in a modular way, CocoaPods is undoubtedly a very good tool. Relatively independent modules should be turned into private pods as much as possible. In this way, the public platform will build the framework of the entire project, and other business departments only need to build a private pod by themselves, and use the private pods built by the public platform for independent development and debugging, without having to submit code to the main project from time to time, which would be very troublesome, such as code merge conflicts and certificate conflicts, which would drive you crazy. When the module development is completed, submit it to the main project. Of course, it is troublesome to have too many private pods. It will be painful to add files to the target when private pods depend on more private pods. Xcode selects all targets by default. I need to give feedback to Apple and hope they will solve it. Regarding data persistence, the most important thing is to keep the data source consistent. Another important thing is forward compatibility after the APP is upgraded. The problem of crashing when you upgrade the app is mostly because the data structure of the new version has changed and does not support the data or settings generated by the old version. I have always preferred sqlite, and the most used one is FMDB. I don’t like CoreData. You should know that Apple’s own app NEWS uses FMDB. I still remember someone asked Facebook engineers "Why is your app slow?" "Because we use core data!" There is an open source library MagicRecord, which deeply encapsulates CoreData. I have used it and it is actually quite good. In addition, is unit testing really necessary? Unit testing can make the logic clear. When you only read the unit test code, you will find that they are written like pseudo code in a programming textbook. This is especially useful when TDD is used. By writing unit tests, you can quickly sort out the logic and then implement it with code. Unit testing can reduce the coupling of code. We know that it is difficult to unit test highly coupled code. On the contrary, if you must do unit testing, you will not write code with high coupling. Unit testing can let you know whether your changes to the code affect the original functions, but this is also what all regression tests can do. The characteristic of unit testing is that it tests something small enough so that it can still be reused after code refactoring. Unit testing is the only test that can achieve 100% coverage. Unit testing is difficult at the beginning, but it will become easier and easier if you continue to do it, because the difficulty is mainly due to the construction of the environment and the lack of stub functions. Unit testing is easy to locate bugs, it seems to have set countless breakpoints in your program. Unit testing is time-consuming, but it takes more time to fix bugs later. Having said so much, let me talk about requirements. I think that when reviewing requirements, we should try to throw out detailed questions to the PM. They don’t understand technology. If the requirements are uncertain, they will blindly develop, and then change the requirements in the middle. This is very demoralizing, especially when it comes to architectural changes. This reminds me of the picture of the PM changing the requirements and being hit by the programmer. Hey! If the requirements are unstable, don’t start the work. I’d rather sit around and read blogs. Okay, I’ve said so much, how many people will see this? I hope to come back and add some content later. |
<<: Digium Open Source Real-Time Audio and Video Communications SDKs
>>: Can the mobile version of Win 10 break through?
According to data from the National Bureau of Sta...
I have heard many of my friends and colleagues ta...
How much does it cost to develop a textbook apple...
Augmented reality (AR) is increasing brand awaren...
In the bidding process, creative writing is essen...
Today, we will focus on the three core functional...
On the one hand, the professionalism of “If you h...
Xiaohongshu is a representative example. There ar...
Whenever the seasons change, people's dressin...
The ultimate goal of the landing page is to serve...
WeChat, as the largest traffic portal on mobile t...
Q: How much does it cost to customize a catering ...
Since it is an Internet company that wants to make...
April is the most beautiful month of the year, wi...
Written in front This article uses a typical bran...