The Software Purist |

TAG | Load Testing

Dec/09

27

Front-End vs. Back-End Development

Hi all. There was a bit of break because of the holidays, but now I’m back with a new post that I hope you will enjoy. In this edition, I wanted to discuss some of the differences between front-end and back-end software development. I would say that one of the interesting things about my career, to date, is that I’ve probably had a pretty even split between front-end and back-end software. As such, I’ve noticed some interesting differences between the two, particularly with how they are approached. When I speak of Front-End development, I’m really speaking more of visual-related code, particularly GUI code. As such, note that some of these observations don’t apply as heavily to related areas. When I speak of Back-End developmet, I’m generally speaking of the logic on a multi-user server application, such as a socket server, which handles requests from many users. With that, let’s get started.

So, the first thing to discuss here is ease of development. I’ll admit, outright, that this is a bit of an unfair category, because it will significantly vary depending on framework. For example, using some well-designed frameworks, setting up the GUI can involve a lot less programming. If you use one of these frameworks, a lot of the work can even be done by artists or designers, without much intervention by developers. Of course, if you’re doing more low-level GUI work, such as pure Win32 or XWindows/Motif, this doesn’t really apply to you. Having said that, for many applications, choosing a relatively high-level GUI framework is commonplace, unless there’s restrictions that prevent this from occurring, such as performance reasons or customer requirements. So, from the front-end side, you often wind up in a state, where the framework you’re using is already in place, and you’re making small extensions and the application basically derives from that. From a pure GUI standpoint, while designing the overall architecture is important useful, in some cases, especially in smaller applications, you can get away without it, or possibly define it later, through some refactoring techniques.

From the back-end side, the framework you’re using is often lower-level. Even if it’s higher-level, you still need to architect an application to integrate well for future needs and a lot of user requests, including making use of multiple cores and taking advantage of latency. Back-end work mixes both low-level and high-level concepts, and there is often a significant amount of work required to get something up and running. In many back-end applications, the logic on the back-end can be heavy, for the reason of security. At other levels, the data may not be trusted. On the back-end it is. Furthermore, back-end software typically operates with a database. The database has the interesting property of both making things simpler, in terms of coordinating many simulatenous requests, and also more complicated than typical front-end data storage. For example, on the front-end, it may be perfectly acceptable to store all data as XML and write all data to file immediately. This of course, would not scale to the back-end. Furthermore, the back-end has to worry about synchronization. Front-end applications can potentially get away with not making great use of idle processing time, but this is often not so on the back-end.

The front-end is a world where there is a lot more instant gratification. For example, you can design a new button, click a wizard option to add a handler, enable/disable the button at certain times and handle the button press, but initiating a file to be saved. You can code this and be testing, verify it and have new functionality to show the same day. This is usually not the case for back-end development. On the back-end you might be designing functionality such as saving some data to the database. So, you write the code to handle the request message from the client, you write the stored procedure you need (possibly to be tweaked by a DBA later), you code up the response to the message. After the same amount of time as spent on the GUI, are you done? Unfortunately, no. Firstly, having gone this far, the functionality isn’t actually verified; so it can potentially look like you haven’t done any work. This will continue until there is front-end code to interact with the back-end. However, sometimes the integration process can get messy, so it’s best to sprearhead problems before they can occur. Therefore, the next step is to write an automated test to restore the database to a known state, simulate the message occurring, verify the expected response and then verify the database has the correct data. You may require n of these types of tests, until you’re at a  point where you have confidence. From there, are you done? Alas, no. You still need to handle many users, so now it’s time to test many users performing the same thing. You would write an additional automated test, with a high number of users, repeatedly performing the same action: restore db to known state at beginning of test, simulate the message, verify the expected response, and verify correct data for that user… repeatedly for the number of users. Failure can happen at any time, so you might have cases where 8 out of 10,000 attempts fail, and you need to look at this and know why. Until your test passes, you’re not done. Then, until the front-end is making use of your code and integration has happened, nobody has seen it: which can be days, weeks, or longer. So, verification takes a very different route. This can be somewhat spearheaded by having the same developer work on both the front-end and the back-end for a particularly piece of functionality. There’s some merit to this approach, so I generally applaud this attempt.

