软件工程师,全面思考问题很重要

这篇具有很好参考价值的文章主要介绍了软件工程师,全面思考问题很重要。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

为什么要全面思考问题

        □ 在软件开发中,对一个问题思考得越全面,编写出的代码就会越严谨,出现bug的几率就越低;反之,如果没有对一个问题进行全面而深入的思考,编写出的代码就会漏洞百出,出现各种莫名其妙、无法复现的bug的几率也就急剧增加。

        □ 软件就是数据加逻辑,数据是“肉身”,逻辑是“灵魂”。如果不全面思考问题,在某些情况下, “灵魂”就会“精神错乱”,甚至损坏“肉身”,进而导致无法正常工作。

        □ 只有经过全面思考编写出的代码,才是严谨的,才能保证可靠性。一份代码即使严格遵守了代码规范,重构了设计模式,但思考不全面,逻辑不严谨,也不能称之为优雅。

        □ 没有经过全面思考开发出的软件,虽然短期内可能能正常工作,但长远来看,各种问题和漏洞一定会爆发出来,从而导致系统的可靠性、可维护性和稳定性大打折扣。记住墨菲定律:凡是你认为可能会出错的,它一定会出错。

        下面,我们通过几个实例来理解如何进行全面思考。

实例1

        输入若干个整数作为数组,将数组中每一个元素除以第一个元素的结果,作为新的数组元素值。

        这道编程题并不难,稍加一思索,很容易给出下面的答案。

#include <iostream>
using namespace std;

static void DivArray(int *pnArray, int nSize)
{
    for (int i = 0; i < nSize; i++)
    {
        pnArray[i] /= pnArray[0];
    }
}

int main()
{
    int nSize = 0;
    cin >> nSize;
    int *pnNumber = new int[nSize];
    for (int i = 0; i < nSize; i++)
    {
        cin >> (*pnNumber++);
    }

    DivArray(pnNumber, nSize);
    delete pnNumber;
    pnNumber = NULL;
    return 0;
}

        看着是不是也没什么大问题?实际上,这段代码至少有以下6个问题:

        1、没有对输入的nSize进行检查,nSize可能为负数、0或者很大的一个正数(可能会导致内存溢出)。

        2、从cin输入数组元素后,pnNumber已经不指向第一个数组元素了,后面使用和释放会出错。

        3、函数DivArray中,没有对传入的两个参数进行检查。

        4、函数DivArray中,数组中第一个元素可能为0,被0除会导致程序崩溃。

        5、函数DivArray中,从0开始遍历数组,导致数组中第一个元素已经变成了1,后面元素的逻辑均不正确。

        6、释放pnNumber时,应当使用delete [],而不是delete。

        从这个例子可以看出来,问题简单,并不代表不需要全面思考。不全面思考,后果很严重,你的代码中到处都充斥着漏洞和bug。

实例2        

        自行封装一个函数,用于实现内存拷贝,函数原型如下:

        void *memcpy(void *dest, const void *src, size_t count);

        有的新手看到这个题目,觉得so easy,立马写出了下面的代码。

void *memcpy(void *dest, const void *src, size_t count)
{
    if (src == NULL || dest == NULL)
    {
        return NULL;
    }

    while (count--)
    {
        *dest++ = *src++;
    }

    return dest;
}

        很可惜,上面的代码除了一些低级的语法错误外,思考得也不够全面。

        1、src和dest都是void *类型,不能对其进行++操作。

        2、返回的dest指针,已经不是原始传入的dest指针了。

        3、当dest指向的内存区域,与src指向的内存区域有重叠时,可能导致拷贝错误的数据。

        正确的实现可以参考下面的代码。

void *memcpy(void *dest, const void *src, size_t count)
{
    if (src == NULL || dest == NULL)
    {
        return NULL;
    }

    if (dest > src && (char *)dest < (char *)src + count)
    {
        char *pSrc = (char *)src + count - 1;
        char *pDest = (char *)dest + count - 1;
        while (count--)
        {
            *pDest-- = *pSrc--;
        }
    }
    else
    {
        char *pSrc = (char *)src;
        char *pDest = (char *)dest;
        while (count--)
        {
            *pDest++ = *pSrc++;
        }
    }

    return dest;
}

        实际上,如果更进一步思考,上面的代码还有优化的空间。

        1、当count为0时,其实可以直接返回dest,后面的逻辑就不用考虑count了,更简洁。

        2、当src和dest相等时,说明它们指向的是同一块区域,可以直接返回dest,不需要再去拷贝。

        3、当count较大时,一个字节一个字节拷贝的方式,效率非常低。如果追求效率的话,需要考虑字节对齐和多字节拷贝等,可参考glibc中memcpy的实现(不支持内存重叠)。

