Breaking up methods/functions to do one thing only is considered a good practice as it leads to more maintainable and readable code but it increase number of operations in many cases . How to achieve both ie. optimum number of operations while still keeping readability/maintainability ?
As illustrated in this dummy example . I want to find count of Js in a string but also want to check if addition of all positive integers is even or odd . Two separate methods for these 2 different tasks leads to excellent readability but increases number of operations by n where n is size of input string . Combining them in a method leads to very low readability but decreases number of operations.
class UserText{
constructor(userProvidedText){
this.content = userProvidedText;
}
_findCharCount(char){
let count = 0;
for (let i = 0; i < this.content.length; i++) {
if (this.content[i] === char) {
count++;
}
}
return count
}
_isDigit(char) {
return !isNaN(parseInt(char));
}
// Excellent Readability and maintainability
findLetterCount(char){
return this._findCharCount(char)
}
// Excellent Readability and maintainability
CheckIfDigitsAdditionEven(){
let count = 0;
for (let i = 0; i < this.content.length; i++) {
console.log(this.content[i])
if (!this._isDigit(this.content[i])){
continue
}
count+=parseInt(this.content[i]);
}
if (count % 2 === 0){
return true
}
return false
}
// Combining functionalities in 1 function . Not readable. Not maintainable But time complexity is decreased.
CheckIfDigitsAdditionEvenAndCountLetter(char){
let count1 = 0;
let count2 = 0;
let res1 = false;
for (let i = 0; i < this.content.length; i++) {
if (this.content[i] === char) {
count2++;
}
if (this._isDigit(this.content[i])){
count1+=parseInt(this.content[i]);
}
}
if (count1 % 2 === 0){
res1 = true
}
return [res1, count2]
}
}
ut = new UserText("SOME..STRING..12311.HHIIJJJJKKKLL ")
/*
Breaking up functions and using them one at a time . One method , one purpose..
Maintainable and readable but iterates by 2n.
*/
JCount=ut.findLetterCount("J")
evenCheck=ut.CheckIfDigitsAdditionEven()
/*
Using 1 function for the task . One method , multi-purposed..
Maintainable and readable is very low but iterates by "n" only .
*/
cr=ut.CheckIfDigitsAdditionEvenAndCountLetter("J")
// Some custom logic here .
console.log(JCount, evenCheck)
console.log(cr[0], cr[1])
First of all, thinking about performance issues while designing the model is good, but Premature Optimization should be avoided.
Second, the OP's code in my opinion is neither clean/lean nor maintainable, where the OP claims it to be. And the implementation with all the pseudo-privately annotated prototype methods already starts as a big mess.
Third, the OP's
CheckIfDigitsAdditionEvenAndCountLettermethod intermingles two tasks which anyhow have to be implemented each separately ... e.g. ashasEvenTotalDigitCountandgetTotalLetterCountFor.Thus said, the OP should write a lot of helper/utility functions which each do one thing a time. These helpers then get re/used by the very few and only really necessary methods, the OP wants the model to feature.
A much better readable, maintainable version of what the OP did provide could look like the following example code ...
Edit according to the OP's comment ...
If there is a 500MB String in RAM, it depends on the target platform. A browser might not be the best environment for running an application which has such requirements whereas a highly performant node server environment might not even getting close to being in trouble.
In addition, taking into account the scenario described by the OP, the question arises whether a class based design like the one introduced with the original question does really suite the OP's needs.
But what could be done is the introduction of lazy computation and memoization techniques, in order do the heavy lifting only when it's needed and never twice for one and the same time consuming operation.
And of cause nothing prevents the OP from implementing a function which does all the necessary computation within a single full string iteration when there is no other option. But then again, the implementation of additional functionality which each computes just a fraction of it is entirely obsolete.