Skip to content

Conversation

@Paul7Peterson
Copy link

What Github issue does this PR relate to? Insert link.

What should the reviewer know?

@Paul7Peterson Paul7Peterson added this to the CON & TP: Storybook milestone Jan 13, 2022
@Paul7Peterson Paul7Peterson self-assigned this Jan 13, 2022
@helloanil
Copy link
Contributor

Hey @Paul7Peterson! As I have mentioned also on Slack (also writing here for better visibility for everyone), let's try to avoid changing the format of all files in the project.

Although I agree with the format rules of your formatter, adding this complexity for this work will only make it impossible to review this PR. Reviewing 409 files would probably take ~2 months for me 😂

@ericbolikowski
Copy link
Contributor

@Paul7Peterson, did you use any codemods? I see systemic changes changes, I'm curious how you managed to be so detailed. I hope you didn't read every line of code 😅

@Paul7Peterson
Copy link
Author

@Paul7Peterson, did you use any codemods? I see systemic changes changes, I'm curious how you managed to be so detailed. I hope you didn't read every line of code 😅

I go full vainilla 😅 So yeah, I was doing everything manually and reading everything line by line.

In the end I'm a senior developer, so I know how to do this kind of refactoring and I normally follow some patterns in the search to find the common issues.

@ericbolikowski
Copy link
Contributor

I go full vainilla 😅 So yeah, I was doing everything manually and reading everything line by line.

In the end I'm a senior developer, so I know how to do this kind of refactoring and I normally follow some patterns in the search to find the common issues.

Kudos! 🙌

Copy link
Contributor

@helloanil helloanil left a comment

Choose a reason for hiding this comment

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

Hey @Paul7Peterson, solid work here. There are some key take-aways we would like to discuss for this PR:

  • Using FC for React Components is discouraged, even by the React team. (See here and also see here). We can either use JSX.Element, or let TS infer the type itself, which works very well.
  • Regarding refactoring of TpJobseeker to TpJobSeeker, there are two things:
    • Jobseeker can be a one word in English, not Job Seeker 😅
    • This is very dangerous because we have our DB and BE models in Production as TpJobseekerProfile. (See the screenshot below) So changing these would have a breaking impact in our applications. Can we avoid that for now? These will anyway change in a few months when we complete the Salesforce migration.
      image
  • We've seen some changes from undefined to null. Can you elaborate on this one? What's the end goal with these changes?

We've spent 1 hour 15 minutes with @ericbolikowski on this PR and we were able to review only 10% of it. If there's still a chance to split this PR into smaller chunks, we'd highly appreciate it and I'm sure it will be way more time-efficient for everyone. An example pattern I can see here is:

  • A PR for semi colons
  • A PR for TS in Admin Panel
  • A PR for replacing certain words
  • and so on

Let us know what you think. But again, we're both astonished with the amazing mind and time spent here. Big kudos many times. True champ!

image

Comment on lines 9 to 14
"cSpell.words": [
"Formik",
"mentee",
"mentees",
"redi"
]
Copy link
Contributor

Choose a reason for hiding this comment

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

Issues with the spelling of these words was never brought up by other developers so I'm inclined towards thinking that this might be a very specific problem to a developer. Do you think having these kind of config in your local would make more sense?

In contrast, if we want to have something like this in our project, there are three things we can do:

  • We should come up with more words in this glossary
  • Have a separate config file for this concern
  • Document the usage of this extension and benefits in the Readme file

Copy link
Author

Choose a reason for hiding this comment

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

I use spell checkers to avoid a big amount of issues that are coming from that. In the PR can be seen in some places how I was fixing many typing errors that I found because of this. The configuration of glossaries can be done per user or per workspace, but makes no sense to be done for the first.

The words in the glossary (that must be in the .vscode/settings.json file) are not for describing terms in the project, but for including terms that are not recognized per the English and language-specific database of the extension. So the first bullet makes no sense for this specific case, but can be done in a separated .md file without any problem. And the second bullet it's because it's the config of an extension and must go in this specific file. I would also recommend setting a .vscode/extensions.json with the recommendation.

About the documentation of the extension, you can name the recommended extension and set a link to the source documentation, but the use of this extensión is exactly the same as the auto-corrector in word.

