关于设计,如何设计我的类?刚开始考虑设计啊,一头雾水

时间:2021-07-16 19:26:58
我定义了三个不同的类:学生、教室、课程,每个类都有不同的属性
然后我又定义了三个管理类:学生管理、教室管理、课程管理,每个管理类都有一个list存放相应的对象,并提供了Add、Delete等操作,还有编号计算功能等
==============
我发现了,这三个管理类都是很类似的,我很想把他变成一个类。可是每个ADD的传入对象都是不一样的。
我想来想去,想使用泛型写一个管理类。
可是我又在想,正在读的《深入浅出设计模式》这本书里没有提到泛型啊(嗯,才读到400页)。
如果不用泛型呢,应当是什么样子的?请大家指点

18 个解决方案

#1


引用 楼主 santawen 的回复:
我发现了,这三个管理类都是很类似的,

让我们看看你说的管理类都做什么?

#2


嗯,把个数据库表“增删改”就叫做管理类了,你让sql语言都害羞了啊。啥东西都叫做“管理”,那么真正的业务有什么?

不可否认,有些人一旦编程序,原先那些“会写管理类”的豪言壮语可以骗过HR,但是实际工作中就会发现原来他只是知道增删改、充其量还为了应聘而死记硬背了几段“三层”代码。那么“设计”软件为什么不学一学呢?这需要动手能力。

#3


我在想这些东西的时候,是排除了数据库的,确是,这些删增改在数据库里是很简单的,其实,List同样的有Add、Delete的默认操作。我只是想完全的从类的角度去考虑一些问题。

我这里的管理只是说明了想象中这个类的职责定位,并不是说我这个类功能多强大。

回到我的问题,假设我的管理类只有三个方法:Add、Delete、SetID(Object),请提出宝贵建议

#4


我建议你多看看设计的书,例如手机设计,甚至是电冰箱的设计、闹钟的设计......

进行软件设计,仅仅纠结在一个数据的“增删改”,甚至那种自以为搞定了世界上最基本的分层概念“三层”就万能了的不出产品只出理论的程序员,实在是浪费了“设计”的这个概念。

设计,就是不一样,就是让人感到眼前一亮。而不是那种不值钱的千篇一律地抄袭,更不是纠结于底层的千分之一的“技术”。在设计面前,技术不重要。

#5


如果你想学最八股的对象关联图“设计”,那么你可以看看UML(显然,对象关联图仅仅是UML最初的一个小部分)。

别人的设计过程可能是实践者的过程,而你的设计过程是学习过程,所以你要是有更好的理念、始终明白设计的目的是技术还是实践,才不至于以后陷入那种不出产品只出理论的设计误区。

#6


不得不说,你的回答对我完全无帮助。

我正在读《深入浅出设计模式》,因此,我尝试做自己的设计,为此,我找了一个自己写过的小程序,重新考虑如何实现。我也担心流于空泛,因此我考虑了比较简单、实际的场景。但是似乎,你只在抒发自己的感想,而没有真正的去考虑应当如何实现这个具体的需求。

#7


没有泛型,只能传递object了。
或者使用“代码生成器”,事实上,你可以理解泛型的本质就是一个在CLR层面的代码生成器,自动根据泛型类编译创造出具体的类。

#8


引用 2 楼 sp1234 的回复:
嗯,把个数据库表“增删改”就叫做管理类了,你让sql语言都害羞了啊。啥东西都叫做“管理”,那么真正的业务有什么?

不可否认,有些人一旦编程序,原先那些“会写管理类”的豪言壮语可以骗过HR,但是实际工作中就会发现原来他只是知道增删改、充其量还为了应聘而死记硬背了几段“三层”代码。那么“设计”软件为什么不学一学呢?这需要动手能力。


没必要老是这么挑别人刺,你想说的就是ddd思想吧,但显然楼主还是在基础学习阶段,你扯ddd,对别人有一丁点帮助吗?
泛型加反射,没充分分析,就现阶段需求,应该可以实现,但随着基础功能的扩展,你维护你的反省管理类,难度将是几何级数的上升。
就用三层吧,三层虽然确实是个很傻瓜的构架,但就像新手从傻瓜相机学起,也没什么不好,有一定功力了,再上单反。

#9


