Test yourself on method sizes.


Here's a little test for you. You think it's hard to judge whether a method compiles to fewer than 50 bytes? Well, train yourself with the first table below and then try to guess the answers in the second table. Hint: 10 bytes = 1 line. Roughly.

Method Bytes

    public int getTotalWork() {
	return 1;
    }

2

    public int getProgressValue() {
	if (tuplesProcessed) {
	    return 1;
	}
	return 0;
    }

11

    private void addNewOwnedTarget(Element ownedParent,
				   Map ownedParentToOwnedTarget, Element upperChild,
				   Element ownedChild) {
	Target target =
	    getTarget(ownedParent, ownedParentToOwnedTarget, upperChild);
	connectParentToTarget(ownedParent, ownedParentToOwnedTarget, upperChild,
			      ownedChild, target);
    }

21

    private void clearGeneralState() {
	dependencyStrength.clear();
	subLevelAlgorithm.clear();
	currentElementScopes.clear();
    }

24

    private void addElement(ConcreteTuple tuple, Element element) {
	if (isCancelled) {
	    return;
	}
	if (element.getProperties().isInternal()) {
	    processElement(tuple, element);
	} else {
	    tuples.add(tuple);
	}
    }

43

    public boolean isLastElement(Element element) {
	if (elements.isEmpty()) {
	    return false;
	}
	Element lastElement = elements.get(elements.size() - 1);
	return element.equals(lastElement);
    }

44

    public int getSubLevelDependencyCount(Element upperParent) {
	Model model = registry.get(Model.class);
	Level level = model.getLevel();
	Map ownedParentToOwnedTarget = levelToDependencies.get(level);
	if (ownedParentToOwnedTarget == null) {
	    return 0;
	}
	return getSubLevelDependencyCount(ownedParentToOwnedTarget,
					  upperParent);
    }

52

    private Collection getOwnedChildren(Map ownedParentToOwnedTarget, 
                                        Element ownedParent) {
	Collection ownedChildren = new HashSet();
	Target target = ownedParentToOwnedTarget.get(ownedParent);
	for (Collection targetChildren : 
		 target.upperChildToOwnedChildren.values()) {
	    ownedChildren.addAll(targetChildren);
	}
	return ownedChildren;
    }

56

    private Collection generateTuples() {
	isCancelled = false;
	Collection levelTuples = levelToTuples.get(level);
	if (!levelTuples.isEmpty()) {
	    return levelTuples;
	}
	if (level == Level.FUNCTION) {
	    return generateHardTuples();
	}
	Options options = registry.get(Options.class);
	if (!options.isTrue(OptionTag.IS_RESTRICTIVE_TUPLE_GENERATION)) {
	    return generateHardTuples();
	}
	return generateTuplesByInferingLowerLevelTuples();
    }

65

OK, test time. Which of the following methods are less than 50 bytes long? Answers below.

Method Bytes

    public boolean isActive() {
	Options options = registry.get(Options.class);
	return options.isTrue(OptionTag.ABSOLUTE_ANALYSIS);
    }

A.

    private void storeAllAccessibleCousins(Collection elements) {
	Ensemble ensemble = registry.get(Ensemble.class);
	EnsembleFactory ensembleFactory = registry.get(EnsembleFactory.class);
	if (model.getLevel() == Level.FUNCTION) {
	    for (Element element : elements) {
		Element owningOwningSet = element.getRelations().getOwningSet()
		    .getRelations().getOwningSet();
		if (!owningOwningSetToOwned.keySet()
		    .contains(owningOwningSet)) {
		    recordCousins(ensemble, ensembleFactory, owningOwningSet);
		}
	    }
	}
    }

B.

    private Element storeElementValue(Element element) {
	Collection elements = getAccessibleElements(element);
	int value = elements.size();
	element.setAnalysisValue(this, value);
	summaryValue += value;
	return element;
    }

C.

    public void calculateHighlightedElements() {
	highlightedElements.clear();
	highlightedElements
	    .addAll(analysisLib.getAllSelectedAndImmediateRelations());
    }

D.

    public Element map(Element element) {
	if (!element.getProperties().isInternal()) {
	    return element;
	}
	if (model.getLevel() == Level.FUNCTION) {
	    return storeElementValue(element);
	}
	inferValueFromOwnedElements(element);
	return element;
    }

E.

    private void storeAllPublicElements(Collection elements) {
	EnsembleFactory ensembleFactory = registry.get(EnsembleFactory.class);
	Predicate isPublicPredicate =
	    ensembleFactory.createIsPublicPredicate();
	elements = ensemble.select(elements, isPublicPredicate);
	if (model.getLevel() != Level.PACKAGE) {
	    elements = ensemble.select(elements, new IsOwnerPublicPredicate());
	}
	allPublicElements.addAll(elements);
    }

F.

    public Collection getDescription(Element element) {
	Collection paragraphs =
	    localLib.getInitializedParagraphs(registry, element, this,
					      Analysis.ABSOLUTE_ANALYSIS_NAME + ": ");
	if (model.getLevel() != Level.FUNCTION) {
	    paragraphs.add(getContainedElementsDescription(element));
	} else {
	    addFunctionDescription(element, paragraphs);
	}
	return paragraphs;
    }

G.

    public void clearCache() {
	Ensemble ensemble = registry.get(Ensemble.class);
	ensemble.map(analyses, new ClearCacheFunction());
    }

H.

    public Collection getActiveAnalyses() {
	Ensemble ensemble = registry.get(Ensemble.class);
	return ensemble.select(analyses, new IsActivePredicate());
    }

I.

    private Collection getIncomingTuples(Element element) {
	Collection tuples = model.getSFTsContaining(element);
	tuples = ensemble.map(tuples, new GetShortenedTupleFunction(element));
	tuples = new HashSet(tuples); // Remove duplicates
	return removeDependenciesOnSelf(element, tuples);
    }

J.

    public Element map(Element element) {
	if (!element.getProperties().isInternal()) {
	    return element;
	}
	int value = getAmplificationValue(element);
	element.setAnalysisValue(this, value);
	summaryValue += value;
	return element;
    }

K

Answers.

A = yes (25 bytes). B = hell no (130 bytes). C = yes (35 bytes). D = yes (29). E = yes (44 bytes). F = no (79 bytes). G = no (54 bytes). H = yes (34 bytes). I = yes (33 bytes). J = yes (46 bytes). K = yes (46 bytes).

Again, the point here is not to force Java programmers to be compilers, but just to get familiar with some baseline examples so that they can map these to their own style of programming and thereafter forget about it.

Broadly, limiting a method to four or five lines of code will usually bring it in under the 50-byte mark, which many projects have as their goal. The hard bytecode limit merely ensures that teams can avoid those petty code-review arguments over subjective size standards and that the results are automatically verifiable.