{"id":17921410,"url":"https://github.com/gotson/canvashell","last_synced_at":"2025-04-03T08:40:49.740Z","repository":{"id":69097851,"uuid":"116353086","full_name":"gotson/canvashell","owner":"gotson","description":"A simple drawing application implemented in DDD with Spring Shell","archived":false,"fork":false,"pushed_at":"2018-02-28T10:00:30.000Z","size":69,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-08T22:14:12.232Z","etag":null,"topics":["ascii","domain-driven-design","spring-shell"],"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/gotson.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":"2018-01-05T06:56:54.000Z","updated_at":"2018-11-02T14:22:20.000Z","dependencies_parsed_at":null,"dependency_job_id":"0b0fe2cc-602e-4e5f-83bd-4b725b3ce940","html_url":"https://github.com/gotson/canvashell","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gotson%2Fcanvashell","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gotson%2Fcanvashell/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gotson%2Fcanvashell/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gotson%2Fcanvashell/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gotson","download_url":"https://codeload.github.com/gotson/canvashell/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246970251,"owners_count":20862496,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["ascii","domain-driven-design","spring-shell"],"created_at":"2024-10-28T20:33:45.256Z","updated_at":"2025-04-03T08:40:49.705Z","avatar_url":"https://github.com/gotson.png","language":"Java","readme":"# Canvashell\n\n## About\n\nA simple console drawing application.\n\n## Build \u0026 Run\n\n### Requirements\n\n* Java 8 JDK\n\n### Build\n\nTo build the project, just run the following command from the root folder:\n\n```gradlew build```\n\n### Run\n\nTo run the application, run the following command from the root folder:\n\n```java -jar build\\libs\\canvashell-0.0.1-SNAPSHOT.jar```\n\n### Usage\n\nOnce the application starts, you will be met with a shell invite:\n\n```enter command: ```\n\nYou can input a command with its arguments and press `Enter` to execute it.\n\nThe following commands are supported:\n\n| Command         | Description                                                                                           |\n|-----------------|-------------------------------------------------------------------------------------------------------|\n| `C w h`         | Create a new canvas of width 'w' and height 'h'.                                                      |\n| `L x1 y1 x2 y2` | Draw a line from (x1,y1) to (x2,y2) with color 'x'. Only horizontal and vertical lines are supported. |\n| `R x1 y1 x2 y2` | Draw a rectangle whose opposite corners are (x1,y1) and (x2,y2), with color 'x'.                      |\n| `B x y c`       | Bucket fill the entire area connected to (x,y) with color 'c'.                                        |\n| `Q`             | Quit the program.                                                                                     |\n\n## Design and implementation choices\n\n### Design\n\nI decided to use Domain Driven Design with onion architecture for this project.\n\nDrawing applications are usually of 2 types: bitmap or vector.\nBitmap only keeps the resulting effect of operations on the drawn canvas, while vector holds a list of drawn objects,\nwhich can be later on modified.\n\nGiven the bucket fill operation in vector is quite complex to achieve, as it doesn't have a shape, I decided to\nimplement a bitmap drawing application.\n\nThe domain is quite simple, I am using `Point` to address coordinates, and `Pixel` holds the representation of\none dot of the `Canvas`, which is the centerpiece of our domain.\n\nDrawing operations are performed on the `Canvas`, but as we don't need to keep a list of shapes drawn, using the\n_command pattern_ felt natural to implement the different drawing operations.\nEach `Command` is self-contained, and by extending an abstract base all commands are validated (Domain validation)\nbefore execution.\n\nFor the shell itself, I decided to use _Spring Shell_, first because my goto default framework is always _Spring Boot_,\nand second because implementing a shell is quite complex, and leveraging on what the good guys at Pivotal did seemed\nlike a good idea.\n\nSpring Shell provides out of the box the following features:\n\n* Command and arguments autocompletion\n* Command parsing and arguments validation (type and number of arguments)\n* Error handling on missing arguments or unknown commands\n\nNote that validation can be done at 2 levels: request (here, the shell) and domain. I decided to rely only on\ndomain validation, since the validation is mostly required at the whole Command object level (Points being inside the\ncanvas for example), and not at individual parameters level, and also because _Spring Shell_ already handles the basic\nchecks around valid commands and parameters.\n\n### Extensibility\n\nBecause of the DDD design choices, adding new commands has to be done at 2 levels:\n\n* implement a new command in the `domain.command` package\n* add the necessary `@ShellMethod` inside `interfaces.shell.ShellController`\n\nOne could argue that we could have added some command metadata (invoke letter, parameters, description) inside the\n`Command` object, and generate automatically all the necessary shell input methods (via reflection for example),\nbut to me that would break the DDD design choice.\nIndeed, the domain should not have concerns about how it is called.\nFor instance, if later on we added a REST interface, or a GUI, each of those interfaces would have their own input\nmethods, and would not necessarily care about the 'invoke letter' inside the `Command` for instance.\nOr maybe we would like to have a different set of available commands per interface.\n\n### Testing\n\nGiven the nature of the application, it made sense to perform integration testing with given commands against expected\ndrawn Canvas or error messages. I decided to use Cucumber for this, which helps to define reusable steps for each\ntesting scenario.\n\nI did not add any unit tests for the following reasons:\n\n* the `domain.model` package is composed of Data objects\n* the `domain.command` package contains some logic, but it is much easier to test using integration tests for the\nCanvas result than to try and look programmatically at the content of the resulting `Canvas`\n* Spring Shell already provides all the encapsulation necessary for the input commands validation\n* Since there are no dependencies to mock, integration tests can cover the full perimeter easily\n\n## Example run\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgotson%2Fcanvashell","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgotson%2Fcanvashell","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgotson%2Fcanvashell/lists"}