初识三层,你觉得,哎呦,这思路真清晰,写法真简单。所有的业务,我这一招全部可以搞定,上来就代码生成器刷刷刷把架子搭起来,写的真爽。
一段时间之后,当你纠结于无尽的sql 增删改,联表查询,数据绑定,交叉引用,互相依赖的时候,你会大骂,这当初是哪个sb设计的,一件事,我tm要做三遍才能完成,大量ctrl c+v代码,一会dataTable 一会DataObject。
这个时候,你就会思考,我为什么要分层。我的理解是业务抽象,解耦,封装,职责划分。
明白了这些,就不需要在纠结业务层的划分了,到时候2层还是4,5,6层、中间需不需要夹个orm都随你了。

再然后。。。好吧 我说不出来了 ,p哥帮我接吧。
@sp1234 

#10


业务类虽然看起来相似,但其实实践中设计为范型类很少有成功的例子,

不要把三个管理类设计为一个范型,

#11


这三个归结到一个类是可以做的,我一般用orm,你用的什么我不清楚,你可以参考一下EF的。

/// <summary>
    /// Repository , CURD
    /// </summary>
    public partial interface IRepository<T> where T : BaseEntity
    {
        T GetById(object id);
        void Insert(T entity);
        void Update(T entity);
        void Delete(T entity);
        IQueryable<T> Table { get; }
    }


EF 中可以这样: 增删改查类似
        public new IDbSet<TEntity> Set<TEntity>() where TEntity : BaseEntity
        {
            return base.Set<TEntity>();
        }

#12


引用 11 楼 blue_apple2006 的回复:
这三个归结到一个类是可以做的,我一般用orm,你用的什么我不清楚,你可以参考一下EF的。

/// <summary>
    /// Repository , CURD
    /// </summary>
    public partial interface IRepository<T> where T : BaseEntity
    {
        T GetById(object id);
        void Insert(T entity);
        void Update(T entity);
        void Delete(T entity);
        IQueryable<T> Table { get; }
    }


EF 中可以这样: 增删改查类似
        public new IDbSet<TEntity> Set<TEntity>() where TEntity : BaseEntity
        {
            return base.Set<TEntity>();
        }

/// <summary>
    /// Entity Framework repository
    /// </summary>
    public partial class EfRepository<T> : IRepository<T> where T : BaseEntity
    {
        private readonly IDbContext _context;
        private IDbSet<T> _entities;

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="context">Object context</param>
        public EfRepository(IDbContext context)
        {
            this._context = context;
        }

        public T GetById(object id)
        {
            return this.Entities.Find(id);
        }

        public void Insert(T entity)
        {
            try
            {
                if (entity == null)
                    throw new ArgumentNullException("entity");

                this.Entities.Add(entity);

                this._context.SaveChanges();
            }
            catch (DbEntityValidationException dbEx)
            {
                var msg = string.Empty;

                foreach (var validationErrors in dbEx.EntityValidationErrors)
                    foreach (var validationError in validationErrors.ValidationErrors)
                        msg += string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage) + Environment.NewLine;

                var fail = new Exception(msg, dbEx);
                //Debug.WriteLine(fail.Message, fail);
                throw fail;
            }
        }

        public void Update(T entity)
        {
            try
            {
                if (entity == null)
                    throw new ArgumentNullException("entity");

               this._context.SaveChanges();
            }
            catch (DbEntityValidationException dbEx)
            {
                var msg = string.Empty;

                foreach (var validationErrors in dbEx.EntityValidationErrors)
                    foreach (var validationError in validationErrors.ValidationErrors)
                        msg += Environment.NewLine + string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);

                var fail = new Exception(msg, dbEx);
                //Debug.WriteLine(fail.Message, fail);
                throw fail;
            }
        }

        public void Delete(T entity)
        {
            try
            {
                if (entity == null)
                    throw new ArgumentNullException("entity");

                this.Entities.Remove(entity);

                this._context.SaveChanges();
            }
            catch (DbEntityValidationException dbEx)
            {
                var msg = string.Empty;

                foreach (var validationErrors in dbEx.EntityValidationErrors)
                    foreach (var validationError in validationErrors.ValidationErrors)
                        msg += Environment.NewLine + string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);

                var fail = new Exception(msg, dbEx);
                //Debug.WriteLine(fail.Message, fail);
                throw fail;
            }
        }

        public virtual IQueryable<T> Table
        {
            get
            {
                return this.Entities;
            }
        }

        private IDbSet<T> Entities
        {
            get
            {
                if (_entities == null)
                    _entities = _context.Set<T>();
                return _entities;
            }
        }
    }

