代碼和設計是如何一步步腐化的

經歷了幾個從商業角度來看或成功或失敗的項目,都會發現代碼、設計都會慢慢地、在不經意間腐化。而且有一個項目開始的時候,架構是經過精心設計的,也有較為嚴格的代碼規範,並且通過靜態代碼檢查來盡量保證代碼的質量,連code review都有一個可供參考的checklist。但半年一年之後,還是會發現,很多代碼都已經臃腫走樣,到處都是複製粘貼,動輒好幾千行代碼的模塊,能 work、但不 right的代碼。

getting it work is easy
getting it right is hard

不禁想問問代碼和設計是如何一步步腐化的?

本文地址:https://www.cnblogs.com/xybaby/p/13173047.html

代碼如何開始腐爛

其實大家都聽說過 clean code,但不一定真正意識到其重要性,且知道並不等同於做到,而時間更是一把殺豬刀,讓程序員禿了,讓代碼爛了。

一個新項目開始的時候,大家都是滿懷壯志,期待靈活可復用的架構,期待成功的產品。與此同時,敏捷開發告訴我們不要過度設計,當然,本身也是很難預料到以後需求變化的方向,於是應該等到第一次變化的時候才去考慮如何重構以應對這一類型的變化。但問題很可能就會出現在這裏。

也就是說,也許哪一天,當我們需要加一個新功能的時候,會發現原來的設計和代碼不是很方便增加這個新功能。當然,我們不應該過多苛責之前的設計,因為以前沒有預料到這個新功能,也就沒有在這個地方引入抽象。這個時候有兩種解決辦法:第一種是重構術,就是加功能之前先了解、重構已有的代碼,比如調整一下類的基礎體系、抽象出基類、或者引入一個間接層以隔離變化。另一種則是修補術,在現有的函數中加一個 if-else(或者 switch case)、在現有的類中加幾個特殊字段。這兩種方法都能解決問題,修補術治標,重構術治本,但顯然,治標來得更快,治本對程序員的要求更高。

什麼時候程序員會選擇修補術而不是重構術呢?

也許這個程序員看過 clean code、refactor,精通設計模式和面向對象,也非常希望維護一份漂亮的代碼。但我們知道,重構是需要時間的,而且還可能引入bug。也許重構耗費的時間就超過了用修補術 workaround 的時間,就短期來說,修補術的性價比是更高的。那麼長遠來說呢,也許重構術的性價比更高?可是只顧眼前、及時行樂是人的本能,走捷徑、偷懶是無時不存在的誘惑。當然,也許有追求的程序員會抵制這種誘惑,但是社會心理學告訴我們,在壓力、干擾面前我們很難理智思考,自控力也會失效。時間、進度壓力就是垂懸在程序員頭上的達摩克利斯之劍,這壓力可能讓人失眠、讓人頭禿,寫點垃圾代碼似乎也無可厚非。

況且,重構還可能引入bug,重構的前提是要有完備的測試機制,單元測試、功能測試、集成測試一個都不能少。可是,理想很豐滿,現實很骨感,單元測試覆蓋率往往不足,而且還可能依靠手動回歸測試。把代碼重構好了可能壓根沒人知道,沒人來感謝你、給你點個贊,但萬一重構出了bug呢,大家都會收到事故報告,說不定還會影響KPI?不求有功但求無過,Leader、經理是否認可重構的價值,也很大程度影響組員對於重構的积極性。

當然,增加新功能的也許是一個新手,新手加入團隊后,一般就是從維護某個模塊,實現一些小需求入手。新手有可能水平本身就不行,而且業務邏輯和代碼都是陌生的,如果缺乏完善的文檔以及足夠的掌握,新手是萬萬不敢重構的,修補術是最自然的選擇,複製、粘貼、稍微修改一下、build、run,成功啦!又實現了一個需求!你知道,新人是急於證明自己的,快速的實現一個又一個需求是證明自己的最佳辦法。

你有可能說,新人不是應該有個導師嗎,導師得review新人的代碼啊。首先,導師得懂這一塊業務;其次,導師得願意花時間指導新人。指導新人是否影響導師的KPI呢?帶好了是否有獎,出問題了是否有懲?如果全憑導師自律,這個不確定性就太大了。

上面提到的是新人,其實老手也可能寫出“德不配位”的代碼,比如一個需求,可能涉及到多個模塊,有的模塊是這個老手負責的,有的則不是。理想的情況下,各個模塊提供好接口供老手調用即可,但某個模塊的負責人很忙,沒有時間,這個時候老手就會直接去修改相應模塊。可是,可能由於老手特有的自尊、或者面子,老手往往不願意去請教對應模塊的負責人,而是按照自己的經驗魔改出一段可以工作,但既不優雅、也不高效的代碼。

代碼如何加速腐爛

