DEV Community

loading...
Cover image for Refactoring: Functional Cross Referencing

Refactoring: Functional Cross Referencing

jwp profile image John Peters ・2 min read

Scenario:
Two Views: A Parent View, containing a Child View. Each also have one typescript module each. We prefer to put most of our code into the modules because we want to focus on reusability.

Cross Functional Referencing

//Both of these functions are in 
//the folder named functions, 
//they are our reusable code.

function alterChild(ap:Parent){
  // Contains Child
  let child = ap.child;
  child.property = "New Value"
}

function async fillAParentGrid(bc:Child){
 let persons = await bc.service.getPersons();
 // 5 levels deep from child component
 bc.Parent.matTable.dataSource.data = persons;
}
Enter fullscreen mode Exit fullscreen mode

While this design works well, there is a question:

"In the function fillAParentGrid, shouldn't there be less mandatory knowledge just to set the data"?

While it's true that intellisense easily autodiscovers everything we see above; a new person to the team, will not have knowledge of how a MatTable works.

This requires cross-functional internals knowledge that shouldn't be required. 5 levels deep is too much.

Morphism is great but...
We want to make our api, 'new user' friendly, therefore we can do this:

In our parent function module simply add this function.

function async setData(ap:Parent, data:array<T>){
  // this hides the internals,  
  // the how it's done part.
  ap.matTable.DataSource.data = data;
}
Enter fullscreen mode Exit fullscreen mode

This makes having to know the API of the parent View much easier in the child module.

function async fillAParentGrid(bc:BChild){
 let persons = await bc.service.getPersons();
 // 3 levels deep from child component
 await bc.AParent.setData(persons);
 // or in the child view itself
 // 2 levels deep.
 await AParent.setData(persons)
}
Enter fullscreen mode Exit fullscreen mode

If we standardize our API and reserve the name setData for each component we're all set.

This is more in line with the new developer's thoughts at the time. "I want to set the data in the Parents' datagrid. To call this function from the BChild View it's simply

fillAParentGrid(this);
Enter fullscreen mode Exit fullscreen mode

A Better Improvement

 // This function name is ambiguous
 fillAParentGrid(this);

// These function names are not

//non compositional
 fillAParentGridPersons(); 
//compositional is better
 fillAParentGrid(persons); 

Enter fullscreen mode Exit fullscreen mode

The compositional pattern is better because the new developer may want to reuse the function to fill in different types : employees, cities, addresses, reports etc.

Discussion

pic
Editor guide