Free Online Courses for Software Developers - MrBool
× Please, log in to give us a feedback. Click here to login
×

You must be logged to download. Click here to login

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

Refactoring in the Visual Studio 2005

Demonstrating the code refactoring technique and the new features available in the Visual Studio 2005 to promote it, are the objectives of this article. Review and have fun!

Visual Studio

Refactoring in the Visual Studio 2005

 

This article examines:

This article uses the following technologies:

·       Best performances;

·       Refactoring in the Visual Studio 2005;

·       Code revision.

Visual Studio 2005 e C#

 

Do you agree that part of a software developer working time involves code revision? This parcel of time tends to increase alongside with the course of the project, although, normally, it is not recognized or even mentioned in it.

Knowing techniques and resources to make code revision faster and more productive must be amongst the priorities of a developer, so that he can deliver his project with greater quality and lesser effort.

Demonstrating the code refactoring technique and the new features available in the Visual Studio 2005 to promote it, are the objectives of this article. Review and have fun!

 

Concept

Refactoring is not a new technique and it was not created for the Visual Studio 2005. It is very likely that you use it on a day to day basis, although, perhaps not calling it after its formal name. Refactoring is formally the process of rewriting codes in order to promote their understanding and legibility, maintaining unaltered their performance or external use.

You are applying refactoring when, for example, you change the name of a variable to ConvertionRate instead of CR; when you change a “hard-coded” value for an enumeration and when, instead of repeating the same part of a code in two different methods, you center it in one and make the first two, its customers.

Observe that, in these three examples, the external behavior of software itself was not modified, only its internal structure, making it more understandable and clear. The objective of the refactoring is not to add new functionalities to the software or to correct bugs, although the application of refactoring makes it much easier to detect them, because they will become more visible.

Depending on size of the company in which you work and of the degree of maturity of the software that it produces, you must be used to developing codes following a determined standardization. In the majority of cases, this standardization appears accordingly with the time, which means that there is non standardized code and already standardized.

The refactoring, that is, the review and modification of a preexisting code are useful in this context, because they help to standardize the old code. The standardized code, in its turn, increases the legibility and promotes greater velocity and productivity in the development.

Another important aspect about refactoring is that refactoring a code does not mean modifying a great stretch of code at once, but merely performing small modifications in small stretches. It is the sum of the small alterations that improves the code significantly.

Each modification in the code, also called code transformation, complies with a known standard and has a name. Returning to the examples mentioned previously, to rename a variable means to apply the Rename standard; to substitute a hard-coded value for an enumeration means to apply the Substitute Magic Number For Symbolic Constant standard and, finally, to cut a code piece and use it to create a new method is to apply the Extract Method standard.

Martin Fowler, expert on the subject, wrote the book Refactoring: Improving the Design of Existing Code (Bookman Publishing company, ISBN 8536303956) which describes almost one hundred refactoring standards. He is also the author of the www.refactoring.com site, where you can find articles and descriptions for all the refactoring standards.

In agreement to the previous explanation, refactoring is not a new technique or one created for the Visual Studio 2005. However, the features for refactoring before the Visual Studio 2005 were reduced, mainly, in copy-paste and cut-paste actions and there was no other kind of support to make the task easier.

Fortunately, the Visual Studio 2005 brings new functionalities created to make refactoring easier and to reduce the problems generated at the time when this task was performed without resources (copy-paste and cut-paste, believe me, contributes more to disseminate problems than to decide them).

In the next sections we will demonstrate the new functionalities delivered by the Visual Studio 2005 to smoothen the task of refactoring.

 

Support to refactoring in the visual Studio 2005

The Visual Studio 2005 supports seven of the most common refactoring standards, used in a practical context menu called Refactor and to which you may gain access to with a click of the mouse.

Consider that along with the possibility to modify references in multiple projects and you will have an idea of how useful and easy to use they may be. Figure 1 displays the new context menu Refactor.

 

Figure 1. Refactor Menu

 

We have mentioned that refactoring is a risky task if not performed carefully and avoiding that large code stretches be altered at one time. The Visual Studio 2005 helps guarantee that the modifications are correct, displaying a preview window so that you may visualize all the modifications to be made and decide whether you should confirm them or not. Figure 2 displays the preview window.

 

Figure 2. Preview window for refactoring

 