#13


哎,很遗憾,sp的回复应该对你是最有用的才对。

#14


http://bbs.csdn.net/topics/390466572?page=1#post-394558774
跪求大神

#15


用接口我觉得挺好的。。 

#16


非常感谢各位的回复。
就我有限的知识,三层的架构往往是在比较大的软件系统、多人合作的时候发挥威力,作为我单枪匹马考虑问题来说,是有点不配套。但是我看自己的代码呢,也觉得需要适当的梳理一下,否则真的看着很不舒服。

在我这个场景里,让我很不爽的是。我要写三个管理类,每个类都要写一遍add、delete、以及SavetoFile之类的函数。这三个类太相似了!唯一的区别就是每个函数的传入参数类型不一致。按照设计模式的理念,代码不应当重复,否则就有坏味道。因此,我很想解决他。更何况,如果有第四个类,我怎么办?

我想来想去,泛型也不好用。因为每个管理类可能还有自己独有的函数。这些类是相似,但不是完全一样。

我记得哪里听说,微软内部也是有使用代码生成器的。也许,这样的代码重复从现实实现上讲是无法避免的?真正的解决方法,就是ORM 这些了。
昨晚苦思不得解,可能对sp1234的语气有所不善,在此一并致歉!

#17


嗯,我也想过接口。
以我有限的能力,我感觉接口只是规定要实现这些功能,而真正的代码还是要在管理类里重新写,并没有减轻代码量。现在的这点东西,加了一层接口,反而更复杂了。

#18


OK,来结贴了。

我在MSDN上也提问了,并且得到了很大的帮助。
http://social.msdn.microsoft.com/Forums/zh-cn/vstszhchs/thread/90c30227-b7e2-44ca-96cd-c9ec879c91e5
最终,我使用的还是泛型,正如ProgrammingVolunteer所说:“设计模式的那个时候还没有泛型这个概念,呵呵。”用泛型不是设计模式的错。

很好笑的是,blue_apple2006 当时回复我的代码,我看的头疼,也就是看不懂。略过了。当我写出自己的代码后,才发现自己的代码和他贴出来的类似,我就是在朝这份代码前进!

#1


引用 楼主 santawen 的回复:
我发现了,这三个管理类都是很类似的,

让我们看看你说的管理类都做什么?

#2


嗯,把个数据库表“增删改”就叫做管理类了,你让sql语言都害羞了啊。啥东西都叫做“管理”,那么真正的业务有什么?

不可否认,有些人一旦编程序,原先那些“会写管理类”的豪言壮语可以骗过HR,但是实际工作中就会发现原来他只是知道增删改、充其量还为了应聘而死记硬背了几段“三层”代码。那么“设计”软件为什么不学一学呢?这需要动手能力。

#3


我在想这些东西的时候,是排除了数据库的,确是,这些删增改在数据库里是很简单的,其实,List同样的有Add、Delete的默认操作。我只是想完全的从类的角度去考虑一些问题。

我这里的管理只是说明了想象中这个类的职责定位,并不是说我这个类功能多强大。

回到我的问题,假设我的管理类只有三个方法:Add、Delete、SetID(Object),请提出宝贵建议

#4


我建议你多看看设计的书,例如手机设计,甚至是电冰箱的设计、闹钟的设计......

进行软件设计,仅仅纠结在一个数据的“增删改”,甚至那种自以为搞定了世界上最基本的分层概念“三层”就万能了的不出产品只出理论的程序员,实在是浪费了“设计”的这个概念。

设计,就是不一样,就是让人感到眼前一亮。而不是那种不值钱的千篇一律地抄袭,更不是纠结于底层的千分之一的“技术”。在设计面前,技术不重要。

#5


如果你想学最八股的对象关联图“设计”,那么你可以看看UML(显然,对象关联图仅仅是UML最初的一个小部分)。

