Abstract thinking facilities us in solving many problems and solving them efficiently. Ability to say A is like B, helps us cheaply export solutions developed in A to solve B. This further refines the abstract pattern and makes it more robust and reusable (evolution!).
To solve problems in astronomy ancient Greeks developed abstract patterns to study geometry of triangles, Trigonometry. Now trigonometry helps us in solving problems ranging from construction of buildings to measuring current in electrical circuits.
Abstraction in Programming:
One of the primary objectives of programming is to come up with a code to mimic a real world process as precisely as possible. More precision results in bug free code which preforms adequately in most of the circumstances encountered in the process.
Example: Compare two dates to find out which is one earlier than other.
- Write dates in string format "YYYY-MM-DD hh:mm:ss"
- Do string comparison date1 < date2 to find the answer
Such trivial string comparison is a proxy model for underlying process. Therefore, it has tendency to break when program and process depart from one another (at Y-10k).
- Get dates as date object of your favorite programming language
- Do required comparison per your programming language
Now we are very precise by doing the date comparison more closely to required process. Besides any technical machine issue (floating points!) mostly we will get right answer.
Abstract patterns in programming provide us with tools/mental models, which are very generic and versatile to precisely model many applications of value. Good abstractions are hard to develop and evolve over a long period of time of combined effort.
In my opinion following are the most prominent abstractions in world of Frontend/UI Development.
As history has it, Netscape failed to get other programming languages to work in browser environment. To create a more dynamic web, existing programming languages lacked vital responsiveness to user interactions.
User interactions occur independently of program and act as triggers to various functions of program therefore abstracting these interactions as events for program helped in developing adequate response mechanism for ad-hoc user requests.
In frontend world, next major development happened on February 18, 2005 with publication of Ajax: A New Approach to Web Applications. In pursuit of developing more responsive web and enhancing user experience it became ample clear that client side of applications need to share more workload.
Additionally, to deliver more intuitive experience to users, applications needed to respond conditionally based on what users expect per their state within application usage interface.
More predictable state management was required to develop more complex and richer client-side. Predictable state management has been the core value proposition of all three major frontend projects: Angular, React and Vue.
Amazing people in React’s development team have discovered the next major abstraction for frontend developer’s toolkit: Effect (useEffect).
Together with state, effects enable developer to develop complex applications with much ease. Hopefully ending the era of complex lifecycle management rules and flowchart diagrams, developers needed to put on their walls to be productive!
Consider following behavior for a conventional select all checkbox scenario (3 checkboxes: Red, Green, and Blue, and 1 Select-All checkbox):
- When Select-All is checked all other checkboxes should get checked.
- When Select-All is unchecked all other checkboxes should get unchecked.
- If checking any Red, Green, and Blue results in a state that all of Red, Green, and Blue are checked, then Select-All should get checked automatically.
- When all checkboxes are checked then unchecking any of Red, Green, and Blue should uncheck Select-All.
Following are two approaches to solve this problem:
a. Using only events associated with checking and conditionally performing automatic checking of boxes, which were not clicked.
b. Using effect after any checking event to complete the automatic checking of other boxes.
Select-All click event function is common in both solutions:
- On check – Check Select-All, Red, Green, and Blue
- On uncheck – Un-check Select-All, Red, Green, and Blue
A. Events abstraction only
Click event for Red checkbox:
- We need to overwrite default checking behavior (only check/uncheck the clicked box).
- Conditionally test state of other boxes and perform actions accordingly.
Though this code solves the problem it has following issues:
- It is hard to maintain: Developer will experience some cognitive stress when reading and understanding this code.
- Developer will need to be careful regarding which checkbox (Red, Green, or Blue) they are coding for and adjust code accordingly – again cognitive stress and prone to error.
- Developers will need to be very careful when adding new checkbox or removing any checkbox.
B. Using Effect with Events
Click event for Red checkbox:
- Default checking behavior (only check/uncheck) Red when Red is clicked.
- If using libraries like Formik we get this behavior for free without writing any click event function!
Effect to follow the click event
- Test state of all the checkboxes if all are checked, check the Select-All box.
- Else uncheck the Select-All box.
Beauty of this solution: this program helps us mimic the problem statement more precisely. On any of interaction with checkboxes, user expects:
- Select-All gets checked when all Red, Green and Blue are checked
- Select-All gets un-checked when any of Red, Green and Blue are un-checked
This is exactly what Effect has helped us code, thereby increasing precision of our program.
Adding and removing checkboxes in this code is a breeze we just need to add the new checkbox state in the effect function and select-all click event function.
Conclusion – Memoir
While developing a complex form for a client, I was having a lot of challenges fixing legacy code. Also, making changes always resulted in major headaches. Based on many interactions with product owners expected requirements will sound like:
- When I click this checkbox, these other fields should appear.
- When user has filled these fields, these other fields should be disabled.
Reading (obsessing, actually!) these requirements over and over, it struck me that all the posterior behaviors are in fact effects! And, modeling them as such results in more intuitive, maintainable and bug free code!
Through this article I wanted to highlight the benefits of effectively using effects. Might as well have called titled it Effectively useEffect, or something. However, I took a longer route to place effects on similar footing as other well know major UI abstractions, again this is my own opinion.
Recommendation: While designing your UIs try to word users’ expectations in these 3 buckets:
- What event users will fire when using your application.
- Maintaining which states are crucial to your business/user experience.
- What effects are expected after certain state changes or events.
These steps have helped me in writing much better code, hopefully they will help you too.