分享
 
 
 

Creating Reusable Software Libraries

王朝other·作者佚名  2008-06-01
窄屏简体版  字體: |||超大  

By Rob Tougher

-----------------------------------------------------------------------

1. IntrodUCtion

2. Making It Easy To Use

2.1 Keeping It Simple

2.2 Being Consistent

2.3 Making It Intuitive

3. Testing Thoroughly

4. Providing Detailed Error Information

5. Conclusion

1. Introduction

Software libraries provide functionality to application developers. They consist of reusable code that developers can utilize in their projects. Software libraries targeted for Linux are usually available in both binary and source code form.

A well-written software library:

is easy to use

works flawlessly

provides detailed error information

This article describes the above principles of library creation, and gives examples in C++.

Is This Article For You?

Create software libraries only when you have to. Ask yourself these questions before proceeding:

Will anyone (including you) need functionality X in future applications?

If so, does a library implementing functionality X already exist?

If no one will need the functionality you are developing, or a software library implementing it already exists, don't create a new library.

2. Making It Easy To Use

The first step in creating a software library is designing its interface. Interfaces written in procedural languages, like C, contain functions. Interfaces written in object-oriented languages, like C++ and Python, can contain both functions and classes.

Remember this motto when designing your interface:

The easier to use, the better

As a library designer, I am constantly faced with finding the right balance between functionality and ease of use. The above motto helps me resist adding too much functionality into my designs.

Stick with the following guidelines, and you'll be fine.

2.1 Keeping It Simple

The more complex a library, the harder it is to use.

Keep It Simple, Stupid

I recently encountered a C++ library that consisted of one class. This class contained 150 methods. 150 methods! The designer was most likely a C veteran using C++ - the class acted like a C module. Because this class was so complex, it was very difficult to learn.

Avoid complexity in your designs, and your interfaces will be cleaner and easier to understand.

2.2 Being Consistent

Users learn consistent interfaces more easily. After learning the rules once, they feel confident in applying those rules across all classes and methods, even if they haven't used those classes and methods before.

One example I am guilty of involves public Accessors for private variables. I sometimes do the following:

class point

{

public:

int get_x() { return m_x; }

int set_x ( int x ) { m_x = x; }

int y() { return m_y; }

private:

int m_x, m_y;

};

Do you see the problem here? For the m_x member, the public accessor is "get_x()", but for the m_y member, the public accessor is "y()". This inconsistency generates more work for the users - they have to look up the definition of each accessor before using it.

Here's another example of an inconsistent interface:

class DataBase

{

public:

recordset get_recordset ( const std::string sql );

void RunSQLQuery ( std::string query, std::string connection );

std::string connectionString() { return m_connection_string; }

long m_sError;

private:

std::string m_connection_string;

};

Can you spot its problems? I can think of at least these items:

Methods and variables are not named consistently

Two different terms, sql and query, are used to denote a SQL string

m_sError does not have a public accessor

get_recordset() does not have a connection in its argument list

Here is a revised version that solves these problems:

class database

{

public:

recordset get_recordset ( const std::string sql );

void run_sql_query ( std::string sql );

std::string connection_string() { return m_connection_string; }

long error() { return m_error; }

private:

std::string m_connection_string;

long m_error;

};

Keep your interfaces as consistent as possible - your users will find them much easier to learn.

2.3 Making It Intuitive

Design an interface how you would eXPect it to work from a user's point of view - don't design it with the internal implementation in mind.

I find that the easiest way to design an intuitive interface is to write code that will use the library before actually writing the library. This forces me to think about the library from the user's standpoint.

Let's look at an example. I was recently considering writing an encryption library based on OpenSSL. Before thinking about the library design, I wrote some code snippets:

crypto::message msg ( "My data" );

crypto::key k ( "my key" );

// blowfish algorithm

msg.encrypt ( k, crypto::blowfish );

msg.decrypt ( k, crypto::blowfish ):

// rijndael algorithm

msg.encrypt ( k, crypto::rijndael );

msg.decrypt ( k, crypto::rijndael ):

This code helped me think about how I should design the interface - it put me in the user's shoes. If I decide to implement this library, my design will flow from these initial ideas.

3. Testing Thoroughly

A software library should work flawlessly. Well not flawlessly, but as close to flawless as possible. Users of a library need to know that the library is performing its tasks correctly.

Why use a software library if it doesn't work correctly?

I test my software libraries using automated scripts. For each library, I create a corresponding application that exercises all features of the library.

For example, say I decided to develop the encryption library I introduced in the previous section. My test application would look like the following:

#include "crypto.hpp"

int main ( int argc, int argv[] )

{

//

// 1. Encrypt, decrypt, and check

// message data.

//

crypto::message msg ( "Hello there" );

crypto::key k ( "my key" );

msg.encrypt ( k, crypto::blowfish );

msg.decrypt ( k, crypto::blowfish );

if ( msg.data() != "Hello there" )

{

// Error!

}

//

// 2. Encrypt with one algorithm,

// decrypt with another, and check

// message data.

//

// etc....

}

I would occasionally run this application to make sure that my software library did not have any major errors.

4. Providing Detailed Error Information

Users need to know when a software library cannot perform its tasks correctly.

Alert the user when there is a problem

Software libraries written in C++ use exceptions to pass information to its users. Consider the following example:

#include <string>

#include <io

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有