实例3

        有一根长为L的平行于x轴的细木杆,其左端点的x坐标为0(故右端点的x坐标为L)。刚开始时,上面有N只蚂蚁,第i(1≤i≤N)只蚂蚁的横坐标为xi(假设xi已经按照递增顺序排列),方向为di(0表示向左,1表示向右)。每只蚂蚁都以速度v向前走,当任意两只蚂蚁碰头时,它们会同时调头朝相反方向走,速度不变。编写程序求解以下问题:

        1、所有蚂蚁都离开木杆需要多长时间?

        2、所有蚂蚁都离开木杆共碰撞了多少次?

        3、第i只蚂蚁离开木杆需要多长时间?

软件工程师,全面思考问题很重要

        以下为这道题的思考过程。

        1、因为每只蚂蚁的初始方向是任意的,两只蚂蚁碰头后会调头,因此,所有蚂蚁的实时坐标是动态的,且是相互影响的,直接编程很难处理。考虑下面两只蚂蚁的情况,从碰头到离开木板的时间,是x和10-x的较大值。

软件工程师,全面思考问题很重要

软件工程师,全面思考问题很重要

        如果两只蚂蚁碰头后,不调头,而是仍按原方向前进,从碰头到离开木板的时间,也是x和10-x的较大值,只不过后离开木板的那只蚂蚁变了。也就是说,蚂蚁碰头后不调头,不影响所有蚂蚁离开木板的时间。

软件工程师,全面思考问题很重要

        2、同上面的分析,蚂蚁碰头后不调头,不影响蚂蚁碰撞的次数,只影响哪两只蚂蚁碰撞了。在此假设下,每只蚂蚁碰撞的次数,就是初始时,与其前进方向相反的蚂蚁的个数。
        3、与问题1和2不同,这里求解的是某只蚂蚁离开木杆的时间,需要我们更深入地分析和思考问题。不管某只蚂蚁中间和其他蚂蚁碰撞了多少次,到最后一次碰撞时,这两只蚂蚁爬行的时间和路程是相同的,假设路程用A表示。碰撞后,各自调头,离开目标,则向左离开木板的那只蚂蚁爬行的总路程为:A+x。而这个A+x也可以理解为另一只蚂蚁之前爬行的路程加上继续向左离开木板爬行的路程。
        怎么更形象地理解呢?可以假设每只蚂蚁背着一粒米,碰头时,交换各自的米,然后调头。这样,蚂蚁虽然调头了,但米的前进方向始终不变。蚂蚁爬行的路程,就是它离开木板时背着的米走过的路程。那么,两者如何关联起来呢?
        假设初始时,有P只蚂蚁向左,则有N-P只蚂蚁向右。因为每次碰撞后,向左和向右的蚂蚁数量不变,因此,最终肯定有P只蚂蚁从左边离开木板,有N-P只蚂蚁从右边离开木板。是哪P只蚂蚁呢?
        假如蚂蚁a初始在蚂蚁b左边,则根据规则,任何时候,蚂蚁a的相对位置都在蚂蚁b左边。故初始时靠左的前P只蚂蚁,必定会从左边离开木板,其他N-P只蚂蚁,必定会从右边离开木板。
        假如i不大于P,则第i只蚂蚁会从左边离开木板,它爬行的路程,就是它离开木板时背着的米走过的路程。它背着的米哪来的?来自初始时第i只向左的蚂蚁。故初始时第i只向左的蚂蚁的坐标,就是第i只蚂蚁爬行的路程。同理,假如i大于P,则L减去第i-P只向右的蚂蚁的坐标,就是第i只蚂蚁爬行的路程。