Comment on lines +59 to 66
"TpJobSeekerProfile": {
"dataSource": "mongodb",
"public": true
},
"TpJobseekerCv": {
"TpJobSeekerCv": {
"dataSource": "mongodb",
"public": true
},
Copy link
Contributor

Choose a reason for hiding this comment

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

We should definitely avoid this. Please see the main comment on the PR 🙏

Copy link
Author

Choose a reason for hiding this comment

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

Ok, I will undo everything about the Jobseeker rename.

const styleClasses = useNotificationStyles()

const Icon = state ? variantIcon[state.variant] : null
const Icon = variantIcon[state?.variant] || null
Copy link
Contributor

Choose a reason for hiding this comment

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

This makes total sense but it loses a bit of quick readability when we switch to this. Thinking of more junior developers who can contribute to this project, I think keeping it the old way has more value. What do you think?

Copy link
Author

Choose a reason for hiding this comment

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

The one on top misses the case of not having a variantIcon with that variant name, returning undefined instead of null, and leading to 3 possible return types.

A junior benefits from being in contact with code that is not made for dummies and that enforces good practices. That's what my experience as Tech Lead and Senior has been taught me. on top you have three elements to analyze; down just two, and one is a fallback, so I can focus on just one element.

Placeholder,
} from '@talent-connect/shared-atomic-design-components'
import { RedProfile } from '@talent-connect/shared-types'
import { mapStateToProps } from '../../helpers';
Copy link
Contributor

Choose a reason for hiding this comment

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

Again a very cool idea here, I really liked the helper. Can we just change the name again to make it easier for more junior developers to understand. This might create confusion as it's exported from react-redux with exactly the same name. So if we use a more specific name for the domain, would be easily understood that it's a custom helper. What's your take on this?

Copy link
Author

Choose a reason for hiding this comment

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

Yeah, a better naming should solve your concern, but I'm just using the one that was set.

{userType === 'public-sign-up-mentor-pending-review' && (
<>
{' '}
{' '} {/* TODO: what is this? */}
Copy link
Contributor

Choose a reason for hiding this comment

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

It's just a whitespace to make sure it's not removed by React and we don't have a funky text 😅

Copy link
Author

Choose a reason for hiding this comment

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

Ufff... These kinds of things are hard, man... HTML has elements for these purposes...

Comment on lines +140 to +148
{currentUserIsMentor && application.status === 'applied' && (
<>
<ConfirmMentorship
match={application}
hasReachedMenteeLimit={hasReachedMenteeLimit}
/>
<DeclineMentorshipButton match={application} />
</>
) : null}
)}
Copy link
Contributor

Choose a reason for hiding this comment

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

It's just a matter of preference most of the time but there are again certain conventions we'd like to follow in the project, according to here. I'm sure it's gonna work the same but let's avoid this kind of a refactor, if it's not gonna bring too much value.

If you have any other ideas, or a strong opinion against the ternary method, can you share with us?

Copy link
Author

@Paul7Peterson Paul7Peterson Feb 6, 2022

Choose a reason for hiding this comment

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

The shortcut is "faster" and less verbose than a ternary. And considering the size of the components that we are building (that would be another topic), being more concise would be always better.

I understand why ternary is suggested to be used in this "Tao", but in the end, it's an opinion of a developer and the only given argument is a bad return that, in case of being done with a ternary, leads to a 50% of chance to match the expected behavior. So for me, the ternary is a trap; is a way of hiding a possible error inside a bad understood "poka-yoke". And considering that unit testing has not been a priority for the design of the components, it's way better to have a weird return of a 0 or whatever so evident wrong thing to be rendered that can be noticed than a rendered-or-not component based on a not-so-transparent behavior. A ternary is ticking yourself in solitaire.