The next sections detail each one of the refactoring standards available in the Visual Studio 2005. Since refactoring is a much more a technique or a good skill rather than exactly a technology, we will try to demonstrate it in the most practical way, using short, however coherent, examples. All the examples are based on the day-to-day of a virtual music store.

 

Rename

The Rename standard is the simplest of the refactoring standards and also the most useful. You may rename local variables, methods, properties, types, namespaces etc. Visual Studio 2005 even allows these modifications to affect comments made with the name of the modified item. Consider the code in Listing 1.

 

Listing 1. Code before Rename operation

using System;

using System.Text.RegularExpressions;

namespace MrBoolRefactoring

{

    public class Search

    {

       public string name = string.Empty;

       public string SearchArtist()

       {

            string aN = this.name;

            string returnText = String.Empty;

            if (aN != string.Empty)

            {

               aN = Regex.Replace(aN, "[áäàâã]", "a");

               aN = Regex.Replace(aN, "[éëèê]", "e");

               aN = Regex.Replace(aN, "[íïìî]", "i");

               aN = Regex.Replace(aN, "[óöòôõ]", "o");

               aN = Regex.Replace(aN, "[úüùû]", "u");

               aN = Regex.Replace(aN, "[ç]", "c");

               aN = Regex.Replace(aN, "[ñ]", "n");

               aN = Regex.Replace(aN, "[ÁÄÀÂÃ]", "A");

               aN = Regex.Replace(aN, "[ÉËÈÊ]", "E");

               aN = Regex.Replace(aN, "[ÍÏÌÎ]", "I");

               aN = Regex.Replace(aN, "[ÓÖÒÔÕ]", "O");

               aN = Regex.Replace(aN, "[ÚÜÙÛ]", "U");

               aN = Regex.Replace(aN, "[Ç]", "C");

               aN = Regex.Replace(aN, "[Ñ]", "N");

               aN = Regex.Replace(aN, "[.]", "");

               aN = Regex.Replace(aN, "[,]", "");

               aN = Regex.Replace(aN, "[;]", "");

               returnText =

                 "Number of musics by artist " +

                 aN + ": 10 results.";

            }

            else

            {

                returnText =

                  "Supply the artist's name!";

            }

            return (returnText);

        }

    }

}

 

Its functionality is to allow the user to inform the name of an artist and to receive a reply disclosing the amount of songs found by the search. Without this explanation and imagining that this twenty lines code had 300 lines how easy would it be to interpret the intention of the variable aN?

The code would be more legible and easy to maintain in case the purpose of the variable aN was fully revealed in a more coherent name such as “artistName”. To perform this operation, it is enough to right-click over the variable aN and, in the context menu Refactor, select the Rename option.

Figure 3 displays a Rename window where it will inform the new name of the selected item, whether it wishes a preview of the modifications and if the comments containing the name of the item shall also be modified. Listing 2 displays the code in this example after the Rename operation. Much better, isn’t it?

 

Figure 3. Refactoring window Rename

 

Hint: You may also activate the Rename operation using a keyboard shortcut. Click over the item to be renamed and press CTRL + R, CTRL + R.

 

Listing 2. Code after Rename operation

using System;

using System.Text.RegularExpressions;

namespace MrBoolRefactoring

{

  public class Search

  {

    public string name = string.Empty;

    public string SearchArtist()

    {

      string artistName = this.name;

      string returnText = String.Empty;

      if (artistName != string.Empty)

      {

        artistName = Regex.Replace(artistName,

          "[áäàâã]", "a");

        artistName = Regex.Replace(artistName,

          "[éëèê]", "e");

        artistName = Regex.Replace(artistName,

          "[íïìî]", "i");

        artistName = Regex.Replace(artistName,

          "[óöòôõ]", "o");

        artistName = Regex.Replace(artistName,

          "[úüùû]", "u");

        artistName = Regex.Replace(artistName,

          "[ç]", "c");

        artistName = Regex.Replace(artistName,

          "[ñ]", "n");

        artistName = Regex.Replace(artistName,

          "[ÁÄÀÂÃ]", "A");

        artistName = Regex.Replace(artistName,

          "[ÉËÈÊ]", "E");

        artistName = Regex.Replace(artistName,

          "[ÍÏÌÎ]", "I");

        artistName = Regex.Replace(artistName,

          "[ÓÖÒÔÕ]", "O");

        artistName = Regex.Replace(artistName,

          "[ÚÜÙÛ]", "U");

        artistName = Regex.Replace(artistName,

          "[Ç]", "C");

        artistName = Regex.Replace(artistName,

          "[Ñ]", "N");

        artistName = Regex.Replace(artistName,

          "[.]", "");

        artistName = Regex.Replace(artistName,

          "[,]", "");

        artistName = Regex.Replace(artistName,

          "[;]", "");

        returnText =

          "Number of musics by artist " +

          artistName + ": 10 results.";

      }

      else

      {

        returnText = "Supply the artist's name!";

      }

            return (returnText);

     }

  }

}

 

