How to encapsulate private fields that apply to only a few methods

I am working on modeling a business domain object in a class and wondering what would be the best way to properly encapsulate private fields that apply only to a few methods.

When I started, my code initially looked like this:

public class DiscountEngine { public Cart As Cart { get; set;} public Discount As Discount { get; set;} public void ApplySKUGroupDiscountToCart() { ... } } 

However, ApplySKUGroupDiscountToCart() starting to get ugly, so I decided to refactor the code into smaller private methods that are called from ApplySKUGroupDiscountToCart() . I started by passing a large number of local variables to a helper method, but then decided to pull out the variables common to both routines and make them private modular variables. The new code is as follows:

 public class DiscountEngine { public Cart As Cart { get; set;} public Discount As Discount { get; set;} private int _SKUGroupItemDiscountsApplied = 0 private int _SKUGroupTotalDiscounts = 0 private int _SKUGroupID = 0 public void ApplySKUGroupDiscountToCart() { ... } private void ApplyDiscountToSingleCartItem(ref CartItem cartI, ref DiscountItem discountI) { ... } } 

On the one hand, three private integer fields are useful for allowing related methods to use shared variables without having to pass them back and forth as parameters. However, these variables only apply to these related methods, and any other methods that I could add should not be visible to them.

Is there a way to encapsulate private fields and their associated methods while remaining part of the DiscountEngine class? Is there a better way to solve this problem?

+4
source share
5 answers

Usually creating a private class field implies "I have enough discipline to ensure that this field is used only appropriately inside this class." If your class is too large for you to say with certainty, then perhaps the class is trying to do too many different things and needs to be separated (see SRP ).

In any case, enough theory :-). If you want to stick to one class, you can always encapsulate these three fields in a private nested class, for example.

 public class DiscountEngine { public Cart As Cart { get; set;} public Discount As Discount { get; set;} private class SKUGroup { public int ItemDiscountsApplied = 0 public int TotalDiscounts = 0 public int ID = 0 } public void ApplySKUGroupDiscountToCart() { ... } private void ApplyDiscountToSingleCartItem(ref CartItem cartI, ref DiscountItem discountI) { ... } } 

This gives you a little more opportunity to pass class instances around your code as method parameters.

You can do this even further and transfer any private methods that also affect SKU data to a nested class.

+6
source

First, you most likely do not need to pass the ApplyDiscountToSingleCartItem parameters as ref . Short version: if you are not actually assigning a value to the variable that you want to see in the calling code, you do not need ref . Changing the values ​​of variables and properties on them will be visible to the calling code without passing them as ref .

Secondly, there is no way to encompass a variable between an instance and a local that you ask. The only way to achieve this is to reorganize this functionality into another class (probably a nested private class).

However, do not use instance variables as a way to transfer data between functions. If after a function call the data becomes "obsolete", then this should be a parameter, not an instance variable.

+2
source

I would say that the only way I can handle it is to extract all the methods and private variables associated with them into a separate class. This way you store everything that is encapsulated. But not sure if this will make sense in the context of your domain objects.

+1
source

You can always create a nested (inner) class to combine together parameters that have a common use. Thus, you can still pass them to your private methods without passing l.ots arguments - you just pass the private type instance.

+1
source

"these variables apply only to these related methods, and any other methods that I could add would not have to see them."

First of all, keep in mind that one of the first rules for developing an OO is to create what the client wants. THEN applies the OO design as the basic rules and patterns of OO. Your quote comes down to the fact that you want to plan the unknown. Be careful that unknowns are β€œmore alike,” not new requirements. Otherwise, this class will eventually become the Object of God.

If you find that you have many members that are not used by these methods, divide them and win.

0
source

Source: https://habr.com/ru/post/1314466/


All Articles