Say, you have the complete codebase of a software application. How would you go about creating another application (having many common functionalities)? You copy-paste the codebase as a fresh project and start making changes to the cloned one, huh? It’s not a good approach. What’s wrong about this approach is that you will have two different codebases to maintain for future — when you fix a bug in one, you have to replicate the fix in the other. With these applications evolving in their separate ways, this replication is going to be harder and harder in future. Ouch! You just created a lot of extra work for you that’s going to need extra manpower and extra expense. Can these be saved? Yes, read on.
This is a case study of how we have started creating a job portal out of our existing recruitment software — HeadTracker. The fact that HeadTracker is built with Xsemble opens up unique opportunities of saving all this future effort. This article primarily covers these unique aspects, so that it becomes a guide to such kind of application spawning.
Functionality Similarily and Differences
One would expect a recruitment application and a job portal to have a lot of common functionality:
- You have clients and their requirements and candidates are searched against those requirements.
- Matching candidates are proposed for the requirements and these proposals are then tracked through the recruitment lifecycle.
But then there are some differences too:
- “Who Does What” Changes: The users in a recruitment application are the recruitment team members. On the other hand, you have candidates and clients (employers) directly logging in to a job portal. The recruitment admin can be retained as the site admin, who has access to all the functionality. With these change in roles, “who does what” changes. For example, the search for candidates against a requirement, which was a function of a recruiter is now a function of a client.
- “Who Accesses What” Changes: A client (employer) would have access to only their profile and requirements and not to the other clients’. Similarly, a candidate would have access to only their own profile and not to other candidates.
- “Who Sees What” Changes: There are some new functionalities that need to be added — such as client registration and candidate registration. Similarly, some functionalities of the recruitment software are no more relevant for the new roles and they need to be masked away / disabled for the new roles.
The following figure summarizes this understanding:
First Step: Cloning the Application Without Duplicating Source Code
As we saw above, the first step would have been be a copy-paste of the whole codebase if the application were built with a conventional way. If you used microservices and if you are lucky, you might be able to find some microservices that may be common across the old and the new applications. But you will have to copy-paste for the rest anyway.
Not with an Xsemble application!
An Xsemble application contains two separate parts:
- Repositories and components: There are repositories that contain components. The component implementations contain the source code that runs when the component is executed. (There are some non-executive components too, but let’s keep that aside for the sake of simplicity.)
- Projects (X-flowcharts): A project or the X-flowchart is a flow diagram that contains the control flow and data flow of an application. The nodes of the graph are based on the components in repositories — they do not have any execution logic within them. So, when the application is executed, the code inside the components is invoked on behalf of a node when it is called for execution.
They are neatly segregated under the workspace folders.
Our HeadTracker recruitment application is in a workspace named “headtracker” which is a folder on my system. All the projects within the workspace are under the “pro” subfolder under it; and all the repositories within the workspace are under the “repo” subfolder under it. Thus our starting point is:
- A repository “repo” (located under the repo subfolder)
- A project “pro” (located under the pro subfolder)
We cloned the project folder with a name “jobportal” within the same folder.
This created the new “jobportal” project. The new project contains all the nodes that were in the “pro” project. (All the nodes are represented as json files within the project folder.) Opening it in Assembler’s Workbench and saving it set the correct project name in all the node json files. These nodes are still based on the components within the “repo” repository, which means that the code is not duplicated.
Here is a schematic what we just achieved with this one copy-paste operation.
What is so exciting about it is that the codebase is still in a single place. Even as the job portal gets its own functionality changes, most functionality being common, most of the codebase will be common. In future, when you fix a problem with this code, you will need to fix it exactly in one place, and both applications will get the fix.
Next Step: Strategizing Further Development
Code Segregation Aspects
HeadTracker is already a complex application. It has roughly 1200 nodes and 500 components. (These numbers are already too high for a single project or single repository. But consider that it was developed at a time when Xsemble did not feature a neat way of separating them out.) In the interest of avoiding further clutter to the existing repository and project, we shall keep the new development (functionality specific to job portal) in a separate repository. We shall also try to find opportunities to segregate further functionalities into separate subprojects.
Dealing with Code that’s Almost the Same
There is a neat trick that can help us to keep the codebase common. There are invariably some places in the code that need to behave slightly differently in the separated applications. Creating a separate component for such a small change would be an overkill, and it will add to future maintenance.
The trick to use in such cases, is parameterization. A parameter is simply a name-value pair. One can define a node parameter (the name) at the component level, and set its value at the node level. (A burn-time parameter definition will do.) Thus, different nodes based on the same component can have different values set for the same parameter. We shall use this technique to assign one value to the parameter of the node in the recruitment application and another value to the same parameter of the node in the job portal application.
With the parameter defined on component level, our component code can go like:
if param value is one_way: functionality valid for one application else if param value is another_way: functionality valid for another application
In this article, we saw how we are spawning a related job portal application from our already existing recruitment application. The process is generic enough to be used spawn an application from an existing base application with common functionality. The base application needs to be an Xsemble application for this to work.
Copying an Xsemble project allowed us to create a replica of the design while keeping the same code base. Both the applications can be further modified as per their business needs and have their own life. Their common functionality stays within the common components within a common repository, thus keeping the maintenance effort low. We also saw how to strategize the code and functionality separation for further development of the application.