Extract Method

Some times you finish writing a code and realize that a part of it has functionality good and independent enough to be in a separate method. Other times, during the maintenance of the code you realize (with certain disgust) that the same code stretch was copied in two or three different places.

In both cases you would like to remove the code stretch transforming it into a new method while, at the same time, you modify your old methods to consume it. This is exactly behavior of the Extract Method standard made available by the Visual Studio 2005.

Return to the code in Listing 2. This code comprises three actions performed in sequence: to obtain the name of the artist typed by the user (informed by the field name); to transform it and to return it back to the user.

The second action performed is a normalization of the name typed using regular expressions to change to all the special characters for more simple and universal characters. Consider that a music store receives estate from various record labels around the world.

It is reasonable to imagine that this catalogue contains names of artists or albums or songs with several special characters. Since the users can type names with or without these special characters, it is common to normalize them in order to obtain best results.

As we have mentioned, so much the names of the artists as the names of albums and songs ought to be normalized. However, the whole normalization code is inlaid in the artist search code and is not available to the other much classes or methods of the project. Certainly, when writing the search method by songs, this functionality will be necessary.

One should, therefore, extract the whole code responsible for the normalization in a new method, totally separate from who will consume it. To perform this operation, just select the code to be extracted and activate the Extract Method option in the context menu Refactor.

Figure 4 shows the Extract Method window where the Visual Studio 2005, automatically configures the variable artistName as signature argument of the new method to be created.

 

Figure 4. Extract Method refactoring window

 

It is not over yet. The new NormalizeName contains, as signature argument, a parameter called artistName. Since the method is supposedly generic for albums and songs, this name may cause misunderstanding to those who come to use it, even if this person is you after two days.

Because of that, we employ the Rename standard in the artistName parameter, modifying it to name. Listing 3 displays the code after the employment of the Extract Method and Rename standards.

 

Tip: You may also activate the Extract Method operation using a keyboard shortcut. Select the code stretch desired and press CTRL + R, CTRL + M.

 

Listing 3. Code after Extract Method operation

using System;

using System.Text.RegularExpressions;

namespace MrBoolRefactoring

{

  public class Search

  {

    public string name = string.Empty;

   

    public string SearchArtist()

    {

      string artistName = this.name;

      string returnText = String.Empty;

      if (artistName != string.Empty)

      {

        artistName = NormalizeName(artistName);

        returnText =

          "Number of musics by artist " +

          artistName + ": 10 results.";

      }

      else

      {

        returnText = "Supply the artist's name!";

      }

      return (returnText);

    }

   

     private static string NormalizeName(string name)

     {

       name = Regex.Replace(name, "[áäàâã]", "a");

       name = Regex.Replace(name, "[éëèê]", "e");

       name = Regex.Replace(name, "[íïìî]", "i");

       name = Regex.Replace(name, "[óöòôõ]", "o");

       name = Regex.Replace(name, "[úüùû]", "u");

       name = Regex.Replace(name, "[ç]", "c");

       name = Regex.Replace(name, "[ñ]", "n");

       name = Regex.Replace(name, "[ÁÄÀÂÃ]", "A");

       name = Regex.Replace(name, "[ÉËÈÊ]", "E");

       name = Regex.Replace(name, "[ÍÏÌÎ]", "I");

       name = Regex.Replace(name, "[ÓÖÒÔÕ]", "O");

       name = Regex.Replace(name, "[ÚÜÙÛ]", "U");

       name = Regex.Replace(name, "[Ç]", "C");

       name = Regex.Replace(name, "[Ñ]", "N");

       name = Regex.Replace(name, "[.]", "");

       name = Regex.Replace(name, "[,]", "");

       name = Regex.Replace(name, "[;]", "");

       return name;

     }

   }

}

 

