解决  如何创建具有太多方法的文件的抽象

帕沙

知名会员
已加入
2020年4月29日
留言内容
64
编程经验
1-3
大家好,

我有一个文件是通用方法,并且在一个类文件中有太多方法,现在我想创建层次结构,以便可以借助抽象将其进一步划分,我尝试了很少的事情,但是后来我对如何访问不同的方法?

主要通用方法文件,其中包含许多方法:
using Base;
using Constants;
using Entities;
using Extensions;
using SeleniumExtensions;
using  救命 ers;
using Model;
using AtlasNav;
using Model.PaymentOptions;
using Pages.DesignPages.DesignViews;
using Pages.UserAccount_Pages;
using Repositories;
using Pages;
using Pages.CheckoutPages;
using Pages.CMSPages;
using Pages.KlarnaCheckoutPages;
using Pages.SellerStorePages;
using Framework.DataAccessLayer.EntitiyFramework.Repositories;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using TestConfigurationCDO = Config.TestConfigurationCDO;

namespace ManualRegressionSuite.CommonMethods
{   public class CommonMethods : Base
    {
        public TestConfigurationCDO _testConfiguration;
        WebDriverWait wait;
        public IList<Site> _sites;
        public string _bolUkSiteUrl;
        public string _cmsSiteUrl;
        public Site _site;

        public CommonMethods(SharedParameters test_properties)
        {
            this.shared_parameters = test_properties;
            this.Driver = test_properties.Driver;
            this._testConfiguration = test_properties.testConfiguration;
            this._sites = test_properties.sites;
            this._bolUkSiteUrl = test_properties.SiteBag.domain_url;
            this._cmsSiteUrl = test_properties.SiteBag.cms_url;
            this._site = test_properties.site;
        }
        /// <summary>
        ///
        /// </summary>
        public void CommonMethod_SellerLogIn()
        {
            var site = shared_parameters.site.GetName();

            var homePage = GetInstance<HomePage>();
            homePage.To_SignInPage(site);

            var signInPage = GetInstance<SignInPage>();
            signInPage.To_SellerLandingPage();
        }
        /// <summary>
        /// Below method will navigate to Product Page through Atlas Navigation
        /// </summary>
        /// <param name="productId"></param>
        public void CommonMetho_GoToProductPage(int productId)
        {
            var homePage = GetInstance<HomePage>();
            homePage.To_ProductPage(productId);
        }
        /// <summary>
        /// Below method will:
        ///
        /// </summary>
        /// <param name="param"></param>
        public void CommonMethod_DesignProduct(WorkflowParameters param)
        {
            var generalProductPage = GetInstance<MasterProductPage>();
            generalProductPage.To_DesignPage();

            var designPage = GetInstance<DesignPage, DesignPageArgs>(new DesignPageArgs());
            designPage.basketToolbarView.UpdateProductQuantity(param.quantity.ToString());
            
            designPage.Design(param.designMethod);
        }
        /// <summary>
        /// Below method will Add product to Basket
        /// </summary>
        public void CommonMethod_AddToBasket()
        {
            var designPage = GetInstance<DesignPage, DesignPageArgs>(new DesignPageArgs());
            designPage.AddToCart();
        }
        /// <summary>
        /// Below method will review the basket item:
        /// </summary>
        /// <param name="productId"></param>
        public void CommonMethod_BasketReview(int productId)
        {
            var basketPage = GetInstance<BasketPage, BasketPageArgs>(new BasketPageArgs());

            var check = basketPage.BasketPriceView.CheckBasketPrice();
            Assert.IsTrue(check);

            var isPresent = basketPage.BasketItemsView.Validate_ItemIsInBasket(productId);
            Assert.IsTrue(isPresent);

            Assert.IsTrue(!ImageHelpers.IsEmpty(basketPage.BasketItemsView.GetItemImage(productId)));
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public string CommonMethod_PurchaseItem(WorkflowParameters param)
        {
            var basketPage = GetInstance<BasketPage, BasketPageArgs>(new BasketPageArgs());

            basketPage.To_CheckoutPage(param.paymentOptions.portal);

            var checkoutPage = GetInstance<CheckoutPage>();
            checkoutPage.To_OrderSummaryPage(param.paymentOptions);
            
            var orderConfirmPage = GetInstance<OrderConfirmPage>();
            var _order = orderConfirmPage.To_Self_CheckOrderDatabase();

            return _order.OrderId.ToString(); ;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="OrderId"></param>
        public void CommonMethod_CMSVerification(string OrderId)
        {
            var cmsLoginPage = GetInstance<CMSLoginPage>();
            cmsLoginPage.To_CMSLandingPage();

            var cmsLandingPage = GetInstance<CMSLandingPage>();
            cmsLandingPage.To_OrderPage_OrderCheck(OrderId);

            var cmsOrderPage = GetInstance<CMSOrderPage>();
            cmsOrderPage.orderDetailsView.To_Self_CheckPrices(shared_parameters.price);
            
            var check = cmsOrderPage.orderDetailsView.IsOrderAuthorised(OrderId.ToInt());
            Assert.IsTrue(check);
        }
        /// <summary>
        ///
        /// </summary>
        public void CommonMethod_CMSDespatchNoteVerification()
        {
            var cmsOrderPage = GetInstance<CMSOrderPage>();
            cmsOrderPage.ChangeStatus_ByDropDown(OrderStatus.Dispatched);

            cmsOrderPage.deliveryDetailsView.Check_DespatchNote();
        }
        /// <summary>
        ///
        /// </summary>
        public void CommonMethod_CreateStore()
        {
            var sellerLandingPage = GetInstance<SellerLandingPage>();
            sellerLandingPage.To_SellerMyStoresPage();

            var sellerMyStoresPage = GetInstance<SellerMyStoresPage>();
            var uniqueName = sellerMyStoresPage.To_Self_CreateStore();
        }
        /// <summary>
        ///
        /// </summary>
        public void CommonMethod_NavigateToMyProductsPage()
        {

        }
        /// <summary>
        ///
        /// </summary>
        public void CommonMethod_CreateProduct()
        {

        }
        /// <summary>
        ///
        /// </summary>
        public void CommonMethod_AddProductToStore()
        {

        }
    }
    public class WorkflowParameters
    {
        public int productId = default(int);
        public int orderId = default(int);
        public DesignMethod designMethod = default(DesignMethod);
        public bool signedIn = default(bool);
        public bool increaseBasketQty = default(bool);
        public bool signedInCMS = default(bool);
        public bool editable = default(bool);
        public Site _site = default(Site);
        public PaymentOptions paymentOptions = default(PaymentOptions);
        public bool checkOrderAuthorise = default(bool);
        public int quantity = default(int);
    }
}


现在,我要创建层次结构,以便主文件通用方法将具有方法的定义,并且将有2个单独的类文件,其中一个用于CMS通用方法,一个用于WebSite通用方法。


CMSCommonMethod文件:
using Base;
using Constants;
using Extensions;
using Pages.CMSPages;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ManualRegressionSuite.CommonMethods
{
    public class CMSCommonMethods : Base
    {
        /// <summary>
        ///
        /// </summary>
        /// <param name="OrderId"></param>
        public void CommonMethod_CMSVerification(string OrderId)
        {
            var cmsLoginPage = GetInstance<CMSLoginPage>();
            cmsLoginPage.To_CMSLandingPage();

            var cmsLandingPage = GetInstance<CMSLandingPage>();
            cmsLandingPage.To_OrderPage_OrderCheck(OrderId);

            var cmsOrderPage = GetInstance<CMSOrderPage>();
            cmsOrderPage.orderDetailsView.To_Self_CheckPrices(shared_parameters.price);

            var check = cmsOrderPage.orderDetailsView.IsOrderAuthorised(OrderId.ToInt());
            Assert.IsTrue(check);
        }
        /// <summary>
        ///
        /// </summary>
        public void CommonMethod_CMSDespatchNoteVerification()
        {
            var cmsOrderPage = GetInstance<CMSOrderPage>();
            cmsOrderPage.ChangeStatus_ByDropDown(OrderStatus.Dispatched);

            cmsOrderPage.deliveryDetailsView.Check_DespatchNote();
        }
    }
}

WebSiteCommonMethod:
using Base;
using Entities;
using  救命 ers;
using Pages;
using Pages.CheckoutPages;
using Pages.SellerStorePages;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ManualRegressionSuite.CommonMethods
{
    public class WebSiteCommonMethods:Base
    {
        /// <summary>
        ///
        /// </summary>
        public void CommonMethod_SellerLogIn()
        {
            var site = shared_parameters.site.GetName();

            var homePage = GetInstance<HomePage>();
            homePage.To_SignInPage(site);

            var signInPage = GetInstance<SignInPage>();
            signInPage.To_SellerLandingPage();
        }
        /// <summary>
        /// Below method will navigate to Product Page through Atlas Navigation
        /// </summary>
        /// <param name="productId"></param>
        public void CommonMetho_GoToProductPage(int productId)
        {
            var homePage = GetInstance<HomePage>();
            homePage.To_ProductPage(productId);
        }
        /// <summary>
        /// Below method will:
        ///
        /// </summary>
        /// <param name="param"></param>
        public void CommonMethod_DesignProduct(WorkflowParameters param)
        {
            var generalProductPage = GetInstance<MasterProductPage>();
            generalProductPage.To_DesignPage();

            var designPage = GetInstance<DesignPage, DesignPageArgs>(new DesignPageArgs());
            designPage.basketToolbarView.UpdateProductQuantity(param.quantity.ToString());

            designPage.Design(param.designMethod);
        }
        /// <summary>
        /// Below method will Add product to Basket
        /// </summary>
        public void CommonMethod_AddToBasket()
        {
            var designPage = GetInstance<DesignPage, DesignPageArgs>(new DesignPageArgs());
            designPage.AddToCart();
        }
        /// <summary>
        /// Below method will review the basket item:
        /// </summary>
        /// <param name="productId"></param>
        public void CommonMethod_BasketReview(int productId)
        {
            var basketPage = GetInstance<BasketPage, BasketPageArgs>(new BasketPageArgs());

            var check = basketPage.BasketPriceView.CheckBasketPrice();
            Assert.IsTrue(check);

            var isPresent = basketPage.BasketItemsView.Validate_ItemIsInBasket(productId);
            Assert.IsTrue(isPresent);

            Assert.IsTrue(!ImageHelpers.IsEmpty(basketPage.BasketItemsView.GetItemImage(productId)));
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public string CommonMethod_PurchaseItem(WorkflowParameters param)
        {
            var basketPage = GetInstance<BasketPage, BasketPageArgs>(new BasketPageArgs());

            basketPage.To_CheckoutPage(param.paymentOptions.portal);

            var checkoutPage = GetInstance<CheckoutPage>();
            checkoutPage.To_OrderSummaryPage(param.paymentOptions);

            var orderConfirmPage = GetInstance<OrderConfirmPage>();
            var _order = orderConfirmPage.To_Self_CheckOrderDatabase();

            return _order.OrderId.ToString(); ;
        }

        /// <summary>
        ///
        /// </summary>
        public void CommonMethod_CreateStore()
        {
            var sellerLandingPage = GetInstance<SellerLandingPage>();
            sellerLandingPage.To_SellerMyStoresPage();

            var sellerMyStoresPage = GetInstance<SellerMyStoresPage>();
            var uniqueName = sellerMyStoresPage.To_Self_CreateStore();
        }
        /// <summary>
        ///
        /// </summary>
        public void CommonMethod_NavigateToMyProductsPage()
        {
  
        }
        /// <summary>
        ///
        /// </summary>
        public void CommonMethod_CreateProduct()
        {

        }
        /// <summary>
        ///
        /// </summary>
        public void CommonMethod_AddProductToStore()
        {

        }
    }
}

我不确定这是什么合适的体系结构,以便将来如果我们要扩展,不会有任何问题
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,497
地点
弗吉尼亚州切萨皮克
编程经验
10+
您确定甚至需要层次结构还是适当的层次结构?查看您的代码块#2和#3,我看不到任何东西在它们两个之间共享时会跳出来,因此是您的子类将要实现的接口定义或抽象方法的良好候选者。

回想过去,在人们还不太了解面向对象编程的糟糕年代,继承主要被认为是一种代码共享和数据共享机制,可以最大程度地减少重复代码的数量。那就是你会有这样的事情:
C#:
class Base
{
    // public methods common to Foo  和  Bar
    // protected methods that would be used by both Foo  和  Bar
}

class Foo : Base
{
    // public methods specific to Foo (and may call protected methods on Base)
}

class Bar : Base
{
    // public methods specific to Bar (and may call protected methods on Base)
}
人们了解到,这将导致脆弱的层次结构(特别是在C ++中,如果您触摸了较低级别的类,即使您未触摸任何函数签名,也必须重新编译世界),这是人们进行面向对象编程的主要抱怨之一。

人们开始了解到继承应该主要用于SOLID(Liskov的替换原理)中的L,并且仅当星号对齐时才用于代码共享。这会将上面的内容更改为:
C#:
abstract class Base
{
    // public abstract methods common Foo  和  Bar must expose
    // public methods common to Foo  和  Bar  和  needs no specialization
    // protected methods that would be used by both Foo  和  Bar
}

class Foo : Base
{
    // implementation of abstract methods that Foo  和  Bar must expose with specializaton for Foo
    // public methods specific to Foo (and may call protected methods on Base)
}

class Bar : Base
{
    // implementation of abstract methods that Foo  和  Bar must expose with specializaton for Bar
    // public methods specific to Bar (and may call protected methods on Base)
}

里斯科夫的替代原则所强调的是 接口 用于与对象交谈的对象。如果您使用Autofac或其他IoC系统,则主要是要与接口进行通信,然后实现它们的类将成为偶然事件,因此最终得到:
C#:
 接口  IFooBar
{
    // methods common to Foo  和  Bar
}

interface IFoo : IFooBar
{
    // methods specific to Foo
}

interface IBar : IFooBar
{
    // methods specific to Bar
}

class Foo : IFoo
{
    // implement IFooBar
    // implement IFoo
}

class Bar : IBar
{
    // implement IFooBar
    // implement IBar
}

Yikes, but now we have duplicate the code between FooBar. And so that will lead to either:
C#:
static class FooBarHelpers
{
    // common method implementation between Foo  和  Bar 
}

class Foo : IFoo
{
    // implement IFooBar by call FooBarHelpers
    // implement IFoo
}

class Bar : IBar
{
    // implement IFooBar by call FooBarHelpers
    // implement IFoo
}

或类似于以前的抽象基类,但添加了接口:

C#:
abstract class Base : IFooBar
{
    // public abstract methods common Foo  和  Bar must expose
    // public methods common to Foo  和  Bar  和  needs no specialization
    // protected methods that would be used by both Foo  和  Bar
}

class Foo : Base, IFoo
{
    // implementation of abstract methods that Foo  和  Bar must expose with specializaton for Foo
    // public methods specific to Foo (and may call protected methods on Base)
}

class Bar : Base, IBar
{
    // implementation of abstract methods that Foo  和  Bar must expose with specializaton for Bar
    // public methods specific to Bar (and may call protected methods on Base)
}

(还有使用 默认接口方法,但是恕我直言,当您已经将界面发布到广阔的世界时,应该真正使用它。当您仍在私人内部工作时,请正确设置接口,不要将其用作拐杖。)

顺便说一句,摆脱 蓝精灵命名约定. You already have the class named CommonMethods. There is no need to name each method in the class CommonMethod_foo.
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,497
地点
弗吉尼亚州切萨皮克
编程经验
10+
局部类不是设计模式。它只是让您将事物组织成多个文件而不是一个巨型文件,或者让您将一些手写代码与一些生成的代码结合在一起。
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,497
地点
弗吉尼亚州切萨皮克
编程经验
10+
现在我没有发烧100.7度,现在我想想起来更清楚一点:另一种方法是使用Command设计模式。而不是将相关的方法放在一个类中,而是每个类只有一个Execute()方法。每个类代表一个操作。共享通用代码的所有相关操作都可以从通用基类派生。
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,497
地点
弗吉尼亚州切萨皮克
编程经验
10+
@谢平 使我转到了这个出色的网站,该网站提供了有关“设计模式”的精美插图和说明,并且比过去的GoF书和我过去发现的其他一些网站都方便得多。


在本文中,重点是使用命令模式来隔离和封装需要执行的操作。这是一种行为模式,但看起来您正在寻找结构化模式以保持代码更有条理。
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,923
地点
英国
编程经验
10+
Thank you @跳伞 在您的帮助下,一个疑问是使用部分类设计模式而不是抽象设计好吗?
这是一个很好的问题,但实际上归结为您正在运行的是哪种类型的应用程序,对我来说,最终,您想要实现的目标通常决定了我的开发模式。这也是一个可能持续数小时的讨论,因为有太多上下文可以添加到该主题中。开始了解不同模式的好地方是阅读上述Skydiver共享的链接。如果我记得那是我设计他时给他的链接 布莱克 加密项目?有一天,我将复制该站点上的所有信息,并将其放到我自己的网站上,以免丢失!
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,497
地点
弗吉尼亚州切萨皮克
编程经验
10+
从OP的经验来看,他不是在尝试编写应用程序,而是试图弄清楚如何组织单元测试。
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,923
地点
英国
编程经验
10+
与其说我最近没有经常犯错误,不如说是我有意义地提出了自己的观点。在任何方面,相同的建议都是有效的。如果OP进入学习模式,那么我建议除了给定的链接外没有其他链接。  :)
 

帕沙

知名会员
已加入
2020年4月29日
留言内容
64
编程经验
1-3
@谢平 使我转到了这个出色的网站,该网站提供了有关“设计模式”的精美插图和说明,并且比过去的GoF书和我过去发现的其他一些网站都方便得多。


在本文中,重点是使用命令模式来隔离和封装需要执行的操作。这是一种行为模式,但看起来您正在寻找结构化模式以保持代码更有条理。
哦,我的上帝!!!这是一个了不起的网站!
 

帕沙

知名会员
已加入
2020年4月29日
留言内容
64
编程经验
1-3
@谢平 使我转到了这个出色的网站,该网站提供了有关“设计模式”的精美插图和说明,并且比过去的GoF书和我过去发现的其他一些网站都方便得多。


在本文中,重点是使用命令模式来隔离和封装需要执行的操作。这是一种行为模式,但看起来您正在寻找结构化模式以保持代码更有条理。
是的,我对如何组织上述课程感到困惑
 

帕沙

知名会员
已加入
2020年4月29日
留言内容
64
编程经验
1-3
@跳伞 , @谢平 -我经历了许多模式,但是尽管部分类不是一种模式,但是如果我现在必须组织它,那么该类可以使用吗? -尽管在部分课程中,我也不太了解适当的实现方式-真的很想听听您对此的看法
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,497
地点
弗吉尼亚州切萨皮克
编程经验
10+
很高兴您喜欢这个网站。正如我所说的,这是我的虚拟双胞胎 @谢平 谁使我对它感兴趣。 (我试图向他描述复合模式,并计划以行为方式使用它来完成一些并行处理,而不是通常使用该结构的结构方式,他将我链接到该站点。)

我只有Twitter。我会勉强为我的父母开立FB帐户,以将其关闭。

是的,将代码拆分为多个文件是一种跨多种语言的古老做法,我认为可能没有名称。在C#中,它恰好利用了部分类,因为它没有C / C ++ #include的等效项。
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,923
地点
英国
编程经验
10+
局部类不是设计模式或类。一种提供其他文件使用权的类型;因此,单词partial: 部分类型-C#参考 参见这里的例子: C#中的局部类-GeeksforGeeks.

除此之外,这是一篇旧文章,有时我会把人们关于放屁的事情联系在一起。诚然,单元测试不是我花很多时间做的事情。仍然是一本好书: 设计模式如何帮助您开发支持单元测试的应用程序

但是,如果您想要特定于单元测试的内容或任何类型的测试模式,我强烈建议您阅读:Marc Clifton在这里的文章: 高级单元测试,第五部分-单元测试模式
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,923
地点
英国
编程经验
10+
我认为可能没有名字。在C#中
是不是 几乎 就像嘲笑一样?
我计划以行为方式使用它来完成一些并行处理,而不是通常使用模式的结构方式
嗯,是的,我回想起我现在如何给您该链接。它包含一个模式,我建议您在选择的模式上使用。收到链接后,如果我记得您从这些页面中找到了更合适的模式。该模式就是您转储到Blake3项目中的模式。

自从成为 @跳伞 是所有模式开发查找的goto网站。不过,有时我也会挖矿,让我想起它们!这是一种未充分利用的资源,我希望更多的人会花些时间为书签和通读。
 
最佳 底部