所以說,由於進度壓力、經驗、態度等各種各樣的原因,代碼中慢慢就會開始出現腐朽的問題。可怕的是,垃圾的代碼給出了錯誤的示範,這種示範對於新手或者對於這個模塊不熟悉的同事來說都很強烈,也使得垃圾的代碼、倍增的維護成本、潛在的bug被到處複製,美其名曰“借鑒”。破窗效應,讓後來人寫出垃圾代碼的時候毫無心理負擔,“以前就是這個樣子的”,以前這裡有個變量叫temp,我只是加了個變量叫temp1;以前這裏就有switch case,我只不過加了一個case;以前的代碼就很難讀懂了,於是我copy的一份實現自己的邏輯。

況且,到項目後期,可能不再那麼掙錢了,可能最初寫代碼、制定規範的人已經不再了,誰還會來關心這代碼質量呢?

悲觀的認為,代碼的腐化是必要,只是時間快慢問題。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

數學-高精度

1.Integer Inquiry

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1047

解法:一道求大數之和,我們利用java里的BigInteger就可以輕鬆的解決,不過需要注意下格式的問題,每輸出一個就要空一行,最後一個不用

代碼:

import java.math.BigInteger;
import java.util.Scanner;
public class Main {
    public static void main(String[] arg)
    {
        Scanner in=new Scanner(System.in);
        int t;
        while(in.hasNext())
        {
            t=in.nextInt();
            while(t-->0)
            {
                BigInteger b=new BigInteger("0");
                while(in.hasNextBigInteger())
                {
                    BigInteger c=new BigInteger("0");
                    c=in.nextBigInteger();
                    if(!c.equals(BigInteger.ZERO))
                    {
                        b=b.add(c);
                    }
                    else
                    {
                        System.out.println(b);
                        if(t!=0)
                            System.out.println();
                        break;
                    }
                }
            }
        }
    }
}

 

2.Exponentiation

 題目:https://vjudge.net/problem/POJ-1001/origin

解法:這道是一個浮點數的次冪求解,通過java里的BigDecimal的pow方法,即可完成對應的求解。

對於輸出有特殊要求,小數點后捨去無意義的0,用到stripTrailingZeros()方法去除所有尾部的0,然後再用toPlainString()將BigDecimal轉化為String

之後,在比對轉化的字符串的第一個字符是否為“0”,如果為0,則去掉它只保留小數點之後的數,利用substring(1),截取字符串

代碼:

import java.math.BigDecimal;
import java.util.Scanner;

public class Main {
    public static void main(String[] arg)
    {
        Scanner in=new Scanner(System.in);
        while(in.hasNext())
        {
            BigDecimal a=in.nextBigDecimal();
            int k=in.nextInt();
            a=a.pow(k);
            String str=a.stripTrailingZeros().toPlainString();
            if(str.charAt(0)=='0')
                System.out.println(str.substring(1));
            else
                System.out.println(str);
        }
    }
}

 

3.How many Fibs?

題目:https://vjudge.net/problem/POJ-2413/origin

思路:這是一道求在一定的範圍內,包含的斐波那契數的個數。由於範圍是10的100次方,因此我們設置大整數數組的長度為10000,足以包括。

代碼:

import java.math.BigInteger;
import java.util.Scanner;

public class Main {
    static BigInteger a[]=new BigInteger[10000];
    public static void main(String[] arg)
    {
        Scanner in=new Scanner(System.in);
        for(int i=0;i<10000;i++)
            a[i]=BigInteger.ZERO;
        a[0]=BigInteger.valueOf(1);
        a[1]=BigInteger.valueOf(2);
        for(int i=2;i<10000;i++)
            a[i]=a[i].add(a[i-1].add(a[i-2]));
        BigInteger b,c;
        while(true)
        {
            b=in.nextBigInteger();
            c=in.nextBigInteger();
            if(b.equals(BigInteger.ZERO)&&c.equals(BigInteger.ZERO))
                break;
            int res=0;
            for(int i=0;i<10000;i++)
            {
                if((a[i].compareTo(b)==1||a[i].compareTo(b)==0)&&(a[i].compareTo(c)==-1||a[i].compareTo(c)==0))
                    res++;
                if(a[i].compareTo(c)==1)
                    break;
            }
            System.out.println(res);
        }
    }
}

 

4.Segment

 題目:http://acm.hdu.edu.cn/showproblem.php?pid=5666

解法:這是一道求在一個三角形區域內的整數點的個數,不包含在線上的點。通過遞推分析,找規律後知道,個數為:(q-1)*(q-2)/2%p

由於q很大,所以我們需要用到大整數來進行求解。

代碼:

import java.math.BigInteger;
import java.util.Scanner;

public class Main{
    public static void main(String[] arg)
    {
        Scanner in=new Scanner(System.in);
        int T=in.nextInt();
        while(T-->0)
        {
            BigInteger q=in.nextBigInteger();
            BigInteger p=in.nextBigInteger();
            BigInteger f=q.subtract(BigInteger.valueOf(2));
            BigInteger res=q.subtract(BigInteger.ONE).multiply(f).divide(BigInteger.valueOf(2));
            res=res.mod(p);
            System.out.println(res);
        }
    }
}

 