Encapsulate Field

One of the main foundations of the Object Oriented Programming (OOP) makes clear that no field of any class may be public, since it can be modified outside the class that contains it, causing unexpected problems / behavior.

Instead of that, OOP indicates that the fields must be substituted by properties. The Visual Studio 2005 Encapsulate Field standard allows transforming a field of the class into a property, automatically configuring it with an appropriate get and set.

In all the code listings demonstrated so far, you were able to verify a field called name of the Search class. It is public and, therefore, can be modified without knowledge of the class that contains it. Consider Listing 3 to verify what we are affirming.

Using the Encapsulate Field option, in the context menu Refactor, it is very easy to transform the field name into a property of the Search class. When doing so, the Encapsulate Field window will be presented (Figure 5) where you will be able to inform the name of the property to be created and the purpose of the modification. Selecting the option All, will see to it that all the references to the field are substituted by references to the new property.

 

Figure 5. Encapsulate Field refactoring window

 

Listing 4 displays the new property Name, created for the Search class. The Encapsulate Field standard comprises yet two behaviors that must be highlighted:

1.      The Set session is only created in case the original field hasn’t been modified by the read-only attribute;

2.      It is necessary to place the cursor over the declaration of the field. It is not possible to apply the standard by clicking, for example, over the name of the field being used; you have to do it where it is declared.

 

Tip: You may also activate the Encapsulate Field operation by using a keyboard shortcut. Select the desired field and press CTRL + R, CTRL + E.

 

 

Listing 4. Code after Encapsulate Field operation

...

public class Search

{

   private string name = string.Empty;

       

   public string Name

   {

      get { return name; }

      set { name = value; }

   }

       

   public string SearchArtist()

   {

      string artistName = this.Name;

      ...

   }

}

 

Extract Interface

An interface is an abstract class with all its abstract members. An interface works as a “contract” that defines which methods, properties and events a class needs to be implemented. If you create a class that implements an interface, you must implement in it all the methods and properties defined in the interface.

The .NET Framework contains many interfaces from which you may choose to implement, for example, IComparable, IEnumerable, IEnumerator, IList, among others. Creating an interface is useful when you understand in your classes, that some properties and methods are common to other classes and wish to guarantee that all of them implemented these items.

In order to obtain this guarantee, you will have to create an interface and see to it that all the other classes implement it. The Visual Studio 2005 Extract Interface standard makes the work of removing the properties and methods (and events) of its existing class and declaring in a new interface easier, modifying its class in order to implement it.

Consider Listing 5. The code declares a class called Album and some important properties for an album, such as an ID; an artist name; the name of the album itself and a method to obtain the sales price of the album.

 

Listing 5. Code before Extract Interface operation

using System;

namespace MrBoolRefactoring

{

    class Album

    {

        private int id = 0;

        public int ID

        {

            get { return (id); }

        }

        private string artistName = String.Empty;

        public string ArtistName

        {

            get{ return (artistName); }

        }

        private string name = String.Empty;

        public string Name

        {

            get { return (Name); }

        }

        public double GetPrice() { return (0); }

        //Mais métodos da classe seguem aqui

    }

}

 

Imagine that you now had to implement a class called Music. Music also contains an ID; also contains an artist name; also contains a name and it must also have a method to get the sales price.

At this moment, you realize that it would be interesting to own an interface that defines these common properties and methods for the two classes and see to it so that they only implement the interface.

In order to extract an interface from a class, it is enough to place the cursor over the name of the class and to select the Extract Interface option in the context menu Refactor. At this moment, the Extract Interface window will be displayed (Figure 6).

 

  

Figure 6. Extract Interface refactoring window

The Extract Interface window allows you to select all the properties, methods and events to create your new interface. And more, it allows you to define the name of the new interface, which we will call “ICommonData” and, finally, allows you to define the file name where the interface will be saved. The Visual Studio 2005 will always create a new file to store the newly created interface.

Once the interface is created, the Visual Studio 2005 will automatically add the call for the implementation of the interface in its old class. You can examine this by observing Listing 6. The code generated for the new interface may be verified in Listing 7.

 

