Author: Reinder de Vries, original link, original date: 2016/01/09
Translator: pucca601; proofreading: Indigo K; Final: NUMBBBBB
Editor's note: This article was written by Reinder de Vries, a standalone application developer in learnappmaking.com.
Oh, no! Parse is about to close ... What are you going to do?
On January 28 this year, Parse announced that it would shut down its services. They are slowly reducing the provision of "back-end services" and intend to fully withdraw the service on November 28, 2017.
This is bad news for more than 500,000 developers who have relied on the service since 2011. As Jameson points out in his blog post, developers feel betrayed by their trust.
The Parse was bought by Facebook for $85 million in 2013, but now the first "Big five" has cut off support services for developers in cold blood.
In 2013, the acquisition of Parse was a real risk, but Facebook needed to buy it in the mobile market. Facebook's latest earnings report shows that Q4 's mobile ads grew 52% in 2016 compared with 2014 and 2015, suggesting they have a foothold in the mobile market.
Amazon, Microsoft, and Google's cloud services are becoming more competitive, and you may feel that Facebook no longer needs Parse. I was very much in favor of business, but it was a bad decision from the developer's point of view.
Is that really the case?
For developers, the closing of Parse is an opportunity
I've been developing the site before I did the app. Countless websites. I learned all the necessary skills: HTML, CSS, JavaScript, PHP, and MySQL. My Code quality and elegance will give you goose bumps at the time, but through constant trial and error, I finally mastered the technology of exporting high-quality websites.
Year after year, I occasionally develop a Web application to keep my skills up to date. There are many newer and more advanced tools available, and I can apply them in my work. I migrated from JQuery to Angular to React, and I was exposed to too many JavaScript frameworks, witness package management tools, and GitHub (SourceForge, who else?). ), as well as PHP 4 to PHP 5 to PHP 5.6 and the coming PHP 7. My MySQL form blew up, so I switched to Elasticsearch and Mongo.
Not long ago I wanted to automate the test invitations for newsletter registration and TestFlight. If you subscribe to the newsletter and confirm your subscription, this automated process will automatically add you to the TestFlight test group. I have some knowledge of the FastLane tool and its boarding components, the HTML page of this graphical boarding component must have a POST URL entry point that I can hijack. In fact, I'll crawl the subscriber's email address from my form and put it in the boarding form. Boarding will do the rest, such as adding subscribers to the TestFlight test group.
There is only one problem here: the boarding table has CSRF protection, which means that it requires a unique token in each request. These tokens are generated by the server and are not available in my automation process.
I can access the source code of boarding, so theoretically I can disable CSRF protection to solve this problem. There is only one point to declare: The source code is written by Ruby, but I haven't seen a single line of ruby code in my lifetime (well, maybe one line), not to mention it.
Thanks to my extensive back-end programming experience, I'm not afraid to get started with an unfamiliar technology. Over the course of the trial and error, I have a deep understanding of how the Web works. I'm not ashamed to touch the technology that I know nothing about, on the contrary, I dig deep.
I'm flipping through all kinds of libraries I've never seen, and the strange names they compare (is that a thing?). ), finally found a file to manage the CSRF protection feature. Finally, I found that turning off this feature is equivalent to placing the controller empty.
Back-end black box
Almost every successful application will use a backend service to connect users and persist user data on the server.
Many of the developers I met and mentored lacked a solid understanding of backend programming. They set the Parse configuration item on an extremely simple Dashboard, write a query statement, and then assume that the data is "right there." Who wants to know what's going on in the clouds?
I often interpret Parse as an "applied spreadsheet." This is true: Parse provides a backend service for your app, and its Dashboard is as simple as Google spreadsheets. You don't even need to write the query data statement, instead, you can use the following simple method:
Pfquery (className: "Tweet"). Wherekey ("user", CurrentUser);
This may also be the fault of the Parse. Their pfquerytableviewcontroller are too simple to use, but they are also quite dangerous: it directly associates the backend code with the view controller (already a ViewModel) you are applying. Even if you want to go from Parse to Firebase, because your code and backend are tightly coupled, you have to rewrite the entire application before migrating.
The Pfobject class of parse has a built-in mapping, so you can use string data just as you would with native Swift string objects, and the parse SDK internally transforms that data into data that can be transported over the Internet. If you use Pfobject instances in user-facing code, it can be difficult to replace a new set of backend-as-a-service SDKs in the future.
If you want to build your back end from scratch, you need to know that for example, true (a Boolean value) is converted to True (a string) when encoded as JSON. If that JSON data arrives in your app, you need to deal with a string instance instead of the bool type you expect. Although Swift has an incredibly type system, the If let optional type binding state determination mechanism (optional binding statement) cannot handle mismatched types-it does not solve this problem!
So what is the benefit of the close of Parse? This is a great opportunity to start experimenting again, and you can dig deep into the back-end black box to protect your code from similar things.
Three ways to respond
The next time you want to develop an app, keep these three methods in mind. You can use them to protect yourself (the business) in case the Parse shuts down such things happen again. Don't 100% trust a third-party service provider that is critical to your application's continued development and success.
1. List A list of alternatives
Parse has a few similar providers, such as Firebase. You may not have heard of Firebase before the Parse was closed.
The coolest thing is: Most of these services know you're looking for them. If you Google "parse shutdown (translator: Parse off)" or "Parse migration (Translator Note: Parse migration)", you will be in the middle of many highly relevant Google AdWords ads that call you to migrate to their service ads. Please don't do this!
Instead, you should include a list of alternatives. Try to be familiar with things outside. Make a list of the services and alternatives you need to rely on, just in case. Just like a supermarket has a list of spare milk suppliers to prevent their major suppliers from going bankrupt, you should also have a list of companies that you do business with.
Of course, you can also do some technical and SDK research related to the alternative vendors on the list. I had never heard of onesignal until I started looking for a free push supplier to replace Urban Airship, because I thought the cost of Urban Airship was too expensive.
2. Decoupling your code
Although you have heard it 10,000 times: Model-view-controller (Translator note: Model-View-controller) still makes sense. We are getting used to Model-view-whatever (translator Note: Model-view-anything), but the idea of MVC is: Your Controller cannot configure view, your view should not manipulate a model.
The Cocoa Touch Framework makes it difficult to not use MVVM (Model-view-viewmodel), but that doesn't mean you need to tightly couple your Model code with the View Controller code.
In programming theory we have two principles: coupling and encapsulation. The use of two tightly coupled classes means that ClassA has made many assumptions about the internal functions of ClassB.
Imagine a car and a driver. The driver sits in the front of the car, because the lever is connected directly to the engine, and if the driver suddenly sits behind the car to drive? It certainly won't work. Of course, a situation like this never happens in real life, but it's always there in your code.
One protective measure to deal with tight coupling is encapsulation. This means that each class has a strictly defined set of methods, such as SpeedUp () and Steerleft (). By relying on a combustible engine, you just need to have the driver call SpeedUp () instead of letting the driver inject more petrol into the combustion chamber. In this way the driver does not need to know the complex knowledge about how the engine works, just call a method that he knows to be safe to implement.
When the engine is replaced by an electrically powered engine without a combustion chamber, you do not need to modify the driver's code: he relies on an exposed speedUp () method instead of relying on injectgasmixture (), Gasmixture, and Sparktimer (Translator note: Injection of mixed gasoline, mixed gasoline, electric spark timer).
If you find decoupling and encapsulation difficult to understand, consider them as duties. whose duty is to drive? Driver. Whose duty is to make the car move forward? Engine.
When you are writing an application with back-end capabilities, clearly define the responsibilities of the components and components. Create a middleware that acts only as a medium between the back-end code and the front-end code. The front-end code is built on your own class, like Car, which handles the backend SDK you use and uses classes like Pfobject.
The middleware work is to communicate front-end and back-end. If your backend code is outdated, you can replace the middleware's code with the new backend SDK without rewriting the front-end code.
3. Using Adapter pattern (adapter mode)
The third and final approach is to reduce code coupling. Adapter pattern (adapter mode), older than the internet itself, is an object-oriented programming model. This is a set of programming rules that can be used to make two incompatible classes compatible.
This is similar to constructing a "wrapper (wrapper)", not just exposing the resource interface (like encapsulating a REST API), but also developing a set of rules between two incompatible interfaces. In many programming languages these rules are called interfaces (JAVA and PHP), which are called protocols (protocols) in Swift and Objective-c.
You must know the model of Swift, right? If something swims up and barks like a duck, it must be a duck. Adapter pattern (Adapter mode) also has a similar mechanism. For ClassA and ClassB to be decoupled, you need to construct a ClassA adapter instead of calling ClassB directly in ClassA.
This adapter class contains complex knowledge about how ClassA works. The adapter class also follows a protocol. This agreement says: "You can be sure I have X, Y and Z methods."
ClassB don't know ClassA. It only knows that it wants an instance that follows the adapter protocol. It doesn't care if this instance is a duck, as long as it swims up and barks like a duck.
What are the benefits of using adapters? Assuming your original ClassA code is obsolete, you just need to find another class (for example, another Parse alternative) and write an adapter for the class. As long as the adapter follows the protocol, which is the rule you made earlier, ClassB can still work.
In fact, you can write an adapter (Mytwitteradapter) with a method with the following signature:
Class mytwitteradapter:anytwitterserviceprotocol{ func gettweetswithuser (user:user, Withpage page:Int = 0) { ...
The Protocol (ANYTWITTERSERVICEPROTOCOL) contains the same method signature as above, but it does not have any logical or method implementation, just defines the rules.
Protocol anytwitterserviceprotocol{ Func gettweetswithuser (user:user, Withpage page:int = 0); ...
Front-end Code (mytweetsviewcontroller) has an undefined type of variable Twitter, which ensures that when you replace the adapter you only need to replace the name of the class once (or two times).
If you strictly define the Twitter type as mytwitteradapter, there may be a lot of coupling in your code. In this case, if you want to replace the adapter with a new adapter, you still need to update a lot of code.
Once you've set up this check-up mechanism, you can test the instance that you're working on. Twitter is following anytwitterserviceprotocol.
If let _twitter = Twitter as? anytwitterserviceprotocol{ //Yes, it conforms}
Your front-end code no longer cares whether Twitter is a Car, foobar or Facebook type, as long as it follows Anytwitterserviceprotocol. It just wants to know if this instance has a method called Gettweetswithuser:withpage:.
Note: Suppose you really need to strictly define the type of Twitter, you can use the protocol as a type, so you can also use generics.
What do we do next?
Now that you've learned how to improve your business code, how to deal with the vendors you rely on and protect your code, I think you know how to deal with a similar crisis.
Are you going to go to Firebase? You should know that Firebase belongs to the "Big Five" in Google. While the Parse shutdown does not mean that Firebase will be closed, relying on a new vendor will make your application as vulnerable as before unless you try to protect your code.
Learning back-end programming is a good idea. Parse has released an excellent alternative to parse server, where you can run your own server (as long as it can run NodeJS and MongoDB). In the following article I'll show you how to migrate a simple application, including Heroku and Mongolab, from parse to parse Server.
Continue reading: Guide: How to migrate a simple application, including Heroku and Mongolab, from parse to the parse Server
Another relatively easy exercise is to deploy your push notifications to two services, instead of putting eggs in one basket. It is relatively easy to implement a client SDK for a push service provider, and usually you only need to send a unique ID and create a segment.
Use the Adapter pattern (adapter mode) to create a unified interface for your front-end use. Decoupling the actual adapter from the front-end code by defining a protocol. Pick an alternate push notification service provider (such as Urban Airship, Mixpanel, pusher, or PushOver) and write an alternate adapter. Make sure that the adapter follows this protocol, then simulate the service crash and see how to redeploy the adapter. So, did you solve the problem?
Conclusion
Don't be afraid to go deep into the black box. Writing your own backend REST API is a good way to do it, and you will learn a lot of things.
Do you know crashlytics belongs to Twitter? Any service may be closed ... Figure out what Crashlytics did for you, and how it works. This is the only way to build a stable and reliable business that is always profitable.
Next, you have to walk into the rabbit hole.
About the author
Reinder de Vries is a standalone application developer who teaches aspiring developers and marketers how to build their applications on learnappmaking.com. He has developed more than 50 applications, and his code is used by thousands of users around the world. When he did not write the code, he liked to concentrate on coffee (strong espresso) and travel.
This article is translated by Swiftgg translation Group, has obtained the author's translation authorization, the latest article please visit http://swift.gg.