VB.Net - 530 символов (без пробелов), 634 (без пробелов)
Module ChristmasSong
Sub Main()
Dim i&, f$ : Dim d$() = {"first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "ninth", "tenth", "eleventh", "twelfth"}, g$() = {"a partridge in a pear tree.", "two turtle doves, and ", "three french hens, ", "four calling birds, ", "five gold rings, ", "six geese a-laying, ", "seven swans a-swimming, ", "eigth maids a-milking, ", "nine ladies dancing, ", "ten lords a-leaping, ", "eleven pipers piping, ", "twelve drummers drumming, "}
For i = 0 To 11 : f = g(i) & f : Console.WriteLine("On the {0} day of Christmas, my true love gave to me {1}", d(i), f) : Next
End Sub
End Module
class Volume
FIELDS = %w( name size type owner iscsi_target iscsi_portal date_create date_modified)
SYSTEM = 0
DATA = 1
attr_accessor *FIELDS
def initialize( args= { :type => SYSTEM } )
args.each_pair do | key, value |
self.send("#{key}=", value) if self.respond_to?("#{key}=")
end
end
def inspect
FIELDS.inject({}) do | hash, field |
hash.merge( field.to_sym => self.send(field) )
end.inspect
end
end
Всякий раз, когда вы видите длинный список подобных вещей, обычно вы можете свести все это в единый массив:
class Volume
ATTRIBUTES = [
:name, :size, :type, :owner, :date_created, :date_modified,
:iscsi_target, :iscsi_portal
].freeze
ATTRIBUTES.each do |attr|
attr_accessor attr
end
SYSTEM = 0
DATA = 1
DEFAULTS = {
:type => SYSTEM
}.freeze
def initialize(args = nil)
# EDIT
# args = args ? DEFAULTS : DEFAULTS.merge(args) # Original
args = args ? DEFAULTS.merge(args) : DEFAULTS
ATTRIBUTES.each do |attr|
if (args.key?(attr))
instance_variable_set("@#{attr}", args[attr])
end
end
end
def inspect
ATTRIBUTES.inject({ }) do |h, attr|
h[attr] = instance_variable_get("@#{attr}")
h
end
end
def to_json
self.inspect.to_json
end
end
После этого манипулировать переменными экземпляра становится довольно просто.
Я согласен с ответом Рекса М , но я бы пошел еще дальше. Если вы используете шаблон MVC (или что-то подобное), представление делегирует нажатие кнопки контроллеру. Конечно, методы контроллеров могут быть вызваны из любого места в вашем классе - скажем, из вашего обратного вызова таймера.
Итак, вернемся к вашему исходному коду:
using System.Windows.Forms;
class MyForm : Form
{
private Timer myTimer;
private Button myButton;
private MyController myController;
public MyForm()
{
// ...
// Initialize the components, etc.
// ...
myTimer.Tick += new EventHandler( myTimer_Tick );
myButton.Click += new EventHandler( myButton_Click );
myTimer.Start();
}
private void myTimer_Tick( object sender, EventArgs eventArgs )
{
myTimer.Stop();
myController.SomeMethod()
}
private void myButton_Click( object sender, EventArgs eventArgs )
{
// All the stuff done here will likely be moved
// into MyController.SomeMethod()
myController.SomeMethod();
}
}
Одним из преимуществ использования MVC является отделение контроллера от представления. Контроллер теперь можно легко использовать для нескольких типов представлений, а выход из графического интерфейса пользователя проще поддерживать, поскольку он содержит очень мало логики приложения.
РЕДАКТИРОВАТЬ: добавлено в ответ на комментарии OP
Основные принципы проектирования в разговоре о разработке программного обеспечения о сцеплении и сплоченности. Важно отметить, что мы стремимся минимизировать взаимосвязь между компонентами при максимальной согласованности, так как это приводит к созданию более модульной и удобной в обслуживании системы. Такие шаблоны, как MVC, и принципалы, такие как Open / Closed Principal, основываются на этих основах, предоставляя разработчику более ощутимые шаблоны реализации.
Итак, любой, кто пишет код, как показано в исходной публикации, не понимает основ разработки программного обеспечения и должен значительно развить свои навыки. OP следует похвалить за определение этого «запаха кода» и попытку понять, почему он не совсем правильный.
Некоторые соответствующие ссылки:
#to_hash
.
Нонсенс args.merge (DEFAULTS) .merge (args)
позволяет использовать args
отменяет ПО УМОЛЧАНИЮ
, но
сохраняет любое поведение по умолчанию для args
(скажем, если args == Hash.new (3)
или args == Hash.new {| h, k | h [k]] = h.to_s.length}
class Volume
ATTRIBUTES = %w{
name size type owner date_created date_modified
iscsi_target iscsi_portal
}.map! { |s| s.to_sym }.freeze
attr_accessor *ATTRIBUTES
SYSTEM = 0
DATA = 1
DEFAULTS = { :type => SYSTEM }.freeze
def initialize(args = nil)
args = args ? args.merge(DEFAULTS).merge(args) : DEFAULTS
ATTRIBUTES.each do |attr|
instance_variable_set("@#{attr}", args[attr])
end
end
def to_hash
Hash[ *ATTRIBUTES.map { |attr| [ attr, instance_variable_get("@#{attr}") ] }.flatten ]
end
def inspect
to_hash.inspect
end
def to_json
self.to_hash.to_json
end
end
Вот немного другой вариант ответа Тадмана:
class Volume
ATTRIBUTES = [
:name, :size, :type, :owner, :date_created, :date_modified,
:iscsi_target, :iscsi_portal
].freeze
ATTRIBUTES.each do |attr|
attr_accessor attr
end
SYSTEM = 0
DATA = 1
DEFAULTS = {
:type => SYSTEM
}.freeze
def initialize(&block)
ATTRIBUTES.each do |attr|
self.__send__ "#{attr}=", DEFAULTS[attr]
end
yield(self)
end
def inspect
ATTRIBUTES.inject({}) { |h,attr| h[attr] = self.__send__ attr; h }
end
def to_json
self.inspect.to_json
end
end
Это позволяет сделать это:
vol = Volume.new do |v|
v.name = 'myVolume'
end
Мне это нравится, потому что это дает преимущество сразу же выдавать ошибки, если кто-то сделал опечатка в атрибуте.
Кроме того, в отличие от его ответа, он инициализирует значения по умолчанию, если они не указаны.
или если вы в конечном итоге делаете это много и действительно нуждаетесь в DRY:
module Attributable
@@ATTRIBUTES = []
@@DEFAULTS = {}
def initialize(&block)
@@ATTRIBUTES.each do |attr|
self.class.__send__ :attr_accessor, attr
self.__send__ "#{attr}=", @@DEFAULTS[attr]
end
yield(self)
end
end
class Volume
include Attributable
@@ATTRIBUTES = [ :name, :size, :type, :owner ]
@@DEFAULTS = { :type => 0 }
end
не могли понять, как это сделать с константами, поэтому я сделал это с переменными класса.