如何使内存高效的代码,但仍然有所有可能的代码很好地封装?
我感觉OO (面向对象)方法更直观,代码组织得很好,并且封装得很好,但它可以使用大量内存,因为内存中通常有许多活动对象实例。
相比之下,MVC (控制器、模型(数据库))方法代码封装得更少,但使用的内存却更少,因为内存中的对象只有当客户端请求时才会被处理。
我需要做一个内部健康监测系统,定期平ip摄像头。将有大约10,000个项目(相机)要监控,一个布尔状态-好/坏。
如果我走OO的道路-我将持有一个类为每个项目,它的ping结果,定时器,事件通知一些其他项目。因此,我将始终在内存中得到10000个实例。没有多少,但如果有100,000,000件呢?我更喜欢这种方式,因为它是直观的,对于我可能需要在具体的item类(计时器、事件、处理程序、订阅)中运行的任何代码,我都有一个完美的(封装的)位置。
如果我采用MVC模式,我将把所有的数据保存在数据库中,这样内存使用量就会降到最低。但是我将不得不临时想出一种触发代码执行的方法,比如周期性的定时器、事件、处理程序、订阅。那个代码-它会写在哪里?它会被很好地封装吗?另外,哪些代码将调用这些触发器?它也会被封装吗?例如,我可以制作定时器引擎,并为10000中的每一个保存一个定时器字典,但是代码将不会被封装。
发布于 2020-06-10 04:45:44
不管做什么都行。
甚至MVC也是一种面向对象的设计模式,最初是由SmallTalk (一种纯面向对象语言)引入的。
除非我们讨论的是像JavaScript这样的语言,否则大多数语言都支持一个紧密打包的数据结构。因此,OO做一些事情不会对内存效率产生很大影响。
当您引入诸如子类、混合和属性包之类的灵活性时,会出现一些警告。
我不认为你对MVC到底是什么有很好的理解。
我认为您所讨论的是活动记录集,或者类似的技术,其中数据库表本身是作为表公开给您自己的函数的。
现在可以使用活动记录作为MVC实现中的对象模型。在这种情况下,声明代码封装得较少是不公平的。
这给了你:
1Gb内存(1024 * 1024 * 1024字节)
有了一些技巧,就有可能把这个压得更低。
但是无论您做什么,这些数据都将存在于某个地方,无论是存储在数据库中,还是存储在程序本身中。
请注意,如果程序要求的内存比RAM中存储的内存多,那么它将被分页到磁盘,就像在数据库中发生的情况一样。
一台能够访问2GB内存的现代计算机和一个SSD,能够为您的100,000,000个实例编组所需的6GB内存空间,因为大多数64位应用程序中的可寻址空间目前约为2^40。在超出范围之前,您需要担心手动将数据从流程中交换出来,以便腾出空间进行进一步的工作。
如果这看起来太慢了,真正提高性能的最便宜的方法就是升级服务器内存。如今,16 is并不贵,甚至64 is的价格也是合理的。
如果由于某种原因,你的客户(大概能负担得起1亿台相机)负担不起几台服务器(每个服务器都在处理问题的子集),或者无法负担足够的资源将其全部存放在一台机器上,那么你就无能为力了。
这个数据库的用途是什么?
发布于 2020-06-10 07:42:00
当您反对OOD和MVC时,有一个根本的误解。
还有另一种误解,将MVC与内存中短路对象的数据库导向M联系起来。MVC不知道M是如何与数据库交互的。设计M的方法有很多,例如:
但是还有很多其他的变体。这并不是因为您会将几个域对象保存在内存中才会耗尽您的系统(加载的不是完整的数据库,而是所需的内容)。
如果你想在MVC中寻找一个不错的M设计,而不失去OOD的任何优点,并且了解不同选择的利弊,我可以推荐您Martin的伟大著作"企业应用体系结构模式“。有几个章节专门讨论这个问题。
发布于 2020-06-10 09:37:26
您的假设,您必须有一个对象,为每一个ip相机,如果你做OOP,不支持。而且,您似乎是在假设ip摄像机对象需要在任何时候保存与它们相关的数据,或者每个ip摄像机对象都必须始终存在,这也不是事实。
我知道这是不幸的是,在许多项目中,OO是什么样子,但是对于OO来说,这两种假设都是不需要的。在OO中,你准确地模拟了你需要的东西。如果您只想显示当前值,为什么不这样做:
public interface IpCameras {
UIComponent displayState();
}如果这是您的用例,那么在OO中没有任何理由拥有更多的东西。所有的“模式”、"MVC“之类的东西都不重要。做适当的建模,大多数(如果不是所有的优化问题)都会有一个合适的地方去。
更新:有更多的要求。点击和计时:我假设调度代码已经在平台上了,所以我可能会这样做:
public interface IpCameras {
UIComponent displayState();
void pingAll();
}用pingAll()的电话通过所有的摄像头。这也可能是内部的,IpCameras可以在不公开此方法的情况下这样做,两者都很好。
为了通知一些事情,也许可以用一个参数来扩展这个方法:
void pingAll(PingClient client);
public interface PingClient {
void onPinged(...ip camera...);
void onFailed(...ip camera...);
}然后,您可以有多个PingClient实现,将您想要使用这些信息执行的不同事情分开。一些实现可能是:PingClients (用于多个客户端)、RealTimeClients (用于在线应用程序)、NotificationsClients (用于电子邮件客户端或其他什么)、ThreeFailsClient (仅在连续3次失败注册时才使委托失败)等等。
同样,您可以在不为每个摄像机实例化对象的情况下完成所有这些操作,并且不需要在内存中保留任何多余的数据,同时完全保持封装。
https://softwareengineering.stackexchange.com/questions/411265
复制相似问题