实例4

        嵌入式设备进行升级时,支持升级uboot、内核、根文件系统和程序。以升级程序为例,我们在升级时的大致流程是什么样的?有哪些需要注意的地方?

        我们可以用下面的流程图来理解嵌入式设备升级程序的处理逻辑。

          软件工程师,全面思考问题很重要

        1、返回进度时,应包括接收数据的进度和向分区写入数据的进度两部分,比如:前者占60%,后者占40%,然后根据这个比例计算总的进度。
        2、程序包应当将一些相关信息也打包进去,以便于校验,比如:包的类型、版本号、对应的硬件型号。包的类型用于区分是uboot、内核还是程序;版本号用于和当前系统进行版本的比较;不同硬件的程序包是不能混着升级的,故需要知道硬件型号。
        3、某个客户端正在升级程序时,又有其他客户端升级程序,怎么办?
        最简单的办法:直接返回错误。
        4、程序分区的大小是有限制的,程序包的大小超过了程序分区的大小,怎么办?
        认为程序包非法,终止升级流程,并返回错误码给客户端,由客户端进行提示。
        5、正在向程序分区写入数据时,如果此时数据传输通道异常断开了,怎么办?
        不要终止写入,而应当继续完成整个升级流程(只是不需要返回进度了)。如果此时终止数据写入,已经写入的数据是不完整的,重启后,程序将无法正常运行。
        6、向程序分区写完所有数据,并发送了100%的进度信息后,如果此时立即断开数据传输通道,客户端可能收不到进度为100%的信息,导致客户端认为升级出错了。怎么办?
        发送了100%的进度信息后,应当等待一段时间(比如:3秒钟)后,再跳出工作循环。在这段时间内,正常情况下,客户端应当能收到进度为100%的信息,然后由客户端断开数据传输通道,嵌入式设备检测到连接断开后,跳出工作循环。
        7、正在向程序分区写入数据时,传过来了重启设备或关机的命令,怎么办?
        处理重启设备或关机的命令时,如果发现正在升级程序,直接返回错误。
        8、正在向程序分区写入数据时,断电了怎么办?

         有以下几种处理方式:
        □ 不处理
        上电后,嵌入式设备会变成“砖”,除非通过串口重新写入程序。
        □ 使用备份分区
        当空间足够时,存在一个程序分区和一个备份程序分区。
        (1)升级程序时,先写入备份程序分区,写完并同步后,开始写程序分区,同时置正在升级标志为true。写完程序分区并同步后,置正在升级标志为false,说明升级成功。
        (2)在根文件系统分区或其他分区中,存在一个子程序。子程序运行后,检查正在升级标志。若发现为true,说明升级不成功,需要进行恢复。若发现为false,则检查程序进程是否存在,若不存在,则也需要进行恢复。若不需要进行恢复,则子程序直接退出。恢复的逻辑为:首先读取备份程序分区,并同步写到程序分区;然后,检查正在升级标志是否为true,若为true,则修改为false;最后重启。
        (3)升级程序时,检查子程序进程是否存在,若存在,则直接返回失败,避免同时读写备份程序分区。
        □ 使用链接
        (1)当通过链接下载升级程序包时,可以将链接保存下来。
        (2)子程序发现需要恢复时,从保存的链接下载程序包,再写入程序分区。

总结

        1、全面思考问题的前提条件是经验和积累,只有具备丰富的经验和充足的积累后,才能做到全面思考。因此,需要我们多拓展知识面的宽度,多挖掘知识面的深度。

        2、全面思考问题时,需要考虑一个问题的所有影响因素,以及这些因素之间的关联关系和相互作用。

        3、多从各个角度、各个层面考虑问题,比如:从代码规范的角度看有没有遵守,从封装的角度看合不合理,从逻辑的角度看严不严密,从效率的角度看还能否优化,等等。

        4、当一种思维方式行不通或遇阻时,不要“钻牛角尖”。多尝试跳出这种思维方式,换一个角度,换一种思维方式思考和分析问题。

        5、多反问自己:类里面的成员变量,都有正确赋初始值吗?分配的内存和创建的句柄,有正确释放吗?在当前这个位置必须要释放吗,释放完了其他地方还有没有在使用?… …

        6、多从全局和整体思考问题,这样才能够看到事物的来龙去脉,看到事物发展变化的趋势及其背后的驱动因素。文章来源地址https://www.toymoban.com/news/detail-478418.html