Of course, this is not to say that there is no testing on the GUI. There often is, but for many companies, it’s about putting the work where there is the most value. Take the case where there’s 8 failures out of 10,000. This sort of scenario can happen on the GUI just as easily. The difference is that it may only occur when a particular user uses the software in a particular way. So, perhaps the issue is only noticed by 1 out of 1,000 users, because the other 999 don’t click as fast, or don’t click as repeatedly. As sad as it is to think about, being a software purist, these are the sorts of issues that are unlikely to get fixed, anyway. The type of testing that sometimes happens for GUI code is unit-tests when proper use of the Model-View Controller design pattern has occurred, and the model and control have been kept relatively framework-neutral. This can be difficult to achieve with some frameworks, so I don’t see unit testing happening on the GUI as much as it should. The second type of testing that often occurs on the GUI is using an automated framework that actually simulates a user clicking various buttons and runs through these scenarios. I see a lot of value in this, but often the software is very pricey. Most companies I’ve worked at have shyed away from this option because of the high cost involved.

So, anyway, hopefully this was an interesting discussion. This certainly isn’t the last discussion I will have about the differences and in future articles, I will talk about more steps to streamlining the process.

· · · · · · · · · · · · · · · ·

Dec/09

3

Software Testing

I wanted to migrate this post from my old blog. I have added it here:

I was thinking a good topic would be to talk about a few different types of tests a software developer can do and what each provide.

Unit Tests

The purpose of unit tests is to test the functionality of a generally lower-level software module. External dependencies are stubbed out and mocked, so that you can test components in isolation. Checks are very granular and the test will generally give a pass/fail result, which makes it easily automatable. In my experience, there is often some confusion as to what a unit test can and cannot do well. For example, you might write a unit test that tests a class called String. It might find that you have two issues with this class that you fix. However, this won’t necessarily have a noticeable effect on your product. Unit tests are to make the developer’s life easier, because they take really difficult-to-fix bugs that wouldn’t be found until later stages and make them into generally easy-to-fix bugs at earlier stages. This flows in with a process known as risk mitigation.

However, they don’t necessarily make the development cycle take less time. When unit testing is done elaborately, including using a process like Test-Driven Development and automating these tests when making a build, they can be extremely beneficial. But, where time may be saved is often the deployment and QA teams, not necessarily the developers. Companies have to be willing to pay the extra cost for these tests in the name of higher quality, a smoother process, and to ease refactoring. Finally, unit tests are typically terrible at testing any non-deterministic process, especially when threads are involved. It is also generally difficult to test GUI functionality.

Integration Tests

I find these generally less useful, because this is the middle ground, as has enough overlap with unit tests and broader tests that they sometimes can be excluded. Still, in some scenarios they are quite useful. Just like in unit tests, integration tests tend to be automated, but this is not always the case. Where integration tests differ is that you generally don’t stub out interfaces, unless it’s an interface that is totally superfluous to the test or would prevent the test from running in an automated way. An example of a integration test is it might run the core engine of your application along with another component of the application, such as a logic module. The integration test would start by running a database query to reset the database to a known state, send login requests for 100 users, and verify that the 100 users logged in. It would then check the database and make sure the 100 records were properly set into the database. Then it would clean up the database.

Load Testing

I find that these are the tests I write towards the end of the cycle. You generally can get away without these if you’re making a standalone application, but it is essential for a server application that expects a high user load. The load testing script, often written in a language simpler than your application, such as Python, will simply simulate a bunch of users repeatedly trying to simulate a variety of scenarios during the test. They often all try to simulate the same scenario, but sometimes they try to stimulate different areas of the system at the same time. Verification at this stage is generally minimal, because in most situations, the users can interfere with each other, creating false failures. What you are trying to verify here is longevity test to prove that the server can withstand a constant barrage for n hours with m users. Failure on this test will often be discovered manually when you come in to check it the next morning, and will be something of the nature of a crash, deadlock, excessive memory growth, performance degredation, etc… Smaller issues, such as 1 out of 1000 users not having their record stored in the database are unlikely to be discovered.

Conclusion

While this isn’t all of the types of tests a developer will use, I find these to be the most frequent in my travels. One thing to keep in mind is setting expectations at the appropriate level. Developer-level tests are extremely valuable in making the developer’s life easier and making life easier for your coworkers. The thing I want to keep emphasizing is that they don’t necessarily save time and money, though. I give this caution, even though I’m a huge fan of software-level testing. You write tests for quality, period. Some hidden benefits are that they also provide additional “documentation”, example usage and generally make refactoring easier, because if you have to fit your code into a test, it’s more difficult to take shortcuts.

Overall, I have worked at both companies where quality was held highly and others where it wasn’t the most important factor in the success of a product. You have to decide for yourself what’s most appropriate for what you’re doing. One thing that’s important is setting expectations correctly. Sometimes management will think that if you write a test, the software will be bug-free. There isn’t a single piece of non-trivial software that is bug-free, anywhere in the world.

Also, I came across this, which is a great description of various different types of software testing:

http://bugsniffer.blogspot.com/2007/11/software-testing-types.html

· · · ·

Theme Design by devolux.nh2.me