Reusable Utility Classes – Building Scalable Architecture

Utility classes contain reusable methods that are used across your codebase. Building scalable utility classes is key to maintainable Salesforce applications.

1. String Utility Class


public class StringUtil {
    
    // Check if string is empty or null
    public static Boolean isEmpty(String value) {
        return String.isBlank(value);
    }
    
    // Truncate string to max length
    public static String truncate(String value, Integer maxLength) {
        if (String.isBlank(value)) return value;
        return value.length() > maxLength ? value.substring(0, maxLength) : value;
    }
    
    // Capitalize first letter
    public static String capitalize(String value) {
        if (String.isBlank(value)) return value;
        return value.substring(0, 1).toUpperCase() + value.substring(1).toLowerCase();
    }
    
    // Remove all whitespace
    public static String removeWhitespace(String value) {
        if (String.isBlank(value)) return value;
        return value.replaceAll('\\s', '');
    }
    
    // Convert comma-separated string to list
    public static List<String> parseList(String value, String delimiter) {
        List<String> result = new List<String>();
        if (String.isBlank(value)) return result;
        
        for (String item : value.split(delimiter)) {
            result.add(item.trim());
        }
        return result;
    }
    
    // Join list into comma-separated string
    public static String joinList(List<String> values, String delimiter) {
        return String.join(values, delimiter);
    }
}

// Usage
Account acc = new Account(
    Name = StringUtil.capitalize('acme corp'),  // 'Acme corp'
    Description = StringUtil.truncate(longText, 100)
);
  

2. List Utility Class


public class ListUtil {
    
    // Check if list is empty
    public static Boolean isEmpty(List<Object> list) {
        return list == null || list.isEmpty();
    }
    
    // Get first element safely
    public static Object getFirst(List<Object> list) {
        return isEmpty(list) ? null : list.get(0);
    }
    
    // Remove duplicates
    public static List<String> removeDuplicates(List<String> values) {
        if (isEmpty(values)) return new List<String>();
        
        Set<String> uniqueValues = new Set<String>(values);
        return new List<String>(uniqueValues);
    }
    
    // Check if lists have common elements
    public static Boolean hasCommonElements(List<String> list1, List<String> list2) {
        if (isEmpty(list1) || isEmpty(list2)) return false;
        
        Set<String> set1 = new Set<String>(list1);
        for (String item : list2) {
            if (set1.contains(item)) {
                return true;
            }
        }
        return false;
    }
    
    // Find index of element
    public static Integer indexOf(List<String> list, String value) {
        if (isEmpty(list)) return -1;
        
        for (Integer i = 0; i < list.size(); i++) {
            if (list.get(i) == value) {
                return i;
            }
        }
        return -1;
    }
    
    // Flatten list of lists
    public static List<String> flatten(List<List<String>> nestedList) {
        List<String> result = new List<String>();
        
        for (List<String> subList : nestedList) {
            if (!isEmpty(subList)) {
                result.addAll(subList);
            }
        }
        return result;
    }
}

// Usage
List<String> colors = new List<String>{'red', 'blue', 'red', 'green'};
List<String> unique = ListUtil.removeDuplicates(colors);  // {red, blue, green}
  

3. Map Utility Class


public class MapUtil {
    
    // Safe map get with default value
    public static Object getOrDefault(Map<String, Object> map, String key, Object defaultValue) {
        return map.containsKey(key) ? map.get(key) : defaultValue;
    }
    
    // Invert a map (swap keys and values)
    public static Map<Object, String> invertMap(Map<String, Object> originalMap) {
        Map<Object, String> inverted = new Map<Object, String>();
        
        for (String key : originalMap.keySet()) {
            inverted.put(originalMap.get(key), key);
        }
        return inverted;
    }
    
    // Merge two maps
    public static Map<String, Object> mergeMaps(Map<String, Object> map1, Map<String, Object> map2) {
        Map<String, Object> merged = new Map<String, Object>(map1);
        merged.putAll(map2);
        return merged;
    }
    
    // Filter map by value condition
    public static Map<String, Integer> filterByValue(Map<String, Integer> map, Integer minValue) {
        Map<String, Integer> filtered = new Map<String, Integer>();
        
        for (String key : map.keySet()) {
            if (map.get(key) >= minValue) {
                filtered.put(key, map.get(key));
            }
        }
        return filtered;
    }
}

// Usage
Map<String, Object> user = new Map<String, Object>{
    'name' => 'John',
    'age' => 30
};

String name = (String) MapUtil.getOrDefault(user, 'name', 'Unknown');  // 'John'
String email = (String) MapUtil.getOrDefault(user, 'email', 'N/A');    // 'N/A'
  

4. Date/Time Utility Class


public class DateTimeUtil {
    
    // Get start of day
    public static DateTime startOfDay(Date d) {
        return DateTime.newInstance(d.year(), d.month(), d.day(), 0, 0, 0);
    }
    
    // Get end of day
    public static DateTime endOfDay(Date d) {
        return DateTime.newInstance(d.year(), d.month(), d.day(), 23, 59, 59);
    }
    
    // Check if date is today
    public static Boolean isToday(Date d) {
        return d == Date.today();
    }
    
    // Check if date is in the past
    public static Boolean isPast(Date d) {
        return d < Date.today();
    }
    
