- Single responsibility Øviv †evSvq GKwU class/mehtod Gi change Gi Rb¨ GKwU gvÎ reason _vK‡e A_©vr GKwU class Gi GKwU gvÎ responsibility _vK‡e|
Real world comparison
- Mr. Alex GKwU software firm G team leader wnmv‡e job K‡ib|
- Spare time G wZwb †jLv‡jwL, newspaper editing K‡ib|
- Basically Mr. Alex Gi Rxe‡b multiple responsibilities we`¨gvb|
- hLb work place G †Kvb wKQz Lvivc nq †hgb †Kvb fz‡ji Rb¨ boss Gi frmbv ïb‡Z nq ZLb Ab¨vb¨ mKj Kv‡Ri Performance Lvivc nq †ÿÎwe‡k‡l H mKj Kv‡Ri †KvbwUB m¤úbœ Kiv m¤¢e nq bv|
- Basically GKwU KvR Lvivc n‡j me¸‡jvB Lvivc nq|
Identify Problem in Programming
- Avgiv c~‡e©v³ CodewU ‡`wL-
protected void BtnSearch_Click(object sender,
EventArgs e)
{
var
sbCriteria = new StringBuilder();
using (var
db = new SolidDemoEntities())
{
var
query = db.Documents.AsQueryable();
if (!String.IsNullOrWhiteSpace(TxbAccount.Text))
{
query
= query.Where(d => d.Account.StartsWith(TxbAccount.Text));
sbCriteria.AppendFormat("Account
starts with '{0}' AND ", TxbAccount.Text);
}
if (!String.IsNullOrWhiteSpace(TxbLastName.Text))
{
query
= query.Where(d => d.LastName.StartsWith(TxbLastName.Text));
sbCriteria.AppendFormat("Last
Name starts with '{0}' AND ", TxbLastName.Text);
}
if (!String.IsNullOrWhiteSpace(TxbFirstName.Text))
{
query
= query.Where(d => d.FirstName.StartsWith(TxbFirstName.Text));
sbCriteria.AppendFormat("First
Name starts with '{0}' AND ", TxbFirstName.Text);
}
if (sbCriteria.Length
> 5)
sbCriteria.Remove(sbCriteria.Length
- 5, 5);
else
sbCriteria.Append("--
all records --");
LblCriteria.Text
= sbCriteria.ToString();
LvwResults.DataSource
= query.ToArray();
LvwResults.DataBind();
}
}
- Our beleaguered Search button does far too many jobs.
- Avgv‡`i Search button A‡bK¸‡jv KvR GK‡Î m¤úbœ K‡i
- Bnv Single Responsibility Principle violate K‡i| d‡j wewfbœ RwUjZvi m„wó nq- hv c~‡e© Av‡jvPbv Kiv n‡q‡Q-
- GLb hw` Avgiv BtnSearch_Click method †f‡½ GKvwaK method ˆZix Kwi Z‡e wK GB problem fix n‡e?
- DËi n‡jv bv - KviY ïaygvÎ method mg~n Single responsible Ki‡jB n‡e bv Zvi mv‡_ mv‡_ class †K I single responsibility m¤úbœ n‡Z n‡e|
- GLb cÖkœ n‡jv Avgiv method Gi wK wK separate class G break out Ki‡ev?
- G‡ÿ‡Î Builder Pattern Use K‡i Avgiv SearchCriteria create Ki‡ev|
- Avgiv piece by piece object create Ki‡ev|
- Then piece mg~n add K‡i building process m¤úbœ Ki‡ev|
- Object ‡K piece by piece fvM K‡i D³ piece mg~n add KivB Builder Pattern.
- Avgiv `ywU class create Ki‡ev:
- SearchCriteriaBuilder I SearchCriteria.
- cÖwZwU class Gi GKwU K‡i Responsibility _vK‡e-
- SearchCriteriaBuilder Gi Responsibility n‡jv search criteria assembling Kiv|
- SearchCriteria Gi Responsibility n‡jv Searching Criteria mg~n represent Ki‡e|
- cÖwZwU class Gi Rb¨ Avgiv GKwU K‡i interface add Ki‡ev|
- Interface Øviv builder†K abstracting Gi gva¨‡g (cieZ©x‡Z Av‡iv builders add n‡j) Avgiv Ab¨vb¨ builders Gi substitute wnmv‡e use Ki‡Z cvi‡ev|
·
Dc‡iv³
Diagram G defined
mKj classes I interfaces generic T.
·
GLv‡b T
n‡”Q Avgv‡`i searching object type
i.e. ‡h object Gi Dci searching Ki‡ev Dnvi type (present application G Document)
·
SearchCriteriaBuilder lets you
add criteria with the AndStartsWith method.
·
SearchCriteriaBuilder class Gi AndStartsWith
method wU criteria
add Ki‡Z e¨eüZ nq|
·
SearchCriteria's
single responsibility is to present the criteria to the world.
·
The criteria may take the form of a
"friendly" (comprehensible to a human) string or an Expression
suitable for LINQ to Entities.
·
SearchCriteria class
Solution which will not violate SRP
ISearchCriteriaBuilder<T>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
/// Search criteria
builds search criteria. GLb ïaygvÎ simple 'AND'
Operator Gi search mg~n support Ki‡e.
/// </summary>
/// <typeparam
name="T">T Øviv †h object Search Kiv n‡e
Dnvi type †evSvq</typeparam>
public interface ISearchCriteriaBuilder<T>
{
/// <summary>
/// AND-in a criterion that the property starts with a value.
/// </summary>
/// <param
name="friendlyName">A name
to display to the user.</param>
/// <param
name="propertyName">The name
of the property being queried. It must be a string property.</param>
/// <param
name="value">The property's value must
start with this string in order to make a match.</param>
/// <returns>This object, for a fluent interface.</returns>
ISearchCriteriaBuilder<T> AndStartsWith(string friendlyName, string propertyName, string value);
/// <summary>
/// Get a SearchCriteria object that reflects the criteria
added so far.
/// </summary>
/// <returns>A SearchCriteria object.</returns>
ISearchCriteria<T> GetResult();
}
SearchCriteriaBuilder<T>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
/// Builds search criteria. For now, only simple 'AND'
searches are supported.
/// </summary>
/// <typeparam
name="T">The type of object being searched.</typeparam>
public interface ISearchCriteriaBuilder<T>
{
/// <summary>
/// AND-in a criterion that the property starts with a value.
/// </summary>
/// <param
name="friendlyName">A name
to display to the user.</param>
/// <param
name="propertyName">The name
of the property being queried. It must be a string property.</param>
/// <param
name="value">The property's value must
start with this string in order to make a match.</param>
/// <returns>This object, for a fluent interface.</returns>
ISearchCriteriaBuilder<T> AndStartsWith(string friendlyName, string propertyName, string value);
/// <summary>
/// Get a SearchCriteria object that reflects the criteria
added so far.
/// </summary>
/// <returns>A SearchCriteria object.</returns>
ISearchCriteria<T> GetResult();
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Linq.Expressions;
/// <summary>
/// Represents the criteria for searching for objects of type
T.
/// </summary>
/// <typeparam
name="T">The type of objects being
searched.</typeparam>
public interface ISearchCriteria<T>
{
/// <summary>
/// Get a friendly representation of the criteria.
/// </summary>
string FriendlyString { get; }
/// <summary>
/// Get the criteria as a LINQ Expression.
/// </summary>
Expression<Func<T, bool>> Expression { get; }
}
SearchCriteria<T>
using System;
using System.Diagnostics.Contracts;
using System.Linq.Expressions;
/// <summary>
/// Represents criteria for searching a repository of objects
of type T.
/// </summary>
public class SearchCriteria<T> : ISearchCriteria<T>
{
/// <summary>
/// Get a friendly representation of the criteria.
/// </summary>
public string FriendlyString { get; private set; }
/// <summary>
/// Get the criteria as a LINQ Expression.
/// </summary>
public Expression<Func<T, bool>> Expression { get; private set; }
/// <summary>
/// Constructor. It is internal because it is intended that
the SearchCriteriaBuilder,
/// in this assemby, be used to construct SearchCriteria.
/// </summary>
/// <param
name="friendlyString">A
user-friendly way of expressing the search criteria.</param>
/// <param
name="expression">A LINQ Expression
that contains the search criteria.</param>
internal SearchCriteria(string friendlyString, Expression<Func<T, bool>> expression)
{
Contract.Requires(friendlyString != null);
Contract.Requires(expression != null);
FriendlyString = friendlyString;
Expression = expression;
}
}
For faithfully adhering to the Single
Responsibility Principle, we have been rewarded with a set of classes and
interfaces that are eminently reusable and -- just as important -- easily
testable. That's the 'S' of SOLID.Can a single class can have multiple methods?
·
SRP Gi †ÿ‡Î
GKwU class G multiple method _vK‡Z cvi‡e-
·
GLb cÖkœ
n‡jv
1. GKwU class Gi
single responsibility _vK‡e
2. GKwU method Gi
single responsibility _vK‡e
3. GKwU class G
GKvwaK method _vK‡Z cvi‡e
Bnv wKfv‡e m¤¢e?
·
Responsibility mvavibZ context related nq|
·
Class
Gi †ÿ‡Î D³ Class Gi mKj method mg~n GKwU specific context related Operation Gi Rb¨ responsible _vK‡e-
o
D`vniY
¯^iƒc
EmployeeDB
classwU employee related Database operation mg~‡ni Rb¨ responsible
_vK‡e|
o
Avevi
EmployeeReport
classwU employee reports
related operation mg~‡ni Rb¨ responsible _vK‡e|
·
Method Gi †ÿ‡Î
GKwU method GKwU specific
task handle Ki‡e-
o
‡hgb wb‡¤œi method wU multiple
task handle K‡i
o
wb‡¤œi method wU †hB mKj task
mg~n handle K‡i
Zv wb‡¤œ cÖ`Ë n‡jv-
§
Connectionstring
‡_‡K Connection
create K‡i
§
Parameter array Create K‡i
§
Command
create K‡i
§
Parameter array ‡K command parameter G add K‡i
o
myZivs
wb‡¤œi method wU SRP
violate K‡i
o
wb‡¤œ method definition ‡`qv n‡jv-
//Method with multiple responsibilities
– violating SRP
public void Insert(Employee e)
{
string StrConnectionString = "";
SqlConnection objCon = new SqlConnection(StrConnectionString);
SqlParameter[] SomeParameters=null;//Create Parameter array from values
SqlCommand objCommand = new SqlCommand("InertQuery", objCon);
objCommand.Parameters.AddRange(SomeParameters);
ObjCommand.ExecuteNonQuery();
}
o
Dc‡iv³ Method wU SRP supportable Kivi
Rb¨ Avgiv Method wU †f‡½ wewfbœ fv‡M fvM Kwi hvi definition wb¤œiƒc-
//Method with single responsibility –
follow SRP
public void Insert(Employee e)
{
SqlConnection objCon = GetConnection();
SqlParameter[] SomeParameters=GetParameters();
SqlCommand ObjCommand =
GetCommand(objCon,"InertQuery",SomeParameters);
ObjCommand.ExecuteNonQuery();
}
private SqlCommand
GetCommand(SqlConnection objCon, string InsertQuery, SqlParameter[]
SomeParameters)
{
SqlCommand objCommand = new SqlCommand(InsertQuery, objCon);
objCommand.Parameters.AddRange(SomeParameters);
return objCommand;
}
private SqlParameter[] GetParaeters()
{
//Create Paramter array from values
}
private SqlConnection GetConnection()
{
string StrConnectionString = "";
return new SqlConnection(StrConnectionString);
}
·
GB‡ÿ‡Î Method msL¨ I code quantity †e‡o †M‡jI
o
Testability
ev‡o|
o
Code
readable nq|
o
Specific
method Gi responsibility reduce nq|
কোন মন্তব্য নেই:
একটি মন্তব্য পোস্ট করুন