Listing 6. Code after Extract Interface operation

using System;

namespace MrBoolRefactoring

{

    class Album : MrBoolRefactoring.ICommonData

    {

     ...

}

 

Listagem 7. Código da interface ICommonData

using System;

namespace MrBoolRefactoring

{

    interface ICommonData

    {

        string ArtistName { get; }

        double GetPrice();

        int ID { get; }

        string Name { get; }

    }

}

 

The Extract Interface standard is not restricted only to the classes. You can use it to create a new interface from a struct and even to create a new interface starting from an already existing one.

Tip: You may also activate the Extract Interface operation using a keyboard shortcut. Select the desired class and press CTRL + R, CTRL + I.

 

Promoting Local Variable into Parameter

The Promote Local Variable to Parameter standard allows you to select a local variable in your method and transforms it into a call argument (or parameter) of the method’s signature.

It is useful at the moments when you finish writing the method and realize that a certain parameter will no longer be hard-coded, but, on the other hand, will have to be informed by who uses your method.

Or, in another situation, you may want to keep an internal and hard-coded parameter in your method to facilitate the implementation and, at the end of that, make the parameter public by placing it in the method’s declaration.

Consider Listing 8. In it, we define a class called ShoppingCart which represents a user’s shopping cart.

 

Listing 8. Code before Promote Local Variable Into Parameter operation

using System;

namespace MrBoolRefactoring

{

    class ShoppingCart

    {

        private void GetShoppingCart()

        {

            int userID = 100;

            //Shopping cart logic

        }

        public void PrintShoppingCart()

        {

            GetShoppingCart();

            //Shopping cart print logic

        }

    }

}

 

It comprises a method called PrintShoppingCart which, supposedly, prints the user’s purchase data. In order to perform the job, it consults a second method called GetShoppingCart that effectively returns the user’s purchase data.

In the first line of the implementation of GetShoppingCart we define a variable called userID and we configure a default value “100”. At the end of the implementation of GetShoppingCart, we decide that it is time to make the userID parameter public and configurable by any one that activates the method.

In order to achieve this transformation one must place the cursor over the variable and, in the context menu Refactor, select the Promote Local Variable to Parameter option. For this standard, the preview window is not displayed and the actions are immediately performed.

In Listing 9, you can observe that the parameter is now part of the signature of GetShoppingCart and you can also observe that the call to GetShoppingCart inside PrintShoppingCart included the default value 100.

 

Listing 9. Code after the Promote Local Variable into Parameter operation

using System;

namespace MrBoolRefactoring

{

    class ShoppingCart

    {

        private void GetShoppingCart(int userID)

        {

                            ...

        }

        public void PrintShoppingCart()

        {

            GetShoppingCart(100);

                            ...

        }

    }

}

 

Visual Studio 2005 automatically corrects the calls to the method altered by the Promote Local Variable to Parameter refactoring.

 

Tip: You may also activate the Promote Local Variable to Parameter operation using a keyboard shortcut. Select the desired variable and press CTRL + R, CTRL + P.

 

Removing Parameters

The Remove Parameters standard is instinctive. You may use it to remove a parameter of a method’s signature, an indexer or a delegate at the same time during which all the calls for this method are corrected.

Consider Listing 9. The GetShoppingCart obligatorily needs to receive the userID parameter so that it can return the user’s shopping cart purchase data to the PrintShoppingCart. However, since the two methods belong to the same class (ShoppingCart), why not remove the GetShoppingCart parameter and transform it into a property of the class?

In terms of OOP and code reading, this small modification would make a lot of sense. It is clear that this option is only fully viable because we are still implementing the class. If the class had already been implemented before and other methods used it, perhaps you would not be able to remove the parameter.

However, in this example, removing the parameter is valid. In order to remove the userID parameter of the GetShoppingCart signature it is enough to click on the method’s signature and, in the Refactor context menu, select the Remove Parameters option. Following that, the Remove Parameters window will be displayed (Figure 7) where it is possible to select all the parameters that are to be removed (click on one at a time, in case there is more than one). In this example, we clicked on the userID parameter and on the Remove button.

 

 

Figure 7. Remove Parameters refactoring window

 

The Remove Parameters standard is not complicated; however, it can cause your code to behave in an inadequate way. You must keep the Preview reference changes option selected so that the modifications’ preview window is displayed and you can be certified that the modifications will not affect the code’s behavior.

Listing 10 displays the result of the Remove Parameters operation. The next step, according to the explanation, would be to create a userID property for the ShoppingCart class.

 

Tip: You may also activate the Remove Parameters operation using a keyboard shortcut. Click over the signature of the method, indexer or delegate and press CTRL + R, CTRL + V.

 

Listing 10. Code after Remove Parameters operation

using System;

namespace MrBoolRefactoring

{