别人的设计过程可能是实践者的过程,而你的设计过程是学习过程,所以你要是有更好的理念、始终明白设计的目的是技术还是实践,才不至于以后陷入那种不出产品只出理论的设计误区。

#6


不得不说,你的回答对我完全无帮助。

我正在读《深入浅出设计模式》,因此,我尝试做自己的设计,为此,我找了一个自己写过的小程序,重新考虑如何实现。我也担心流于空泛,因此我考虑了比较简单、实际的场景。但是似乎,你只在抒发自己的感想,而没有真正的去考虑应当如何实现这个具体的需求。

#7


没有泛型,只能传递object了。
或者使用“代码生成器”,事实上,你可以理解泛型的本质就是一个在CLR层面的代码生成器,自动根据泛型类编译创造出具体的类。

#8


引用 2 楼 sp1234 的回复:
嗯,把个数据库表“增删改”就叫做管理类了,你让sql语言都害羞了啊。啥东西都叫做“管理”,那么真正的业务有什么?

不可否认,有些人一旦编程序,原先那些“会写管理类”的豪言壮语可以骗过HR,但是实际工作中就会发现原来他只是知道增删改、充其量还为了应聘而死记硬背了几段“三层”代码。那么“设计”软件为什么不学一学呢?这需要动手能力。


没必要老是这么挑别人刺,你想说的就是ddd思想吧,但显然楼主还是在基础学习阶段,你扯ddd,对别人有一丁点帮助吗?
泛型加反射,没充分分析,就现阶段需求,应该可以实现,但随着基础功能的扩展,你维护你的反省管理类,难度将是几何级数的上升。
就用三层吧,三层虽然确实是个很傻瓜的构架,但就像新手从傻瓜相机学起,也没什么不好,有一定功力了,再上单反。

#9


初识三层,你觉得,哎呦,这思路真清晰,写法真简单。所有的业务,我这一招全部可以搞定,上来就代码生成器刷刷刷把架子搭起来,写的真爽。
一段时间之后,当你纠结于无尽的sql 增删改,联表查询,数据绑定,交叉引用,互相依赖的时候,你会大骂,这当初是哪个sb设计的,一件事,我tm要做三遍才能完成,大量ctrl c+v代码,一会dataTable 一会DataObject。
这个时候,你就会思考,我为什么要分层。我的理解是业务抽象,解耦,封装,职责划分。
明白了这些,就不需要在纠结业务层的划分了,到时候2层还是4,5,6层、中间需不需要夹个orm都随你了。

再然后。。。好吧 我说不出来了 ,p哥帮我接吧。
@sp1234 

#10


业务类虽然看起来相似,但其实实践中设计为范型类很少有成功的例子,

不要把三个管理类设计为一个范型,

#11


这三个归结到一个类是可以做的,我一般用orm,你用的什么我不清楚,你可以参考一下EF的。

/// <summary>
    /// Repository , CURD
    /// </summary>
    public partial interface IRepository<T> where T : BaseEntity
    {
        T GetById(object id);
        void Insert(T entity);
        void Update(T entity);
        void Delete(T entity);
        IQueryable<T> Table { get; }
    }


EF 中可以这样: 增删改查类似
        public new IDbSet<TEntity> Set<TEntity>() where TEntity : BaseEntity
        {
            return base.Set<TEntity>();
        }

#12


引用 11 楼 blue_apple2006 的回复:
这三个归结到一个类是可以做的,我一般用orm,你用的什么我不清楚,你可以参考一下EF的。

/// <summary>
    /// Repository , CURD
    /// </summary>
    public partial interface IRepository<T> where T : BaseEntity
    {
        T GetById(object id);
        void Insert(T entity);
        void Update(T entity);
        void Delete(T entity);
        IQueryable<T> Table { get; }
    }


EF 中可以这样: 增删改查类似
        public new IDbSet<TEntity> Set<TEntity>() where TEntity : BaseEntity
        {
            return base.Set<TEntity>();
        }

