Designing SocialMediaLink in OOP

Beginning of Software Design

Requirement: Design an Actor class which has personal details and social media links.

A note on design:

The current design, with direct properties for each social media link and separate methods for updating/removing each, is more rigid and might lead to more boilerplate code as the number of social media platforms increases.

This design has some potential disadvantages:

  1. Rigidity:
    • If you wanted to add support for another social media platform, you'd have to modify the Actor class, adding a new property and accompanying methods to update and remove the link. This breaks the Open/Closed Principle (OCP) of SOLID, which states that a class should be open for extension but closed for modification.
  2. Duplication:
    • The IsValidLink method is invoked in every UpdateXXXLink method. If the validation logic changes, it will be correctly applied across all methods, but the repetitive structure is a red flag that there might be a more elegant design solution.
  3. No Single Responsibility:
    • The Actor class is currently handling both the data representation of an actor and the management and validation of links. This can be seen as a violation of the Single Responsibility Principle (SRP) of SOLID. Ideally, an Actor shouldn't have to be concerned with the intricacies of URL validation.
  4. Null State Ambiguity:
    • Using null to represent the absence of a link can lead to potential null reference exceptions if not handled properly elsewhere in the code. While setting the value to null does represent the absence of a value, it requires other parts of your application to consistently check for null before using a link.
  5. Lack of History/Tracking:
    • In the current design, there's no way to keep track of changes to an actor's social media links. If link history or auditing is a requirement (either now or in the future), this design would need to be significantly refactored.
  6. Potential for Incomplete Removals:
    • If a developer forgets to call the removal method, old data might remain in the system. In the design where links were contained in a list, you could have just cleared the list or removed specific items, ensuring all links of that type were removed.
  7. Scalability Concerns:
    • As new properties or methods are added, this class will grow, making it harder to maintain. A larger class tends to be more error-prone and harder to debug.

Recommendation:

A more flexible approach would involve encapsulating the behaviour and data of social media links into their own classes (as shown in the next designs). It allows for easier additions of new link types, centralized validation logic, and a clearer separation of concerns.

Continue reading

Visitor Design Pattern Notes

Visitor classes are commonly used to perform operations on a set of objects without modifying the structure of their underlying classes.

Visitor Design Pattern allows you to add new operations(behaviours) via Visitor classes to existing classes without modifying their structure. Instead of adding the operation within the existing class, you create a visitor class named as operation you want to have in existing class, so that the operation is externalised from a set of objects without modifying the structure of their underlying classes.

Visitor Design Pattern is more about adding new operations to existing classes via Visitor classes without modifying their structure, rather than adding new fields or methods directly to the classes themselves.

Consider a system where you have a hierarchy of classes representing different shapes, like Circle, Rectangle, and Triangle. Each of these shapes implements Visitable interface(or its equivalent) to allow visitor classes to operate on them.

Continue reading

How to install .NET with dotnet-install script

Find more details in Microsoft scripted installation

  1. .NET SDK (Software Development Kit): The SDK includes everything you need to build and run .NET applications. This means it includes the runtime, but also includes other tools for developing, building, running, and testing .NET applications. This includes the .NET CLI (Command Line Interface), compilers, and libraries. You need the SDK to develop and build .NET applications.
  2. .NET Runtime: The runtime includes just the resources required to run existing .NET applications. It does not include the tools and libraries used for building applications. It's a smaller installation package compared to the SDK. When you deploy a .NET application to a server or a client machine, you usually only need to have the appropriate .NET Runtime installed on that machine, not the full SDK.

Installation

$ curl -sSL https://dot.net/v1/dotnet-install.sh > dotnet-install.sh
$ chmod +x dotnet-install.sh
$ echo 'export DOTNET_ROOT=$HOME/.dotnet' >> ~/.zshrc
$ echo 'export PATH=$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools' >> ~/.zshrc

dotnet-install Script Reference

find reference for dotnet-install script reference in dotnet-install script reference

find options for dotnet-install script in dotnet-install script options

Continue reading

Python Azure Function Debugging in Pyenv-virtualenv virtual environment

Creating virtual environment

$ mkdir python_demo
$ cd python_demo
$ pyenv local 3.9.16
$ pyenv virtualenv 3.9.16 python_demo-3.9.16

# OR pyenv-virtualenv will use local python runtime with the following command
$ pyenv virtualenv python_demo-3.9.16

setting pyenv local version to created virtual environment will allow to activate virtual environment automatically when we enter project folder, so exiting from project folder will deactivate virtual environment.

$ pyenv local python_demo-3.9.16

Activating virtual environment

$ pyenv activate python_demo-3.9.16
Continue reading

Python listing virtual environments for conda, pipenv, pyenv-virtualenv

Conda

$ conda env list

# conda environments:
#
base                     /opt/homebrew/Caskroom/miniconda/base
python_azure_function_conda_virtual_env-3.9  *  /opt/homebrew/Caskroom/miniconda/base/envs/python_azure_function_conda_virtual_env-3.9
python_demo-3.9          /opt/homebrew/Caskroom/miniconda/base/envs/python_demo-3.9
test34-3.9               /opt/homebrew/Caskroom/miniconda/base/envs/test34-3.9
test35-3.9               /opt/homebrew/Caskroom/miniconda/base/envs/test35-3.9
test36-3.9               /opt/homebrew/Caskroom/miniconda/base/envs/test36-3.9

