{"id":"code-dev-java-optional-chain-blank-city","audience":"developers","category":"coding","track":"coding","technique":"constraints","title":"Refactor nested null checks into an Optional chain","free":false,"task":"Refactor cityLabel into a single Optional chain with no if statements or null checks. Product also wants blank or whitespace-only cities treated like missing ones, and the fallback text is now exactly 'Unknown city' (not 'N/A'). Clean the city with strip(), not trim(), because the old CRM sends Unicode spaces. Keep the signature. Return only the method in exactly 1 code block of at most 9 lines, under 20 words of text.","materialLabel":"The method and its callers (attached to your prompt automatically)","material":"// ShippingLabels.java  (Java 17, Parcelwise)\nimport java.util.Optional;\n\npublic final class ShippingLabels {\n\n    public static String cityLabel(Customer customer) {\n        if (customer != null) {\n            Address address = customer.getAddress();\n            if (address != null) {\n                String city = address.getCity();\n                if (city != null) {\n                    return city;\n                }\n            }\n        }\n        return \"N/A\";\n    }\n}\n\n// Customer.getAddress() and Address.getCity() can both return null.\n//\n// Callers: LabelPrinter.print(), ManifestExport.row()\n// Labels are printed on 4x6 thermal stickers, one city line per label.\n// Last change to this file: 2024 (Darnell), when Customer got addresses.","rules":[{"type":"codeBlocks","count":1},{"type":"maxCodeLines","max":9},{"type":"maxProseWords","max":20}],"mistakes":[{"title":"Missing the blank case","why":"A straight conversion still returns \"   \" for blank cities, and trim() misses Unicode spaces.","fix":"Add: \"map(String::strip) and treat blank as missing.\"","checks":["r1"]},{"title":"The old fallback","why":"The AI keeps \"N/A\" because that's what the code says.","fix":"Add: \"Fallback exactly 'Unknown city'.\"","checks":["r2"]},{"title":"Half a refactor","why":"The AI may keep an if or a null check around the chain.","fix":"Add: \"One Optional chain, no ifs or null checks.\"","checks":["r0"]},{"title":"The whole class and a lecture","why":"The AI reprints the class and explains Optional.","fix":"Add: \"Only the method, one code block, no text.\"","checks":["codeBlocks","maxCodeLines","maxProseWords"]}],"promptHints":[{"label":"Asks for an Optional chain","patterns":["optional","ofNullable","chain"]},{"label":"Handles blank cities","patterns":["blank","whitespace","strip","empty"]},{"label":"Gives the new fallback","patterns":["unknown city"]},{"label":"Protects the signature","patterns":["signature","same (name|method)"]},{"label":"Asks for only the method","patterns":["only the method","just the method"]}],"hint":"A refactor that keeps the old bug isn't finished. Tell the AI the blank-city rule, the new fallback text and that you want only the method.","rubricLabels":["Is one Optional chain (e.g. Optional.ofNullable(customer).map(Customer::getAddress).map(Address::getCity)...) with no if statements or explicit null checks","Cleans the city with strip() (e.g. .map(String::strip)), not trim(), and treats blank cities as missing (e.g. .filter(c -> !c.isEmpty()))","Falls back to exactly \"Unknown city\" with orElse, and keeps public static String cityLabel(Customer customer)"]}