5.Problem B

題目:https://vjudge.net/problem/HDU-5686/origin

解法:這應該是百度的某道題,模擬幾組數據后發現竟然是一個斐波那契數列,因此就很簡單了,N<=200的因此普通的longlong滿足不了,我們需要使用BigInteger

代碼:

import java.math.BigInteger;
import java.util.Scanner;

public class Main {
    public static void main(String[] arg)
    {
        Scanner in=new Scanner(System.in);
        BigInteger a[]=new BigInteger[10000];
        for(int i=0;i<10000;i++)
            a[i]=BigInteger.ZERO;
        a[0]=BigInteger.valueOf(1);
        a[1]=BigInteger.valueOf(1);
        for(int i=2;i<10000;i++)
            a[i]=a[i].add(a[i-1].add(a[i-2]));
        while(in.hasNext())
        {
            int k=in.nextInt();
            if(k>=1&&k<=200)
                System.out.println(a[k]);
        }
    }
}

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

QT槽函數獲取信號發送對象

Qt 在槽函數中獲取信號發送對象

Qt中提供了一個函數 qobject_cast(QObject *object),可以通過這個函數判斷信號發出對象

Qt 幫助文檔的解釋:
Returns the given object cast to type T if the object is of type T (or of a subclass); otherwise returns nullptr. If object is nullptr then it will also return nullptr.
The class T must inherit (directly or indirectly) QObject and be declared with the Q_OBJECT macro.
A class is considered to inherit itself.
The qobject_cast() function behaves similarly to the standard C++ dynamic_cast(), with the advantages that it doesn’t require RTTI support and it works across dynamic library boundaries.

  • 簡單來說 就是使用這個函數會得到你轉型的的一個實例,但是這個類必須繼承自QObject 或者其子類並且聲明Q_OBJECT 這個宏
  • QT 幫助文檔中一個Example
    QObject *obj = new QTimer; 
    QTimer *timer = qobject_cast<QTimer *>(obj);
    

這裏順便記錄一下RTTI 與RAII,RAII 通常應用於對象資源管理,RTTI 可以動態判斷對象類型,但使用RTTI會增加程序運行時間,這裏簡單記錄區分一下 。

  1. RTTI : Run-time type information
    #include <iostream>
    #include <typeinfo>
    
    class Base {
    public:
        virtual ~Base() = default;
    };
    
    class Derived : public Base {};
    
    int main() {
        Base base;
        Derived derived;
        Base* ptr = &derived;
        Base& ref = derived;
        std::cout << typeid(base).name()<< std::endl;  // class Base 
        std::cout << typeid(derived).name()<< std::endl;  // class Derived
        std::cout << typeid(ptr).name()<< std::endl;  // class Base *
        std::cout << typeid(*ptr).name() << std::endl;  //class Derived           
        std::cout << typeid(ref).name() << std::endl;  //class Derived
    
    }
    
  2. RAII : Resource Acquisition Is Initialization
    代碼來源 https://en.cppreference.com/w/cpp/language/raii
    std::mutex m;
    
    void bad() 
    {
        m.lock();                    // acquire the mutex
        f();                         // if f() throws an exception, the mutex is never released
        if(!everything_ok()) return; // early return, the mutex is never released
        m.unlock();                  // if bad() reaches this statement, the mutex is released
    }
    
    void good()
    {
        std::lock_guard<std::mutex> lk(m); // RAII class: mutex acquisition is initialization
        f();                               // if f() throws an exception, the mutex is released
        if(!everything_ok()) return;       // early return, the mutex is released
    }
    

下面是QT通過qobject_cast獲取信號發送對象的一個Demo,通過Qt Desinger 繪製兩個按鈕和一個文本框,將兩個按鈕的點擊事件連接到同一個槽函數,在槽函數裏面判斷信號的發送者並作出不同的響應
主要的代碼如下:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

public slots:
    void onButtonClicked();

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H


#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QDebug>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(ui->leftButton,&QPushButton::clicked,this,&MainWindow::onButtonClicked);
    connect(ui->rightButton,&QPushButton::clicked,this,&MainWindow::onButtonClicked);

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::onButtonClicked()
{
    QPushButton *button =  qobject_cast<QPushButton *>(sender());

    ui->textLabel->setText(button->text());

    if(ui->leftButton == button)
    {
        qDebug()<<"left Button clicked";
        ui->textLabel->setStyleSheet("background-color:yellow");
        button->setStyleSheet("background-color:yellow");

    }
    else
    {
        ui->textLabel->setStyleSheet("background-color:green");
        button->setStyleSheet("background-color:green");
    }

}


完整的代碼已上傳Github

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

網頁設計最專業,超強功能平台可客製化

C/C++語言的學習方向

這個世界上有太多的坑,如果我們不具備查閱資料的能力和對現實世界的思考能力,入坑是大概率的事情。

C/C++語言能做什麼?C/C++程序員在做什麼?企業需要什麼樣的C/C++程序員?對初學者來說,要搞清楚這些問題並不容易。