/// <summary>
    /// Entity Framework repository
    /// </summary>
    public partial class EfRepository<T> : IRepository<T> where T : BaseEntity
    {
        private readonly IDbContext _context;
        private IDbSet<T> _entities;

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="context">Object context</param>
        public EfRepository(IDbContext context)
        {
            this._context = context;
        }

        public T GetById(object id)
        {
            return this.Entities.Find(id);
        }

        public void Insert(T entity)
        {
            try
            {
                if (entity == null)
                    throw new ArgumentNullException("entity");

                this.Entities.Add(entity);

                this._context.SaveChanges();
            }
            catch (DbEntityValidationException dbEx)
            {
                var msg = string.Empty;

                foreach (var validationErrors in dbEx.EntityValidationErrors)
                    foreach (var validationError in validationErrors.ValidationErrors)
                        msg += string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage) + Environment.NewLine;

                var fail = new Exception(msg, dbEx);
                //Debug.WriteLine(fail.Message, fail);
                throw fail;
            }
        }

        public void Update(T entity)
        {
            try
            {
                if (entity == null)
                    throw new ArgumentNullException("entity");

               this._context.SaveChanges();
            }
            catch (DbEntityValidationException dbEx)
            {
                var msg = string.Empty;

                foreach (var validationErrors in dbEx.EntityValidationErrors)
                    foreach (var validationError in validationErrors.ValidationErrors)
                        msg += Environment.NewLine + string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);

                var fail = new Exception(msg, dbEx);
                //Debug.WriteLine(fail.Message, fail);
                throw fail;
            }
        }

        public void Delete(T entity)
        {
            try
            {
                if (entity == null)
                    throw new ArgumentNullException("entity");

                this.Entities.Remove(entity);

                this._context.SaveChanges();
            }
            catch (DbEntityValidationException dbEx)
            {
                var msg = string.Empty;

                foreach (var validationErrors in dbEx.EntityValidationErrors)
                    foreach (var validationError in validationErrors.ValidationErrors)
                        msg += Environment.NewLine + string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);

                var fail = new Exception(msg, dbEx);
                //Debug.WriteLine(fail.Message, fail);
                throw fail;
            }
        }

        public virtual IQueryable<T> Table
        {
            get
            {
                return this.Entities;
            }
        }

        private IDbSet<T> Entities
        {
            get
            {
                if (_entities == null)
                    _entities = _context.Set<T>();
                return _entities;
            }
        }
    }

#13


哎,很遗憾,sp的回复应该对你是最有用的才对。

#14


http://bbs.csdn.net/topics/390466572?page=1#post-394558774
跪求大神

#15


用接口我觉得挺好的。。 

#16


非常感谢各位的回复。
就我有限的知识,三层的架构往往是在比较大的软件系统、多人合作的时候发挥威力,作为我单枪匹马考虑问题来说,是有点不配套。但是我看自己的代码呢,也觉得需要适当的梳理一下,否则真的看着很不舒服。

在我这个场景里,让我很不爽的是。我要写三个管理类,每个类都要写一遍add、delete、以及SavetoFile之类的函数。这三个类太相似了!唯一的区别就是每个函数的传入参数类型不一致。按照设计模式的理念,代码不应当重复,否则就有坏味道。因此,我很想解决他。更何况,如果有第四个类,我怎么办?

我想来想去,泛型也不好用。因为每个管理类可能还有自己独有的函数。这些类是相似,但不是完全一样。

我记得哪里听说,微软内部也是有使用代码生成器的。也许,这样的代码重复从现实实现上讲是无法避免的?真正的解决方法,就是ORM 这些了。
昨晚苦思不得解,可能对sp1234的语气有所不善,在此一并致歉!

#17


嗯,我也想过接口。
以我有限的能力,我感觉接口只是规定要实现这些功能,而真正的代码还是要在管理类里重新写,并没有减轻代码量。现在的这点东西,加了一层接口,反而更复杂了。

#18


OK,来结贴了。

我在MSDN上也提问了,并且得到了很大的帮助。
http://social.msdn.microsoft.com/Forums/zh-cn/vstszhchs/thread/90c30227-b7e2-44ca-96cd-c9ec879c91e5
最终,我使用的还是泛型,正如ProgrammingVolunteer所说:“设计模式的那个时候还没有泛型这个概念,呵呵。”用泛型不是设计模式的错。

很好笑的是,blue_apple2006 当时回复我的代码,我看的头疼,也就是看不懂。略过了。当我写出自己的代码后,才发现自己的代码和他贴出来的类似,我就是在朝这份代码前进!