改善丑陋的代码
if-else系列——卫语句
解决问题——多个if else语句嵌套。
do{
if(oOld > 35){
consloe.log("Old is not suitable")
break;
}
if(strMajor != "Software Engineering"){
consloe.log("Major is not suitable")
break;
}
if(!bIsPassChoose){
consloe.log("PassChooseis not suitable")
break;
}
if(!bIsPassInterview){
consloe.log("PassInterviewis not suitable")
break;
}
bIsPassed = true;
}while(false)
if-else系列——条件合并提炼
let userInfo = {name:"Jerry", id:6879, isActivated:true, status:"valid"}
function getUserInfoContent(userInfo){
if(userInfo.name == ""){
return "Invalid data received";
}
if(userInfo.id <= 0){
return "Invalid data received";
}
if(userInfo.status == ""){
return "Invalid data received";
}
if(!userInfo.isActivated:true){
return "User status is not normal";
}
if(userInfo.status != "valid"){
return "User status is not normal";
}
return "Welcome" + userInfo.name
}
let userInfo = {name:"Jerry", id:6879, isActivated:true, status:"valid"}
function getUserInfoContent(userInfo){
if(userInfo.name == "" || userInfo.id <= 0 || userInfo.status == ""){
return "Invalid data received";
}
if(!userInfo.isActivated:true || userInfo.status != "valid"){
return "User status is not normal";
}
return "Welcome" + userInfo.name
}
let userInfo = {name:"Jerry", id:6879, isActivated:true, status:"valid"}
function getUserInfoContent(userInfo){
if(!isDataValid(){
return "Invalid data received";
}
if(!isUserStatusNormal(){
return "User status is not normal";
}
return "Welcome" + userInfo.name
}
function isDataValid(){
if(userInfo.name == "" || userInfo.id <= 0 || userInfo.status == ""){
return false;
}
return true;
}
function isUserStatusNormal(){
if(!userInfo.isActivated:true || userInfo.status != "valid"){
return false;
}
return true;
}
if-else系列——表驱动
function Format(strDay){
if(strDay=="Mon"){
return "Monday";
}
else if(strDay=="Tue"){
return "Tuesday";
}
else if(strDay=="Wed"){
return "Wednesday";
}
else if(strDay=="Thu"){
return "Thursday";
}
else if(strDay=="Fri"){
return "Friday";
}
else if(strDay=="Sat"){
return "Satarday";
}
else if(strDay=="Sun"){
return "Sunday";
}
else{
return "Unknown";
}
}
function Calcualte(command,num1,num2){
if(command == "add"){
return num1 + num2;
}
else if("sub"){
return num1 - num2;
}
else if("mul"){
return num1 * num2;
}
else if(""div){
return num1 / num2;
}
else{
return 0
}
}
let mapDayFormat = {
"Mon" : "Monday",
"Tue" : "Tuesday",
"Wed" : "Wednesday",
"Thu" : "Thursday",
"Fri" : "Friday",
"Sat" : "Satarday",
"Sun" : "Sunday",
"Other" : "Unknown",
}
function FormatDay(strDay){
if (mapDayFormat[strDay]!=null){
return mapDayFormat[strDay];
}
return mapDayFormatDay["Other"]
}
let mapCalculate = {
"add":function (num1,num2){
return num1 + num2;
}
"sub":function (num1,num2){
return num1 - num2;
}
"mul":function (num1,num2){
return num1 * num2;
}
"div":function (num1,num2){
return num1 / num2;
}
"other":function (num1,num2){
return 0;
}
}
function Caculate(command,num1,num2){
if(mapCalculate[command!=null]){
mapCalculate[command](num1,num2);
}
return mapCalculate["other"](num1,num2);
}
if-else系列—— 策略模式
策略模式可以设置多种策略 。
let mapCalculate = {
"add":function (num1,num2){
return num1 + num2;
}
"sub":function (num1,num2){
return num1 - num2;
}
"mul":function (num1,num2){
return num1 * num2;
}
"div":function (num1,num2){
return num1 / num2;
}
"other":function (num1,num2){
return 0;
}
}
function Caculate(command,num1,num2){
if(mapCalculate[command!=null]){
mapCalculate[command](num1,num2);
}
return mapCalculate["other"](num1,num2);
}
class Calculator{
constructor(){
this.stategy = null;
}
setStrategy(stategy){
this.stategy = stategy;
}
calculateResult(){
return this.strategy.excute(num1,num)
}
}
class Add{
execute(num1,num2){
return num1 + num2;
}
}
class Sub{
execute(num1,num2){
return num1 - num2;
}
}
class Mul{
execute(num1,num2){
return num1 * num2;
}
}
class Div{
execute(num1,num2){
return num1 / num2;
}
}
if-else系列—— 简单工厂模式
class TeacherUser{
constructor(){
this.name = "teacher";
this.permissionList = ["upload","modify","notify"];
}
showPermission(){
console.log(this.permissionList);
}
}
class StudentUser{
constructor(){
this.name = "student";
this.permissionList = ["query","comment"];
}
showPermission(){
console.log(this.permissionList);
}
}
class VisitorUser{
constructor(){
this.name = "visitor";
this.permissionList = ["browse"];
}
showPermission(){
console.log(this.permissionList);
}
}
let loginUserType = "visitor";
let user;
if(loginUserType === "teacher"){
user = new TeacherUser();
}
if(loginUserType === "teacher"){
user = new StudentUser();
}
if(loginUserType === "teacher"){
user = new VisitorUser();
}
user.showPermission();
class UserSimpleFactory(){
getInstance(userType){
let user = null;
switch(userType){
case "teacher":
user = new TeacherUser();
break;
case "student":
user = new StudentUser();
break;
case "visitor":
user = new VisitorUser();
break;
}
}
}
let loginUserType = "visitor";
let userSimpleFactor = new UserSimpleFactory();
let user = userSimpleFactory.getInstance(loginUserType);
user.showPermission()
函数命名
//如何优雅地命名函数
//1. 函数命名不应追求过于简短, 而是尽可能清晰地表达出函数的
//2. 高质量的函数命名是可以让函数体本身或是被调用出无需任何
//3. 函数命名应该偏像函数功能而非执行过程
let arrHeight = {
{name:"xiaoming",height:172},{name:"xiaoli",height:181},
{name:"xiaozhao",height:189}
}
//select heightest student
function QueryHeightAndCompare(arrHeightInfo){//违反3和2
let heighestStudent="";
let heighestValue = 0;
for (let index=0;;index<arrHeightInfo.length;++index){
if(arrHeightInfo[index].height > heighestValue){
heightStudent = arrHeightInfo[index].name;
heightValue = arrHeightInfo[index].height;
}
}
}
//calculate average height
function CalAverHgt(arrHeightInfo){//违反1和2
let sumHeight = 0;
for(let index=0;index<arrHeightInfo.length;++index){
sumHeight = sumHeight + arrHeightInfo[index].height;
heightestValue = arrHeightInfo[index].height;
}
}
function showResult(heightSudent, averageHeight){//违反1,2
console.log("Here is the result");
console.log("Average height is : " + averageHeight +
"The highest student is :" + highestStudent);
}
function Fun1(){//违反1,2,3
showResult(QueryHeightAndCompare(arrHeight),CalAverHgt(arrHeight));
}
//如何优雅地命名函数
//1. 函数命名不应追求过于简短, 而是尽可能清晰地表达出函数的
//2. 高质量的函数命名是可以让函数体本身或是被调用出无需任何
//3. 函数命名应该偏像函数功能而非执行过程
let arrHeight = {
{name:"xiaoming",height:172},{name:"xiaoli",height:181},
{name:"xiaozhao",height:189}
}
//select heightest student
function GetHeighestStudentName(arrHeightInfo){
let heighestStudent="";
let heighestValue = 0;
for (let index=0;;index<arrHeightInfo.length;++index){
if(arrHeightInfo[index].height > heighestValue){
heightStudent = arrHeightInfo[index].name;
heightValue = arrHeightInfo[index].height;
}
}
}
//calculate average height
function CalculateAverageHeight(arrHeightInfo){
let sumHeight = 0;
for(let index=0;index<arrHeightInfo.length;++index){
sumHeight = sumHeight + arrHeightInfo[index].height;
heightestValue = arrHeightInfo[index].height;
}
}
function PrintHeighestStudentAndAverageHeight(heightSudent, averageHeight){
console.log("Here is the result");
console.log("Average height is : " + averageHeight +
"The highest student is :" + highestStudent);
}
function ShowHeighestStudentAndAverageHeight(){
PrintHeighestStudentAndAverageHeight(GetHeighestStudentName(arrHeight),CalculateAverageHeight(arrHeight));
}
函数命名——判断性函数命名推荐
let userList = [
//....
]
//判断用户是否存在
function checkUserNameExist(userName){
//....
}
//判断用户名是否可以修改
function checkUserNameExist(userName){
//....
}
class Hotel{
constructor(name, destination, serviceList){
}
//判断宾馆是否有WIFI
judegeWifi(){
}
//判断宾馆是否可以预定
canOrderHotel(){
}
}
普通工具和工具方法
前缀词+名词+动词(is/can/has/...+something+verb)
类方法
前缀次+名词(is/can/has/...+somethin)
前缀词
表示是否符合的状态——is
表示是否能执行的状态——can
表示是否包含的状态——has/include/contain
表示是否需要的状态——should/needs
let userList = [
//....
]
//判断用户是否存在
function iskUserNameExist(userName){
//....
}
//判断用户名是否可以修改
function shouldkUserNameChange(userName){
//....
}
class Hotel{
constructor(name, destination, serviceList){
}
//判断宾馆是否有WIFI
hasWifi(){
}
//判断宾馆是否可以预定
canOrder(){
}
}
函数命名——数据获取
userInfo = {id:1233,name:"xiaoming",score:[70,56,4,32,69]}
//直接从对象,数据结构中获取数据
function getUserId(){
return userInfo.id;
}
//通过计算获取数据
function getUserAverageScore(){
}
//数据库查找数据
function getUserName(){
}
//从配置文件中加载数据
function getUserInfo(){
}
//网络请求获取数据
function getUserInfo(){
}
直接从对象,数据结构中获取数据 ——get
通过计算获取数据——calculate/cal
数据库查找数据——find/query
从配置文件中加载数据——load(直接在某个字段)/parse(通过配置文件解析出来)/build(多个内容拼接出来)
网络请求获取数据——fetch
userInfo = {id:1233,name:"xiaoming",score:[70,56,4,32,69]}
//直接从对象,数据结构中获取数据
function getUserId(){
return userInfo.id;
}
//通过计算获取数据
function calUserAverageScore (){ //calUserAverageScore calculateUserAverageScore
}
//数据库查找数据
function findUserName (){//findUserName queryUserName
}
//从配置文件中加载数据
function laodUserInfo (){//laodUserInfo parseUserInfo buildUserInfo
}
//网络请求获取数据
function fectchUserInfo(){//fectchUserInfo
}
引入解释性变量优化复杂语句
//总价格为商品总价(单价*数量) - 折扣(超过100个以上的打9折) + 邮费(原价的10%,50元封顶)
let orderInfo = {
quantity : 150,
price : 3.7
}
function getToalPrice(){
return orderInfo.quantity * orderInfo.price
- Math.max(0,orderInfo.quantity - 100)*orderInfo.price * 0.1
+ Math.max(orderInfo.quantity*orderInfo.price*0.1,50);
}
//总价格为商品总价(单价*数量) - 折扣(超过100个以上的打9折) + 邮费(原价的10%,50元封顶)
let orderInfo = {
quantity : 150,
price : 3.7
}
function getToalPrice(){
let baseSumMonday = orderInfo.quantity * orderInfo.price;
let discountMoney = Math.max(0,orderInfo.quantity - 100)*orderInfo.price * 0.1;
let postMoney = Math.max(orderInfo.quantity*orderInfo.price*0.1,50);
return baseSumMonday - discountMoney + postMoney
}
为什么尽量少用bool型的函数参数?
-
可能造成函数语义不明确
-
函数职责不单一
j解决方法:对函数进行拆分,去除bool变量。
function calFinalAmount(originalAmount, isChild){
if(isChild){
return originalAmount * 0.5;
}else{
return originalAmount;
}
}
function printWelcomeWords(isActivated){
if(isActivate){
console.log("Welcome! Please select your product");
}else{
console.log("Welcome! Please log in");
}
}
//1.不可以从函数调用本身知道函数的意图,必须看代码才知道传递bool值的意义
//2. 函数职责不单一,上述连个函数毕竟要判断,还要实现其他逻辑
calFinalAmount(200,true);
printWelcomeWords(true);
function calFinalAmountForChild(originalAmount){
return originalAmount*0.5;
}
function calFinalAmountForChild(originalAmount){
return originalAmount;
}
function printWelcomeWordsOnActivated(){
console.log("Welcome! Please select your product");
}
function printWelcomeWordsOnUnactivated(){
cconsole.log("Welcome! Please log in");
}
calFinalAmountForChild(200);
calFinalAmountForChild(200);
printWelcomeWordsOnActivated();
printWelcomeWordsOnUnactivated();
字符串组合拼接
let userId = 8001;
let userName = "xiaoming";
let userToken = "a56y07g0";
function createHeaderContent(){
let userInfo = "User Info: " + "Id: " + userId.toString() + "Name: "
+ userName + "Token: " + userToken;
let headerContent = "start|" + userId + "|" + userName + "|" + userToken
+ "|end";
console.log(userInfo);
return headContent;
}
console.log(createHeaderContent());
//C++ : stringstream, snprintf
//C# : string.Format
//Java : String.format
let userId = 8001;
let userName = "xiaoming";
let userToken = "a56y07g0";
function createHeaderContent(){
//let userInfo = "User Info: " + "Id: " + userId.toString() + "Name: "
// + userName + "Token: " + userToken;
//let headerContent = "start|" + userId + "|" + userName + "|" + userToken
// + "|end";
let userInfo = 'User Info : Id : ${userId.toString()} Name: ${userName} Token${userToken}';
let headerContent = 'strat|${userId}|${userName}|${userToken}|end';
console.log(userInfo);
return headContent;
}
console.log(createHeaderContent());
函数可复用性的提高——状态带入
let userInfoList = [
{userId : 1, age : 23, status: "off"},
{userId : 2, age : 12, status: "busy"},
{userId : 3, age : 34, status: "on"},
{userId : 4, age : 56, status: "off"},
{userId : 5, age : 90, status: "on"},
]
function queryUserStatusIsOn(userInfoList){
let resUserInfo = [];
for(let index=0;index<userInfoLisr.length;index++){
if(userInfoList[index].status == "on"){
resUserInfoList.push(userInfoList[index]);
}
}
return resUserInfoList;
}
function queryUserStatusIsBusy(userInfoList){
let resUserInfo = [];
for(let index=0;index<userInfoLisr.length;index++){
if(userInfoList[index].status == "busy"){
resUserInfoList.push(userInfoList[index]);
}
}
return resUserInfoList;
}
console.log(queryUserStatusIsOn(userInfoList));
console.log(queryUserStatusIsBusy(userInfoList));
let userInfoList = [
{userId : 1, age : 23, status: "off"},
{userId : 2, age : 12, status: "busy"},
{userId : 3, age : 34, status: "on"},
{userId : 4, age : 56, status: "off"},
{userId : 5, age : 90, status: "on"},
]
function queryUserStatusByStatus(userInfoList,staus){
let resUserInfo = [];
for(let index=0;index<userInfoLisr.length;index++){
if(userInfoList[index].status == staus){
resUserInfoList.push(userInfoList[index]);
}
}
return resUserInfoList;
}
console.log(queryUserStatusByStatus(userInfoList,"on"));
避免魔法数字
namespace AvoidMagicNumber{
enum UserType{
Child,
Adult,
Elder
}
class Entrance{
static int QueryUserType(){
//1 ——child, 2——Adult, 3——Elder
return userType.Child;
}
static void main(string[] args){
int nUserType = QueryUserType();
if(nUserType == userType.Child){
console.Writeline("child");
}else if(nUserType == userType.Adult){
console.Writeline("adult");
}else if(nUserType == userType.Elder){
console.Writeline("elder");
}
}
}
}
冗长函数分解优化——单一职责
每当感觉需要点什么来注释点什么东西的时候,我们就要把说明的东西写写到独立的函数中并为其命名。
function CalcualteMoneyAndGenRandomCode(purchaseInfo){
//calculate sum money
let sumMoney = 0;
for(let index = 0;index<purchaseInfo.purchaseList.length;index++){
sumMoney += purchaseInfo.purchaseList[index].purchaseNumber
* perchaseInfo.purchaseList[index].unitPrice;
}
if(purchaseInfo.isVip){
sumMoney = sumMoney * 0.95;
}
//generate random code
let randomCode = "";
for(let index=0;index<6;index++){
let randomNumber = Math.floor(Math.random(0,9)*10);
randomCode = randomCode + randomNumber.toString();
}
console.log("This order's sum money is" + sumMoney);
if(randomCode==""){
console.log("User doesn't need safety auth");
}else{
console.log("User need safety auth with random code" + randomCode);
}
}
function calculateMoney(purchaseInfo){
//calculate sum money
let sumMoney = 0;
for(let index = 0;index<purchaseInfo.purchaseList.length;index++){
sumMoney += purchaseInfo.purchaseList[index].purchaseNumber
* perchaseInfo.purchaseList[index].unitPrice;
}
if(purchaseInfo.isVip){
sumMoney = sumMoney * 0.95;
}
console.log("SumMoney: "+sumMoney );
}
function genRandomCode(purchaseInfo){
//generate random code
let randomCode = "";
for(let index=0;index<6;index++){
let randomNumber = Math.floor(Math.random(0,9)*10);
randomCode = randomCode + randomNumber.toString();
}
console.log("This order's sum money is" + sumMoney);
if(randomCode==""){
console.log("User doesn't need safety auth");
}else{
console.log("User need safety auth with random code" + randomCode);
}
}
复用函数提炼——相同逻辑提取
let dailySalesVolumes = [10, 15, 13, 12, 11, 17, 20];
function FormatSalesVolumeContent(SalesVolume){
let sumSalesVolume = 0;
for(let i=0;i<SalesVolume.length;i++){
sumSalesVolume = sumSalesVolume = SalesVolume[i];
}
let salesVolume = sumSalesVolume / SalesVolume.length;
return "Show the sales volume : " + salesVolume;
}
function GetNextStagePointVolume(SalesVolume){
}
function GetNextStageMinVolume(SalesVolume){
}
console.log(FormatSalesVolumeContent(dailySalesVolumes))
console.log(GetNextStagePointVolume(dailySalesVolumes))
console.log(GetNextStageMinVolume(dailySalesVolumes))
优化临时变量——查询方法
class Cashier {
contructor(quantity, itemPrice){
this.quantity = quantity;
this.itemPrice = itemPrice;
}
getPrice(){
let basePrice = this.quantity * this.itemPrice;
let dicountFactor;
if(basePrice > 1000){
dicountFactory = 0.95;
}else{
discountFactor = 0.98;
}
return basePrice * discountFactor;
}
}
let cashier1 = new Cashier(30, 40);
let cashier2 = new Cashier(30, 30);
console.log(casheri.getPrice(),casher2.getPrice());
//将临时变量替代为查询方法可以使计算过程原子化,便于对原子化过程进行单元
class Cashier {
contructor(quantity, itemPrice){
this.quantity = quantity;
this.itemPrice = itemPrice;
}
getPrice(){
let basePrice = this.getBasePrice();
let dicountFactor;
if(basePrice > 1000){
dicountFactory = 0.95;
}else{
discountFactor = 0.98;
}
return basePrice * discountFactor;
}
getBasePrice(){
return this.quantity * this.itemPrice;
}
}
let cashier1 = new Cashier(30, 40);
let cashier2 = new Cashier(30, 30);
console.log(casheri.getPrice(),casher2.getPrice());
//将临时变量替代为查询方法可以使计算过程原子化,便于对原子化过程进行单元
class Cashier {
contructor(quantity, itemPrice){
this.quantity = quantity;
this.itemPrice = itemPrice;
}
getPrice(){
let basePrice = this.getBasePrice();
let dicountFactor = this.getDiscountFactor();
return basePrice * discountFactor;
}
getBasePrice(){
return this.quantity * this.itemPrice;
}
getDiscountFactor(){
if(this.getBasePrice() > 1000){
return 0.95;
}
else{
return 0.98;
}
}
}
let cashier1 = new Cashier(30, 40);
let cashier2 = new Cashier(30, 30);
console.log(casheri.getPrice(),casher2.getPrice());