一個农民種菜之前,會考慮菜的行情(包括銷量和價錢),如果您打算學習C/C++語言,也應該先了解C/C++程序員的行情。

了解菜的行情要去菜市場,了解C/C++程序員的行情去人才市場,中國最大的IT人才市是前程無憂。

我們先來查一些資料。

一、中國編程語言的排名情況

登錄前程無憂的官網,分別輸入java、C++、python、javascript、.net、C#、PHP、SQL、IOS關鍵字,城市選擇北京、上海、廣州和深圳,查詢到的招聘職位分別是31032、22842、19274、14091、6956、8018、5284、21302、6014個。(這是2020年6月查到的數據,不同時期的查詢結果略有不同)

數據显示企業的JAVA和C++職位比例約6:4,培訓機構的主流課程是JAVA和Python等,進一步導致了C/C++程序員的缺乏。

培訓機構不願意開設C/C++課程,C/C++語言的教學對老師的能力要求非常高,普通講師難以信任。

編程語言的選擇是人生大事,必須慎重,誰都不希望在工作幾年後被迫從一種編程語言轉向另一種編程語言。

JAVA和C/C++是程序員可選的兩個方向(其它編程語言根本不在考慮範圍),無所謂哪一種更好,我個人偏向C/C++,因為JAVA程序員的工作太累了。

更多的人選擇學習JAVA,在較短的時間內就可以上手,從簡單的WEB頁面做起,所見即所得,容易有成就感,但是C/C++不一樣,學生在學完基礎知識后還是不知道它能做什麼,離企業需求仍然差得很遠,堅持下去的人很少,“從入門到放棄”是多數人的無奈的選擇。

二、企業對C/C++程序員的技能要求

從前程無憂的招聘數據看,中國企業對C/C++的技能要求主要有網絡通信、硬件驅動(嵌入式)、數據庫、視頻音頻、網絡遊戲、桌面圖形、機器學習、大數據、物聯網,如下圖。

以上數據可以從前程無憂的官網查詢,分別輸入“C++ 網絡”、“C++ 嵌入式”、“C++ 數據庫”、“C++ 遊戲”等關鍵字,範圍選北京、上海、廣州和深圳。

值得注意的是,近年來被媒體反覆炒作的人工智能、大數據、物聯網、區塊鏈等高大上的概念,企業需求其實很少,現在股票也不抄這個概念了。

輸入“ C++ Linux”關鍵字搜索,結果有9767條記錄,輸入“C++ Windows”關鍵字搜索,只有2500條記錄。這說明windows作為服務器的操作系統,正在被淘汰中。

目前,大部分的學校和培訓機構讓學生windows平台下學習C/C++語言,而企業要求的卻是linux。

我們應該學習主流技術,不能成為非主流,否則有被淘汰的風險。

三、數據比石油更珍貴

在我們的生活中,數據無處不在,但是,常人對它不敏感。

人口戶藉數據在公安局。

駕照數據和車輛數據也在公安局的交警支隊。

醫院保存了每個病人的基本資料和就診數據。每個產婦在醫院生了小孩子,計劃生育部門也會知道,它們與公安局和醫院有聯網交換數據。

銀行有開戶數據,轉帳記錄。

證券公司有行情數據、股東基本數據、持股數據和交易日誌。

電信公司有開戶數據、通話清單、帳單。

電力局有居民的基本數據和用電帳單。

火車票、機票都是數據。

騰訊公司有QQ帳戶數據、微信帳戶數據、聊天日誌、轉帳日誌等。

阿里公司有淘寶帳戶數據,商戶數據,商品數據、交易日誌等。

煤氣公司、自來水公司……

一個人的身高、體重、學歷、年齡是數據。

圖片、視頻、音頻、文章也是數據。

……

四、C/C++程序員在做什麼

用C/C++做桌面程序的比例約11%,其它的C/C++程序都運行在後台Linux服務器上,普通用戶看不見。

在很多培訓機構的教程中,把貪吃蛇、俄羅斯方塊、打地鼠、球球大作戰等程序當成項目實戰,太過兒戲,這些程序的源代碼網上到處都是,真正的程序員不玩這個。

真正的C/C++程序員在工作,掌握的是謀生的技能,不是在玩過家家。

我們每天都在用微信軟件聊天、付款、轉帳等,對普通用戶來說,只看到微信軟件的操作界面,不清楚有後台系統的存在,以轉帳功能為例。

1)付款人在手機微信中輸入轉帳金額和支付密碼;

2)手機微信軟件把轉帳金額和密碼發送給騰訊公司的微信服務器;

3)微信服務器核對用戶的密碼和轉帳金額,向中國銀聯發起轉帳請求,中國銀聯把轉帳請求轉發給付款方的開戶行銀行,開戶銀行從付款人的帳戶中扣除金額。

4)微信服務器把扣款成功信息返回給手機微信軟件,显示轉帳成功。

