I have a little bit more time here today, so it hopefully will be a little more helpful.
How do I run your application? How can I contribute to your application? Pimp out this readme! Here is a repo of templates for you to use.
Woah! that is a lot of buttons, is there any way that we can automate the process of rendering these? outside of that, your semantics look good!
why is your entry point index.js
? you don't even have an index.js
file in your directory?
Source control handles versioning, most of the time if we have dead code, we can delete it before we check back in.
Also, I think for we should stick with either rgba
or hsla
, seems we are using both here. Additionally, some of you indentation is jacked, not sure what is going on there.
We don't need the breaks after the returns, it is redundant because the code block is going to finalize anyways, which is what the eslint rule is yelling about. You can remove the eslint disable lines and the break
keywords from :27-:43
. I believe I spoke about this class yesterday, it still seems like there is a lot in here that isn't related to the class. I still think that we can pull the whole applyOperation
method out, and just make it a util
function instead, reworking your class around that refactor. But this is fine.
Running with python3 -m http.server 8001
This thing seems broken..
so when i 2+8
it will equal 10
but when i then try to add 50 + 60
it will then equal 910
.. Lets try to find the root cause and see if we can refactor some things on the way.
So from my understanding we are applying each of the values AFTER we click the operation? Why would we want to do that? Shouldn't we be applying immediately after we press the button? This leaves some messy mutation of state and weird logic that is happening.
Also, just from looking at what we are doing within our Button
class, I think we should pull some of that logic out, it is doing a whole lot. I think that we should be creating 3 different buttons (apply value, calculate and apply operator) the inherit behavior from a base button, that way we can keep our classes nice and small and still follow the single responsibility principle (I linked this yesterday I believe), but basically if you didn't read it, the principle basically says that we should build out our classes in a way each class has one purpose.
Here is a small example demonstrating
class Button {
// what are some things that a button does?
// - handles a press?
constructor(id, parentCalculator) {
this.id = id
this.parentCalculator = parentCalculator
}
handlePress() {
throw Error('Not implemented')
}
}
// our equal button
class EqualButton extends Button {
constructor(id, parentCalculator) {
super(id, parentCalculator)
}
handlePress() {
this.parentCalculator.calculate()
}
}
So far, we have been talking about OOP approaches to OOP code, this is a functional approach, where we have some global state that that we update with pure functions: (Really just something to think about, and possibly show off some new looking code).
const { state, dispatch } = store()
// I would call this on the equal button
const calculate = () => {
const currentState = state()
return applyOperator(
state.operator,
state.values
)
}
// I would call this on each of the value buttons
const handleValue = (value) => dispatch({
type: 'APPLY_VALUE',
value
})
// I would call this on each of the operator buttons
const handleOperator = (value) => dispatch({
type: 'APPLY_OPERATOR',
value
})
where my store might looks something like this
const reducer = (state, { type, value }) => {
switch (type) {
case 'APPLY_VALUE': {
return { ...state, values: [
state.values[1],
value,
]}
}
case 'APPLY_OPERATOR': {
return { ...state, operator: value }
}
// could also put a reset in here to reset all of the values back to normal.
}
return state
}
const store = () => {
let state = {
values: [0,0]
operator: ''
}
return {
dispatch: (action) => {
state = reducer(state, action)
},
state: () => state,
}
}
So as you see int this example, the code is pretty straight-forward and easy to follow, no mutation of state outside of what is delegated by the physical store, etc.
Going to stop now, but good stuff, I can definitely see your code quality improve, looking forward to your next iteration.
Thanks a lot!
Yeah, my HTML and CSS is super messy. I threw it together not thinking I'd show it to anyone and by the time I decided to share it I completely forgot to clean it up. Don't know what was going on with the indentation in the CSS file.
As far as the package file I just used the default one. I just started learning about that stuff a couple days ago and still figuring it out. But yeah definitely shouldn't be index.js haha
You are right that it doesn't work properly if doing say: 2+2 = 4, and then without clearing, doing say 50+50 will return the wrong result. I didn't notice as when testing it I was always chaining operations (like 2+2=4 +50 = 54... etc.) I definitely think having the equal button be different is the right idea here, I'll implement this.
I'm not too sure what you mean by:
"So from my understanding we are applying each of the values AFTER we click the operation? Why would we want to do that? Shouldn't we be applying immediately after we press the button? This leaves some messy mutation of state and weird logic that is happening."
Do you mean that I should be applying each digit to the values array as soon as a number button is pressed? I thought about that, but didn't know if I could add them to the same value in the array one at a time.
Otherwise I know the logic is pretty weird as in I'm kinda keeping my operator one step behind if that makes sense? My thinking was if I hit say: 2 + 2 - , I wanted to then execute the 2 + 2 and print the result on the display when I hit the - button. It did feel awkward writing that logic though which makes sense that it would read awkward as well. I think if I follow your advice and make the = a separate type of button with separate function, maybe I can just call the equal function at the beginning of the function handling the operator buttons.
I am now seeing that a functional approach was probably better for this project. I might try my own version of that in the future. The code you wrote is definitely much more straightforward and clean than mine. I think I need to focus on planning out the best approach in my mind before starting rather than just starting to code and figuring it out as I go.
Anyways thanks a lot again! I'll go through and try to make it better tomorrow :)