如何创建“真正可扩展的”应用程序班级

发布于 2024-08-23 11:04:56 字数 458 浏览 8 评论 0原文

我读过很多关于开发类的文章(我使用的是 php),其标签行是: “可扩展、稳健、可维护和可扩展”。

但作为一个初学者,我一直在创建用我的话来说“只是抽象的”类。这意味着我只是将一堆或重复的代码分开,并将它们放入一个类中,并提供用于访问常见任务的方法。

问题是,我找不到一种方法来使我的类可扩展(我知道抽象类等概念,我什至正在使用它们,但只是为了定义我的其他类将遵循的方法)。问题是,我总是发现自己编辑核心类只是为了添加功能

关于使我的课程可扩展有什么建议吗? (我用谷歌搜索过这个,弹出的所有内容都是对抽象类、接口和 OOP 的解释,没有关于指针的讨论或一些创建可扩展类的技巧)。

哦,顺便说一句,对我放轻松,我九个月前就开始了“实际的”oop 编程(我所在的大学让我继续进行 OOP 理论,但他们让我们按照程序进行工作,因为它更快,而且可以满足该死的项目截止日期,这种情况持续了四年,直到我毕业)。

I have read a lot of articles on developing classes (I am using php), with the tag lines :
'scalable, robust, maintainable and extensible'.

But as a beginner, I have been creating classes that are, in my words, "just abstracted". Meaning I just separated a bunch or repetitive codes and put them in a class and provide methods for accessing common tasks.

The thing is, I can't find a way to make my class extensible (I know the concept of abstract classes and such, I am even using them, but just to define methods that my other classes will follow). The thing is, I always find myself editing the core class just to add functionlities.

Any tips on making my class extensible? (I have googled on this and everything that pops out are explanations of abstract classes, interfaces and OOP, no discussions on pointers or some tips for making extensible classses).

Oh, btw, go easy on me, I have started "actual" oop programming 9 mos ago (the university I'm from had me going on theories on OOP, but they had us working PROCEDURALLY, because it's faster and it meets damn project deadlines, and that went on for 4 years until I graduated).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

盗琴音 2024-08-30 11:04:56

你应该看看这本书设计模式:可重用面向对象软件的元素

正如您所发现的,可扩展类正在将系统分解为有用且可重用的对象。

这项任务很困难,因为有很多因素在起作用:封装、粒度、依赖性、灵活性、性能、演进、可重用性等等。

您是否正在尝试对某些现实世界场景进行建模,或者您是否专注于应用程序内部的通信/协作和依赖关系?

这是一个我认为可以说明您正在寻找的内容的示例。当然还有更多、更好的例子:

我想开发一个缓存系统,为我的开发人员提供一个简单、规范化的 API,无论他们在哪里缓存什么内容。我在缓存系统中想要什么(在基础层面)?

  • 我希望能够缓存某些东西(设置)
  • 我希望能够检索某些东西(获取)
  • 我希望能够使缓存无效(删除)

我想出了这个:

abstract class MyNs_Cache
{
    abstract public function Set($key, $data, $ttl);
    abstract public function Get($key);
    abstract public function Delete($key, $ttl);
}

这是我的可扩展基类。然后我得到了三个缓存类 MyNs_Cache_FsMyNs_Cache_ApcMyNs_Cache_Memcache

class MyNs_Cache_Fs
{
     ...

    public function Set($key, $data, $ttl)
    {
        // here I use fopen/fwrite/etc. to create the cached data
    }

    public function Get($key)
    {
        // here I retrieve the file from the filesystem (if it exists)
    }

    public function Delete($key) { ... }
 }

这相当简单。它以文件系统的形式实现缓存。它不提供任何超出我原来的课程的内容。

class MyNs_Cache_Apc
{
    ...

    public function Set($key, $data, $ttl)
    {
        return apc_add($key, $data, $ttl); // NOT A FILESYSTEM CALL
    }

    public function Get($key) { ... } // you get the idea.

    // This is specific to APC, so I add the functionality HERE
    // NOT in my main Caching class.
    public function PurgeCache()
    {
        return apc_clear_cache();
    }
}

我的 APC 缓存可以在缓存系统中执行我想要的所有操作(设置/获取/删除),但它还提供清除整个缓存的功能(这对我的文件系统缓存没有用处,并且对于 memcached 来说是不可能的)

class MyNs_Cache_Memcache
{
    // Memcached needs a pool of servers. APC and filesystem don't.
    private $servers = array(..);

    // It also uses a memcached object.
    private $conn;