Comment on lines 36 to 58
export function createComponentForm<C extends object> () {
return {
/** ... */
validation<T extends object> (formSchema: YupConstructor<T>) {
const validationSchema = Yup.object(formSchema(Yup));
type FormType = ValidationObjectType<typeof validationSchema>;

return {
/** Definition of the initial values using the context of the component */
initialValues: (initialValues: (context: C) => FormType) => ({
/** ... */
formikConfig: (config?: FormikModifiedConfig<FormType>) => ({
/** ... */
onSubmit: onSubmitFactory(validationSchema, initialValues, config)
}),
/** ... */
onSubmit: onSubmitFactory(validationSchema, initialValues)
})
};
}
}
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Another very cool idea here, we definitely needed an abstraction for the sake of consistency of the forms in the project. Very well done 💯

However, I have some concerns here:

  • Should createComponentForm utility be in a file named yup.ts? Yup is a tool to use for validation but this function does way more than accepting validation. We might need to move it somewhere else.
  • Also, with this kind of an API (chaining functions to each other), we lose the sake of configuration being order-ignorant. I mean, when anybody uses this function, they're enforced to use the functions to create a form in the exact order you set. Also, for the forms that don't require any validation or initial values, they will need to be sent in the right order with an empty object, just to make sure onSubmit works. I think this problem can be avoided with a good documentation but again, this can be a very mind and time consuming process for a junior developer, which we have time to time, contributing to these projects. Do you have any ideas how we can tackle this challenge? I'm really keen on discussing this further and make it work because this idea is very very cool!

Copy link
Author

Choose a reason for hiding this comment

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

I would rename the file to form-helper.ts or so, yeah. The folding of the project it's a topic that I still don't want to open until this PR is ready, but there's a big room for improvement when it comes to organizing the whole repo. Some good practices were already applied in the design system library as you can notice.

The order of the functions serves a strong typing purpose that eliminates the inconsistencies between three elements: formik, yup, and the initial and referenced values. I found situations in many components where the typing casting was covering a bad definition of the variables, leading to unexpected behaviors with undefined or even worse scenarios with an absolute mismatch between the use of variables and configurations. This specific order and currying solve that:

  • A friendly and unified API for the creation of the logic of forms.
  • The possibility of unit testing the form behavior independently of the UI implementation.
  • Eliminates the continuous imports done in all components, leading to clearer and smaller bundles.
  • Allows using naming conventions of files for separation of concerns and easier PR reviews in the future.
  • Keeps the react components cleaner and allows a lot of reusability that is still not implemented.
  • The junior developer doesn't require to fully understand the logic of the formik and yup libraries, creating an abstraction that makes it way more comprehensible and easy to use.
  • The validation() step can be used only for type definition, letting yup do the parsing for us without any further config, leading to an empty object return in initialValues() but still having, in the end, a return formik object that you can use with the design components as they are (while we decouple formik from them, with is a terrible thing to see and that, in my opinion, makes that something like a Dropdown select has an API 10 times more complicated than this factory and with zero documentation). Showing juniors how to solve complicated problems with easy solutions like this must be also a priority in a learning path.
  • I still have to properly document this in the JSDocs, but since everything is pretty straightforward; it makes the logic of the form way more comprehensive with some embed docs than the wild and wrong compositions that I've seen.

@Paul7Peterson
Copy link
Author

Paul7Peterson commented Feb 6, 2022

Hey @helloanil, to answer the top-level topics you proposed.

  • You're absolutely right with the FC<Props> approach and I recently encounter the issues described in the link you set. Years ago, when I learned React, was the easiest way for typing components, but TypeScript is way better nowadays. I made that change to be able to use TypeScript to catch issues, but I will remove the FC<Props> approach and change it to a direct typed function. I'll make sure that everything works as expected and preserve the changes I made for type inferring.
  • A small comment based on the previous point; I've seen that you use the default export for the components. Is there a specific reason for that? My concern and the reason why I personally void the default export is that you can and have to use your own name on the import of the component and even sometimes; destroying the documentation chain on the way.
  • About the Jobseeker rename, I won't discuss it. Your argument is totally right, so I will undo that.
  • About the null vs undefined; every time that I see a written undefined in the code, it gives me goosebumps. The biggest distinction between both is that undefined is provided by the behavior of JS/TS and null is an explicit absence. No code in vanilla JS returns null, it's always the intention of someone explicitly saying that the value is missing. null indicated that there is intentionally no value (like in compiled languages), and not because of some wrong access to the memory position.

About splitting the PR:

  • For the semi-colons in the JS files, yeah, I can remove them.
  • The change for the admin panel to TS is to catch problems, but yeah, it could be also part of another PR.
  • The words I do it when I see the issue, that way I don't forget about it. Setting a // TODO will increase also the PR without solving the issue, and we are even discussing semi-colons.

The changes done are all derived from the changes in the design system components. And maybe some refactoring could have been done in another PR, but takes me less time if I do it when I see it and for me, it's just natural. There are way more things that I already commented out that are coming out from seeing things, but they will imply way more changes and I consider that they can be done after this PR as we already discussed. But correcting small details that I see and typing most of the things the right way is helping me a lot to make everything work and to catch hidden issues. I know it looks like I'm touching things that are not related to the purpose of this PR, but they are when you follow the trace of bad practices and errors' covering. That's why I've invested that much time; so I can trust TypeScript and my own testing for the changes in absence of unit testing.

@gitguardian
Copy link

gitguardian bot commented Apr 27, 2023

⚠️ GitGuardian has uncovered 4 secrets following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secrets in your pull request
GitGuardian id Secret Commit Filename
753993 Generic High Entropy Secret b3e7f20 nx.json View secret
753993 Generic High Entropy Secret ad5445b nx.json View secret
753993 Generic High Entropy Secret 863d333 nx.json View secret
753993 Generic High Entropy Secret e7ef109 nx.json View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secrets safely. Learn here the best practices.
  3. Revoke and rotate these secrets.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

Our GitHub checks need improvements? Share your feedbacks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Icebox

Development

Successfully merging this pull request may close these issues.

[Storybook:] Configure Storybook to host an atomic design component system

4 participants