5)微信服務器向收款人的手機微信軟件發送收錢提醒,收款人點擊收款后,微信服務器把金額存入收款人的微信帳戶中。

在上述轉帳流程中,蘋果手機的微信軟件採用Objective-C語言開發,其它品牌手機的微信軟件採用JAVA開發;微信服務器、中國銀聯和開戶銀行都是非常龐大的系統,系統之間進行了多次數據傳輸,對數據庫進行了查詢、修改和插入操作,都是採用C/C++語言開發,系統運行在UNIX系統上,效率極高、穩定性極強,工程量巨大,是精英程序員們的心血之作。

對騰訊的開發團隊來說,手機上安裝的微信APP軟件,開發的工作量不會超過整個微信項目的5%。

五、總結一下

1)網絡通信和數據處理以C/C++語言為主,數據輸入、數據展示以java為主。

2)作為服務器的操作系統,必選Linux,Windows已被淘汰,以VC、QT等作為C程序的開發環境極不明智。

3)網絡通信是C/C++程序員的必備技能。

4)數據處理是C/C++程序員的必備技能。

5)嵌入式開發的職位比較多,技術上偏硬件(通信、电子等專業),軟件為輔,無硬件基礎者要慎重考慮。

6)放棄幻想,不要追逐那些高大上的潮流(區塊鏈、大數據、人工智能等),也不要聽那些從入門到精通的鬼話,踏實一點,先成為一個普通程序員,這個世界上從來就沒有捷徑。

7)要學會自己查資料,www.51job.com上的信息量非常大,不要視而不見,不能被別人隨便忽悠。

六、關於視頻教程

2019年五月,我計劃錄製C/C++語言基礎知識的視頻課程,打算採用知名的書藉作為教材,在翻閱多本書藉之後,我非常的失望。作為一個骨灰程序員,二十年來,我非常清楚如何成為一個合格的C/C++程序員,包括學習方向、企業的需求和必備技能等。書店裡能買到的C/C++
書藉,絕大部分是教授和講師編寫出來的,普遍存在三個方面的問題:

1)只介紹知識點,不結合應用的場景,示例代碼和課後作業與實際項目開發嚴重脫節;

2)重點內容不突出,C/C++的知識點非常多,很多內容已經過時,在工作中極少使用,這些內容增加了學習的負擔;

3)紙上談編程,不注重培養程序員的感覺。

從職業程序員的角度出發,我把C/C++語言的基礎知識內容寫成文章,在C語言技術網發布,本教程有以下特點:

1)以Linux平台為學習和開發環境,Linux是C/C++程序員的主流工作平台;

2)斷章取義,重點突出實際開發中常用的內容,略過不常用的知識;

3)設計了大量的課後作業,這些作業與實際開發內容息息相關,把培養程序員的感覺放在首位;

4)本教程的目標是為職業C/C++程序員打基礎,不合適在校大學生的畢業考試和計算機等級考試。

七、獲取視頻教程

百萬年薪程序員錄製,《C/C++高性能服務開發基礎》視頻教程已在CSDN學院發布,優惠價12元,地址如下:
https://edu.csdn.net/course/play/29402

八、版權聲明

C語言技術網原創文章,轉載請說明文章的來源、作者和原文的鏈接。

來源:C語言技術網(www.freecplus.net)

作者:碼農有道

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務

※教你寫出一流的銷售文案?

SSH免密登錄詳解

SSH免密登錄詳解

SSH(Security Shell)安全外殼協議,是較為可靠的,專為遠程登錄會話和其他網絡服務提供安全保證的協議。

​ 對於傳統的網絡服務程序(例如,FTP,Telnet等)來說,其本質上並不是安全的,主要原因在於,這些網絡應用程序在網絡上都是直接使用明文傳輸口令和數據的,對於別有用心的人來說,這些口令和數據是很容易被截獲的。另外,這些網絡服務程序的安全驗證方式也是存在弱點的,非常容易受到中間人(Man-In-The-Middle)這種方式的攻擊,簡而言之,就是中間人冒充真正的服務器接收你傳輸的數據,然後,再將數據轉發給真正的服務器,通過這種方式中間人就可以神不知鬼不覺地拿到你所有數據。

​ 通過使用SSH,則可以將所有傳輸的數據及口令進行加密,從而防止中間人攻擊,還可以防止DNS和IP欺騙,另外,使用SSH還有加快傳輸速度的好處,原因在於,SSH是可以對數據進行壓縮的。

SSH安裝詳解

SSH是安全外殼協議,而open-ssh則是SSH的開源實現,CentOS通常是默認安裝了open-ssh的。

整個SSH服務是包含SSH服務端(openssh-server)和SSH客戶端(openssh-clients)的,常用的ssh命令就是客戶端一部分。

SSH服務端與SSH客戶端之間的關係:節點A想要控制節點B,則節點A上需要安裝SSH客戶端,而節點B上需要安裝相應的SSH服務端,這樣,節點A才能向節點B發送控制命令和數據。