到了这里,关于软件工程师,全面思考问题很重要的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 工程师成长到最后,最重要的到底是什么?

    🍉 CSDN 叶庭云 : https://yetingyun.blog.csdn.net/ 工程师成长到最后最重要的到底是什么? 原文来源:https://chinese.catchen.me/2023/02/engineer-career-growth-endgame.html。这篇文章讨论了一个关于工程师成长的问题,即工程师成长到最后最重要的是什么。对于新人来说,他们往往认为自己需要

    2024年02月05日
    浏览(29)
  • 机器人应用工程师的入职思考day3

    [1]学习高级弧焊内容,了解机器人在导轨与变位机等设备的配合下进行弧焊的方式 [2]了解专家焊内容,学会如何用两个机器人进行同步焊接 [3]场景应用 1、高级弧焊的运动学相关操作 2、两个或多个机器人之间进行同步焊接的方法 3、之前的疑惑点答疑 周二 2024/4/2 上午9:3

    2024年04月28日
    浏览(29)
  • 【技术人生】工程师面对新质生产力的思考和选择

    本文参考了正和岛采访米磊的一篇文章“未来30年大变局,讲透国运与人运”。对被周期控制的技术发展与软件工程师该进行怎样的选择有思考的意义。 原文链接:正和岛 https://mp.weixin.qq.com/s/x3DIZDD1r6ZTipJBSs2XGQ 康波周期(Kondratiev Wave),又称为长波理论或库兹涅茨周期,是由

    2024年03月13日
    浏览(33)
  • Java开发工程师是做什么的?高考结束最重要的专业选择!

    各位同学大家好,我是小源,明天就是高考了,对于正常的一个考生来说,专本线的同学已经开始陆陆续续准备看专业。今天,好程序员分享一个专业,他的名字叫做Java开发工程师,不知道同学有没有听说过这个专业?目前咱们现在国家,还有社会都是依托互联网进行发展的

    2024年02月08日
    浏览(37)
  • 软件测试工程师

    一、什么是软件测试? 1、定义:使用技术手段验证软件是否满足使用需求 2、目的:减少软件缺陷,保障软件质量。 二、主流技术: 1、功能测试:验证程序的功能是否满足需求 2、自动化测试:使用代码或工具代替手工,对项目进行测试 3、接口测试:有硬件接口、软件接

    2023年04月10日
    浏览(72)
  • 面试(软件实施工程师)

    应聘软件实施工程师时,面试时常会问到的问题。 在面试时面试官常问的几个问题做一个总结。 专业能力,工作思维,软实力,意识,进取心。我们要具有项目进度、优先级别、质量观念和服务意识。 1、具有扎实的计算机专业知识。这是软件开发人员能够从事软件一切工作

    2024年02月16日
    浏览(33)
  • SaaS软件工程师成长路径

           SaaS软件工程师的成长需要循序渐进,和SaaS业务一样有耐心。SaaS工程师需要在“业务”、“技术”、“管理”三个维度做好知识储备、技能沉淀。本文基于“能力-知识-技能”模型,给出SaaS软件工程师成长路径、学习建议及要求。         “Ability(能力)”更多依

    2024年02月15日
    浏览(41)
  • 软件开发工程师 - 面试手册

    软件开发工程师是IT行业中最常见的岗位之一,主要负责设计、开发和维护软件应用。他们需要熟悉至少一种编程语言,了解软件开发的基本流程和原理,具备良好的解决问题能力和团队合作精神。 在招聘广告中,公司通常会对软件开发工程师的要求做出如下描述: 熟悉至少

    2024年02月06日
    浏览(48)
  • 软件UI工程师的职责模板

      软件UI工程师的职责模板1 职责: 1.负责产品的UI视觉设计(手机软件界面 网站界面 图标设计产品广告及 企业文化的创意设计等); 2.负责公司各种客户端软件客户端的UI界面及相关图标制作; 3.设定产品界面的整体视觉风格; 4.为开发工程师创建详细的界面说明文档,保证工程师

    2024年02月13日
    浏览(34)
  • 软件工程师,入门下深度学习吧

    概述         ChatGPT,英文全称为Chat Generative Pre-trained Transformer,是OpenAI研发的聊天机器人程序。ChatGPT是人工智能技术驱动的自然语言处理工具,它能够通过理解和学习人类的语言来进行对话,还能根据聊天的上下文进行互动,真正像人类一样来聊天交流。除此之外,还能

    2024年02月11日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包