{"id":25129830,"url":"https://github.com/lightquantumarchive/ee458_exm_py","last_synced_at":"2025-04-02T22:12:49.081Z","repository":{"id":103065340,"uuid":"357864580","full_name":"LightQuantumArchive/ee458_exm_py","owner":"LightQuantumArchive","description":"SJTU EE458, excuse me?","archived":false,"fork":false,"pushed_at":"2021-04-14T11:29:22.000Z","size":10,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-26T22:42:59.804Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LightQuantumArchive.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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":"2021-04-14T10:27:31.000Z","updated_at":"2025-01-14T00:40:49.000Z","dependencies_parsed_at":null,"dependency_job_id":"8a901656-c8c7-4d34-b10e-b110c37d553b","html_url":"https://github.com/LightQuantumArchive/ee458_exm_py","commit_stats":null,"previous_names":["lightquantumarchive/ee458_exm_py"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LightQuantumArchive%2Fee458_exm_py","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LightQuantumArchive%2Fee458_exm_py/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LightQuantumArchive%2Fee458_exm_py/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LightQuantumArchive%2Fee458_exm_py/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LightQuantumArchive","download_url":"https://codeload.github.com/LightQuantumArchive/ee458_exm_py/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246899664,"owners_count":20851898,"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":[],"created_at":"2025-02-08T12:25:44.007Z","updated_at":"2025-04-02T22:12:49.059Z","avatar_url":"https://github.com/LightQuantumArchive.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# EE458, excuse me?\n\nAdapted from Java code because I don't have JVM installed locally.\n\nIntended to serve as demo code for 1-N object design model.\n\n## Definition\n\nThe definition of objects can be found at [definition.py](definition.py).\n\nAn `Advertiser` can hold multiple `Account`s,\n\nAn `Account` may only exist in a single `Advertiser`.\n\n`Account.set_owner` may change its owner.\n\n`Advertiser.add_account` may add an `Account` to its accounts, and vice versa.\n\n## Tests\n\nTest code can be found at [tests.py](tests.py). Run test by executing [main.py](main.py)\n\n``` shell\n$ python3 main.py\ntest_owner (tests.TestAddToDifferentAdvertiser) ... FAIL\ntest_contains (tests.TestAddToDifferentAdvertiser) ... FAIL\ntest_owner (tests.TestResetOwner) ... FAIL\ntest_contains (tests.TestResetOwner) ... FAIL\n\n======================================================================\nFAIL: test_owner (tests.TestAddToDifferentAdvertiser)\n----------------------------------------------------------------------\nAssertionError: unexpectedly None : Who's my owner?\n\n======================================================================\nFAIL: test_contains (tests.TestAddToDifferentAdvertiser)\n----------------------------------------------------------------------\nAssertionError: \u003cAccount \"alice\" owner=None\u003e not found in \u003cAdvertiser \"daniel\" accounts=set()\u003e : I should be one of daniel.\n\n======================================================================\nFAIL: test_owner (tests.TestResetOwner)\n----------------------------------------------------------------------\nAssertionError: unexpectedly None : Who's my owner?\n\n======================================================================\nFAIL: test_contains (tests.TestResetOwner)\n----------------------------------------------------------------------\nAssertionError: \u003cAccount \"alice\" owner=None\u003e not found in \u003cAdvertiser \"daniel\" accounts=set()\u003e : I should be one of daniel.\n\n----------------------------------------------------------------------\nRan 4 tests in 0.001s\n\nFAILED (failures=4)\n```\n\nSo how may I change the owner of an `Account` without setting its owner to `None`(`null`) first?\n\n## Fixed Solution\n\nA fixed solution is given in [fixed_definition.py](fixed_definition.py).\n\n```shell\ntest_owner (tests.get_test_classes.\u003clocals\u003e.TestAddToDifferentAdvertiser) ... ok\ntest_contains (tests.get_test_classes.\u003clocals\u003e.TestAddToDifferentAdvertiser) ... ok\ntest_owner (tests.get_test_classes.\u003clocals\u003e.TestResetOwner) ... ok\ntest_contains (tests.get_test_classes.\u003clocals\u003e.TestResetOwner) ... ok\n\n----------------------------------------------------------------------\nRan 4 tests in 0.001s\n\nOK\n```\n\nThe point is, it's easy to break the constraint if both elements (`Account`) and containers (`Advertiser`)\ncan mutate the state, or more specifically, trying to manage the ownership of an element (`Account`) at the same time.\n\nThe correct way to implement this relation is to leave all the mutation work to one of them (the `N` part in this relation,\ni.e. container `Advertiser`), and link the element (`Account`) to its container only.\n\nWhen considering concurrency, you need sync and transaction to make all these things work. Yes, all the mutex and locking\nmechanism stuff.\n\nIf you are lucky enough and have a relational database on your hand, use `foreign keys` to add links from your\n`Account` to `Advertiser` instead.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flightquantumarchive%2Fee458_exm_py","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flightquantumarchive%2Fee458_exm_py","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flightquantumarchive%2Fee458_exm_py/lists"}