# 安裝openssh-server
[root@cos1 ~]# yum install -y openssh-server
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirrors.ustc.edu.cn
 * extras: mirrors.ustc.edu.cn
 * updates: mirrors.ustc.edu.cn
Package openssh-server-7.4p1-21.el7.x86_64 already installed and latest version
# 啟動openssh-server
[root@cos1 ~]# systemctl start sshd.service
# 安裝openssh-clients
[root@cos1 ~]# yum install -y openssh-clients
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirrors.ustc.edu.cn
 * extras: mirrors.ustc.edu.cn
 * updates: mirrors.ustc.edu.cn
Package openssh-clients-7.4p1-21.el7.x86_64 already installed and latest version

openssh服務的主配置文件路徑:/etc/ssh/sshd_config

# SSH-Server常見的配置項
# 如果SSH連接提示端口不可用,可以在改文件中查看SSH端口,端口沒問題,就要考慮SSH服務是否正常啟動了
# SSH客戶端與服務端連接的默認端口號
Port 22

默認情況下,SSH服務提供了以下兩個非常有用的功能:

1、類似Telnet遠程連接服務器功能,即SSH服務(安全可靠的遠程登錄會話服務)

# 遠程連接服務
ssh user@hostname/ip

2、類似FTP的sftp-server服務,藉助SSH協議來傳輸數據,提供更安全的SFTP服務(vsftp, proftp).

# 文件拷貝服務
scp files user@hostname:/path/

SSH免密登錄配置

​ 對於分佈式環境組件(例如,Hadoop,HBase等)來說,組件的主/從節點通常需要遠程登錄到集群中其他節點並執行Shell命令,如果不使用SSH,則集群安全就無法保證,使用SSH服務的話,又需要用戶輸入目標服務器的免密,而主/從節點何時訪問其他節點是不可控的,而且,頻繁的需要用戶輸入密碼也是不可行的,這時候,免密登錄就非常重要的。

主機A通過SSH實現免密登錄主機B所需的配置過程大致可以分為以下兩步:

1、主機A在本地通過加密算法生成公鑰和私鑰

通過rsa算法生成公鑰和私鑰key對,默認情況下,身份驗證信息(也就是私鑰)保存在/user/.ssh/id_rsa文件下,而公鑰信息則保存在/user/.ssh/id_rsa.pub文件中。

[root@cos1 .ssh]# pwd
/root/.ssh
[root@cos1 .ssh]# ll
total 8
-rw-------. 1 root root 1679 Jun 22 00:04 id_rsa
-rw-r--r--. 1 root root  391 Jun 22 00:04 id_rsa.pub

2、將主機A的公鑰拷貝到主機B的授權文件(authorized_keys)中

# 通過ssh-copy-id命令將本地服務器公鑰上傳到指定服務器
[root@cos1 ~]# ssh-copy-id root@cos
... ... ... ... ... ... 
Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@cos'"
and check to make sure that only the key(s) you wanted were added.
# 現在,可以通過ssh root@cos訪問主機cos了
[root@cos1 ~]# ssh root@cos
Last login: Thu Jun 18 06:38:25 2020 from 192.168.58.1
[root@cos ~]# 

為了安全起見,通常將保存具體哪些主機可以免密訪問當前主機的授權文件authorized_keys文件設置為及root具有查看和修改的權限,用戶組及其他人無權訪問。

通過ssh-copy-id將主機A的公鑰拷貝到主機B之後,本質上,是在主機B的授權文件中添加了主機A的公鑰。

[root@cos .ssh]# ll
total 8
-rw-------. 1 root root 781 Jun 22 00:16 authorized_keys
-rw-r--r--. 1 root root 176 Jun 18 07:34 known_hosts

注意:

1、免密登錄,是用戶對用戶的,切換為其他用戶時,仍需要輸入密碼

2、免密登錄是單向的,也就是說,主機A將公鑰拷貝到主機B后,主機A可以免密登錄主機A,而主機B登錄主機A時仍然需要輸入密碼

圖解SSH免密登錄原理

通過上面一頓操作,主機A就可以免密登錄到主機A了,感覺有點神奇,那麼,免密登錄到底是怎麼實現的呢?也就是說,SSH協議又到底是什麼樣子呢?且看下圖分解~

上圖便是整個SSH免密登錄的配置及原理圖:

1、ServerA生成公鑰並上傳到ServerB上

2、Step 1: ServerA發送鏈接請求到ServerB

3、Step 2: ServerB在authorized_key中檢索ServerA的公鑰,隨機生成字符串,隨後利用公鑰對字符串進行加密,併發送給ServerA

4、Step 3: ServerA接收到密文後,利用私鑰進行解密,並將內容以明文的形式發送給ServerB

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

一文讀懂:梯度消失(爆炸)及其解決方法

梯度消失問題和梯度爆炸問題,總的來說可以稱為梯度不穩定問題

【要背住的知識】:用ReLU代替Sigmoid,用BN層,用殘差結構解決梯度消失問題。梯度爆炸問題的話,可以用正則化來限制。sigmoid的導數是【0,0.25】.

