Sooner or later, every developer creates an own toolkit of small utilities, which is reused from project to project. I cannot share sources of my toolkit, because I don’t own them. But I think, describing some of my ideas can help others. Here is top 3 of my favorite web development ideas.
Magic numbers are normally replaced with named constants. But if you think about it, making those constants to parameters often makes more sense in web apps.
Unlike system code, where magic numbers might represent some port address or byte offset in MP4 file, typical web app magic numbers are, for example, timeouts and number of retries, or animation duration, or URLs to various backend web services (who has said magic “numbers” cannot be strings?). Making all those things to be parameters can suddenly both make development and debugging much more efficient and enjoyable; and create more business value a for very little investment.
Normally I gather all those things as properties of a singleton object. When this object gets created, its properties get some reasonable default values. Next, when the app is fully loaded and starts initialization, I overwrite the default property values by reading the corresponding app configuration. Next, I parse the URL query string parameters of current document. When the name of a query string parameter can be found as a property of my singleton object, I overwrite its value again.
Why is it cool? It is useful in uncountable number of ways. Here are just some examples.
- I can change the backend my web app is speaking to, by appending &BackendUrl=xxx in my browser address box. Very handy for development, or for checking how the new frontend version behaves with the current live version of the backend.
- When developing a complicated animation, I can set its duration to several seconds, to see exactly, how it goes from key point to key point.
- When developing an error overlay telling the user about the timeout, I can set the timeout to 10 milliseconds (I always have all time and duration parameters in milliseconds) and get the timeout for each request. No need to put Thread.Sleep() somewhere in the backend, recompile it, then waiting 30 seconds every test run, then removing the sleep again…
- A designer can come by to me, we run an animation, she tells me what to change, I write another parameter in the URL, reload the page – here we go, we can see the change in action. And after several iterations, when she has prepared the perfect UX, we can copy the browser address line and just send it to some other decision maker for final approval.
- You need to demo your app to someone important, but your backend is not fully operational. You just send them a link with BackendUrl parameter pointing to your test server containing mock data.
- Because I tend to replace most of important literals with parameters, someone can change almost anything about how my app works or looks like, just by changing its configuration file. No need to bother me with trivial change requests.
- Finally, the most important one. My web app on production behaves badly. I cannot reproduce it locally, but its reproducible with the app on the live server. I go to the live server, add URL parameter LoggingVerbosity=255, and then read a LOT of things in the console.
Yes, I leave MagicConf in production code – for purpose.
Q. But is this secure (for us)?
A. As soon as your visitor has obtained the web app, it belongs to him. Changing any source code is almost as easy as changing a URL parameter. The backend web services have to make sanity and security check anyway.
A. As soon as we don’t eval the parameters, we should be reasonably safe. When in doubt, perform a security review of your code, or use your common sense. For example, I wouldn’t use MagicConf in a web page for credit card processing.
Q. But this means we lose control over the app!
A. As soon as your visitor has obtained the web app, it is his app, not yours.
Q. But visitors can change our UX and then share a link on Facebook, damaging our CI.
A. Some mega corporations spend millions of dollars to animate folks on the Internet to remix their logos or advertisements. If you have visitors that are ready to spend time remixing your app, it is a good problem to have.
I prefer having a pure API between the web app and the backend: the backend provides data, and is responsible for authentication, authorization and payment. Everything else happens in the frontend. Having it this way, normally results in a very concise, truly RESTful communication. And as a side effect, it is easy to mock.
When I develop web apps, I always mock the backend, unless I’m also the one who develops the backend. In the cases when I’m also backend developer, I mock the backend only in 50% of cases.
The process can for example look like this:
- I create a new file with .json (or .xml – it depends on project) extension and open it in my text editor. I also create a new Word file, and write there “Project X API Specification”.
- Then I write first piece of the JSON data I need my web app to get from backend, and save the file.
- Then I configure the directory with this file in my local web server, and point my web app to this directory to use it as mock backend (or Mockend, for short)
- Next, I write the web app code to get and use the JSON data in my UI.
- Run the app, see the data in the UI. Possibly change the data, add or remove data parameters or re-shuffle fields.
- When I’m satisfied, I copy the JSON from this mock file into my Word file, and create another chapter for this RESTful endpoint. If I need to, I describe the data exchange format in the Word more thoroughly, for example, provide minimal and maximal limits for integers.
- Send a copy of the Word file to backend for development.
- Rinse and repeat for the next RESTful endpoint.
Why is it cool?
- My development timeline doesn’t depend on the backend developer.
- My software quality and stability don’t depend on the backend developer. When I’m ready, I can immediately show my app, finely working on my mock files.
- My web app can be delivered to QA and customer approval much sooner, if backend development happens to be slower than me.
- I define the API, and I define it to be perfect for the web app. While the backend can usually generate data in any format, they can’t tell a comfortable format from a not very comfortable one. I can.
The process can also be backend driven, if needed:
- I call the existing backend with proper parameters, and save the result into my local Mockend. Now I have the full control over the data, and can for example create some other mock files testing extreme conditions (no result, too large result, format errors, etc).
- I write the web app to get data from my local mock file and use it in the UI.
- Rinse and repeat.
Last time I’ve developed a browser-based web app for money, I’ve used Microsoft Silverlight. It is much cleaner than HTML5 in that, that a) there are apps, which are downloadable zip archives of graphical assets and compiled code, just like mobile apps, and b) it has a traditional control model, with control tree, user-defined controls, and all that stuff. There is also a plugin framework allowing to package separate controls into apps, and then download one app from another and get access to all its code and assets – dynamically in the run-time.
This has enabled the following coolness:
- You develop a control, for example a carousel with wet floor reflections (who has said iTunes?)
- You package it into an own app, and in the Main method of it, you instantiate it using some dummy data (of course, parametrized with Magic Conf)
- At this point, you can already show this app to your customer and QA, unit test it, let UX designers tinker with its animations, PMs approve it, and so on.
- At the same time, in your main app (the real app) you develop loading of this carousel plugin, and instantiate the control feeding it with real data from the backend (or your Mockend).
- When you’re ready with that, you can show the carousel as part of the real app, and get final approval for it.
A neat side effect of this approach is that all your modules are built as separate app files, so that if you take some care defining the proper interfaces between your main app and the controls, you are off for a modular deployment. This means, if somebody suddenly needs to replace carousel with a iPad-like grid, you can just develop a new control, package it into the app, and then deploy just this app on the server, replacing the old carousel app with it. Nothing will get hurt.
Oh, and it improves load time of your app, because plugins are loaded on-demand.
As for the HTML5 world, I’m still lacking hands on experience. Web components als things like Mustache seem to go to proper direction. I’m still not sure though, if they are not against the HTML spirit and the ideology of most popular frameworks.