{"id":20828770,"url":"https://github.com/perty/examples-of-good-code","last_synced_at":"2026-04-29T05:32:12.546Z","repository":{"id":258765631,"uuid":"875651580","full_name":"perty/examples-of-good-code","owner":"perty","description":"Compilation of good code design.","archived":false,"fork":false,"pushed_at":"2024-10-20T15:28:34.000Z","size":8,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-12-27T14:10:54.210Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/perty.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-10-20T14:44:52.000Z","updated_at":"2024-10-20T15:28:38.000Z","dependencies_parsed_at":"2024-10-21T20:52:49.566Z","dependency_job_id":null,"html_url":"https://github.com/perty/examples-of-good-code","commit_stats":null,"previous_names":["perty/examples-of-good-code"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/perty/examples-of-good-code","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perty%2Fexamples-of-good-code","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perty%2Fexamples-of-good-code/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perty%2Fexamples-of-good-code/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perty%2Fexamples-of-good-code/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/perty","download_url":"https://codeload.github.com/perty/examples-of-good-code/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perty%2Fexamples-of-good-code/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32412887,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T05:20:56.964Z","status":"ssl_error","status_checked_at":"2026-04-29T05:19:54.749Z","response_time":110,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-17T23:18:24.701Z","updated_at":"2026-04-29T05:32:12.533Z","avatar_url":"https://github.com/perty.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Examples of good code\n\nA bit ambitious, but I have some ideas on the mini-level of design.\n\nThe context is a type safe language, in this case Java, giving us the short feedback loop of the compiler.\n\n* Parameters - how to design your interfaces.\n* State - make impossible states impossible.\n\n## Parameters\n\nIn any system of considerable size, you will have to deal with parameters, their\norder, their type, and their meaning. When calling a function, you should not need to\nwaste energy on figuring out what the parameters are, and what they mean.\n\n### Parameters should be of the different types\n\nHaving the same type gives the risk of mixing up the order of the parameters.\n\nHere are two examples of bad parameter design found in the wild:\n\n```java\n\npublic void method(BigDecimal interest, BigDecimal amortization, BigDecimal fee) {\n    // ...\n}\n\npublic void method1(LocalDate start, LocalDate end) {\n    // ...\n}\n```\nIn the first example, not only are method1 exposed to the risk of mixing up the order of the parameters, \nbut the BigDecimal class allows for huge values, which is not what we want in this case.\n\nIn the second example, we could, by accident, switch the start and end dates.\n\n### Better\n\nLet's make the parameters type safe, and give them a name that makes sense.\n\n```java\npublic void method2(Money interest, Money amortization, Money fee) {\n\n}\n```\nThey are now of the type Money, which is a class that only allows for positive values. We still can\nmix them up.\n\n### Even better\n\n`Money` is like a primitive but in the financial domain. Let's state the intention of each value\nand rise the level of abstraction.\n\n```java\npublic void method3(Interest interest, Amortization amortization, Fee fee) {\n\n}\n```\n### Representing a date range\n\nInstead of having two dates, we can represent a date range. The method could of course be responsible\nfor checking that the start date is before the end date. But, it has other responsibilities, and we\nwish to focus on that. And there might be other methods that have the same need.\n\nTherefor we introduce a DateRange class and guarantee that the start date is before the end date.\n\n```java\npublic void method2(LocalDateRange dateRange) {\n\n}\n\npublic class LocalDateRange {\n    private final LocalDate start;\n    private final LocalDate end;\n\n    private LocalDateRange(LocalDate start, LocalDate end) {\n        this.start = start;\n        this.end = end;\n    }\n\n    public static DateRangeBuilder start(LocalDate start) {\n        return new DateRangeBuilder(start);\n    }\n\n    public static class DateRangeBuilder {\n        private final LocalDate start;\n\n        public DateRangeBuilder(LocalDate start) {\n            this.start = start;\n        }\n\n        public LocalDateRange end(LocalDate end) {\n            if(end.isAfter(start)) {\n                return new LocalDateRange(start, end);\n            }\n            throw new IllegalArgumentException(\"End date must be after start date\");\n        }\n    }\n    ...\n```\n\nHere we use a builder pattern to lessen the risk of mixing up the start and end date. We also guarantee\nthat the end date is after the start date but only at runtime.\n\nHere's how you would use it:\n\n```java\nLocalDateRange localDateRange = LocalDateRange\n        .start(LocalDate.of(2024, 10, 20))\n        .end(LocalDate.of(2024, 10, 30));\n```\n\n## State\n\nWhen designing your classes, you should make impossible states impossible. This means that you should\ndesign your classes in such a way that they can never be in an invalid state.\n\nConsider a traffic light. It can be in three lights: Red, Yellow, and Green. A naive implementation\nwould be to have three boolean fields, red, yellow, and green.\n\n```java\npublic class TrafficLight1 {\n    private boolean red;\n    private boolean yellow;\n    private boolean green;\n    ...\n```\n\nThis allows for 8 states, half of which are invalid. Instead, we can use an enum.\n\n```java\npublic class TrafficLight2 {\n    private State state;\n\n    public enum State {\n        RED( true, false, false),\n        RED_YELLOW( true, true, false),\n        GREEN( false, false, true),\n        YELLOW( false, true, false);\n\n        final boolean red;\n        final boolean yellow;\n        final boolean green;\n\n        State( boolean red, boolean yellow, boolean green) {\n            this.red = red;\n            this.yellow = yellow;\n            this.green = green;\n        }\n    }\n    ...\n```\n\nWe are now down to 4 states, all of which are valid. But one problem remains: we can still do state\ntransitions that are invalid. We can solve this by using a state machine.\n\n```java\npublic class TrafficLight3 {\n    private State state;\n\n    public enum State {\n        RED,\n        RED_YELLOW,\n        GREEN,\n        YELLOW\n    }\n\n    public void nextState() {\n        state = switch (state) {\n            case RED -\u003e RED_YELLOW;\n            case RED_YELLOW -\u003e GREEN;\n            case GREEN -\u003e YELLOW;\n            case YELLOW -\u003e RED;\n        };\n    }\n    ...\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fperty%2Fexamples-of-good-code","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fperty%2Fexamples-of-good-code","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fperty%2Fexamples-of-good-code/lists"}