Pyenv-virtualenv

$ pyenv virtualenvs

  3.10.3/envs/test31-3.10.3 (created from /Users/kenanhancer/.pyenv/versions/3.10.3)
  3.10.5/envs/test31-3.10.5 (created from /Users/kenanhancer/.pyenv/versions/3.10.5)
  3.10.5/envs/test32-3.10.5 (created from /Users/kenanhancer/.pyenv/versions/3.10.5)
  3.11.4/envs/python_demo-3.11.4 (created from /Users/kenanhancer/.pyenv/versions/3.11.4)
  3.11.4/envs/test31-3.11.4 (created from /Users/kenanhancer/.pyenv/versions/3.11.4)
  3.11.4/envs/test32-3.11.4 (created from /Users/kenanhancer/.pyenv/versions/3.11.4)
  3.6.15/envs/test31-3.6.15 (created from /Users/kenanhancer/.pyenv/versions/3.6.15)
  3.9.1/envs/test29-3.9.1 (created from /Users/kenanhancer/.pyenv/versions/3.9.1)
  3.9.1/envs/test30-3.9.1 (created from /Users/kenanhancer/.pyenv/versions/3.9.1)
  3.9.1/envs/test31-3.9.1 (created from /Users/kenanhancer/.pyenv/versions/3.9.1)
  3.9.17/envs/python_demo-3.9.17 (created from /Users/kenanhancer/.pyenv/versions/3.9.17)
  3.9.17/envs/test29-3.9.17 (created from /Users/kenanhancer/.pyenv/versions/3.9.17)
  3.9.17/envs/test30-3.9.17 (created from /Users/kenanhancer/.pyenv/versions/3.9.17)
  3.9.17/envs/test31-3.9.17 (created from /Users/kenanhancer/.pyenv/versions/3.9.17)
  python_demo-3.11.4 (created from /Users/kenanhancer/.pyenv/versions/3.11.4)
  python_demo-3.9.17 (created from /Users/kenanhancer/.pyenv/versions/3.9.17)
  test29-3.9.1 (created from /Users/kenanhancer/.pyenv/versions/3.9.1)
  test29-3.9.17 (created from /Users/kenanhancer/.pyenv/versions/3.9.17)
  test30-3.9.1 (created from /Users/kenanhancer/.pyenv/versions/3.9.1)
  test30-3.9.17 (created from /Users/kenanhancer/.pyenv/versions/3.9.17)
  test31-3.10.3 (created from /Users/kenanhancer/.pyenv/versions/3.10.3)
  test31-3.10.5 (created from /Users/kenanhancer/.pyenv/versions/3.10.5)
  test31-3.11.4 (created from /Users/kenanhancer/.pyenv/versions/3.11.4)
  test31-3.6.15 (created from /Users/kenanhancer/.pyenv/versions/3.6.15)
  test31-3.9.1 (created from /Users/kenanhancer/.pyenv/versions/3.9.1)
  test31-3.9.17 (created from /Users/kenanhancer/.pyenv/versions/3.9.17)
  test32-3.10.5 (created from /Users/kenanhancer/.pyenv/versions/3.10.5)
  test32-3.11.4 (created from /Users/kenanhancer/.pyenv/versions/3.11.4)

Pipenv

$ ls -lat ~/.local/share/virtualenvs/

Python Azure Function Debugging in Conda virtual environment

Creating virtual environment

$ mkdir python_demo
$ cd python_demo

don't forget to update name of environment name, and i added pip, ptvsd packages to debug azure function.

$ cat > environment.yml <<EOL
name: python_demo-3.9
channels:
  - defaults
dependencies:
  - python=3.9
  - pip
  - pip:
    - ptvsd
EOL
$ conda env create -f environment.yml

Collecting package metadata (repodata.json): done
Solving environment: done

Downloading and Extracting Packages

Preparing transaction: done
Verifying transaction: done
Executing transaction: done
Installing pip dependencies: - Ran pip subprocess with arguments:
['/opt/homebrew/Caskroom/miniconda/base/envs/python_azure_function_conda_virtual_env-3.9/bin/python', '-m', 'pip', 'install', '-U', '-r', '/Users/kenanhancer/Documents/projects/python-projects-kenanhancer/python_azure_function_conda_virtual_env/condaenv.5uk0y5ie.requirements.txt', '--exists-action=b']
Pip subprocess output:
Collecting ptvsd (from -r /Users/kenanhancer/Documents/projects/python-projects-kenanhancer/python_azure_function_conda_virtual_env/condaenv.5uk0y5ie.requirements.txt (line 1))
  Using cached ptvsd-4.3.2-py2.py3-none-any.whl (4.9 MB)
Installing collected packages: ptvsd
Successfully installed ptvsd-4.3.2

done
#
# To activate this environment, use
#
#     $ conda activate python_azure_function_conda_virtual_env-3.9
#
# To deactivate an active environment, use
#
#     $ conda deactivate
Continue reading