    class ShoppingCart

    {

        //Create a userID property here

 

        private void GetShoppingCart()

        {

            ...

        }

        public void PrintShoppingCart()

        {

            GetShoppingCart();

            ...

        }

    }

}

 

Reordering Parameters

When we work with overloading of methods, it can happen that we change the order of the parameters between one overload and another, making it possible that the methods’ signatures do not to coincide. The Visual Studio 2005 Reorder Parameters standard is useful so that you may adjust the order of the parameters in the methods’ signatures and standardize them.

Consider Listing 11. In it you can observe that there exist three overloads for the GetAlbums method which, supposedly, returns a list of albums for an informed artist.

 

Listing 11. Code before Reordering Parameters operation

using System;

namespace MrBoolRefactoring

{

  class Catalog

  {

    public void GetAlbums(string artistName) { }

    public void GetAlbums(string ordenation,

      string artistName) { }

    public void GetAlbums(string ordenation,

      int initialPage, string artistName) { }

  }

}

 

The first overload receives only one parameter with the name of the artist. The second receives an ordering parameter (for example, date of release, best selling, etc.) and the parameter with the name of the artist.

Finally, the third overload receives the same ordering parameter, a parameter indicating as from which page the result must be sent (for example, an artist with 30 albums could be displayed for the user in three pages of 10 albums) and the parameter with the name of the artist.

From the point of view of the code, overloads are correct; however, for those who will use them, the lack of standard of the signatures can make their use confusing. In order to correct this, we can use the Visual Studio 2005 Reorder Parameters to rearrange the parameters in the methods’ signatures.

In order to perform this operation, it is enough to click on the method’s signature (one at a time) and, in the context menu Refactor, select the Reorder Parameters option.  The Visual Studio 2005 will display the Reorder Parameters window (Figure 8) which, through the arrows, is possible to reorder the parameters in the method’s signature. Listing 12 shows the result of the reordering made by the Reorder Parameters.

 

Tip: The reordering of parameters may be used in indexers and delegates also. Just follow the same procedures.

 

Figure 8. Reorder Parameters refactoring window

 

Listing 12. Code after Reorder Parameters operation

using System;

namespace MrBoolRefactoring

{

  class Catalog

  {

    public void GetAlbums(string artistName) { }

    public void GetAlbums(string artistName,

      string ordenation) { }

    public void GetAlbums(string artistName,

      string ordenation, int initialPage) { }

  }

}

 

The Visual Studio 2005 will automatically correct the calls to the methods reordering also the parameters that are to e sent!

 

Tip: You may also activate the Reorder Parameters operation using a keyboard shortcut. Click over the signature of the method, indexer or delegate CTRL + R, CTRL + O.

 

Conclusion

The refactoring technique is used widely on the day-to-day of a developer and a great deal of his time is spared performing this task. The Visual Studio 2005 included a series of features to make this task more productive and allows the developer to spend less time in accomplishing it.

 

Link

Site about Refactoring

www.refactoring.com

Refactoring for VB. NET

msdn.microsoft.com/vbasic/downloads/tools/refactor



colunista nao disponivel

What did you think of this post?
Services
[Close]
To have full access to this post (or download the associated files) you must have MrBool Credits.

  See the prices for this post in Mr.Bool Credits System below:

Individually – in this case the price for this post is US$ 0,00 (Buy it now)
in this case you will buy only this video by paying the full price with no discount.

Package of 10 credits - in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download few videos. In this plan you will receive a discount of 50% in each video. Subscribe for this package!

Package of 50 credits – in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download several videos. In this plan you will receive a discount of 83% in each video. Subscribe for this package!


> More info about MrBool Credits
[Close]
You must be logged to download.

Click here to login