    // Check if date is in the future
    public static Boolean isFuture(Date d) {
        return d > Date.today();
    }
    
    // Add business days (excluding weekends)
    public static Date addBusinessDays(Date startDate, Integer daysToAdd) {
        Date result = startDate;
        Integer count = 0;
        
        while (count < daysToAdd) {
            result = result.addDays(1);
            
            // Skip weekends (Saturday = 7, Sunday = 1)
            Integer dayOfWeek = Math.mod(result.toStartOfWeek().daysBetween(result) + 1, 7);
            if (dayOfWeek > 1 && dayOfWeek < 7) {
                count++;
            }
        }
        
        return result;
    }
    
    // Get age from birthdate
    public static Integer getAge(Date birthDate) {
        Integer age = Date.today().year() - birthDate.year();
        if (Date.today().dayOfYear() < birthDate.dayOfYear()) {
            age--;
        }
        return age;
    }
}

// Usage
Date dueDate = DateTimeUtil.addBusinessDays(Date.today(), 5);  // 5 business days from today
DateTime endOfToday = DateTimeUtil.endOfDay(Date.today());     // 23:59:59 today
  

5. Math/Number Utility Class


public class NumberUtil {
    
    // Safe integer conversion
    public static Integer toInteger(String value, Integer defaultValue) {
        try {
            return Integer.valueOf(value);
        } catch (Exception e) {
            return defaultValue;
        }
    }
    
    // Safe decimal conversion
    public static Decimal toDecimal(String value, Decimal defaultValue) {
        try {
            return Decimal.valueOf(value);
        } catch (Exception e) {
            return defaultValue;
        }
    }
    
    // Round to nearest
    public static Decimal roundTo(Decimal value, Integer places) {
        Decimal multiplier = Math.pow(10, places);
        return Math.round(value * multiplier) / multiplier;
    }
    
    // Calculate percentage
    public static Decimal getPercentage(Decimal part, Decimal whole) {
        if (whole == 0) return 0;
        return (part / whole) * 100;
    }
    
    // Check if number is between range
    public static Boolean isBetween(Decimal value, Decimal min, Decimal max) {
        return value >= min && value <= max;
    }
    
    // Get absolute value
    public static Decimal abs(Decimal value) {
        return value < 0 ? -value : value;
    }
}

// Usage
Decimal rounded = NumberUtil.roundTo(10.556, 2);  // 10.56
Decimal percentage = NumberUtil.getPercentage(75, 100);  // 75.0
  

6. Query Utility Class


public with sharing class QueryUtil {
    
    // Safe SOQL query with error handling
    public static List<SObject> safeQuery(String query) {
        try {
            return Database.query(query);
        } catch (QueryException e) {
            System.debug('Query error: ' + e.getMessage());
            return new List<SObject>();
        }
    }
    
    // Count records without throwing exception
    public static Integer countRecords(String objectName) {
        try {
            String countQuery = 'SELECT COUNT() FROM ' + objectName;
            return Database.countQuery(countQuery);
        } catch (Exception e) {
            System.debug('Count failed: ' + e.getMessage());
            return 0;
        }
    }
    
    // Build dynamic WHERE clause
    public static String buildWhereClause(Map<String, Object> filters) {
        List<String> conditions = new List<String>();
        
        for (String field : filters.keySet()) {
            Object value = filters.get(field);
            
            if (value instanceof String) {
                conditions.add(field + ' = \'' + String.escapeSingleQuotes((String)value) + '\'');
            } else if (value instanceof Integer) {
                conditions.add(field + ' = ' + value);
            } else if (value instanceof Decimal) {
                conditions.add(field + ' = ' + value);
            }
        }
        
        return conditions.isEmpty() ? '' : String.join(conditions, ' AND ');
    }
}

// Usage
List<SObject> accounts = QueryUtil.safeQuery('SELECT Id, Name FROM Account LIMIT 100');
Integer count = QueryUtil.countRecords('Account');
  

7. File/JSON Utility Class


public class JsonUtil {
    
    // Safely deserialize JSON
    public static Object deserialize(String jsonString, Type classType) {
        try {
            return JSON.deserialize(jsonString, classType);
        } catch (JSONException e) {
            System.debug('JSON parse error: ' + e.getMessage());
            return null;
        }
    }
    
    // Safely serialize to JSON
    public static String serialize(Object obj) {
        try {
            return JSON.serialize(obj);
        } catch (Exception e) {
            System.debug('Serialization error: ' + e.getMessage());
            return null;
        }
    }
    
    // Get value from map with type safety
    public static String getStringValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        return value != null ? String.valueOf(value) : null;
    }
    
    // Get nested value from map
    public static Object getNestedValue(Map<String, Object> map, String dotPath) {
        List<String> paths = dotPath.split('\\.');
        Object current = map;
        
        for (String path : paths) {
            if (current instanceof Map<String, Object>) {
                current = ((Map<String, Object>) current).get(path);
            } else {
                return null;
            }
        }
        
        return current;
    }
}

// Usage
WeatherResponse weather = (WeatherResponse) JsonUtil.deserialize(jsonStr, WeatherResponse.class);
String json = JsonUtil.serialize(weatherObject);
  

Best Practices for Utility Classes

Key Takeaways