I regularly help out our smaller customers with tasks that might be a thorn in their side, and which would drag them away from their normal business priorities.  These tasks often involve that I have a cursory look at their Uniface repository, and a gain a general knowledge of their application architecture. Whilst performing some of these tasks, I often see all kinds of objects that are dead wood in the application.  There are the warning signs … objects that start with TEST, objects with developer’s first names embedded, last updated in 1998, obsolete objects (UVCS model), and so on.  It is so tempting to delete these objects, but I act professionally, and wouldn’t load that kind of regression testing burden onto customers, unless instructed to. So does anything happen to this dead wood?  I do hope that the developers spend just a little time cleaning up their repositories, but inevitably this requires more than a little time, and developers are handed higher priorities.  This I understand; our work has to be able to demonstrate added value to our masters.  If the work does not obviously show savings or improved performance in some way; if there is nothing that visibly changes, why invest in the work? This is the answer to that question: because you are building up “technical debt”, and it might be cheaper to fix it sooner than later.  For a wider explanation, have a look at Ton Blankers’ white paper on “CONTAINING AND MANAGING TECHNICAL DEBT WITH UNIFACE”.  Your masters may argue that they’ll never need to repay that technical debt, but there is a lot of current discussion on modernizing applications, and cleaning up your code, and understanding your assets, are important process steps in modernization. I do know how dead code gets created, and there is a respectable amount of time that it can remain in the repository … “just in case”.  Rather than put a use-by date on dead code, it might be better to schedule a little time when you can review your code, maybe straight after a major maintenance release you could get rid of last year’s dead code (as distinct from the latest dead code), or in those quiet weeks of the summer holidays.  It also makes sense to do it whilst the original author can remember the code, or particularly whilst the author is still employed by your masters.  It can only cost more to do it later.  Besides, if a business case is drawn up for modernization, it would be great to start doing some new development ASAP, rather than spend a lot of time rediscovering the ancient history of your application. I mentioned some of the obvious ways to spot dead code earlier on.  There are tools for a more deterministic approach to code coverage analysis.  You can turn on proc tracing and run it for a while.  This should be avoided in production, but with a good suite of regression tests, it should be possible to capture the traces in a test environment.  Don’t forget to add a line like this to the assignment file:  $PROC_TRACING_ADDITION="%%$componentname  >>>>".   There could be more done to automate the examination of these trace files, but it shouldn’t be too hard to match trace files against a list of components.  There will always be some manual investigation to be done, and the Uniface Cross Reference tools will be helpful here. So, don’t shy away from pruning that dead code out of your application, even if it’s a branch at a time.  If you have some ideas or tool strategies for finding dead code, please share them with us.

5 Comments

  1. Hi Eddy, looking from a more practical point we come to the question "how can I be 100% sure a component is no longer in use in the production scenario" (and I have seen some TEST_xxx components even in production). This include once-a-year actions like "end-of-year", occasional use-cases like "unlock a customer with login-errors" and the very special controlling reports, ... So we need a way to constantly collect data under production conditions. Proc tracing is not the best because it slows down performance, creats big piles of data and needs to be processed afterwards. Let me recommend an enhancement of the INIT operation of any component, (service ..) If a component "CollectComponent" is in the instance pool, just report your componentname to it. So it takes just a newinstance of the CollectComponent in the startup-shell to start/stop the collection mechanism. The Cleanup Operation of "CollectComponent" will save the used components perhaps with a last-used timestamp. Code analysis from the repository unfortunately does not help us a lot: Once, I used the information from the assembly workbench to find which components call which components and created some invocation trees from it. But real code nowadays is full of handles, variables, procs to open components so you find a lot of connections to $call_form$ or p_callform. So at the very end it may be the best to "archive your own dead wood" from time to time (as long as you remember it was some experimental component or so) to an export file plus a little documentation just in case you need it again and the delete it from the repository.
  2. Background: A friend of mine is just in that situation: His customer switched their uniface provider and he is left with the usual undocumented repository and a "we deliver the complete frms etc. to the customer" mentality, He found a lot of 1:1 relationships once used to add new fields to existing entities, but no actual document of architecture, concept, use-cases, why-have-we-done-this. Now some changed functionality (SEPA) has to be implemented and it would be nice to slim down the amount of candidates which need modifications. But this requires a "which components are actually used in the application?" one can rely on.
  3. Some good thoughts Uli. I still think that static repository analysis is worth doing. It doesn't impact running systems, and you may well be using such tools for other reasons, like impact analysis for potential changes. Usually such tools let you make global edits as well. As for removing dead code, it is more a case of getting fast results cheaply, rather than aiming for a comprehensive clean up. Of course analysis of actual usage is going to give much better results, with the tradeoff being effort to do it. As you ask, how can we get 100% accuracy? I suspect that, as in many testing approaches, you probably shouldn't expect to. It's more a question of what level is accepted as minimal risk. After all, we're just talking about code that won't be executed, but might add some unnecessary maintenance effort. If there is a determined effort to monitor production usage, it may be worth looking at using performance monitoring tools (if they can provide the code coverage information required). Such tools are designed to be left on all the time, and impose as little overhead to performance as possible. Besides, the information on performance at the component level could be handy too. But that's for discussion on another blog.
  4. Hi eddy, let's assume that in the code ANY "component not found" is reported back to the user then it's an easy task: whenever a component is missing, re-activate it. But checking $status each time is very rare in the codes I have seen. when you talk about performance monitoring, do you mean the uniface internal one? When I experimented with it, it usually created a massive output file which in turn slows down performance especially when it comes to bulk processing. And all that big data collection only to identify which components are in use? Think it's the same as if you run PROC_TRACING with the $componentname. Lots of lines to be outputted for each component because I have not seen how one can reduce the scope. But as you said: this would be a topic for another blog
  5. Unused components are a bit difficult to find, but there are plenty of other Uniface object that are quite easy to identify. An entity subtype that is not painted on any component is not (can not!) be used in Uniface. Same for an Application Model. An include proc that is not included anywhere can safly be removed. Uniface has many kinds of templates. It is easy to check whether they are used or not. Etc, etc. Of course this works best if you first remove the components that are not needed anymore, but even without that you can clean up your application quite a lot with these kind of static repository queries. Compuware's Services department has created a tool for cleaning up your repository. Hire one of their consultants for a day or two, He or she will bring the tool and for a relative small amount of money you have a clean repository. Or yuo can build a tool yourself. All you need is a couple of weeks, a sharp mind and a Uniface manual.