在设计应用程序类 [英] designing application classes

查看:183
本文介绍了在设计应用程序类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

除了使用单一职责原则,设计类应用程序之一写,什么应在牢记的时候,要保持code可维护,可重复使用的,坚持原则的OOP?

我发现它很难设计的应用程序,我试图写的类,因为在做一件决定什么(功能)变为哪一类,是否真的应该在派生类中还是应该有一个抽象类或接口,这个类?

我知道这可能是有许多答案的话题,但没有任何人有任何好的指引(preferably简单)对设计类和类层次结构是简单的维护,不要使一个烂摊子创建大的应用程序时?

编辑:

在那里的有10个方法及以上,并有一个抽象基类和功放类;它从派生的接口。也有类内部以及更多全球引用3辛格尔顿类。听起来像它需要一些'重构'应用?

很抱歉,如果这是一个漫长的例子,但你看我面临的问题,我想它的一些投入。请单看设计,而不是技术问题。

我举一个例子:

我创建这个类:(而回)

 类ExistingUserLogon:登录,ILogonUser
    {
        #区域成员变量        LogonEventArgs _logoneventargs;
        LogonData lgndata;
        工厂F = Factory.FactoryInstance;
        PasswordEncrypt.Collections.AppLoginDataCollection applogindatacollection;
        PasswordEncrypt.Collections.SQlLoginDataCollection sqllogindatacollection;
        布尔?比较;
        静态ExistingUserLogon existinguserlogon;
        PasswordEncrypt.SQLDatabase.DatabaseLogin dblogin;
        串数据库名称=的String.Empty;        #endregion        #区域属性        公共静态ExistingUserLogon ExistingUserLogonInstance
        {
            得到
            {
                如果(existinguserlogon == NULL)
                    existinguserlogon =新ExistingUserLogon();
                返回existinguserlogon;
            }
        }
        公共字符串登录名
        {
            得到;
            组;
        }
        #endregion        #区域Contructors
        公共ExistingUserLogon(布尔?比较,LogonData logondata)
        {
            this.compare =比较;
            this.lgndata = logondata;
            this.applogindatacollection = f.AppLoginDataCollection;
            this.sqllogindatacollection = f.SqlLoginDataCollection;
        }        公共ExistingUserLogon()
        {
            this.applogindatacollection = f.AppLoginDataCollection;
            this.sqllogindatacollection = f.SqlLoginDataCollection;
        }        #endregion        #区域代表        公共委托无效ConnStrCreated(对象发件人,LogonEventArgs E);        #endregion        #区域活动        公共事件ConnStrCreated ConnectionStringCreated;        #endregion        OnConnectionStringCreated私人无效(对象发件人,LogonEventArgs E)
        {
            如果(ConnectionStringCreated!= NULL)
            {
                ConnectionStringCreated(发件人,E);
            }
        }        公共无效LoginNewUser()
        {
            dblogin =新PasswordEncrypt.SQLDatabase.DatabaseLogin();
            如果(!string.IsNullOrEmpty(登录名))
            {
                字符串TEMP = dblogin.GenerateDBUserName(登录名);
                如果(温度!=已经存在)
                {                    如果(比较== true)而
                    {
                        IterateCollection(lgndata.HahsedUserName.HashedUserName,新动作<串GT;(OnDatabaseName));
                        IterateCollection(温度,新动作<布尔,字符串,字符串>(OnIterateSuccess));
                    }
                }            }
            其他
            {
                LogonEventArgs E =新LogonEventArgs();
                e.Success = FALSE;
                e.ErrorMessage =错误!没有用户名;
                的OnError(这一点,E);            }        }        私人无效OnDatabaseName(字符串名称)
        {
            this.databasename =名称;
        }        私人无效OnIterateSuccess(布尔成功,串PSW,字符串userid)
        {
            如果(成功)
            {
                //创建的ConnectionString
                ConnectionStringCreator cnstrCreate = ConnectionStringCreator.ConnectionStringInstance;
                如果(数据库名称!=的String.Empty)
                {
                    康涅狄格州字符串= ConnectionStringCreator.CreateConnString(数据库名称,用户ID,PSW);
                    布尔databaseExists;                    databaseExists = DataManagementVerification.DoDatabaseExists(康涅狄格州);                    如果(databaseExists)
                    {
                        FormsTransfer.ConnectionString =康恩;                        康恩=的String.Empty;
                    }
                    其他
                    {
                        LogonEventArgs E =新LogonEventArgs();
                        e.Success = FALSE;
                        e.ErrorMessage =数据库中不存在!
                        的OnError(这一点,E);
                    }                    // OnConnectionStringCreated(这一点,E);                   // PasswordEncrypt.LINQtoSQL.PasswordDatabase DB =新PasswordEncrypt.LINQtoSQL.PasswordDatabase(康涅狄格州);                / * PasswordEncrypt.LINQtoSQL.EncryptData _encryptdata =新PasswordEncrypt.LINQtoSQL.EncryptData()
                    {
                        EncryptID = 1,
                        IV =测试,
                        PrivateKey =你好,
                        公钥=托尼
                    };                    db.EncryptionData.InsertOnSubmit(_encryptdata);                   // db.SubmitChanges(); * /                    //PasswordEncrypt.LINQtoSQL.Data _data =新PasswordEncrypt.LINQtoSQL.Data()
                    // {
                    // EncryptionID = 1,
                    //用户名=TBONE
                    //密码=worstje
                    // IDCol = 2
                    //};                    //db.Data.InsertOnSubmit(_data);                    //db.SubmitChanges();                    //IEnumerable<PasswordEncrypt.LINQtoSQL.Data> _ddata = db.Data.Where(数据=&GT; data.Password ==worstje); ;
                    //的foreach(在_ddata PasswordEncrypt.LINQtoSQL.Data数据)
                    // {                    // MessageBox.Show(数据值:+ data.Username +,+ data.Password);
                    //}
                }
                其他
                {
                    的MessageBox.show(找不到数据库名称,数据库名称错误);
                }
            }
            其他
            {
                //无法创建的ConnectionString
            }
        }        私人无效IterateCollection(用户名字符串,动作&LT;布尔,字符串,字符串&GT; OnSucceed)
        {
            布尔成功= FALSE;
            dblogin =新PasswordEncrypt.SQLDatabase.DatabaseLogin();            串PSW;
            字符串用户ID;            的foreach(KeyValuePair&LT; PasswordEncrypt.Collections.GItem&LT;串&gt;中PasswordEncrypt.Collections.GItem&LT;串GT;&GT;千伏sqllogindatacollection)
            {
                清单&LT;焦炭&GT; TEMPA =新的List&LT;&烧焦GT;();
                清单&LT;焦炭&GT; tempb =新的List&LT;&烧焦GT;();                TEMPA = dblogin.GetNumber(用户名);
                tempb = dblogin.GetNumber(kv.Key.Item);                如果(tempa.Count == tempb.Count)
                {
                    的for(int i = 0; I&LT; tempa.Count;我++)
                    {
                        如果(tempa.ElementAt(ⅰ).Equals(tempb.ElementAt(ⅰ)))
                        {
                            如果(ⅰ==(tempa.Count -1))
                                成功= TRUE;
                            继续;
                        }
                        其他
                        {
                            KeyValuePair&LT; PasswordEncrypt.Collections.GItem&LT;串&gt;中PasswordEncrypt.Collections.GItem&LT;串GT;&GT;最后= sqllogindatacollection.Last();
                            如果(kv.Key.Item.Equals(last.Key.Item))
                            {
                                MessageBox.Show(无法匹配用户名数据库,错误,MessageBoxButtons.OK,MessageBoxIcon.Exclamation);
                                成功= FALSE;
                                //让GUI知道......
                                LogonEventArgs E =新LogonEventArgs();
                                e.Success =成功;
                                的OnError(这一点,E);
                                打破;
                            }
                            其他
                            {
                                打破;
                            }                        }                    }
                   // MessageBox.Show(找到一个SQL的用户名匹配);
                }
                //现在去执行方法登录到数据库中...
                如果(成功)
                {
                    PSW = kv.Value.Item;
                    用户id = kv.Key.Item;
                    OnSucceed(成功,PSW,用户ID);
                }
                成功= FALSE;
            }
        }        私人无效IterateCollection(字符串键,动作&LT;串GT; OnDatabaseName)
        {
            的foreach(KeyValuePair&LT; PasswordEncrypt.Collections.GItem&LT;串&gt;中PasswordEncrypt.Collections.GItem&LT;串GT;&GT;千伏applogindatacollection)
            {
                如果(键== kv.Key.Item)
                {
                    的MessageBox.show(找到一个匹配);
                    OnDatabaseName(kv.Value.Item);
                }
                其他
                {
                   // MessageBox.Show(不匹配);
                }
            }
        }        #地区的公共方法        公共BOOL? ReadFromRegistry(HashedUsername用户名,HashedPassword hashedpassword)
        {
            返回RegistryEdit.ReadFromRegistry(用户名,hashedpassword);
        }        公共BOOL WriteToRegistry(HashedUsername用户名,HashedPassword hashedpassword)
        {
            返回RegistryEdit.WriteToRegistry(用户名,hashedpassword);
        }        公共覆盖无效登录(文本框的用户名,密码文本框)
        {
            base.Login(用户名,密码);
            登录(username.Text,password.Text);
        }        保护覆盖无效登录(用户名字符串,字符串密码)
        {
            base.Login(用户名,密码);
            lgndata = base._logondata;
            比较= base._regRead;            如果(比较== true)而
            {
                登录名=用户名;
                LoginNewUser();
                ///在登录成功让UI类知识
                _logoneventargs =新LogonEventArgs();
                _logoneventargs.Success = TRUE;                OnExistingUserLoggedIn(这一点,_logoneventargs);
            }
            其他
            {
                _logoneventargs =新LogonEventArgs();
                _logoneventargs.Success = FALSE;
                _logoneventargs.ErrorMessage =无法登录该用户,请再试一次。
                的OnError(这一点,_logoneventargs);
            }
            ///获取用户名和密码的数据库?
            ///使用正确的用户数据和放大器来登录;权限
            ///数据库登录数据在运行时产生
            ///然后,如果用这样的名称数据库中存在检查
            /// 登录...        }
        #endregion
    }


解决方案

听到我张贴一些句子,我没有从我最喜欢的书架构的Microsoft®.NET解决方案的企业,我强烈建议阅读这本书拿即使你不是一个软件架构师。

这取决于
它总是依赖。作为一个建筑师,你永远不会确定任何事情。总有那么你失去了一些东西的可能性。然而,角色要求的决定作出,所以你必须能够评估所有选项,并作出明智的决定,而要做到这一点迅速,需要作出决定的时候。买自己一些时间,并在后台激活您的心理过程,先说,这取决于,然后解释为什么,什么答案取决于。如果你不确定什么点取决于,默认的回答是,这取决于环境。

的要求是主全部之上
建筑师是一个软件项目中的演员的天然链上任何一环。客户说,他想要什么。如果客户不知道自己想要什么,有人会出现提示他的细节。分析师形式化客户需要什么。项目经理prepares的正式定义项目的基础。建筑师得到需求的包和排序出来。开发商按照建筑师。数据库管理员做他最好使数据库有效地支持应用程序。需要注意的是客户领导链,什么客户需要的是法律。什么是客户想要的要求名义去。当然,只有少数客户知道什么是他们想要的。因此,需求的变化。

计划到接口
即使你谋生了实现code,你应该利用接口尽可能。我们重复:没有实现可能没有一个接口。环顾四周,总是有可以提取的界面。

保持简单但不能简单化
你知道KISS(保持简单,愚蠢的),对吗?这仅仅是我们的定制版本。简洁明了,通常等同于伟大的,做得很好。瞄准简单,但给自己范围的低端边界。如果你去,较低的界限以下,你的解决方案将变得简单化。这是不是一件好事。

继承是多态,不能再用
面向对象编程(OOP)告诉我们,我们应该再编写一个类,永远重复使用和随意扩展。而这可能要归功于遗传。这是否自然延伸到类的重用?重用是比你想象起初更微妙的概念。多态是OOP的关键方面来利用。多态是指可以交替使用两个继承的类。正如其他人所说,再利用是一个很好的副作用有。但是,重用不应该是你的目标,或者换一种说法,不要重复使用通过继承一个类只是重用的类。这是更好地编写一个新的类,它更多的precisely适合比需求要尽量继承不是设计作业现有的类。

不是DAL?不要触摸SQL然后
我们重复:关注点分离关注点分离。推送数据访问code和细节(如连接字符串,命令和表名)的角落。或早或晚,你需要从持久性分开照顾他们,但考虑业务和presentation逻辑。如果可能的话,委托持久性专案的工具,如对象/关系映射(O / RM)的工具。

可维护性第一
如果你能挑只有一个属性为你的软件,它会是什么?可扩展性?安全?性能?可测试性?可用性?对我们来说,这将是以上皆非。对于我们来说,什么是第一位的是可维护性。经过维修,可以实现在任何时间任何东西。

所有的用户输入是邪恶的
你应该已经听到了这一点。如果有一种方法为用户做错事,他们会找到它。哦,这听起来像墨菲定律。是的,你应该听说过这一个,也已。

验尸优化
高德纳说,premature优化是所有软件罪恶的根源。我们走得更远。不要优化系统。相反,它的设计为不断完善,在任何时间延长。但着眼于只有当系统被驳回纯优化。

安全和可测试性由设计
如果你认真的系统属性,设计,它从一开始。安全性和可测试性也不例外,并且有一个国际标准化组织(ISO)标准,具体是这么说的。

我希望你这会帮助你。

Besides using the Single Responsibility Principle, when designing classes for an application one is writing, what should one keep in mind, to keep the code maintainable, reusable and adhere to OOP principles?

I'm finding it hard to design the classes of applications I'm trying to write, because when does one decide what (functionality) goes in which class and whether it should really be in a derived class or there should be an abstract class or interface for this class?

I know this is probably a topic with many answers, but does anyone have any good guidelines (preferably simple) to designing classes and class hierarchies that are simple to maintain and don't make a mess when creating big applications?

EDIT:

When there's classes that have 10 methods and over and have an abstract base class & interfaces which it derives from. Also has 3 Singleton classes referenced globally inside the class and much more. Sounds like it needs a bit of 'refactoring' applied?

Sorry if it's a long example, but you see the problem I'm facing and I want some input on it. Please just look at design, not at technicalities.

I give an example:

I created this class: (a while back)

  class ExistingUserLogon : Logon, ILogonUser
    {
        #region Member Variables

        LogonEventArgs _logoneventargs;
        LogonData lgndata;
        Factory f = Factory.FactoryInstance;
        PasswordEncrypt.Collections.AppLoginDataCollection applogindatacollection;
        PasswordEncrypt.Collections.SQlLoginDataCollection sqllogindatacollection;
        bool? compare;
        static ExistingUserLogon existinguserlogon;
        PasswordEncrypt.SQLDatabase.DatabaseLogin dblogin;
        string databasename = string.Empty;

        #endregion

        #region Properties

        public static ExistingUserLogon ExistingUserLogonInstance
        {
            get
            {
                if (existinguserlogon == null)
                    existinguserlogon = new ExistingUserLogon();
                return existinguserlogon;
            }
        }
        public string loginname
        {
            get;
            set;
        }
        #endregion

        #region Contructors
        public ExistingUserLogon(bool? compare, LogonData logondata)
        {
            this.compare = compare;
            this.lgndata = logondata;
            this.applogindatacollection = f.AppLoginDataCollection;
            this.sqllogindatacollection = f.SqlLoginDataCollection;
        }

        public ExistingUserLogon()
        {
            this.applogindatacollection = f.AppLoginDataCollection;
            this.sqllogindatacollection = f.SqlLoginDataCollection;
        }

        #endregion

        #region Delegates

        public delegate void ConnStrCreated( object sender, LogonEventArgs e );

        #endregion

        #region Events

        public event ConnStrCreated ConnectionStringCreated;

        #endregion

        private void OnConnectionStringCreated( object sender, LogonEventArgs e )
        {
            if (ConnectionStringCreated != null)
            {
                ConnectionStringCreated(sender, e);
            }
        }

        public void LoginNewUser()
        {
            dblogin = new PasswordEncrypt.SQLDatabase.DatabaseLogin();
            if (!string.IsNullOrEmpty(loginname))
            {
                string temp = dblogin.GenerateDBUserName(loginname);
                if (temp != "Already Exists")
                {

                    if (compare == true)
                    {
                        IterateCollection(lgndata.HahsedUserName.HashedUserName, new Action<string>(OnDatabaseName));
                        IterateCollection(temp, new Action<bool, string, string>(OnIterateSuccess));
                    }
                }

            }
            else
            {
                LogonEventArgs e = new LogonEventArgs();
                e.Success = false;
                e.ErrorMessage = "Error! No Username";
                OnError(this, e);

            }

        }

        private void OnDatabaseName(string name)
        {
            this.databasename = name;
        }

        private void OnIterateSuccess( bool succeed, string psw, string userid )
        {
            if (succeed)
            {
                // Create connectionstring
                ConnectionStringCreator cnstrCreate = ConnectionStringCreator.ConnectionStringInstance;
                if (databasename != string.Empty)
                {
                    string conn = ConnectionStringCreator.CreateConnString(databasename, userid, psw);
                    bool databaseExists;

                    databaseExists = DataManagementVerification.DoDatabaseExists(conn);

                    if (databaseExists)
                    {
                        FormsTransfer.ConnectionString = conn;

                        conn = string.Empty;
                    }
                    else
                    {
                        LogonEventArgs e = new LogonEventArgs();
                        e.Success = false;
                        e.ErrorMessage = "Database does not Exist!";
                        OnError(this, e);
                    }

                    //OnConnectionStringCreated(this, e);

                   // PasswordEncrypt.LINQtoSQL.PasswordDatabase db = new PasswordEncrypt.LINQtoSQL.PasswordDatabase(conn);

                /*    PasswordEncrypt.LINQtoSQL.EncryptData _encryptdata = new PasswordEncrypt.LINQtoSQL.EncryptData()
                    {
                        EncryptID = 1,
                        IV = "Test",
                        PrivateKey = "Hello",
                        PublicKey = "Tony"
                    };

                    db.EncryptionData.InsertOnSubmit(_encryptdata);

                   // db.SubmitChanges();*/

                    //PasswordEncrypt.LINQtoSQL.Data _data = new PasswordEncrypt.LINQtoSQL.Data()
                    //{
                    //    EncryptionID = 1,
                    //    Username = "Tbone",
                    //    Password = "worstje",
                    //    IDCol = 2
                    //};

                    //db.Data.InsertOnSubmit(_data);

                    //db.SubmitChanges();

                    //IEnumerable<PasswordEncrypt.LINQtoSQL.Data> _ddata = db.Data.Where(data => data.Password == "worstje"); ;
                    //foreach (PasswordEncrypt.LINQtoSQL.Data data in _ddata)
                    //{

                    //    MessageBox.Show("Data Found: " + data.Username + "," + data.Password);
                    //}
                }
                else
                {
                    MessageBox.Show("Found no Database name", "Database name error");
                }
            }
            else
            {
                // Unable to create connectionstring
            }
        }

        private void IterateCollection( string username, Action<bool, string, string> OnSucceed )
        {
            bool succeed = false;
            dblogin = new PasswordEncrypt.SQLDatabase.DatabaseLogin();

            string psw;
            string userid;

            foreach (KeyValuePair<PasswordEncrypt.Collections.GItem<string>, PasswordEncrypt.Collections.GItem<string>> kv in sqllogindatacollection)
            {
                List<char> tempa = new List<char>();
                List<char> tempb = new List<char>();

                tempa = dblogin.GetNumber(username);
                tempb = dblogin.GetNumber(kv.Key.Item);

                if (tempa.Count == tempb.Count)
                {
                    for (int i = 0; i < tempa.Count ; i++)
                    {
                        if (tempa.ElementAt(i).Equals(tempb.ElementAt(i)))
                        {
                            if ( i == (tempa.Count -1) )
                                succeed = true;
                            continue;
                        }
                        else
                        {
                            KeyValuePair<PasswordEncrypt.Collections.GItem<string>, PasswordEncrypt.Collections.GItem<string>> last =  sqllogindatacollection.Last();
                            if (kv.Key.Item.Equals(last.Key.Item))
                            {
                                MessageBox.Show("Failed to match usernames for Database", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                                succeed = false;
                                // Let GUI Know...
                                LogonEventArgs e = new LogonEventArgs();
                                e.Success = succeed;
                                OnError(this, e);
                                break;
                            }
                            else
                            {
                                break;
                            }

                        }

                    }


                   // MessageBox.Show("Found a sql username match");
                }
                // Now go execute method to logon into database...
                if (succeed)
                {
                    psw = kv.Value.Item;
                    userid = kv.Key.Item;
                    OnSucceed(succeed, psw, userid);
                }
                succeed = false;
            }


        }

        private void IterateCollection(string key, Action<string> OnDatabaseName )
        {
            foreach (KeyValuePair<PasswordEncrypt.Collections.GItem<string>, PasswordEncrypt.Collections.GItem<string>> kv in applogindatacollection)
            {
                if (key == kv.Key.Item)
                {
                    MessageBox.Show("Found a match");
                    OnDatabaseName(kv.Value.Item);
                }
                else
                {
                   // MessageBox.Show("No Match");
                }
            }
        }

        #region Public Methods

        public bool? ReadFromRegistry( HashedUsername username, HashedPassword hashedpassword )
        {
            return RegistryEdit.ReadFromRegistry(username, hashedpassword);
        }

        public bool WriteToRegistry( HashedUsername username, HashedPassword hashedpassword )
        {
            return RegistryEdit.WriteToRegistry(username, hashedpassword);
        }

        public override void Login(TextBox username, TextBox password)
        {
            base.Login(username, password);
            Login(username.Text, password.Text);
        }

        protected override void Login(string username, string password)
        {
            base.Login(username, password);
            lgndata = base._logondata;
            compare = base._regRead;

            if (compare == true)
            {
                loginname = username;
                LoginNewUser();
                /// on login succeeded let UI class know
                _logoneventargs = new LogonEventArgs();
                _logoneventargs.Success = true;

                OnExistingUserLoggedIn(this, _logoneventargs);
            }
            else
            {
                _logoneventargs = new LogonEventArgs();
                _logoneventargs.Success = false;
                _logoneventargs.ErrorMessage = "Cannot Login this user, please try again.";
                OnError(this, _logoneventargs);
            }
            /// Get username and password for database... 
            /// to login using correct user data & permissions
            /// Login data for database is generated at runtime
            /// then by checking if database with such a name exists
            /// login...

        }
        #endregion
    }

解决方案

Hear I post some of sentence that I did take from my favorite book "Architecting Microsoft® .NET Solutions for the Enterprise" that I strongly recommend to read this book even if you’re not a Software Architect.

It Depends It always depends. As an architect, you are never sure about anything. There's always the possibility that you're missing something. However, the role requires that decisions be made, so you must be able to evaluate all options and make an informed decision, and to do this promptly, when a decision is required. To buy yourself some time and activate your mental processes in the background, first say, "It depends," and then explain why and what the answer depends on. If you are unsure about what a point depends on, the default answer is, "It depends on the context."

Requirements Are Lord Over All The architect is just one link in the natural chain of actors in a software project. The customer says what he wants. If the customer doesn't know what he wants, someone will be there to prompt him for specifics. The analyst formalizes what the customer wants. The project manager prepares the groundwork for the formally-defined project. The architect gets the bundle of requirements and sorts them out. Developers follow the architect. The database administrator does his best to make the database support the application effectively. Note that the customer leads the chain, and what the customer wants is the law. What the customer wants goes under the name of requirements. Of course, only few customers know what it is they want. So requirements change.

Program to an Interface Even if you make a living out of implemented code, you should leverage interfaces wherever possible. Repeat with us: "No implementation is possible without an interface." Look around, there's always an interface that can be extracted.

Keep It Simple but Not Simplistic You know KISS (Keep It Simple, Stupid), right? This is just our customized version. Simple and concise is usually equivalent to great and well done. Aim at simplicity, but give yourself a boundary for the low end of the range. If you go below that lower boundary, your solution will become simplistic. And this is not a good thing.

Inheritance Is About Polymorphism, Not Reuse Object-oriented programming (OOP) taught us that we should write a class once and reuse it forever and extend it at will. And this is possible thanks to inheritance. Does this naturally extend to class reuse? Reuse is a much subtler concept than you might think at first. Polymorphism is the key aspect of OOP to leverage. Polymorphism means you can use two inherited classes interchangeably. As others have said, "Reuse is a nice side effect to have." But reuse shouldn't be your goal, or put another way, don't reuse a class through inheritance just to reuse the class. It's better to write a new class that more precisely fits the needs than to try to inherit an existing class that wasn't designed for the job.

Not the DAL? Don't Touch SQL Then Repeat with us: "Separation of concerns. Separation of concerns." Push data access code and details (such as connection strings, commands, and table names) to the corner. Sooner or later, you need to take care of them, but consider business and presentation logic separately from persistence. And if possible, delegate persistence to ad hoc tools such as Object/ Relational Mapper (O/RM) tools.

Maintainability First If you could pick only one attribute for your software, what would it be? Scalability? Security? Performance? Testability? Usability? For us, it would be none of the above. For us, what comes first is maintainability. Through maintainability, you can achieve anything else at any time.

All User Input Is Evil You should have heard this already. If there's a way for users to do something wrong, they'll find it. Oh, this sounds like Murphy's Law. Yes, you should have heard this one, too, already.

Post-Mortem Optimization Donald Knuth said that premature optimization is the root of all software evil. We go even further. Do not optimize the system. Instead, design it for being improved and extended at any time. But focus on pure optimization only when the system is dismissed.

Security and Testability Are by Design If you're serious about a system attribute, design for it right from the beginning. Security and testability are no exception to this rule, and there's an International Organization for Standardization (ISO) standard that specifically says so.

I hope you this will help you.

这篇关于在设计应用程序类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