Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DSDK-183] [TS] [DSDK] Error/Type safety with purify-ts #12

Merged
merged 6 commits into from
Jan 29, 2024

Conversation

valpinkman
Copy link
Member

@valpinkman valpinkman commented Jan 25, 2024

  • chore: add purify-ts in the template module
  • chore: setup aliases in project

📝 Description

Following the PoC and study about using a potential FP library in the project, here is a rewrite of the module that ship error safety using purify-ts
The interesting part of this is how we can handle easily the different types of error and at which point we do this.

From what I could see during the implementation of this, the Either (aka Result) and Maybe (aka Option) helpers will be mostly used by the data sources as it might not be safe getting
value from these external sources. The Either and Maybe are handled in the services, and the usecase never knows about these types.
Let's see how we manage to tame this tool into the library: it does make things a little more verbose, however the error/type safety is pretty amazing.

❓ Context

✅ Checklist

Pull Requests must pass the CI and be code reviewed. Set as Draft if the PR is not ready.

  • Covered by automatic tests.
  • [ ] Impact of the changes:


🧐 Checklist for the PR Reviewers

  • The code aligns with the requirements described in the linked JIRA or GitHub issue.
  • The PR description clearly documents the changes made and explains any technical trade-offs or design decisions.
  • There are no undocumented trade-offs, technical debt, or maintainability issues.
  • The PR has been tested thoroughly, and any potential edge cases have been considered and handled.
  • Any new dependencies have been justified and documented.

Copy link

vercel bot commented Jan 25, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
device-sdk-ts-sample ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jan 29, 2024 9:53am

@valpinkman
Copy link
Member Author

valpinkman commented Jan 25, 2024

⚠️ during this PR, i realised that the test.ts files were included in the ./lib when building it.

I have tried removing them from the tsconfig.json file, doing this however will make eslint bitch about the files being linted but not included in the tsconfig.json. I have not dig into it too much yet, but we definitely will not want the test.ts files in the exported ./lib

edit: FIXED

@valpinkman valpinkman marked this pull request as draft January 25, 2024 10:51
@valpinkman valpinkman marked this pull request as ready for review January 25, 2024 10:56
packages/core/jest.config.ts Show resolved Hide resolved
packages/core/tsconfig.json Outdated Show resolved Hide resolved
const parseResponseSpy = jest.spyOn(
RestRemoteConfigDataSource.prototype as any,
"_parseResponse"
);
Copy link
Contributor

@jdabbech-ledger jdabbech-ledger Jan 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[ASK] if we spy on a private class methods to check the method calls of RemoteConfigDataSource, does this class respect the single responsibility principle?
Shouldn't it be splitted with a Repository class?
@mbertin-ledger @smartine-ledger

Copy link

@smartine-ledger smartine-ledger Jan 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point is not the SRP but the Unit Test best practice : a private method must not be tested. To be honest I am not sure to understand why we try doing that 👍 🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so we can have all the different state during the tests (good json, bad formatted json, bad api call etc...).

Copy link

@smartine-ledger smartine-ledger Jan 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case this should be tested through RemoteDataSource.getConfig() (not by calling private methods)😉 . A UT tests what is exposed by your classe (= public / internal methods). Nothing more

Copy link
Member Author

@valpinkman valpinkman Jan 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But the coverage tho....

also we are not testing those private functions, we just make them behave differently so .getConfig() can throw all the possible cases (Error or Success). It would be the same as mocking a fetch or api call.

There is also a test that just run them vanilla so we do go through them "privately".

This way I get into all the different branches of my code and get a 100% coverage on what I've developed

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not have a good understanding when testing in JS/TS. We may need to discuss about that with the team. During a continous improvment? 🙂

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure

Copy link
Contributor

@alexandremgo alexandremgo Jan 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah we should talk about it - I don't think we can reach 100% everywhere. There is probably a layer (the outermost layer in the clean archi) that we won't be able to unit tests without doing some stuff like spying, because what they use is not dependency injected into them.

In the example of RemoteConfigDataSource, we could dependency inject an interface representing the fetch/axios api, so we can mock them without using "spy". But they will probably be cases where it's not practical

export type RemoteConfigFailure =
| ApiCallError
| ParseResponseError
| JSONParseError;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind, but so in our architecture/module structure we should put the error types definitions inside the di folder ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where would you put them ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe in the model or data folder ? Because they are about the model Config ? But i don't have a strong opinion, i'm asking to know where i should put my errors definitions too ahah

);
return JSON.parse(version) as Config;
getConfig(): Either<LocalConfigFailure, Config> {
return Either.encase(() => stubFsReadFile())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh encase seems super practical

Copy link
Contributor

@alexandremgo alexandremgo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great addition, Purify is going to be super useful !

Copy link
Contributor

@jdabbech-ledger jdabbech-ledger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@valpinkman valpinkman merged commit c79f34a into develop Jan 29, 2024
4 checks passed
@valpinkman valpinkman deleted the chore/add-purify-ts branch January 29, 2024 14:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants