Verbosity,
— Niya Panamdanam
Maybe the Key to Better Code?
Tech Lead @ Healthie
A bit about me
@findniya
Tech Lead, Frontend Platform
www.findniya.com
Tech Lead, Frontend Platform
Working in React with Typescript.
Serious coffee addict
DRY Code
"Dry" stands for "Don't Repeat Yourself," which is a principle in software development that encourages the elimination of redundant or duplicated code. Writing "dry code" means creating code that avoids unnecessary repetition and promotes code reusability, readability, and maintainability.
Code Sample
const LandingPage = () => {
return (
<div>
<h1>Sample layout with repeating components</h1>
<section>
<h2>Sed ut perspiciatis</h2>
<p>Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit
aut fugit, sed quia consequuntur magni dolores eos qui ratione
voluptatem sequi nesciunt. Neque porro quisquam est.</p>
<button onClick={onClickFunction}>Click here</button>
</section>
<section>
<h2>Nemo enim ipsam</h2>
<p>Consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.
Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet,
consectetur, adipisci velit, sed quia non numquam.</p>
<button onClick={onClickFunctionTwo}>Learn More</button>
</section>
<section>
<h2>Lorem ipsum dolor</h2>
<p>Amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi.</p>
<button onClick={onClickFunctionThree}>Learn More</button>
</section>
<section>
<h2>Lorem ipsum dolor</h2>
<p>Amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi.</p>
<button onClick={onClickFunctionThree}>Learn More</button>
</section>
</div>
)
}
DRY Code Sample
const Section = ({title, para, onClick, buttonText}) => (
<section>
<h2>{title}</h2>
<p>{para}</p>
<button onClick={onClick}>{buttonText}</button>
</section>
)
const LandingPage = () => {
return (
<div>
<h1>Sample layout with repeating components</h1>
{sectionData.map((section, i)=><Section
key={i}
title={section.title}
para={section.para}
onClick={section.onClickFunctionOne}
buttonText={section.btnText}
/>)}
...etc
</div>
)
}
Verbosity
The quality of using more words than needed; wordiness.
Concise
Giving a lot of information clearly and in a few words.
Brief but comprehensive.
<Form onSubmit={onSubmit} render={({ handleSubmit, submitting, pristine }) =>
<form onSubmit={handleSubmit}>
<Field name='clientId' component='select'>
{clients.map(client => <option value={client.id}>{client.name}</option>)}
</Field>
<Field name={'date'}>
{props => <DatePicker {...props} selected={new Date()} onChange={e => props.input.onChange(e)}/>}
</Field>
<Field name='startTime'>
{props => <DatePicker {...props}
selected={new Date()}
showTimeSelect
showTimeSelectOnly
timeIntervals={15}
dateFormat="h:mm aa"
onChange={e => props.input.onChange(e)}/>}
</Field>
<Field name='endTime'>
{props => <DatePicker {...props}
selected={new Date()}
showTimeSelect
showTimeSelectOnly
timeIntervals={15}
dateFormat="h:mm aa"
onChange={e => props.input.onChange(e)}/>}
</Field>
<Field name='meetingTypeId' component='select'>
{meetingTypes.map(type => <option value={type.id}>{type.name}</option>)}
</Field>
<Field name='meetingFormatId' component='select'>
{meetingFormats.map(format => <option value={format.id}>{format.name}</option>)}
</Field>
<Field name={'notes'} component='textarea' placeholder="Notes"/>
<button type='submit' disabled={submitting || pristine}>Submit</button>
</form>
}
/>
const onSubmit = async (values) => {
try {
const response = await axios.post('/api/accountant/createMeeting', values)
return response.data
} catch (e) {
console.error('Error creating meeting', e)
throw e
}
}
import React from 'react'
import { Field, Form } from 'react-final-form'
import DatePicker from 'react-datepicker'
import axios from 'axios'
const MeetingForm = ({ clients, meetingTypes, meetingFormats }) => {
const onSubmit = async (values) => {
try {
const response = await axios.post('/api/accountant/createMeeting', values)
return response.data
} catch (e) {
console.error('Error creating meeting', e)
throw e
}
}
return (
<Form onSubmit={onSubmit} render={({ handleSubmit, submitting, pristine }) =>
<form onSubmit={handleSubmit}>
<Field name='email' type='text'>
{props => <input type='email' {...props.input}/>}
</Field>
<Field name='clients' component='select'>
{clients.map(client => <option value={client.id}>{client.name}</option>)}
</Field>
<Field name={'date'}>
{props => <DatePicker {...props} selected={new Date()} onChange={e => props.input.onChange(e)}/>}
</Field>
<Field name='startTime'>
{props => <DatePicker {...props}
selected={new Date()} showTimeSelect showTimeSelectOnly timeIntervals={15} dateFormat="h:mm aa" onChange={e => props.input.onChange(e)}/>}
</Field>
<Field name='endTime'>
{props => <DatePicker {...props}
selected={new Date()} showTimeSelect showTimeSelectOnly timeIntervals={15} dateFormat="h:mm aa" onChange={e => props.input.onChange(e)}/>}
</Field>
<Field name='meetingType' component='select'>
{meetingTypes.map(type => <option value={type.id}>{type.name}</option>)}
</Field>
<Field name='meetingFormat' component='select'>
{meetingFormats.map(format => <option value={format.id}>{format.name}</option>)}
</Field>
<Field name={'notes'} component='textarea' placeholder="Notes"/>
<button type='submit' disabled={submitting || pristine}>Submit</button>
</form>
}
/>
)
}
export default MeetingForm
import React from 'react'
import { Field, Form } from 'react-final-form'
import DatePicker from 'react-datepicker'
import axios from 'axios'
const MeetingForm = ({ clients, meetingTypes, meetingFormats }) => {
const onSubmit = async (values) => {
try {
const response = await axios.post('/api/accountant/createMeeting')
return response.data
} catch (e) {
console.error('Error creating meeting', e)
throw e
}
}
return (
<Form onSubmit={onSubmit} render={({ handleSubmit, submitting, pristine }) =>
<form onSubmit={handleSubmit}>
<Field name='email' type='text'>
{props => <input type='email' {...props.input}/>}
</Field>
<Field name='clients' component='select'>
{clients.map(client => <option value={client.id}>{client.name}</option>)}
</Field>
<Field name={'date'}>
{props => <DatePicker {...props} selected={new Date()} onChange={e => props.input.onChange(e)}/>}
</Field>
<Field name='startTime'>
{props => <DatePicker {...props}
selected={new Date()} showTimeSelect showTimeSelectOnly timeIntervals={15} dateFormat="h:mm aa" onChange={e => props.input.onChange(e)}/>}
</Field>
<Field name='endTime'>
{props => <DatePicker {...props}
selected={new Date()} showTimeSelect showTimeSelectOnly timeIntervals={15} dateFormat="h:mm aa" onChange={e => props.input.onChange(e)}/>}
</Field>
<Field name='meetingType' component='select'>
{meetingTypes.map(type => <option value={type.id}>{type.name}</option>)}
</Field>
<Field name='meetingFormat' component='select'>
{meetingFormats.map(format => <option value={format.id}>{format.name}</option>)}
</Field>
<Field name={'notes'} component='textarea' placeholder="Notes"/>
<button type='submit' disabled={submitting || pristine}>Submit</button>
</form>
}
/>
)
}
export default MeetingForm
const clients = {
id: ID
name: string
...otherClientInformation
}[]
const meetingTypes = {
id: ID
label: string
...otherMeetingTypesInformation
}[]
const meetingFormats = {
id:ID
name: string
...otherMeetingFormatsInformation
}[]
Company growing.
Customers want more...
User Client List View
Client Calendar View
Client Dashboard View
Select clients
Select accountants
User Meeting Form
Client Meeting Form
Product Requirements
User Calendar
- The date and start time should not be prefilled.
- The client should be pre-selected.
- On submission, we should save the form information and the current user who booked this meeting.
User Client List
- The date and start time should not be prefilled.
- On submission, we should save the form information and the client information who booked this meeting.
Client Dashboard
- Prefill the date and start time, based on which calendar area is clicked.
- On submission, we should save the form information and the client information who booked this meeting.
Client Calendar
- Prefill the date and start time, based on which calendar area is clicked.
- On submission, we should save the form information and the current user who booked this meeting.
User Calendar
- Prefill the date and start time, based on which calendar area is clicked.
- On submission, we should save the form information and the current user who booked this meeting.
const MeetingForm: React.FC = ({ clients, meetingTypes, meetingFormats, initialValues, currentUser }) => {
const onSubmit = async (values) => {
try {
const updatedValues = {...values, accountantId:currentUser.id}
const response = await axios.post('/api/accountant/createMeeting', meetingData: updatedValues)
return response.data
} catch (e) {
console.error('Error creating meeting', e)
throw e
}
}
return (
<Form onSubmit={onSubmit} initialValues={initialValues} render={({ handleSubmit, submitting, pristine }) =>
<form onSubmit={handleSubmit}>
...the rest of the form fields
</form>
}
/>
)
}
const initialValues = {
date: Date
startTime: Date
endTime: Date
clientId: null
meetingType: null
meetingFormat: null
notes: null
}
User Calendar View
<Field name={'date'}>
{props => <DatePicker {...props}
selected={initialValues?.date ?? new Date()}
onChange={e => props.input.onChange(e)}/>
}
</Field>
<Field name='startTime'>
{props => <DatePicker {...props}
selected={initialValues?.date ?? new Date()}
showTimeSelect
showTimeSelectOnly
timeIntervals={15}
dateFormat="h:mm aa"
onChange={e => props.input.onChange(e)}/>
}
</Field>
<Field name='endTime'>
{props => <DatePicker {...props}
selected={initialValues?.date ?? new Date()}
showTimeSelect
showTimeSelectOnly
timeIntervals={15}
dateFormat="h:mm aa"
onChange={e => props.input.onChange(e)}/>
}
</Field>
User Client List
- The date and start time should not be prefilled.
- The client should be pre-selected.
- On submission, we should save the form information and the current user who booked this meeting.
const MeetingForm: React.FC = ({ clients, meetingTypes, meetingFormats, initialValues, currentUser }) => {
const onSubmit = async (values) => {
try {
const updatedValues = {...values, accountantId:currentUser.id}
const response = await axios.post('/api/createMeeing', meetingData: updatedValues)
return response.data
} catch (e) {
console.error('Error creating meeting', e)
throw e
}
}
return (
<Form onSubmit={onSubmit} initialValues={initialValues} render={({ handleSubmit, submitting, pristine }) =>
<form onSubmit={handleSubmit}>
...the rest of the form fields
</form>
}
/>
)
}
const initialValues = {
date: null
startTime: null
endTime: null
clientId: ID
meetingType: null
notes: null
}
User Client List
Client Dashboard
- The date and start time should not be prefilled.
- On submission, we should save the form information and the client information who booked this meeting.
Client Dashboard View
const MeetingForm: React.FC = ({
clients,
meetingTypes,
meetingFormats,
initialValues,
currentUser,
accountants,
isClientView
}) => {
const onSubmit = async (values) => {
try {
const updatedValues = isClientView
? {...values, clientId: currentUser.id}
: {...values, accountantId: currentUser.id}
const response = await axios.post('/api/createMeeing', meetingData: updatedValues)
return response.data
} catch (e) {
console.error('Error creating meeting', e)
throw e
}
}
return (
<Form onSubmit={onSubmit} initialValues={initialValues} render={({ handleSubmit, submitting, pristine }) =>
<form onSubmit={handleSubmit}>
{isClientView
? <Field name='accountantId' component='select'>
{accountants.map(accountant => <option value={accountant.id}>{accountant.name}</option>)}
</Field>
:<Field name='clientId' component='select'>
{clients.map(client => <option value={client.id}>{client.name}</option>)}
</Field>
}
... the rest of the fields
</form>
}
/>
)
}
Client Dashboard View
const MeetingForm: React.FC = ({
clients,
meetingTypes,
meetingFormats,
initialValues,
currentUser,
accountants,
isClientView
}) => {
return (
<Form onSubmit={onSubmit} initialValues={initialValues}
render={({ handleSubmit, submitting, pristine }) =>
<form onSubmit={handleSubmit}>
{isClientView
? <Field name='accountantId' component='select'>
{accountants.map(accountant => <option value={accountant.id}>{accountant.name}</option>)}
</Field>
:<Field name='clientId' component='select'>
{clients.map(client => <option value={client.id}>{client.name}</option>)}
</Field>
}
... the rest of the fields
</form>
}
/>
)
}
const initialValues = {
date: null
startTime: null
endTime: null
accountantId: null
meetingType: null
meetingFormat: null
notes: null
}
Client Dashboard View
const onSubmit = async (values) => {
try {
const path = isClientView
? '/api/accountant/createMeeting'
: '/api/client/createMeeting'
const updatedValues = isClientView
? {...values, clientId: currentUser.id}
: {...values, accountantId: currentUser.id}
const response = await axios.post(path, meetingData: updatedValues)
return response.data
} catch (e) {
console.error('Error creating meeting', e)
throw e
}
}
Client Calendar
- Prefill the date and start time, based on which calendar area is clicked.
- On submission, we should save the form information and the client information who booked this meeting.
Client Calendar View
const MeetingForm: React.FC = ({
clients,
meetingTypes,
meetingFormats,
initialValues,
currentUser,
accountants,
isClientView
}) => {
const onSubmit = async (values) => {
try {
const path = isClientView
? '/api/accountant/createMeeting'
: '/api/client/createMeeting'
const updatedValues = isClientView
? {...values, clientId: currentUser.id}
: {...values, accountantId: currentUser.id}
const response = await axios.post(path, meetingData: updatedValues)
return response.data
} catch (e) {
console.error('Error creating meeting', e)
throw e
}
}
return (
<Form onSubmit={onSubmit} initialValues={initialValues} render={({ handleSubmit, submitting, pristine }) =>
<form onSubmit={handleSubmit}>
{isClientView
? <Field name='accountantId' component='select'>
{accountants.map(accountant => <option value={accountant.id}>{accountant.name}</option>)}
</Field>
:<Field name='clientId' component='select'>
{clients.map(client => <option value={client.id}>{client.name}</option>)}
</Field>
}
... the rest of the fields
</form>
}
/>
)
}
const initialValues = {
date: Date
startTime: Date
endTime: Date
accountantId: null
meetingType: null
meetingFormat: null
notes: null
}
Current Meeting Form
import React from 'react'
import { Field, Form } from 'react-final-form'
import DatePicker from 'react-datepicker'
import axios from 'axios'
const MeetingForm: React.FC = ({
clients,
meetingTypes,
meetingFormats,
initialValues,
currentUser,
accountants,
isClientView,
}) => {
const onSubmit = async (values) => {
try {
const path = isClientView
? '/api/accountant/createMeeting'
: '/api/client/createMeeting'
const updatedValues = isClientView
? {...values, clientId: currentUser.id}
: {...values, accountantId: currentUser.id}
const response = await axios.post(path, meetingData: updatedValues)
return response.data
} catch (e) {
console.error('Error creating meeting', e)
throw e
}
}
return (
...Form
)
}
export default MeetingForm
Current Meeting Form
<Form onSubmit={onSubmit}
initialValues={initialValues}
render={({ handleSubmit, submitting, pristine }) =>
<form onSubmit={handleSubmit}>
{isClientView
? <Field name='accountantId' component='select'>
{accountants.map(accountant => <option value={accountant.id}>{accountant.name}</option>)}
</Field>
:<Field name='clientId' component='select'>
{clients.map(client => <option value={client.id}>{client.name}</option>)}
</Field>
}
<Field name={'date'}>
{props => <DatePicker {...props}
selected={initialValues?.date ?? new Date()} onChange={e => props.input.onChange(e)}/>}
</Field>
<Field name='startTime'>
{props => <DatePicker {...props}
selected={initialValues?.startTime ?? new Date()} showTimeSelect showTimeSelectOnly timeIntervals={15} onChange={e => props.input.onChange(e)}/>}
</Field>
<Field name='endTime'>
{props => <DatePicker {...props}
selected={initialValues?.endTime ?? new Date()} showTimeSelect showTimeSelectOnly timeIntervals={15} onChange={e => props.input.onChange(e)}/>}
</Field>
<Field name='meetingType' component='select'>
{meetingTypes.map(type => <option value={type.id}>{type.name}</option>)}
</Field>
<Field name='meetingFormat' component='select'>
{meetingFormats.map(format => <option value={format.id}>{format.name}</option>)}
</Field>
<Field name={'notes'} component='textarea' placeholder="Notes"/>
<button type='submit' disabled={submitting || pristine}>Submit</button>
</form>
}
/>
Edit Booked Meeting
User Calendar
- Prefill the form with existing meeting data.
- On submission, save updated form fields.
Client Dashboard
- Prefill the form with existing meeting data.
- On submission, save updated form fields.
Client Calendar
- Prefill the form with existing meeting data.
- On submission, save updated form fields.
Updated For Edit
const creatMeeting = async (values) =>{
try {
const path = isClientView
? '/api/accountant/createMeeting'
: '/api/client/createMeeting'
const updatedValues = isClientView
? {...values, clientId: currentUser.id}
: {...values, accountantId: currentUser.id}
const response = await axios.post(path, meetingData: updatedValues)
return response.data
} catch (e) {
console.error('Error creating meeting', e)
throw e
}
}
const editMeeting = async (values) =>{
try {
const path = isClientView
? '/api/accountant/editMeeting'
: '/api/client/editMeeting'
const updatedValues = isClientView
? {...values, clientId: currentUser.id, id: meetingId}
: {...values, accountantId: currentUser.id, id:meetingId}
const response = await axios.post(path, meetingData: updatedValues)
return response.data
} catch (e) {
console.error('Error creating meeting', e)
throw e
}
}
Updated For Edit
const creatMeeting = async (values) =>{
try {
const path = isClientView
? '/api/accountant/createMeeting'
: '/api/client/createMeeting'
const updatedValues = isClientView
? {...values, clientId: currentUser.id}
: {...values, accountantId: currentUser.id}
const response = await axios.post(path, meetingData: updatedValues)
return response.data
} catch (e) {
console.error('Error creating meeting', e)
throw e
}
}
const editMeeting = async (values) =>{
try {
const path = isClientView
? '/api/accountant/editMeeting'
: '/api/client/editMeeting'
const updatedValues = isClientView
? {...values, clientId: currentUser.id, id: meetingId}
: {...values, accountantId: currentUser.id, id:meetingId}
const response = await axios.post(path, meetingData: updatedValues)
return response.data
} catch (e) {
console.error('Error creating meeting', e)
throw e
}
}
const onSubmit = async (values) => {
try {
const response = meetingId === null
? await creatMeeting(values)
: await editMeeting(values)
return response.data
} catch (e) {
console.error('Error creating meeting', e)
throw e
}
}
import React from 'react'
import { Field, Form } from 'react-final-form'
import DatePicker from 'react-datepicker'
import axios from 'axios'
const MeetingForm: React.FC = ({
clients,
meetingTypes,
meetingFormats,
initialValues,
currentUser,
accountants,
isClientView,
meetingId
}) => {
const creatMeeting = async (values) =>{
try {
const path = isClientView
? '/api/accountant/createMeeting'
: '/api/client/createMeeting'
const updatedValues = isClientView
? {...values, clientId: currentUser.id}
: {...values, accountantId: currentUser.id}
const response = await axios.post(path, meetingData: updatedValues)
return response.data
} catch (e) {
console.error('Error creating meeting', e)
throw e
}
}
const editMeeting = async (values) =>{
try {
const path = isClientView
? '/api/accountant/editMeeting'
: '/api/client/editMeeting'
const updatedValues = isClientView
? {...values, clientId: currentUser.id, id: meetingId}
: {...values, accountantId: currentUser.id, id:meetingId}
const response = await axios.post(path, meetingData: updatedValues)
return response.data
} catch (e) {
console.error('Error creating meeting', e)
throw e
}
}
const onSubmit = async (values) => {
try {
const response = meetingId === null
? await creatMeeting(values)
: await editMeeting(values)
return response.data
} catch (e) {
console.error('Error creating meeting', e)
throw e
}
}
return (
<Form onSubmit={onSubmit} initialValues={initialValues} render={({ handleSubmit, submitting, pristine }) =>
<form onSubmit={handleSubmit}>
{isClientView
? <Field name='accountantId' component='select'>
{accountants.map(accountant => <option value={accountant.id}>{accountant.name}</option>)}
</Field>
:<Field name='clientId' component='select'>
{clients.map(client => <option value={client.id}>{client.name}</option>)}
</Field>
}
<Field name={'date'}>
{props => <DatePicker {...props} selected={initialValues?.date ?? new Date()} onChange={e => props.input.onChange(e)}/>}
</Field>
<Field name='startTime'>
{props => <DatePicker {...props} selected={initialValues?.startTime ?? new Date()} showTimeSelect showTimeSelectOnly timeIntervals={15} onChange={e => props.input.onChange(e)}/>}
</Field>
<Field name='endTime'>
{props => <DatePicker {...props} selected={initialValues?.endTime ?? new Date()} showTimeSelect showTimeSelectOnly timeIntervals={15} onChange={e => props.input.onChange(e)}/>}
</Field>
<Field name='meetingType' component='select'>
{meetingTypes.map(type => <option value={type.id}>{type.name}</option>)}
</Field>
<Field name='meetingFormat' component='select'>
{meetingFormats.map(format => <option value={format.id}>{format.name}</option>)}
</Field>
<Field name={'notes'} component='textarea' placeholder="Notes"/>
<button type='submit' disabled={submitting || pristine}>Submit</button>
</form>
}
/>
)
}
export default MeetingForm
return (
<Form onSubmit={onSubmit} initialValues={initialValues} render={({ handleSubmit, submitting, pristine }) =>
<form onSubmit={handleSubmit}>
{isClientView
? <Field name='accountantId' component='select'>
{accountants.map(accountant => <option value={accountant.id}>{accountant.name}</option>)}
</Field>
:<Field name='clientId' component='select'>
{clients.map(client => <option value={client.id}>{client.name}</option>)}
</Field>
}
<Field name={'date'}>
{props => <DatePicker {...props}
selected={initialValues?.date ?? new Date()} onChange={e => props.input.onChange(e)}/>}
</Field>
<Field name='startTime'>
{props => <DatePicker {...props}
selected={initialValues?.startTime ?? new Date()}
showTimeSelect showTimeSelectOnly timeIntervals={15} onChange={e => props.input.onChange(e)}/>}
</Field>
<Field name='endTime'>
{props => <DatePicker {...props}
selected={initialValues?.endTime ?? new Date()}
showTimeSelect showTimeSelectOnly timeIntervals={15} onChange={e => props.input.onChange(e)}/>}
</Field>
<Field name='meetingType' component='select'>
{meetingTypes.map(type => <option value={type.id}>{type.name}</option>)}
</Field>
<Field name='meetingFormat' component='select'>
{meetingFormats.map(format => <option value={format.id}>{format.name}</option>)}
</Field>
<Field name={'notes'} component='textarea' placeholder="Notes"/>
<button type='submit' disabled={submitting || pristine}>Submit</button>
</form>
}
/>
)
}
export default MeetingForm
Even more...
As the business grows there can be more and more feature-specific requirements.
For Example: On List view disable date and times where the accountant already has meetings.
Common Problems
Complexity
The complexity of the component increases with each new product requirement.
1.
Debugging
Increased complexity, leads hard to read code, which makes debugging even harder.
2.
Product Locked
Each of the different product areas are now locked together. A change in one means a bug or change in the other.
3.
Developer Frustration
Developer productivity suffers and it becomes increasingly harder to make changes to the component.
Business Logic
Focuses on the rules and workflows for a user, specific to a particular business.
Developer Logic
Is the technical decisions and coding practices employed by developers to implement the business logic.
User Calendar
User Client List
Client Dashboard
Client Calendar
User Calendar
User Client List
Client Dashboard
Client Calendar
User Calendar
User Client List
1.
User clicks on Calendar day/ time slot
2.
Modal with Meeting Form appears with day/time pre-filled
3.
User inputs blank fields and submits form
4.
Meeting is booked and appears on the calendar.
1.
User clicks on Book Meeting button for a specific client.
2.
Modal with Meeting Form appears with client data pre-filled
3.
User inputs blank fields and submits form
4.
Meeting is booked.
Client Calendar
Client Dashboard
1.
Client clicks on Calendar day/ time slot
2.
Modal with Meeting Form appears with day/time pre-filled
3.
Client inputs blank fields and submits form
4.
Meeting is booked and appears on the calendar
1.
Client clicks on Book Meeting button
2.
Modal with Meeting Form appears
3.
Client inputs blank fields and submits form
4.
Meeting is booked and appears on the dashboard
Business Decisions
By making the Meeting Form Component the same for each unique feature area, the developer has made the Business Decision to make the features dependent on each other.
A Meeting Form Component for each area
Be Verbose.
Duplicate your code.
Add comments.
- Smart parent component specific for each area.
- Simple component that just renders the form.
- Create duplicate component if what it renders is different.
- Document your simple components.
Get concise after.
Parent Component Specific For Each Feature
const AccountantCalendarMeeting = () => {
const creatMeeting = async (values) =>{
...post call for creating meeting
}
}
const editMeeting = async (values) =>{
try {
...poset call for editing
}
}
const onSubmit = async (values) => {
try {
const response = meetingId === null
? await creatMeeting(values)
: await editMeeting(values)
return response.data
} catch (e) {
console.error('Error creating meeting', e)
throw e
}
}
// fetch and format data for form dependencies.
// handle the opening and closing of the modal
return (
<MeetingForm
onSubmit={onSubmit}
initialValues={initialValues}
clients={clients}
userId={currentUser.id}
meetingTypes={meetingTypes}
meetingFormats={meetingFormats}
meetingId={meetingId ?? null}
/>
)
}
Parent Component Specific For Client
const ClientCalendarMeeting = () => {
const creatMeeting = async (values) =>{
...post call for creating meeting
}
}
const editMeeting = async (values) =>{
try {
...poset call for editing
}
}
const onSubmit = async (values) => {
try {
const response = meetingId === null
? await creatMeeting(values)
: await editMeeting(values)
return response.data
} catch (e) {
console.error('Error creating meeting', e)
throw e
}
}
// fetch and format data for form dependencies.
// handle the opening and closing of the modal
return (
<ClientMeetingForm
onSubmit={onSubmit}
initialValues={initialValues}
accountants={accoutants}
userId={currentUser.id}
meetingTypes={meetingTypes}
meetingFormats={meetingFormats}
meetingId={meetingId ?? null}
/>
)
}
Meeting Form Component, just for the Accountants.
Accountant Meeting Form Component
<Form onSubmit={onSubmit}
initialValues={initialValues}
render={({ handleSubmit, submitting, pristine }) =>
<form onSubmit={handleSubmit}>
<Field name='accountantId' component='select'>
{accountants.map(accountant =>
<option value={accountant.id}>{accountant.name}</option>)}
</Field>
<Field name={'date'}>
{props => <DatePicker {...props}
selected={initialValues?.date ?? new Date()} onChange={e => props.input.onChange(e)}/>}
</Field>
<Field name='startTime'>
{props => <DatePicker {...props}
selected={initialValues?.startTime ?? new Date()}
showTimeSelect showTimeSelectOnly timeIntervals={15}
onChange={e => props.input.onChange(e)}/>}
</Field>
<Field name='endTime'>
{props => <DatePicker {...props}
selected={initialValues?.endTime ?? new Date()}
showTimeSelect showTimeSelectOnly timeIntervals={15}
onChange={e => props.input.onChange(e)}/>}
</Field>
<Field name='meetingType' component='select'>
{meetingTypes.map(type => <option value={type.id}>{type.name}</option>)}
</Field>
<Field name='meetingFormat' component='select'>
{meetingFormats.map(format => <option value={format.id}>{format.name}</option>)}
</Field>
<Field name={'notes'} component='textarea' placeholder="Notes"/>
<button type='submit' disabled={submitting || pristine}>Submit</button>
</form>
}
/>
Sample docs
Use Storybook or something like it for your component documentation
Image from: https://design-system.atoka.io/?path=/story/forms-form--full-form
As product grows the complexity of code doesn't have to grow.
Concise code is better.
- Duplication is necessary. We write code for other people to read.
- Add comments and docs explaining your code. Answer why you did it this way.
- DRY your code after a certain amount of duplication.
- Be ver careful that in the process of DRY code you are not making Business Decisions.
Q&A
Verbosity
By Niya Panamdanam
Verbosity
- 165