出現原因

兩者出現原因都是因為鏈式法則。當模型的層數過多的時候,計算梯度的時候就會出現非常多的乘積項。用下面這個例子來理解:

這是每層只有1個神經元的例子,每個神經元的激活函數都是sigmoid,然後我們想要更新b1這個參數。
按照大家都公認的符號來表示:

  • \(w_1\*x_1 + b_1 = z_1\)這就是z的含義;
  • \(\sigma(z_1)=a_1\),這是a的含義。

可以得到這個偏導數:
\(\frac{\partial C}{\partial b_1} = \frac{\partial z_1}{\partial b_1}\frac{\partial a_1}{\partial z_1} \frac{\partial z_2}{\partial a_2}\frac{\partial a_2}{\partial z_2} \frac{\partial z_2}{\partial a_3}\frac{\partial a_3}{\partial z_3} \frac{\partial z_3}{\partial a_4}\frac{\partial a_4}{\partial z_4} \frac{\partial C}{\partial a_4}\)

然後化簡:
\(\frac{\partial C}{\partial b_1}=\sigma'(z_1)w_2\sigma'(z_2)w_3\sigma'(z_3)w_4\sigma'(z_4)\frac{\partial C}{\partial a_4}\)

關鍵在於這個\(\sigma'(z_1)\),sigmoid函數的導數,是在0~0.25這個區間的,這意味着,當網絡層數越深,那麼對於前面幾層的梯度,就會非常的小。下圖是sigmoid函數的導數的函數圖:

因此經常會有這樣的現象:

圖中,分別表示4層隱含層的梯度變化幅度。可以看到,最淺的那個隱含層,梯度更新的速度,是非常小的。【圖中縱軸是指數變化的】。

那麼梯度爆炸也很好理解,就是\(w_j\sigma'(z_j)>1\),這樣就爆炸了。
【注意:如果激活函數是sigmoid,那麼其導數最大也就0.25,而\(w_j\)一般不會大於4的,所以sigmoid函數而言,一般都是梯度消失問題】

【總結】:

  1. 梯度消失和梯度爆炸是指前面幾層的梯度,因為鏈式法則不斷乘小於(大於)1的數,導致梯度非常小(大)的現象;
  2. sigmoid導數最大0.25,一般都是梯度消失問題。

解決方案

更換激活函數

最常見的方案就是更改激活函數,現在神經網絡中,除了最後二分類問題的最後一層會用sigmoid之外,每一層的激活函數一般都是用ReLU。

【ReLU】:如果激活函數的導數是1,那麼就沒有梯度爆炸問題了。

【好處】:可以發現,relu函數的導數在正數部分,是等於1的,因此就可以避免梯度消失的問題。
【不好】:但是負數部分的導數等於0,這樣意味着,只要在鏈式法則中某一個\(z_j\)小於0,那麼這個神經元的梯度就是0,不會更新。

【leakyReLU】:在ReLU的負數部分,增加了一定的斜率:

解決了ReLU中會有死神經元的問題。

【elu】:跟LeakyReLU一樣是為了解決死神經元問題,但是增加的斜率不是固定的:

但是相比leakrelu,計算量更大。

batchnorm層

這個是非常給力的成功,在圖像處理中必用的層了。BN層提出來的本質就是為了解決反向傳播中的梯度問題

在神經網絡中,有這樣的一個問題:Internal Covariate Shift
假設第一層的輸入數據經過第一層的處理之後,得到第二層的輸入數據。這時候,第二層的輸入數據相對第一層的數據分佈,就會發生改變,所以這一個batch,第二層的參數更新是為了擬合第二層的輸入數據的那個分佈。然而到了下一個batch,因為第一層的參數也改變了,所以第二層的輸入數據的分佈相比上一個batch,又不太一樣了。然後第二層的參數更新方向也會發生改變。層數越多,這樣的問題就越明顯。

但是為了保證每一層的分佈不變的話,那麼如果把每一層輸出的數據都歸一化0均值,1方差不就好了?但是這樣就會完全學習不到輸入數據的特徵了。不管什麼數據都是服從標準正太分佈,想想也會覺得有點奇怪。所以BN就是增加了兩個自適應參數,可以通過訓練學習的那種參數。這樣吧每一層的數據都歸一化到\(\beta\)均值,\(\gamma\)標準差的正態分佈上。

【將輸入分佈變成正態分佈,是一種去除數據絕對差異,擴大相對差異的一種行為,所以BN層用在分類上效果的好的。對於Image-to-Image這種任務,數據的絕對差異也是非常重要的,所以BN層可能起不到相應的效果。】

殘差結構

殘差結構,簡單的理解,就是讓深層網絡通過走捷徑,讓網絡不那麼深層。這樣梯度消失的問題就緩解了。

正則化

之前提到的梯度爆炸問題,一般都是因為\(w_j\)過大造成的,那麼用L2正則化就可以解決問題。

喜歡的話請關注我們的微信公眾號~【你好世界煉丹師】。

  • 公眾號主要講統計學,數據科學,機器學習,深度學習,以及一些參加Kaggle競賽的經驗。
  • 公眾號內容建議作為課後的一些相關知識的補充,飯後甜點。
  • 此外,為了不過多打擾,公眾號每周推送一次,每次4~6篇精選文章。

微信搜索公眾號:你好世界煉丹師。期待您的關注。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

網頁設計最專業,超強功能平台可客製化

廣汽首款混合動力車型傳祺亮相廣州車展

在此次廣州車展上,廣汽發佈了該品牌首款型傳祺混動版。

新車的外觀與普通版車型基本保持一致,只是車頭和車尾的LOGO採用了藍色底色以表明這款車與普通版車型的不同,另外前進氣格柵加入了更多鍍鉻裝飾條。

該車的混合動力技術為廣汽自主研發,新車已經進入國家的公務車採購目錄,預計公車採購將成為它的主要銷售份額。動力方面,混動版傳祺在驅動方式上將有兩驅和四驅可選,對應的百公里綜合油耗分別為7.5L/km和6.6L/km。汽油機方面,它搭載的1.8L發動機最大功率可達106kW(144PS),電動機方面的資訊還尚不明確。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

通用再次投資電動巴士生產企業Proterra

于2010年成立的通用汽車公司的投資機構風投(GM Ventures)近期再次投資位於南卡羅來納州Greenville的電動快充巴士公司Proterra。

Proterra透露稱通用風投和其他六家公司此次共向Proterra投資兩千三百萬美元。而通用風投尚未作出任何投資資訊的公開。其他六家分別為Hennessey資本管理(Hennessey Capital Management LLC ),NMT資本(NMT Capital),Kleiner Perkins Caufield & Byers(KPCB),Mitsui & Co.全球投資(Mitsui & Co. Global Investment Inc.,),88綠色風投(88 Green Ventures),遠景山脊夥伴(Vision Ridge Partners)。

此前在2011年,通用風投由KPCB代理向Proterra投資了六百萬美元,那次融資Proterra一共得到了三千萬。

通用風投公司主要投資的對像是汽車相關技術的新公司,包括:電池或電機等環保車技術;車輛互聯設備如聲音識別、個人設備連接;高級輕量化材料;無人駕駛採用的設備例如感測器、處理器和記憶體;有助於提高生產效率和產量的製造技術。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

財政部研究開徵環境保護稅加快新能源汽車發展

財政部部長助理鄭曉松在“2012中國節能與低碳發展論壇”上表示,鑒於目前依然嚴峻的節能減排形勢,財政部將加快建設有利於節約資源與環境保護的財稅制度,積極推進環境稅費改革,研究開徵環境保護稅,深化資源稅改革。

鄭曉松指出,2007年以來,財政部會同相關部門出臺多項財稅政策和制度辦法,截至今年,中央財政已累計投入3380億元專項資金,帶動上萬億元社會資金投入,大大加快了節能環保、和新能源汽車等新興產業發展。

鄭曉松表示,下一步將繼續在鋼鐵、石化、有色金屬和建材等行業採取一攬子措施,推進節能改造工作。從今年起,中央財政每年還將安排10億到20億元專項資金,重點支援具備量產條件的新能源汽車產業化以及支援節能汽車技術研發和產業鏈建設。

鄭曉松還指出,財政部將積極推進環境稅費改革,研究開徵環境保護稅,深化資源稅改革,調整完善消費稅制度,穩步擴大營業稅改增值稅試點;儘快出臺排汙權有償使用和交易試點指導意見,推動試點工作在全國全面推開;完善節能量審核辦法,加強節能量協力廠商審核機構管理,研究開展節能量交易,逐步建立與國際“碳交易”制度相銜接的節能量審核交易制度等。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

網頁設計最專業,超強功能平台可客製化

福汽集團投資8000萬元開展A級純電動轎車研發專案

福汽集團與榕籍院士郭孔輝共同建立福汽集團汽車工程研究院院士工作站,開展“A級純電動轎車研發”項目合作。該專案總投資8000萬元,預計可實現產值9億元。目前,該專案已被列為福建省“百項千億”專案及省科技廳2013年“863”儲備專案。

工作站將以福汽集團汽車工程研究院為依託,充分發揮以郭孔輝院士領銜的專家們多學科、多專業的學術優勢和豐富的從業經驗,進行多層次、寬領域的合作,為福汽集團在產業政策的消化、利用以及企業發展戰略和發展規劃的研究提供諮詢和服務,並為福汽集團、發動機、微車產品等領域的自主研發、技術創新提供指導和幫助。

 “A級純電動轎車研發”項目合作將在量產化純電動轎車的底盤換電系統、資訊交互系統、動力系統等核心技術方面展開系統研發。專案立足於福汽集團的整車開發優勢,同時聯合了吉林大學、同濟大學、東南汽車、新鄉新能公司等單位,組建聯合專案團隊共同開發。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心