1
\$\begingroup\$

I have a simple class which holds my product. Someone can add a serial to this product and also a purchase id. On change of the properties, I want to check whether both properties are set, and get the license class and add it to the product.

public class License
{
    public bool IsTrial { get; set; }

    public bool IsValid { get; set; }

    public string Type { get; set; }

    public License()
    {

    }

    public License(string purchaseId, string serial)
    {
        this.IsTrial = true;
        this.IsValid = true;
        this.Type = "Enterprise";
    }

Example License class

public class Product
{
    private License _license;
    public License license
    {
        get
        {
            return _license;
        }
        set
        {
            _license = value;
        }
    }

    public string Name { get; set; }

    private string _purchaseId;
    public string PurchaseId {
        get
        {
            return _purchaseId;
        }
        set
        {
            _purchaseId = value;
            GetLicense();
        }
    }

    private string _serial;
    public string Serial
    {
        get
        {
            return _serial;
        }
        set
        {
            _serial = value;
            GetLicense();
        }
    }

    private void GetLicense()
    {
        if (!string.IsNullOrEmpty(this.Serial) && !string.IsNullOrEmpty(this.PurchaseId))
        { 
            License lice = new License(serial, PurchaseId);
            this.License = lice;
        }
    }

That's the approach I used. Is this a correct way to do it? How is this called and what is the best practice? I need to use .NET Framework 3.5.

\$\endgroup\$
4
  • 2
    \$\begingroup\$ Because this isn't real code, it's really hard to figure out what you're doing and why. If you need to obfuscate your code, try to come up with a meaningful solution that mirrors the behaviour you're talking about in a realistic way. For example this, assign a to b is unlikely to occur in your real solution in such an abstract way: this.ClassB = a \$\endgroup\$
    – forsvarir
    Commented Jul 1, 2016 at 18:38
  • 2
    \$\begingroup\$ "Lets assume that we have a simple class with multiple properties" -> Close vote - hypothetical code. Here at Code Review we prefer concrete working code, not hypothetical examples, as there is no definitive answer for hypotheticals. \$\endgroup\$
    – Pimgd
    Commented Jul 1, 2016 at 18:47
  • \$\begingroup\$ I have changed it. But i have currently no final code, i am only working on a concept. \$\endgroup\$
    – STORM
    Commented Jul 1, 2016 at 18:52
  • \$\begingroup\$ I looks much better now then the I-have-no-idea-how-to-program code before ;-) \$\endgroup\$
    – t3chb0t
    Commented Jul 1, 2016 at 18:56

3 Answers 3

1
\$\begingroup\$

Getters & Setters + Validation

I think it's better to validate the serial and the purchase-id in their setters instead in the GetLicense method that actually could be a readonly-property.

private void GetLicense()
{
    if (!string.IsNullOrEmpty(this.Serial) && !string.IsNullOrEmpty(this.PurchaseId))
    { 
        License lice = new License(serial, PurchaseId);
        this.License = lice;
    }
}

After this tiny refactorings the result is:

public class Product
{
    // it's prettier if you group private fields togehter at the top
    private string _purchaseId;
    private string _serial;   

    public string Name { get; set; }

    public string PurchaseId
    {
        get { return _purchaseId; }
        set
        {
            if (string.IsNullOrEmpty(value)) 
                throw new ArgumentNullException(nameof(PurchaseId));
            _purchaseId = value;
        }
    }


    public string Serial
    {
        get { return _serial; }
        set
        {
            if (string.IsNullOrEmpty(value)) 
                throw new ArgumentNullException(nameof(Serial));
            _serial = value;
        }
    }   

