programming but changing legacy code. • Especially when all authors are now ex-colleagues and there is no document. • Programmers are afraid to change legacy code because they do not know what will they break. • Testing can not save us, because "Testing shows the presence, not the absence of bugs.”
used function in a huge code base, e.g. const sendMailTo = (account: string) => {}; • For some reasons, we need to make it receiving an email rather than an account: const sendMailTo = (email: string) => {}; • Here are some options: 1. Build a new function and keep the legacy one. 2. Change the current function and all callers, then hope tests can save us. 3. Let the type system help us!
email.js import isEmail from './isEmail'; opaque type Email = string; export const createEmail = (s: string): ?Email => { return isEmail(s) ? s : null; }; export const isUnique = (email: Email): boolean => { // some heavy computation return email.startsWith('x'); }; export const signUp = (email: Email): boolean => { return isUnique(email); }; // @flow // app.js import { createEmail, isUnique, signUp } from './ email'; const email = createEmail('[email protected]'); // For better UX, we might want to check an email // is unique before submitting if (email && !isUnique(email)) { alert('The email is duplicated.'); } // Another part of our code base handling submitting if (email) { signUp(email); } // The isUnique is invoked twice for the same email. // Can we avoid it with modularization in mind?