    public function __construct()
    {
        $this->conn = new Memcached;

        foreach ($this->$servers as $server)
            $this->AddServer($server);
    }
    ...  // we do all the standard stuff using memcached methods

    // We also want to be able to manage our connection pool
    public function AddServer($server)
    {
        $this->conn->addServer(...);
    }

    // And in some cases, we use inc/dec from memcached
    // APC doesn't have this, and it makes little sense in a filesystem
    public function Increment($key) { ... }
}

现在我知道我总是可以获取我的缓存对象之一,然后使用 $obj->Get('some_key') ,我总会得到结果。

同样,我还可以访问特定于我当前正在尝试使用的功能。

You should check out the book Design Patterns: Elements of Reusable Object-Oriented Software

The problem with making extensible classes, as you've discovered, is decomposing the system into useful and reusable objects.

The task is difficult because many factors come into play: encapsulation, granularity, dependency, flexibility, performance, evolution, reusability, and on and on.

Are you trying to model some real world scenario, or are you focusing on communication / collaboration and dependencies inside your application?

Here's an example that I think kinda demonstrates what you are looking for. There are certainly a far more, far better examples:

I wanted to develop a caching system that offered my developers a simple, normalized API no matter what / where they were caching something. What do I want in a caching system (at the basic level)?

  • I want to be able to cache something (set)
  • I want to be able to retrieve that something (get)
  • I want to be able to invalidate the cache (delete)

I came up with this:

abstract class MyNs_Cache
{
    abstract public function Set($key, $data, $ttl);
    abstract public function Get($key);
    abstract public function Delete($key, $ttl);
}

There's my extensible base class. I've then got three caching classes MyNs_Cache_Fs, MyNs_Cache_Apc and MyNs_Cache_Memcache

class MyNs_Cache_Fs
{
     ...

    public function Set($key, $data, $ttl)
    {
        // here I use fopen/fwrite/etc. to create the cached data
    }

    public function Get($key)
    {
        // here I retrieve the file from the filesystem (if it exists)
    }

    public function Delete($key) { ... }
 }

That's fairly straight forward. It implements the cache in terms of a FileSystem. It doesn't offer anything past my original class.

class MyNs_Cache_Apc
{
    ...

    public function Set($key, $data, $ttl)
    {
        return apc_add($key, $data, $ttl); // NOT A FILESYSTEM CALL
    }

    public function Get($key) { ... } // you get the idea.

    // This is specific to APC, so I add the functionality HERE
    // NOT in my main Caching class.
    public function PurgeCache()
    {
        return apc_clear_cache();
    }
}

My APC cache does everything I want in a caching system (set/get/delete) but it also offers the ability to clear the entire cache (something that's not useful for my FileSystem cache and impossible with memcached)

class MyNs_Cache_Memcache
{
    // Memcached needs a pool of servers. APC and filesystem don't.
    private $servers = array(..);

    // It also uses a memcached object.
    private $conn;

    public function __construct()
    {
        $this->conn = new Memcached;

        foreach ($this->$servers as $server)
            $this->AddServer($server);
    }
    ...  // we do all the standard stuff using memcached methods

    // We also want to be able to manage our connection pool
    public function AddServer($server)
    {
        $this->conn->addServer(...);
    }

    // And in some cases, we use inc/dec from memcached
    // APC doesn't have this, and it makes little sense in a filesystem
    public function Increment($key) { ... }
}

Now I know that I can always get one of my cache objects and just in with $obj->Get('some_key') and I'll always get a result.

Likewise, I also have access to functionality specific to what I'm currently trying to work with.

守护在此方 2024-08-30 11:04:56

您不需要编辑核心类来添加功能,您可以覆盖子类中的方法,例如:

class A {
 public function filter_string($str){
  return str_replace ('foo', 'bar', $str);
 }
}

class B extends A {
 public function filter_string($str){
  return str_replace ('machin', 'chose', parent::filter_string ($str));
 }
}

$a = new A;
echo $a->filter_string('foo machin'); // echoes 'bar machin'

$b = new B;
echo $b->filter_string('foo machin'); // echoes 'bar chose'

You don't need to edit your core class to add functionality you can overwrite a method in a child class, eg:

class A {
 public function filter_string($str){
  return str_replace ('foo', 'bar', $str);
 }
}

class B extends A {
 public function filter_string($str){
  return str_replace ('machin', 'chose', parent::filter_string ($str));
 }
}

$a = new A;
echo $a->filter_string('foo machin'); // echoes 'bar machin'

$b = new B;
echo $b->filter_string('foo machin'); // echoes 'bar chose'
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文