    public License License
    {
        get { new License(Serial, PurchaseId); }
    }
}

Magic Strings

this.Type = "Enterprise";

You should create a const/readonly string for the "Enterprise" and name it for example DefaultLicenseType


Bug

There is a bug. The license constructor expects purchaseId + serial and you create a license with a serial + purchase id

Constructor signature:

public License(string purchaseId, string serial)

License creation:

new License(serial, PurchaseId);
\$\endgroup\$
5
  • \$\begingroup\$ This may be confusing to the user asking the question, it may be wise to change the name of the variable - public License License{} \$\endgroup\$
    – Tolani
    Commented Jul 3, 2016 at 1:43
  • \$\begingroup\$ @TolaniJaiye-Tikolo well, the property returns an object of the type License so it's I think it's perfectly fine to name the property License as well as it gets a license. What would you do in this case? \$\endgroup\$
    – t3chb0t
    Commented Jul 3, 2016 at 7:11
  • \$\begingroup\$ Yes that's right but good practice requires class names and variable names should be different from each other. The user needs to learn this good practice. \$\endgroup\$
    – Tolani
    Commented Jul 3, 2016 at 8:25
  • \$\begingroup\$ @TolaniJaiye-Tikolo not quite. Class names and namespace names should be different but I've never ever heard about different variable and class names besides this is a property name and not a variable. If this is a good practice then please give an example how to name it correctly. \$\endgroup\$
    – t3chb0t
    Commented Jul 3, 2016 at 8:45
  • 1
    \$\begingroup\$ Although there are controversies around having a class and a property having the same name stackoverflow.com/questions/1095644/…. IMHO I would rather not have it based on the confusion. But others in the forum see it as a good idea . For now I will take back my words ^.^ \$\endgroup\$
    – Tolani
    Commented Jul 3, 2016 at 9:12
1
\$\begingroup\$

The constructor of License takes two arguments that are never used:

public License(string purchaseId, string serial) // makes no sense
{
    this.IsTrial = true;
    this.IsValid = true;
    this.Type = "Enterprise";
}

The method private void GetLicense() is pointless, because any check it performs on the state of the Product object (namely the properties of its _license property) can easily circumvented by setting an arbitrary value via the public setter License:

public License license
{
    get
    {
        return _license;
    }
    set
    {
        _license = value; // where value = new License("warez", "crew 1337");
    }
}
\$\endgroup\$
0
1
\$\begingroup\$

Sorry, am late to the party. As it was already pointed, Some properties were not used including the Name property. You are also breaking one of the SOLID principles - Single Responsibility. Each class should be responsible for one action - your product class should not be responsible for getLicense as the License class should be responsible for that.

Validation is the key here as @t3chb0t specified. Although, there may not be any need for the getLicense in this case but be mindful of your naming conventions. In java, you have get and set methods ; set has a return type void in most cases and get has a return type that is not void. This is quite similar to properties in C#(get and set)

 private void GetLicense()
    {
        if (!string.IsNullOrEmpty(this.Serial) && !string.IsNullOrEmpty(this.PurchaseId))
        { 
            License lice = new License(serial, PurchaseId);
            this.License = lice;
        }
    }

should have been

  private void SetLicense()
    {
        if (!string.IsNullOrEmpty(this.Serial) && !string.IsNullOrEmpty(this.PurchaseId))
        { 
            License lice = new License(serial, PurchaseId);
            this.License = lice;
        }
    }

Note: this keyword is synonyms with java, in c# you can use

isTrial = true

\$\endgroup\$
4
  • \$\begingroup\$ Mhmm, why not Type? I do this all the time. It reads more naturaly and it's clear that Type refers to the parent class. So after instantiation you have license.Type instead of license.LicenseType which is in my option redundant. \$\endgroup\$
    – t3chb0t
    Commented Jul 3, 2016 at 7:09
  • \$\begingroup\$ @t3chb0t in the case of instantiation e.g License.Type is fine has the compiler understands what you mean. In scenarios where you are using Type for other computation in the License class before instantiation e.g Type= "bla bla" . Some times C# frowns at this as it gets confused because Type is a reserved word just as the case you have String as a variable and passing an int e.g String =5. That's not good practice . \$\endgroup\$
    – Tolani
    Commented Jul 3, 2016 at 8:22
  • 1
    \$\begingroup\$ Type is not a reserved word. It's just a name for a type that's called Type because it represents a type. There is no confusion - here's an example: class Foo { public Foo() { String = "bar"; } public string String { get; set; } } see the list of C# Keywords \$\endgroup\$
    – t3chb0t
    Commented Jul 3, 2016 at 8:49
  • \$\begingroup\$ After reading this, it makes sense. I will make necessary amends to my answer \$\endgroup\$
    – Tolani
    Commented Jul 3, 2016 at 9:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.